]> granicus.if.org Git - sudo/commitdiff
Fix the -s and -i flags and add support for the "implied_shell"
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 21 Mar 2010 12:54:06 +0000 (08:54 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 21 Mar 2010 12:54:06 +0000 (08:54 -0400)
option.  If the user does not specify a command, sudo will now pass
in the path to the user's shell and set impied_shell=true.  The
plugin can them either check the command normally or return -2 to
cause sudo to print a usage message and exit.

doc/sudo_plugin.cat
doc/sudo_plugin.man.in
doc/sudo_plugin.pod
plugins/sudoers/sudoers.c
plugins/sudoers/sudoers.h
src/parse_args.c
src/sudo.c
src/sudo.h

index a6dd702e40ae855e73841deee97aba65b3214052..2e0a0b595861e1b8be00f144e538ac281b2e388a 100644 (file)
@@ -61,7 +61,7 @@ S\bSu\bud\bdo\bo P\bPl\blu\bug\bgi\bin\bn A\bAP\bPI\bI
 
 
 
-1.8.0a1                   March 19, 2010                        1
+1.8.0a1                   March 21, 2010                        1
 
 
 
@@ -127,7 +127,7 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
 
-1.8.0a1                   March 19, 2010                        2
+1.8.0a1                   March 21, 2010                        2
 
 
 
@@ -172,6 +172,15 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                    Set to true if the user specified the -i flag, indicating
                    that the user wishes to run a login shell.
 
+               implied_shell=bool
+                   If the user does not specify a program on the command line,
+                   s\bsu\bud\bdo\bo will pass the plugin the path to the user's shell and
+                   set _\bi_\bm_\bp_\bl_\bi_\be_\bd_\b__\bs_\bh_\be_\bl_\bl to true.  This allows s\bsu\bud\bdo\bo with no
+                   arguments to be used similarly to _\bs_\bu(1).  If the plugin
+                   does not to support this usage, it may return a value of -2
+                   from the check_policy function, which will cause s\bsu\bud\bdo\bo to
+                   print a usage message and exit.
+
                preserve_groups=bool
                    Set to true if the user specified the -P flag, indicating
                    that the user wishes to preserve the group vector instead
@@ -182,25 +191,24 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                    command, indicating that the user wishes to ignore any
                    cached authentication credentials.
 
-               login_class=string
-                   BSD login class to use when setting resource limits and
-                   nice value, if specified by the -c flag.
-
-               selinux_role=string
-                   SELinux role to use when executing the command, if
-                   specified by the -r flag.
 
 
+1.8.0a1                   March 21, 2010                        3
 
 
-1.8.0a1                   March 19, 2010                        3
 
 
 
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
-SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+               login_class=string
+                   BSD login class to use when setting resource limits and
+                   nice value, if specified by the -c flag.
 
+               selinux_role=string
+                   SELinux role to use when executing the command, if
+                   specified by the -r flag.
 
                selinux_type=string
                    SELinux type to use when executing the command, if
@@ -247,19 +255,11 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                    terminal device associated with the session, the value will
                    be empty, as in tty=.
 
-               host=string
-                   The local machine's hostname as returned by the
-                   gethostname() system call.
 
-               lines=int
-                   The number of lines the user's terminal supports.  If there
-                   is no terminal device available, a default value of 24 is
-                   used.
 
 
 
-
-1.8.0a1                   March 19, 2010                        4
+1.8.0a1                   March 21, 2010                        4
 
 
 
@@ -268,6 +268,15 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+               host=string
+                   The local machine's hostname as returned by the
+                   gethostname() system call.
+
+               lines=int
+                   The number of lines the user's terminal supports.  If there
+                   is no terminal device available, a default value of 24 is
+                   used.
+
                cols=int
                    The number of columns the user's terminal supports.  If
                    there is no terminal device available, a default value of
@@ -311,21 +320,12 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
            will be set.
 
        check_policy
-            int (*check_policy)(int argc, char * const argv[]
-                                char *env_add[], char **command_info[],
-                                char **argv_out[], char **user_env_out[]);
 
-           The _\bc_\bh_\be_\bc_\bk_\b__\bp_\bo_\bl_\bi_\bc_\by function is called by s\bsu\bud\bdo\bo to determine whether
-           the user is allowed to run the specified commands.  Returns 1 if
-           the command is allowed, 0 if not and -1 on error.  On error, the
-           plugin may optionally call the conversation function with
-           SUDO_CONF_ERROR_MSG to present additional error information to the
-           user.
 
 
 
 
-1.8.0a1                   March 19, 2010                        5
+1.8.0a1                   March 21, 2010                        5
 
 
 
@@ -334,6 +334,17 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+            int (*check_policy)(int argc, char * const argv[]
+                                char *env_add[], char **command_info[],
+                                char **argv_out[], char **user_env_out[]);
+
+           The _\bc_\bh_\be_\bc_\bk_\b__\bp_\bo_\bl_\bi_\bc_\by function is called by s\bsu\bud\bdo\bo to determine whether
+           the user is allowed to run the specified commands.  Returns 1 if
+           the command is allowed, 0 if not and -1 on error.  On error, the
+           plugin may optionally call the conversation function with
+           SUDO_CONF_ERROR_MSG to present additional error information to the
+           user.
+
            The function arguments are as follows:
 
            argc
@@ -377,29 +388,29 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                runas_gid=gid
                    Group ID to run the command as.
 
-               runas_egid=gid
-                   Effective group ID to run the command as.  If not
-                   specified, the value of _\br_\bu_\bn_\ba_\bs_\b__\bg_\bi_\bd is used.
 
-               runas_groups=list
-                   The supplementary group vector to use for the command in
-                   the form of a comma-separated list of group IDs.  If
-                   _\bp_\br_\be_\bs_\be_\br_\bv_\be_\b__\bg_\br_\bo_\bu_\bp_\bs is set, this option is ignored.
 
-               login_class=login_class
-                   BSD login class to use when setting resource limits and
 
+1.8.0a1                   March 21, 2010                        6
 
 
-1.8.0a1                   March 19, 2010                        6
 
 
 
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
-SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+               runas_egid=gid
+                   Effective group ID to run the command as.  If not
+                   specified, the value of _\br_\bu_\bn_\ba_\bs_\b__\bg_\bi_\bd is used.
 
+               runas_groups=list
+                   The supplementary group vector to use for the command in
+                   the form of a comma-separated list of group IDs.  If
+                   _\bp_\br_\be_\bs_\be_\br_\bv_\be_\b__\bg_\br_\bo_\bu_\bp_\bs is set, this option is ignored.
 
+               login_class=login_class
+                   BSD login class to use when setting resource limits and
                    nice value (optional).  This option is only set on systems
                    that support login classes.
 
@@ -442,22 +453,11 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                system call when executing the command.  The plugin is
                responsible for allocating and populating the vector.
 
-           user_env_out
-               The NULL-terminated environment vector to use when executing
-               the command.  The plugin is responsible for allocating and
-               populating the vector.
-
-       list
-            int (*list)(int verbose, const char *list_user,
-                        int argc, char * const argv[]);
 
-           List available privileges for the invoking user.  Returns 1 on
-           success, 0 on failure and -1 on error.  On error, the plugin may
-           optionally call the conversation function with SUDO_CONF_ERROR_MSG
 
 
 
-1.8.0a1                   March 19, 2010                        7
+1.8.0a1                   March 21, 2010                        7
 
 
 
@@ -466,6 +466,18 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+           user_env_out
+               The NULL-terminated environment vector to use when executing
+               the command.  The plugin is responsible for allocating and
+               populating the vector.
+
+       list
+            int (*list)(int verbose, const char *list_user,
+                        int argc, char * const argv[]);
+
+           List available privileges for the invoking user.  Returns 1 on
+           success, 0 on failure and -1 on error.  On error, the plugin may
+           optionally call the conversation function with SUDO_CONF_ERROR_MSG
            to present additional error information to the user.
 
            Privileges should be output via the conversation function using
@@ -509,28 +521,27 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
        invalidate
             void (*invalidate)(int remove);
 
-           The invalidate function is called when s\bsu\bud\bdo\bo is called with the -k
-           or -K flag.  For policy plugins such as _\bs_\bu_\bd_\bo_\be_\br_\bs that cache
-           authentication credentials, this function will invalidate the
-           credentials.  If the _\br_\be_\bm_\bo_\bv_\be flag is set, the plugin may remove the
-           credentials instead of simply invalidating them.
 
-           The invalidate function should be NULL if the plugin does not
-           support credential caching.
-
-       _\bC_\bo_\bn_\bv_\be_\br_\bs_\ba_\bt_\bi_\bo_\bn _\bA_\bP_\bI
 
+1.8.0a1                   March 21, 2010                        8
 
 
 
-1.8.0a1                   March 19, 2010                        8
 
 
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+           The invalidate function is called when s\bsu\bud\bdo\bo is called with the -k
+           or -K flag.  For policy plugins such as _\bs_\bu_\bd_\bo_\be_\br_\bs that cache
+           authentication credentials, this function will invalidate the
+           credentials.  If the _\br_\be_\bm_\bo_\bv_\be flag is set, the plugin may remove the
+           credentials instead of simply invalidating them.
 
-SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+           The invalidate function should be NULL if the plugin does not
+           support credential caching.
 
+       _\bC_\bo_\bn_\bv_\be_\br_\bs_\ba_\bt_\bi_\bo_\bn _\bA_\bP_\bI
 
        If the plugin needs to interact with the user or display informational
        or error messages, it may do so via the conversation function.  A
@@ -566,6 +577,27 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
        usage.
 
    I\bI/\b/O\bO P\bPl\blu\bug\bgi\bin\bn A\bAP\bPI\bI
+
+
+
+
+
+
+
+
+
+
+
+
+1.8.0a1                   March 21, 2010                        9
+
+
+
+
+
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+
+
         struct io_plugin {
         #define SUDO_IO_PLUGIN         2
             unsigned int type; /* always SUDO_IO_PLUGIN */
@@ -586,18 +618,6 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
        disabled, such as passwords).  The log_output function receives output
        from the pseudo-tty that is suitable for replaying the user's session
        at a later time.  Either log_input or log_output may be NULL.  If the
-
-
-
-1.8.0a1                   March 19, 2010                        9
-
-
-
-
-
-SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
-
-
        open function returns 0, no I/O will be sent to the plugin.
 
        The io_plugin struct has the following fields:
@@ -632,6 +652,18 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                A pointer to the conversation function that may be used by the
                _\bs_\bh_\bo_\bw_\b__\bv_\be_\br_\bs_\bi_\bo_\bn function to display version information (see
                show_version below).  The conversation function may also be
+
+
+
+1.8.0a1                   March 21, 2010                       10
+
+
+
+
+
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+
+
                used to display additional error message to the user.
 
            settings
@@ -653,17 +685,6 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                the form of "name=value" strings.  The vector is terminated by
                a NULL pointer.
 
-
-
-1.8.0a1                   March 19, 2010                       10
-
-
-
-
-
-SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
-
-
                When parsing _\bu_\bs_\be_\br_\b__\bi_\bn_\bf_\bo, the plugin should split on the f\bfi\bir\brs\bst\bt
                equal sign ('=') since the _\bn_\ba_\bm_\be field will never include one
                itself but the _\bv_\ba_\bl_\bu_\be might.
@@ -697,6 +718,18 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                of errno set by the _\be_\bx_\be_\bc_\bv_\be(2) system call.  If the command was
                successfully executed, the value of error is 0.
 
+
+
+
+1.8.0a1                   March 21, 2010                       11
+
+
+
+
+
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+
+
        show_version
             int (*show_version)(int verbose);
 
@@ -718,18 +751,6 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
            The function arguments are as follows:
 
-
-
-
-1.8.0a1                   March 19, 2010                       11
-
-
-
-
-
-SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
-
-
            buf The buffer containing user input.
 
            len The length of _\bb_\bu_\bf in bytes.
@@ -757,6 +778,24 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
    S\bSu\bud\bdo\bo i\bim\bmp\bpl\ble\bem\bme\ben\bnt\bta\bat\bti\bio\bon\bn d\bde\bet\bta\bai\bil\bls\bs
        Version macros:
 
+
+
+
+
+
+
+
+
+
+1.8.0a1                   March 21, 2010                       12
+
+
+
+
+
+SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
+
+
         #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
         #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
         #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
@@ -787,6 +826,33 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
 
-1.8.0a1                   March 19, 2010                       12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1.8.0a1                   March 21, 2010                       13
 
 
index 8dd462c15b37891e741741059cf391d523705eeb..46dab62b0c84994758cd44e71095da34690f5851 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "SUDO_PLUGIN @mansectsu@"
-.TH SUDO_PLUGIN @mansectsu@ "March 19, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
+.TH SUDO_PLUGIN @mansectsu@ "March 21, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -295,6 +295,15 @@ the user wishes to preserve the environment.
 .IX Item "login_shell=bool"
 Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that
 the user wishes to run a login shell.
+.IP "implied_shell=bool" 4
+.IX Item "implied_shell=bool"
+If the user does not specify a program on the command line, \fBsudo\fR
+will pass the plugin the path to the user's shell and set
+\&\fIimplied_shell\fR to true.  This allows \fBsudo\fR with no arguments
+to be used similarly to \fIsu\fR\|(1).  If the plugin does not to support
+this usage, it may return a value of \-2 from the \f(CW\*(C`check_policy\*(C'\fR
+function, which will cause \fBsudo\fR to print a usage message and
+exit.
 .IP "preserve_groups=bool" 4
 .IX Item "preserve_groups=bool"
 Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that
index 8f3dbb378f66796cd9a514274284879afad38e93..d1111491073c7433df26aeee511299e69eb39747 100644 (file)
@@ -180,6 +180,16 @@ the user wishes to preserve the environment.
 Set to true if the user specified the C<-i> flag, indicating that
 the user wishes to run a login shell.
 
+=item implied_shell=bool
+
+If the user does not specify a program on the command line, B<sudo>
+will pass the plugin the path to the user's shell and set
+I<implied_shell> to true.  This allows B<sudo> with no arguments
+to be used similarly to L<su(1)>.  If the plugin does not to support
+this usage, it may return a value of -2 from the C<check_policy>
+function, which will cause B<sudo> to print a usage message and
+exit.
+
 =item preserve_groups=bool
 
 Set to true if the user specified the C<-P> flag, indicating that
index 469c5f1ff62ebe408a9aead5ffa57f4803896b46..6a5645fa9ba1399d12237ea78027f557ab5ea25c 100644 (file)
@@ -262,12 +262,6 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
     /* Set login class if applicable. */
     set_loginclass(sudo_user.pw);
 
-#if 0 /* XXX - later */
-    /* Update initial shell now that runas is set. */
-    if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
-       NewArgv[0] = runas_pw->pw_shell;
-#endif
-
     /* XXX */
     user_env = envp; /* stash for later */
 
@@ -305,11 +299,17 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
        return -1;
     }
 
-    /* Local copy of argv */
+    /*
+     * Make a local copy of argc/argv, with special handling
+     * for the '-e', '-i' or '-s' options.
+     * XXX - handle sudoedit
+     */
     NewArgv = emalloc2(argc + 1, sizeof(char *));
     memcpy(NewArgv, argv, argc * sizeof(char *));
     NewArgv[argc] = NULL;
     NewArgc = argc;
+    if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
+       NewArgv[0] = runas_pw->pw_shell;
 
     /* Set environ to contents of user_env. */
     env_init(user_env);
@@ -387,9 +387,9 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
     if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
        def_preserve_groups = TRUE;
 
-    /* If no command line args and "set_home" is not set, error out. */
+    /* If no command line args and "shell_noargs" is not set, error out. */
     if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
-       /* XXX - error message */
+       rval = -2; /* usage error */
        goto done;
     }
 
@@ -447,7 +447,7 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
        goto done;
     } else if (cmnd_status == NOT_FOUND) {
        //audit_failure(NewArgv, "%s: command not found", user_cmnd);
-       warningx("command not found", user_cmnd);
+       warningx("%s: command not found", user_cmnd);
        goto done;
     }
 
@@ -622,12 +622,6 @@ init_vars(char * const envp[])
     (void) tzset();            /* set the timezone if applicable */
 #endif /* HAVE_TZSET */
 
-#if 0
-    /* Default value for cmnd and cwd, overridden later. */
-    if (user_cmnd == NULL)
-       user_cmnd = NewArgv[0];
-#endif
-
     for (ep = envp; *ep; ep++) {
        /* XXX - don't fill in if empty string */
        switch (**ep) {
@@ -644,9 +638,7 @@ init_vars(char * const envp[])
                    user_path = *ep + 5;
                break;
            case 'S':
-               if (strncmp("SHELL=", *ep, 6) == 0)
-                   user_shell = *ep + 6;
-               else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
+               if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
                    user_prompt = *ep + 12;
                else if (strncmp("SUDO_USER=", *ep, 10) == 0)
                    prev_user = *ep + 10;
@@ -683,8 +675,6 @@ init_vars(char * const envp[])
 #ifdef HAVE_MBR_CHECK_MEMBERSHIP
     mbr_uid_to_uuid(user_uid, user_uuid);
 #endif
-    if (user_shell == NULL || *user_shell == '\0')
-       user_shell = estrdup(sudo_user.pw->pw_shell);
 
     /* It is now safe to use log_error() and set_perms() */
 
@@ -692,43 +682,6 @@ init_vars(char * const envp[])
        /* may call log_error() */
        set_fqdn();
     }
-
-#if 0 /* XXX need to adapt this in sudo.c */
-    /*
-     * If we were given the '-e', '-i' or '-s' options we need to redo
-     * NewArgv and NewArgc.
-     */
-    if (ISSET(sudo_mode, MODE_EDIT)) {
-       NewArgv--;
-       NewArgc++;
-       NewArgv[0] = "sudoedit";
-    } else if (ISSET(sudo_mode, MODE_SHELL)) {
-       char **av;
-
-       /* Allocate an extra slot for execve() failure (ENOEXEC). */
-       av = (char **) emalloc2(5, sizeof(char *));
-       av++;
-
-       av[0] = user_shell;     /* may be updated later */
-       if (NewArgc > 0) {
-           size_t size;
-           char *cmnd, *src, *dst, *end;
-           size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) +
-                   strlen(NewArgv[NewArgc - 1]) + 1;
-           cmnd = emalloc(size);
-           src = NewArgv[0];
-           dst = cmnd;
-           for (end = src + size - 1; src < end; src++, dst++)
-               *dst = *src == 0 ? ' ' : *src;
-           *dst = '\0';
-           av[1] = "-c";
-           av[2] = cmnd;
-           NewArgc = 2;
-       }
-       av[++NewArgc] = NULL;
-       NewArgv = av;
-    }
-#endif
 }
 
 /*
@@ -748,6 +701,10 @@ set_cmnd(sudo_mode)
     rval = FOUND;
     user_stat = emalloc(sizeof(struct stat));
 
+    /* Default value for cmnd, overridden below. */
+    if (user_cmnd == NULL)
+       user_cmnd = NewArgv[0];
+
     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
        if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
            set_perms(PERM_RUNAS);
@@ -766,16 +723,9 @@ set_cmnd(sudo_mode)
            char *to, **from;
            size_t size, n;
 
-           /* If we didn't realloc NewArgv it is contiguous so just count. */
-           if (!ISSET(sudo_mode, MODE_SHELL)) {
-               size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
-                       strlen(NewArgv[NewArgc-1]) + 1;
-           } else {
-               for (size = 0, from = NewArgv + 1; *from; from++)
-                   size += strlen(*from) + 1;
-           }
-
            /* Alloc and build up user_args. */
+           for (size = 0, from = NewArgv + 1; *from; from++)
+               size += strlen(*from) + 1;
            user_args = emalloc(size);
            for (to = user_args, from = NewArgv + 1; *from; from++) {
                n = strlcpy(to, *from, size - (to - user_args));
@@ -1197,6 +1147,11 @@ deserialize_info(char * const settings[], char * const user_info[])
            }
            continue;
        }
+       if (MATCHES(*cur, "implied_shell=")) {
+           if (atobool(*cur + sizeof("implied_shell=") - 1) == TRUE)
+               SET(flags, MODE_IMPLIED_SHELL);
+           continue;
+       }
        if (MATCHES(*cur, "preserve_groups=")) {
            SET(flags, MODE_PRESERVE_GROUPS);
            continue;
index 19ac90131070a1747e20873af2449683bbed409e..8a829a19baea7dccdeb93473c88329a6b5738c9b 100644 (file)
@@ -48,7 +48,6 @@ struct sudo_user {
     struct stat *cmnd_stat;
     char *name;
     char *path;
-    char *shell;
     char *tty;
     char *ttypath;
     char *host;
@@ -156,7 +155,6 @@ struct sudo_user {
 #define user_passwd            (sudo_user.pw->pw_passwd)
 #define user_uuid              (sudo_user.uuid)
 #define user_dir               (sudo_user.pw->pw_dir)
-#define user_shell             (sudo_user.shell)
 #define user_ngroups           (sudo_user.ngroups)
 #define user_groups            (sudo_user.groups)
 #define user_tty               (sudo_user.tty)
index 222a190574ccefa97dda3e2afbe513c00c2e70c8..d8837a86a68ce251b820de6420a0ef72b3887eda 100644 (file)
@@ -66,7 +66,6 @@ const char *list_user, *runas_user, *runas_group;
 /*
  * Local functions.
  */
-static void usage(int) __attribute__((__noreturn__));
 static void usage_excl(int) __attribute__((__noreturn__));
 
 /*
@@ -102,7 +101,9 @@ static struct sudo_settings {
     { "runas_user" },
 #define ARG_PROGNAME 12
     { "progname" },
-#define NUM_SETTINGS 13
+#define ARG_IMPLIED_SHELL 13
+    { "implied_shell" },
+#define NUM_SETTINGS 14
     { NULL }
 };
 
@@ -295,13 +296,13 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
        }
     }
 
-    *nargc = argc - optind;
-    *nargv = argv + optind;
+    argc -= optind;
+    argv += optind;
 
     if (!mode) {
        /* Defer -k mode setting until we know whether it is a flag or not */
        if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) {
-           if (*nargc == 0) {
+           if (argc == 0) {
                mode = MODE_INVALIDATE; /* -k by itself */
                sudo_settings[ARG_IGNORE_TICKET].value = NULL;
                valid_flags = 0;
@@ -311,7 +312,7 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
            mode = MODE_RUN;            /* running a command */
     }
 
-    if (*nargc > 0 && mode == MODE_LIST)
+    if (argc > 0 && mode == MODE_LIST)
        mode = MODE_CHECK;
 
     if (ISSET(flags, MODE_LOGIN_SHELL)) {
@@ -347,15 +348,55 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
        warningx("the `-A' and `-S' options may not be used together");
        usage(1);
     }
-    if ((*nargc == 0 && mode == MODE_EDIT) ||
-       (*nargc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
+    if ((argc == 0 && mode == MODE_EDIT) ||
+       (argc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
        usage(1);
-    if (*nargc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL))
+    if (argc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL)) {
        SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
+       sudo_settings[ARG_IMPLIED_SHELL].value = "true";
+    }
 
     if (mode == MODE_HELP)
        usage(0);
 
+    /*
+     * For shell mode we need to rewrite argv
+     */
+    if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {
+       char **av;
+       int ac;
+
+       if (argc == 0) {
+           /* just the shell */
+           ac = argc + 1;
+           av = emalloc2(ac + 1, sizeof(char *));
+           memcpy(av + 1, argv, argc * sizeof(char *));
+       } else {
+           /* shell -c "command" */
+           size_t size;
+           char *src, *dst, *end;
+
+           /* length of the command + NUL terminator */
+           size = (size_t)(argv[argc - 1] - argv[0]) +
+               strlen(argv[argc - 1]) + 1;
+
+           ac = 3;
+           av = emalloc2(ac + 1, sizeof(char *));
+           av[1] = "-c";
+           av[2] = dst = emalloc(size);
+
+           src = argv[0];
+           for (end = src + size - 1; src < end; src++, dst++)
+               *dst = *src == 0 ? ' ' : *src;
+           *dst = '\0';
+       }
+       av[0] = (char *)user_details.shell; /* plugin may override shell */
+       av[ac] = NULL;
+
+       argv = av;
+       argc = ac;
+    }
+
     /*
      * Format setting_pairs into settings array.
      */
@@ -375,6 +416,8 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
 
     *settingsp = settings;
     *env_addp = env_add;
+    *nargc = argc;
+    *nargv = argv;
     return(mode | flags);
 }
 
@@ -388,7 +431,7 @@ usage_out(const char *buf)
  * Give usage message and exit.
  * The actual usage strings are in sudo_usage.h for configure substitution.
  */
-static void
+void
 usage(int exit_val)
 {
     struct lbuf lbuf;
index a595b0aaa251cdaa74a556c2e8aac8885f410525..7b9554955704dae9054e5819e206ee6d899772d2 100644 (file)
@@ -224,8 +224,11 @@ main(int argc, char *argv[], char *envp[])
            ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add,
                &command_info, &argv_out, &user_env_out);
            sudo_debug(8, "policy plugin returns %d", ok);
-           if (ok != TRUE)
-               exit(ok); /* plugin printed error message */
+           if (ok != TRUE) {
+               if (ok == -2)
+                   usage(1);
+               exit(1); /* plugin printed error message */
+           }
            command_info_to_details(command_info, &command_details);
            /* Restore coredumpsize resource limit before running. */
 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
@@ -330,6 +333,12 @@ get_user_info(struct user_details *ud)
        errorx(1, "unable to allocate memory");
     ud->username = user_info[i] + sizeof("user=") - 1;
 
+    /* Stash user's shell for use with the -s flag; don't pass to plugin. */
+    if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') {
+       ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_BSHELL;
+    }
+    ud->shell = estrdup(ud->shell);
+
     easprintf(&user_info[++i], "uid=%lu", (unsigned long)ud->uid);
     easprintf(&user_info[++i], "euid=%lu", (unsigned long)ud->euid);
     easprintf(&user_info[++i], "gid=%lu", (unsigned long)ud->gid);
index 5dcc4871da7ec6154b9bbba954ec76406f992912..2408e9112c8092fbfaeaa9375dbd1a10f80d871a 100644 (file)
@@ -117,6 +117,7 @@ struct user_details {
     const char *cwd;
     const char *tty;
     const char *host;
+    const char *shell;
     GETGROUPS_T *groups;
     int ngroups;
     int ts_cols;
@@ -210,6 +211,9 @@ int exec_setup(struct command_details *details);
 extern int debug_level;
 extern struct plugin_container_list io_plugins;
 
+/* parse_args.c */
+void usage(int) __attribute__((__noreturn__));
+
 #ifndef errno
 extern int errno;
 #endif