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