Add a way to run a command without updating the cached credentials.
This can also be used to test for whether or not the user's credentials are currently cached.
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.TH "SUDO" "@mansectsu@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
|
||||
.TH "SUDO" "@mansectsu@" "August 2, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
|
||||
.nh
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -41,7 +41,7 @@
|
||||
.HP 5n
|
||||
\fBsudo\fR
|
||||
\fB\-v\fR
|
||||
[\fB\-ABknS\fR]
|
||||
[\fB\-ABkNnS\fR]
|
||||
.if \n(BA [\fB\-a\fR\ \fItype\fR]
|
||||
[\fB\-g\fR\ \fIgroup\fR]
|
||||
[\fB\-h\fR\ \fIhost\fR]
|
||||
@@ -51,7 +51,7 @@
|
||||
.HP 5n
|
||||
\fBsudo\fR
|
||||
\fB\-l\fR
|
||||
[\fB\-ABknS\fR]
|
||||
[\fB\-ABkNnS\fR]
|
||||
.if \n(BA [\fB\-a\fR\ \fItype\fR]
|
||||
[\fB\-g\fR\ \fIgroup\fR]
|
||||
[\fB\-h\fR\ \fIhost\fR]
|
||||
@@ -81,7 +81,7 @@
|
||||
.br
|
||||
.HP 9n
|
||||
\fBsudoedit\fR
|
||||
[\fB\-ABknS\fR]
|
||||
[\fB\-ABkNnS\fR]
|
||||
.if \n(BA [\fB\-a\fR\ \fItype\fR]
|
||||
[\fB\-C\fR\ \fInum\fR]
|
||||
.if \n(LC [\fB\-c\fR\ \fIclass\fR]
|
||||
@@ -532,6 +532,22 @@ is specified but not allowed by the policy,
|
||||
\fBsudo\fR
|
||||
will exit with a status value of 1.
|
||||
.TP 12n
|
||||
\fB\-N\fR, \fB\--no-update\fR
|
||||
Do not update the user's cached credentials, even if the user successfully
|
||||
authenticates.
|
||||
Unlike the
|
||||
\fB\-k\fR
|
||||
flag, existing cached credentials are used if they are valid.
|
||||
To detect when the user's cached credentials are valid (or when no
|
||||
authentication is required), the following command can be used:
|
||||
.RS 18n
|
||||
sudo -Nnv
|
||||
.RE
|
||||
.RS 12n
|
||||
.sp
|
||||
Not all security policies support credential caching.
|
||||
.RE
|
||||
.TP 12n
|
||||
\fB\-n\fR, \fB\--non-interactive\fR
|
||||
Avoid prompting the user for input of any kind.
|
||||
If a password is required for the command to run,
|
||||
|
@@ -24,7 +24,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.Dd February 16, 2022
|
||||
.Dd August 2, 2022
|
||||
.Dt SUDO @mansectsu@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -36,7 +36,7 @@
|
||||
.Fl h | K | k | V
|
||||
.Nm sudo
|
||||
.Fl v
|
||||
.Op Fl ABknS
|
||||
.Op Fl ABkNnS
|
||||
.if \n(BA \{\
|
||||
.Op Fl a Ar type
|
||||
.\}
|
||||
@@ -46,7 +46,7 @@
|
||||
.Op Fl u Ar user
|
||||
.Nm sudo
|
||||
.Fl l
|
||||
.Op Fl ABknS
|
||||
.Op Fl ABkNnS
|
||||
.if \n(BA \{\
|
||||
.Op Fl a Ar type
|
||||
.\}
|
||||
@@ -80,7 +80,7 @@
|
||||
.Op Fl i | s
|
||||
.Op Ar command
|
||||
.Nm sudoedit
|
||||
.Op Fl ABknS
|
||||
.Op Fl ABkNnS
|
||||
.if \n(BA \{\
|
||||
.Op Fl a Ar type
|
||||
.\}
|
||||
@@ -505,6 +505,17 @@ If a
|
||||
is specified but not allowed by the policy,
|
||||
.Nm
|
||||
will exit with a status value of 1.
|
||||
.It Fl N , -no-update
|
||||
Do not update the user's cached credentials, even if the user successfully
|
||||
authenticates.
|
||||
Unlike the
|
||||
.Fl k
|
||||
flag, existing cached credentials are used if they are valid.
|
||||
To detect when the user's cached credentials are valid (or when no
|
||||
authentication is required), the following command can be used:
|
||||
.Dl sudo -Nnv
|
||||
.Pp
|
||||
Not all security policies support credential caching.
|
||||
.It Fl n , -non-interactive
|
||||
Avoid prompting the user for input of any kind.
|
||||
If a password is required for the command to run,
|
||||
|
@@ -215,8 +215,8 @@ done:
|
||||
* Only update time stamp if user validated and was approved.
|
||||
* Failure to update the time stamp is not a fatal error.
|
||||
*/
|
||||
if (ret == true && closure.tstat != TS_ERROR) {
|
||||
if (ISSET(validated, VALIDATE_SUCCESS))
|
||||
if (ret == true && ISSET(validated, VALIDATE_SUCCESS)) {
|
||||
if (ISSET(mode, MODE_UPDATE_TICKET) && closure.tstat != TS_ERROR)
|
||||
(void)timestamp_update(closure.cookie, closure.auth_pw);
|
||||
}
|
||||
}
|
||||
|
@@ -84,11 +84,11 @@ parse_bool(const char *line, int varlen, int *flags, int fval)
|
||||
}
|
||||
}
|
||||
|
||||
#define RUN_VALID_FLAGS (MODE_ASKPASS|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_IMPLIED_SHELL|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_PRESERVE_GROUPS|MODE_SHELL|MODE_RUN|MODE_POLICY_INTERCEPTED)
|
||||
#define EDIT_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_EDIT)
|
||||
#define LIST_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_LIST|MODE_CHECK)
|
||||
#define VALIDATE_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_VALIDATE)
|
||||
#define INVALIDATE_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_INVALIDATE)
|
||||
#define RUN_VALID_FLAGS (MODE_ASKPASS|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_IMPLIED_SHELL|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_PRESERVE_GROUPS|MODE_SHELL|MODE_RUN|MODE_POLICY_INTERCEPTED)
|
||||
#define EDIT_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_EDIT)
|
||||
#define LIST_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_LIST|MODE_CHECK)
|
||||
#define VALIDATE_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_VALIDATE)
|
||||
#define INVALIDATE_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_INVALIDATE)
|
||||
|
||||
/*
|
||||
* Deserialize args, settings and user_info arrays.
|
||||
@@ -102,7 +102,7 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
|
||||
const char *remhost = NULL;
|
||||
unsigned char uuid[16];
|
||||
char * const *cur;
|
||||
int flags = 0;
|
||||
int flags = MODE_UPDATE_TICKET;
|
||||
debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN);
|
||||
|
||||
#define MATCHES(s, v) \
|
||||
@@ -280,6 +280,12 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
|
||||
goto bad;
|
||||
continue;
|
||||
}
|
||||
if (MATCHES(*cur, "update_ticket=")) {
|
||||
if (parse_bool(*cur, sizeof("update_ticket") -1, &flags,
|
||||
MODE_UPDATE_TICKET) == -1)
|
||||
goto bad;
|
||||
continue;
|
||||
}
|
||||
if (MATCHES(*cur, "noninteractive=")) {
|
||||
if (parse_bool(*cur, sizeof("noninteractive") - 1, &flags,
|
||||
MODE_NONINTERACTIVE) == -1)
|
||||
@@ -395,6 +401,9 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Ignore ticket trumps update. */
|
||||
if (ISSET(flags, MODE_IGNORE_TICKET))
|
||||
CLR(flags, MODE_UPDATE_TICKET);
|
||||
|
||||
user_gid = (gid_t)-1;
|
||||
user_sid = (pid_t)-1;
|
||||
|
@@ -201,7 +201,8 @@ struct sudo_user {
|
||||
#define MODE_PRESERVE_ENV 0x00400000
|
||||
#define MODE_NONINTERACTIVE 0x00800000
|
||||
#define MODE_IGNORE_TICKET 0x01000000
|
||||
#define MODE_POLICY_INTERCEPTED 0x02000000
|
||||
#define MODE_UPDATE_TICKET 0x02000000
|
||||
#define MODE_POLICY_INTERCEPTED 0x04000000
|
||||
|
||||
/* Mode bits allowed for intercepted commands. */
|
||||
#define MODE_INTERCEPT_MASK (MODE_RUN|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_POLICY_INTERCEPTED)
|
||||
|
@@ -49,6 +49,7 @@ int tgetpass_flags;
|
||||
*/
|
||||
static void help(void) __attribute__((__noreturn__));
|
||||
static void usage_excl(void) __attribute__((__noreturn__));
|
||||
static void usage_excl_ticket(void) __attribute__((__noreturn__));
|
||||
|
||||
/*
|
||||
* Mapping of command line flags to name/value settings.
|
||||
@@ -63,6 +64,7 @@ static struct sudo_settings sudo_settings[] = {
|
||||
{ "run_shell" },
|
||||
{ "login_shell" },
|
||||
{ "ignore_ticket" },
|
||||
{ "update_ticket" },
|
||||
{ "prompt" },
|
||||
{ "selinux_role" },
|
||||
{ "selinux_type" },
|
||||
@@ -111,8 +113,8 @@ struct environment {
|
||||
* There is a more limited set of options for sudoedit (the sudo-specific
|
||||
* long options are listed first).
|
||||
*/
|
||||
static const char sudo_short_opts[] = "+Aa:BbC:c:D:Eeg:Hh::iKklnPp:R:r:SsT:t:U:u:Vv";
|
||||
static const char edit_short_opts[] = "+Aa:BC:c:D:g:h::knp:R:r:ST:t:u:V";
|
||||
static const char sudo_short_opts[] = "+Aa:BbC:c:D:Eeg:Hh::iKklNnPp:R:r:SsT:t:U:u:Vv";
|
||||
static const char edit_short_opts[] = "+Aa:BC:c:D:g:h::KkNnp:R:r:ST:t:u:V";
|
||||
static struct option sudo_long_opts[] = {
|
||||
/* sudo-specific long options */
|
||||
{ "background", no_argument, NULL, 'b' },
|
||||
@@ -137,6 +139,7 @@ static struct option sudo_long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "host", required_argument, NULL, OPT_HOSTNAME },
|
||||
{ "reset-timestamp", no_argument, NULL, 'k' },
|
||||
{ "no-update", no_argument, NULL, 'N' },
|
||||
{ "non-interactive", no_argument, NULL, 'n' },
|
||||
{ "prompt", required_argument, NULL, 'p' },
|
||||
{ "chroot", required_argument, NULL, 'R' },
|
||||
@@ -403,15 +406,16 @@ parse_args(int argc, char **argv, int *old_optind, int *nargc, char ***nargv,
|
||||
sudo_settings[ARG_LOGIN_SHELL].value = "true";
|
||||
SET(flags, MODE_LOGIN_SHELL);
|
||||
break;
|
||||
case 'k':
|
||||
sudo_settings[ARG_IGNORE_TICKET].value = "true";
|
||||
break;
|
||||
case 'K':
|
||||
sudo_settings[ARG_IGNORE_TICKET].value = "true";
|
||||
if (mode && mode != MODE_KILL)
|
||||
usage_excl();
|
||||
mode = MODE_KILL;
|
||||
valid_flags = 0;
|
||||
FALLTHROUGH;
|
||||
case 'k':
|
||||
if (sudo_settings[ARG_UPDATE_TICKET].value != NULL)
|
||||
usage_excl_ticket();
|
||||
sudo_settings[ARG_IGNORE_TICKET].value = "true";
|
||||
break;
|
||||
case 'l':
|
||||
if (mode) {
|
||||
@@ -423,6 +427,11 @@ parse_args(int argc, char **argv, int *old_optind, int *nargc, char ***nargv,
|
||||
mode = MODE_LIST;
|
||||
valid_flags = LIST_VALID_FLAGS;
|
||||
break;
|
||||
case 'N':
|
||||
if (sudo_settings[ARG_IGNORE_TICKET].value != NULL)
|
||||
usage_excl_ticket();
|
||||
sudo_settings[ARG_UPDATE_TICKET].value = "false";
|
||||
break;
|
||||
case 'n':
|
||||
SET(flags, MODE_NONINTERACTIVE);
|
||||
sudo_settings[ARG_NONINTERACTIVE].value = "true";
|
||||
@@ -758,6 +767,19 @@ usage_excl(void)
|
||||
usage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell which options are mutually exclusive and exit.
|
||||
*/
|
||||
static void
|
||||
usage_excl_ticket(void)
|
||||
{
|
||||
debug_decl(usage_excl_ticket, SUDO_DEBUG_ARGS);
|
||||
|
||||
sudo_warnx("%s",
|
||||
U_("Only one of the -K, -k or -N options may be specified"));
|
||||
usage();
|
||||
}
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
|
@@ -1065,6 +1065,12 @@ format_plugin_settings(struct plugin_container *plugin)
|
||||
unsigned int i = 0;
|
||||
debug_decl(format_plugin_settings, SUDO_DEBUG_PCOMM);
|
||||
|
||||
/* We update the ticket entry by default. */
|
||||
if (sudo_settings[ARG_IGNORE_TICKET].value == NULL &&
|
||||
sudo_settings[ARG_UPDATE_TICKET].value == NULL) {
|
||||
sudo_settings[ARG_UPDATE_TICKET].value = "true";
|
||||
}
|
||||
|
||||
/* Determine sudo_settings array size (including plugin_path and NULL) */
|
||||
plugin_settings_size = 2;
|
||||
for (setting = sudo_settings; setting->name != NULL; setting++)
|
||||
|
43
src/sudo.h
43
src/sudo.h
@@ -84,27 +84,28 @@
|
||||
#define ARG_USER_SHELL 5
|
||||
#define ARG_LOGIN_SHELL 6
|
||||
#define ARG_IGNORE_TICKET 7
|
||||
#define ARG_PROMPT 8
|
||||
#define ARG_SELINUX_ROLE 9
|
||||
#define ARG_SELINUX_TYPE 10
|
||||
#define ARG_RUNAS_USER 11
|
||||
#define ARG_PROGNAME 12
|
||||
#define ARG_IMPLIED_SHELL 13
|
||||
#define ARG_PRESERVE_GROUPS 14
|
||||
#define ARG_NONINTERACTIVE 15
|
||||
#define ARG_SUDOEDIT 16
|
||||
#define ARG_CLOSEFROM 17
|
||||
#define ARG_NET_ADDRS 18
|
||||
#define ARG_MAX_GROUPS 19
|
||||
#define ARG_PLUGIN_DIR 20
|
||||
#define ARG_REMOTE_HOST 21
|
||||
#define ARG_TIMEOUT 22
|
||||
#define ARG_CHROOT 23
|
||||
#define ARG_CWD 24
|
||||
#define ARG_ASKPASS 25
|
||||
#define ARG_INTERCEPT_SETID 26
|
||||
#define ARG_INTERCEPT_PTRACE 27
|
||||
#define ARG_APPARMOR_PROFILE 28
|
||||
#define ARG_UPDATE_TICKET 8
|
||||
#define ARG_PROMPT 9
|
||||
#define ARG_SELINUX_ROLE 10
|
||||
#define ARG_SELINUX_TYPE 11
|
||||
#define ARG_RUNAS_USER 12
|
||||
#define ARG_PROGNAME 13
|
||||
#define ARG_IMPLIED_SHELL 14
|
||||
#define ARG_PRESERVE_GROUPS 15
|
||||
#define ARG_NONINTERACTIVE 16
|
||||
#define ARG_SUDOEDIT 17
|
||||
#define ARG_CLOSEFROM 18
|
||||
#define ARG_NET_ADDRS 19
|
||||
#define ARG_MAX_GROUPS 20
|
||||
#define ARG_PLUGIN_DIR 21
|
||||
#define ARG_REMOTE_HOST 22
|
||||
#define ARG_TIMEOUT 23
|
||||
#define ARG_CHROOT 24
|
||||
#define ARG_CWD 25
|
||||
#define ARG_ASKPASS 26
|
||||
#define ARG_INTERCEPT_SETID 27
|
||||
#define ARG_INTERCEPT_PTRACE 28
|
||||
#define ARG_APPARMOR_PROFILE 29
|
||||
|
||||
/*
|
||||
* Flags for tgetpass()
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2007-2010, 2013, 2015, 2017, 2020
|
||||
* Copyright (c) 2007-2010, 2013, 2015, 2017, 2020-2022
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -26,10 +26,10 @@
|
||||
*/
|
||||
#define SUDO_USAGE0 " -h | -V"
|
||||
#define SUDO_USAGE1 " -h | -K | -k | -V"
|
||||
#define SUDO_USAGE2 " -v [-ABknS] @BSDAUTH_USAGE@[-g group] [-h host] [-p prompt] [-u user]"
|
||||
#define SUDO_USAGE3 " -l [-ABknS] @BSDAUTH_USAGE@[-g group] [-h host] [-p prompt] [-U user] [-u user] [command]"
|
||||
#define SUDO_USAGE4 " [-ABbEHknPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] [-D directory] @LOGINCAP_USAGE@[-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] [VAR=value] [-i|-s] [<command>]"
|
||||
#define SUDO_USAGE5 " -e [-ABknS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] @LOGINCAP_USAGE@[-D directory] [-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] file ..."
|
||||
#define SUDO_USAGE2 " -v [-ABkNnS] @BSDAUTH_USAGE@[-g group] [-h host] [-p prompt] [-u user]"
|
||||
#define SUDO_USAGE3 " -l [-ABkNnS] @BSDAUTH_USAGE@[-g group] [-h host] [-p prompt] [-U user] [-u user] [command]"
|
||||
#define SUDO_USAGE4 " [-ABbEHkNnPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] [-D directory] @LOGINCAP_USAGE@[-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] [VAR=value] [-i|-s] [<command>]"
|
||||
#define SUDO_USAGE5 " -e [-ABkNnS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] @LOGINCAP_USAGE@[-D directory] [-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] file ..."
|
||||
|
||||
/*
|
||||
* Configure script arguments used to build sudo.
|
||||
|
Reference in New Issue
Block a user