]> granicus.if.org Git - sudo/commitdiff
Allow the -k flag to be specified in conjunction with a command or
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 24 Feb 2009 13:04:39 +0000 (13:04 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 24 Feb 2009 13:04:39 +0000 (13:04 +0000)
another option that may require authentication.

check.c
sudo.c
sudo.pod
sudo_usage.h.in

diff --git a/check.c b/check.c
index ad4074bdbb9f2ca2895ca167c66918f2f81e8f4b..e7ce829f88f0d7ddf0185961ece0e0a574c9bcb6 100644 (file)
--- a/check.c
+++ b/check.c
@@ -84,24 +84,29 @@ static void  update_timestamp       __P((char *, char *));
  * verify who he/she is.
  */
 void
-check_user(validated, interactive)
+check_user(validated, mode)
     int validated;
-    int interactive;
+    int mode;
 {
     char *timestampdir = NULL;
     char *timestampfile = NULL;
     char *prompt;
     int status;
 
-    if (user_uid == 0 || user_uid == runas_pw->pw_uid || user_is_exempt())
-       return;
+    if (mode & MODE_INVALIDATE) {
+       /* do not check or update timestamp */
+       status = TS_ERROR;
+    } else {
+       if (user_uid == 0 || user_uid == runas_pw->pw_uid || user_is_exempt())
+           return;
 
-    build_timestamp(&timestampdir, &timestampfile);
-    status = timestamp_status(timestampdir, timestampfile, user_name,
+       build_timestamp(&timestampdir, &timestampfile);
+       status = timestamp_status(timestampdir, timestampfile, user_name,
        TS_MAKE_DIRS);
+    }
     if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
        /* Bail out if we are non-interactive and a password is required */
-       if (!interactive)
+       if (ISSET(mode, MODE_NONINTERACTIVE))
            errorx(1, "sorry, a password is required to run %s", getprogname());
 
        /* If user specified -A, make sure we have an askpass helper. */
@@ -139,7 +144,6 @@ check_user(validated, interactive)
 
 /*
  * Standard sudo lecture.
- * TODO: allow the user to specify a file name instead.
  */
 static void
 lecture(status)
diff --git a/sudo.c b/sudo.c
index 71186ef2cc3c8479cc5028b6b75242eb46148a98..f4e4537a2b27b674a095753e2d0d2a6da66ad669 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -95,8 +95,8 @@
 # include <selinux/selinux.h>
 #endif
 
+#include <sudo_usage.h>
 #include "sudo.h"
-#include "sudo_usage.h"
 #include "lbuf.h"
 #include "interfaces.h"
 #include "version.h"
@@ -231,7 +231,7 @@ main(argc, argv, envp)
        user_cmnd = "shell";
     else if (ISSET(sudo_mode, MODE_EDIT))
        user_cmnd = "sudoedit";
-    else
+    else {
        switch (sudo_mode) {
            case MODE_VERSION:
                show_version();
@@ -240,11 +240,12 @@ main(argc, argv, envp)
                usage(0);
                break;
            case MODE_VALIDATE:
+           case MODE_VALIDATE|MODE_INVALIDATE:
                user_cmnd = "validate";
                pwflag = I_VERIFYPW;
                break;
-           case MODE_KILL:
            case MODE_INVALIDATE:
+           case MODE_KILL:
                user_cmnd = "kill";
                pwflag = -1;
                break;
@@ -253,13 +254,16 @@ main(argc, argv, envp)
                exit(0);
                break;
            case MODE_LIST:
+           case MODE_LIST|MODE_INVALIDATE:
                user_cmnd = "list";
                pwflag = I_LISTPW;
                break;
            case MODE_CHECK:
+           case MODE_CHECK|MODE_INVALIDATE:
                pwflag = I_LISTPW;
                break;
        }
+    }
 
     /* Must have a command to run... */
     if (user_cmnd == NULL && NewArgc == 0)
@@ -405,7 +409,7 @@ main(argc, argv, envp)
 
     /* Require a password if sudoers says so.  */
     if (def_authenticate)
-       check_user(validated, !ISSET(sudo_mode, MODE_NONINTERACTIVE));
+       check_user(validated, sudo_mode);
 
     /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
     /* XXX - causes confusion when root is not listed in sudoers */
@@ -438,9 +442,9 @@ main(argc, argv, envp)
        }
 
        log_allowed(validated);
-       if (sudo_mode == MODE_CHECK)
+       if (ISSET(sudo_mode, MODE_CHECK))
            rc = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
-       else if (sudo_mode == MODE_LIST)
+       else if (ISSET(sudo_mode, MODE_LIST))
            display_privs(snl, list_pw ? list_pw : sudo_user.pw);
 
        /* Cleanup sudoers sources */
@@ -448,8 +452,7 @@ main(argc, argv, envp)
            nss->close(nss);
 
        /* Deferred exit due to sudo_ldap_close() */
-       if (sudo_mode == MODE_VALIDATE || sudo_mode == MODE_CHECK ||
-           sudo_mode == MODE_LIST)
+       if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST)))
            exit(rc);
 
        /*
@@ -835,7 +838,7 @@ parse_args(argc, argv)
 {
     int mode = 0;              /* what mode is sudo to be run in? */
     int flags = 0;             /* mode flags */
-    int ch;
+    int allowed_flags, ch;
 
     /* First, check to see if we were invoked as "sudoedit". */
     if (strcmp(getprogname(), "sudoedit") == 0)
@@ -849,6 +852,10 @@ parse_args(argc, argv)
 #define is_envar (optind < argc && argv[optind][0] != '/' && \
            strchr(argv[optind], '=') != NULL)
 
+    /* Flags allowed when running a command */
+    allowed_flags = MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|
+                   MODE_LOGIN_SHELL|MODE_INVALIDATE|MODE_NONINTERACTIVE|
+                   MODE_PRESERVE_GROUPS|MODE_SHELL;
     for (;;) {
        /*
         * We disable arg permutation for GNU getopt().
@@ -887,6 +894,7 @@ parse_args(argc, argv)
                    if (mode && mode != MODE_EDIT)
                        usage_excl(1);
                    mode = MODE_EDIT;
+                   allowed_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
                    break;
                case 'g':
                    runas_group = optarg;
@@ -898,25 +906,26 @@ parse_args(argc, argv)
                    if (mode && mode != MODE_HELP)
                        usage_excl(1);
                    mode = MODE_HELP;
+                   allowed_flags = 0;
                    break;
                case 'i':
                    SET(flags, MODE_LOGIN_SHELL);
                    def_env_reset = TRUE;
                    break;
                case 'k':
-                   if (mode && mode != MODE_INVALIDATE)
-                       usage_excl(1);
-                   mode = MODE_INVALIDATE;
+                   SET(flags, MODE_INVALIDATE);
                    break;
                case 'K':
                    if (mode && mode != MODE_KILL)
                        usage_excl(1);
                    mode = MODE_KILL;
+                   allowed_flags = 0;
                    break;
                case 'L':
                    if (mode && mode != MODE_LISTDEFS)
                        usage_excl(1);
                    mode = MODE_LISTDEFS;
+                   allowed_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
                    break;
                case 'l':
                    if (mode) {
@@ -926,6 +935,7 @@ parse_args(argc, argv)
                            usage_excl(1);
                    }
                    mode = MODE_LIST;
+                   allowed_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
                    break;
                case 'n':
                    SET(flags, MODE_NONINTERACTIVE);
@@ -962,11 +972,13 @@ parse_args(argc, argv)
                    if (mode && mode != MODE_VALIDATE)
                        usage_excl(1);
                    mode = MODE_VALIDATE;
+                   allowed_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
                    break;
                case 'V':
                    if (mode && mode != MODE_VERSION)
                        usage_excl(1);
                    mode = MODE_VERSION;
+                   allowed_flags = 0;
                    break;
                default:
                    usage(1);
@@ -991,8 +1003,15 @@ parse_args(argc, argv)
     NewArgc = argc - optind;
     NewArgv = argv + optind;
 
-    if (!mode)
-       mode = MODE_RUN;
+    if (!mode) {
+       /* Defer -k mode setting until we know whether it is a flag or not */
+       if (ISSET(flags, MODE_INVALIDATE) && NewArgc == 0) {
+           mode = MODE_INVALIDATE;     /* -k by itself */
+           allowed_flags = 0;
+       } else {
+           mode = MODE_RUN;            /* running a command */
+       }
+    }
 
     if (NewArgc > 0 && mode == MODE_LIST)
        mode = MODE_CHECK;
@@ -1008,6 +1027,8 @@ parse_args(argc, argv)
        }
        SET(flags, MODE_SHELL);
     }
+    if ((flags & allowed_flags) != flags)
+       usage(1);
     if (mode == MODE_EDIT &&
        (ISSET(flags, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) {
        if (ISSET(mode, MODE_PRESERVE_ENV))
@@ -1431,7 +1452,7 @@ static void
 usage_excl(exit_val)
     int exit_val;
 {
-    warningx("Only one of the -e, -h, -i, -k, -K, -l, -s, -v or -V options may be specified");
+    warningx("Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified");
     usage(exit_val);
 }
 
@@ -1444,21 +1465,22 @@ usage(exit_val)
     int exit_val;
 {
     struct lbuf lbuf;
-    char *uvec[5];
+    char *uvec[6];
     int i, ulen;
 
     /*
      * Use usage vectors appropriate to the progname.
      */
     if (strcmp(getprogname(), "sudoedit") == 0) {
-       uvec[0] = SUDO_USAGE4 + 3;
+       uvec[0] = SUDO_USAGE5 + 3;
        uvec[1] = NULL;
     } else {
        uvec[0] = SUDO_USAGE1;
        uvec[1] = SUDO_USAGE2;
        uvec[2] = SUDO_USAGE3;
        uvec[3] = SUDO_USAGE4;
-       uvec[4] = NULL;
+       uvec[4] = SUDO_USAGE5;
+       uvec[5] = NULL;
     }
 
     /*
index a8543a79625654abe5adcef2cc1bc6fb029a8669..6aff7c1a50b37539b7c9b911f554f20e70c59eab 100644 (file)
--- a/sudo.pod
+++ b/sudo.pod
@@ -27,10 +27,16 @@ sudo, sudoedit - execute a command as another user
 
 =head1 SYNOPSIS
 
-B<sudo> [B<-n>] B<-h> | B<-K> | B<-k> | B<-L> | B<-V> | B<-v>
+B<sudo> B<-h> | B<-K> | B<-k> | B<-L> | B<-V>
 
-B<sudo> B<-l[l]> [B<-AnS>] S<[B<-g> I<groupname>|I<#gid>]> S<[B<-U> I<username>]>
-S<[B<-u> I<username>|I<#uid>]> [I<command>]
+B<sudo> B<-v> [B<-AknS>]
+S<[B<-a> I<auth_type>]>
+S<[B<-p> I<prompt>]>
+
+B<sudo> B<-l[l]> [B<-AknS>]
+S<[B<-a> I<auth_type>]>
+S<[B<-g> I<groupname>|I<#gid>]> S<[B<-p> I<prompt>]>
+S<[B<-U> I<username>]> S<[B<-u> I<username>|I<#uid>]> [I<command>]
 
 B<sudo> [B<-AbEHnPS>]
 S<[B<-a> I<auth_type>]>
@@ -231,16 +237,23 @@ All other environment variables are removed.
 =item -K
 
 The B<-K> (sure I<kill>) option is like B<-k> except that it removes
-the user's timestamp entirely.  Like B<-k>, this option does not
-require a password.
+the user's timestamp entirely and may not be used in conjunction
+with a command or other option.  This option does not require a
+password.
 
 =item -k
 
-The B<-k> (I<kill>) option to B<sudo> invalidates the user's timestamp
-by setting the time on it to the Epoch.  The next time B<sudo> is
-run a password will be required.  This option does not require a password
-and was added to allow a user to revoke B<sudo> permissions from a .logout
-file.
+When used by itself, the B<-k> (I<kill>) option to B<sudo> invalidates
+the user's timestamp by setting the time on it to the Epoch.  The
+next time B<sudo> is run a password will be required.  This option
+does not require a password and was added to allow a user to revoke
+B<sudo> permissions from a .logout file.
+
+When used in conjunction with a command or an option that may require
+a password, the B<-k> option will cause B<sudo> to ignore the user's
+timestamp file.  As a result, B<sudo> will prompt for a password
+(if one is required by I<sudoers>) and will not update the user's
+timestamp file.
 
 =item -L
 
index 5a1bfc60fc7ad8e083860143d03a19e3c540710a..e6db4ee3fb8edc7aea9c52ed734761522bc4796e 100644 (file)
@@ -5,9 +5,10 @@
  * Usage strings for sudo.  These are here because we
  * need to be able to substitute values from configure.
  */
-#define SUDO_USAGE1 " [-n] -h | -K | -k | -L | -V | -v"
-#define SUDO_USAGE2 " -l[l] [-AnS] [-g groupname|#gid] [-U username] [-u username|#uid] [-g groupname|#gid] [command]"
-#define SUDO_USAGE3 " [-AbEHnPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] [<command>]"
-#define SUDO_USAGE4 " -e [-AnS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..."
+#define SUDO_USAGE1 " -h | -K | -k | -L | -V"
+#define SUDO_USAGE2 " -v [-AknS] @BSDAUTH_USAGE@[-p prompt]"
+#define SUDO_USAGE3 " -l[l] [-AknS] @BSDAUTH_USAGE@[-g groupname|#gid] [-p prompt] [-U username] [-u username|#uid] [-g groupname|#gid] [command]"
+#define SUDO_USAGE4 " [-AbEHknPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] [<command>]"
+#define SUDO_USAGE5 " -e [-AknS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..."
 
 #endif /* _SUDO_USAGE_H */