Fix the -s and -i flags and add support for the "implied_shell"

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.
This commit is contained in:
Todd C. Miller
2010-03-21 08:54:06 -04:00
parent 2e27226a0d
commit 6b180d24da
8 changed files with 284 additions and 190 deletions

View File

@@ -61,7 +61,7 @@ SSuuddoo PPlluuggiinn AAPPII
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 Set to true if the user specified the -i flag, indicating
that the user wishes to run a login shell. that the user wishes to run a login shell.
implied_shell=bool
If the user does not specify a program on the command line,
ssuuddoo will pass the plugin the path to the user's shell and
set _i_m_p_l_i_e_d___s_h_e_l_l to true. This allows ssuuddoo with no
arguments to be used similarly to _s_u(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 ssuuddoo to
print a usage message and exit.
preserve_groups=bool preserve_groups=bool
Set to true if the user specified the -P flag, indicating Set to true if the user specified the -P flag, indicating
that the user wishes to preserve the group vector instead that the user wishes to preserve the group vector instead
@@ -182,18 +191,9 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
command, indicating that the user wishes to ignore any command, indicating that the user wishes to ignore any
cached authentication credentials. 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
@@ -202,6 +202,14 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
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=string
SELinux type to use when executing the command, if SELinux type to use when executing the command, if
specified by the -t flag. specified by the -t flag.
@@ -247,6 +255,19 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
terminal device associated with the session, the value will terminal device associated with the session, the value will
be empty, as in tty=. be empty, as in tty=.
1.8.0a1 March 21, 2010 4
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
host=string host=string
The local machine's hostname as returned by the The local machine's hostname as returned by the
gethostname() system call. gethostname() system call.
@@ -256,18 +277,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
is no terminal device available, a default value of 24 is is no terminal device available, a default value of 24 is
used. used.
1.8.0a1 March 19, 2010 4
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
cols=int cols=int
The number of columns the user's terminal supports. If The number of columns the user's terminal supports. If
there is no terminal device available, a default value of there is no terminal device available, a default value of
@@ -311,6 +320,20 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
will be set. will be set.
check_policy check_policy
1.8.0a1 March 21, 2010 5
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
int (*check_policy)(int argc, char * const argv[] int (*check_policy)(int argc, char * const argv[]
char *env_add[], char **command_info[], char *env_add[], char **command_info[],
char **argv_out[], char **user_env_out[]); char **argv_out[], char **user_env_out[]);
@@ -322,18 +345,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
SUDO_CONF_ERROR_MSG to present additional error information to the SUDO_CONF_ERROR_MSG to present additional error information to the
user. user.
1.8.0a1 March 19, 2010 5
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
The function arguments are as follows: The function arguments are as follows:
argc argc
@@ -377,6 +388,18 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
runas_gid=gid runas_gid=gid
Group ID to run the command as. Group ID to run the command as.
1.8.0a1 March 21, 2010 6
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
runas_egid=gid runas_egid=gid
Effective group ID to run the command as. If not Effective group ID to run the command as. If not
specified, the value of _r_u_n_a_s___g_i_d is used. specified, the value of _r_u_n_a_s___g_i_d is used.
@@ -388,18 +411,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
login_class=login_class login_class=login_class
BSD login class to use when setting resource limits and BSD login class to use when setting resource limits and
1.8.0a1 March 19, 2010 6
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
nice value (optional). This option is only set on systems nice value (optional). This option is only set on systems
that support login classes. that support login classes.
@@ -442,6 +453,19 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
system call when executing the command. The plugin is system call when executing the command. The plugin is
responsible for allocating and populating the vector. responsible for allocating and populating the vector.
1.8.0a1 March 21, 2010 7
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
user_env_out user_env_out
The NULL-terminated environment vector to use when executing The NULL-terminated environment vector to use when executing
the command. The plugin is responsible for allocating and the command. The plugin is responsible for allocating and
@@ -454,18 +478,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
List available privileges for the invoking user. Returns 1 on List available privileges for the invoking user. Returns 1 on
success, 0 on failure and -1 on error. On error, the plugin may success, 0 on failure and -1 on error. On error, the plugin may
optionally call the conversation function with SUDO_CONF_ERROR_MSG optionally call the conversation function with SUDO_CONF_ERROR_MSG
1.8.0a1 March 19, 2010 7
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
to present additional error information to the user. to present additional error information to the user.
Privileges should be output via the conversation function using Privileges should be output via the conversation function using
@@ -509,6 +521,17 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
invalidate invalidate
void (*invalidate)(int remove); void (*invalidate)(int remove);
1.8.0a1 March 21, 2010 8
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
The invalidate function is called when ssuuddoo is called with the -k The invalidate function is called when ssuuddoo is called with the -k
or -K flag. For policy plugins such as _s_u_d_o_e_r_s that cache or -K flag. For policy plugins such as _s_u_d_o_e_r_s that cache
authentication credentials, this function will invalidate the authentication credentials, this function will invalidate the
@@ -520,18 +543,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
_C_o_n_v_e_r_s_a_t_i_o_n _A_P_I _C_o_n_v_e_r_s_a_t_i_o_n _A_P_I
1.8.0a1 March 19, 2010 8
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
If the plugin needs to interact with the user or display informational If the plugin needs to interact with the user or display informational
or error messages, it may do so via the conversation function. A or error messages, it may do so via the conversation function. A
plugin should not attempt to read directly from the standard input or plugin should not attempt to read directly from the standard input or
@@ -566,6 +577,27 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
usage. usage.
II//OO PPlluuggiinn AAPPII II//OO PPlluuggiinn AAPPII
1.8.0a1 March 21, 2010 9
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
struct io_plugin { struct io_plugin {
#define SUDO_IO_PLUGIN 2 #define SUDO_IO_PLUGIN 2
unsigned int type; /* always SUDO_IO_PLUGIN */ 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 disabled, such as passwords). The log_output function receives output
from the pseudo-tty that is suitable for replaying the user's session 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 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. open function returns 0, no I/O will be sent to the plugin.
The io_plugin struct has the following fields: 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 A pointer to the conversation function that may be used by the
_s_h_o_w___v_e_r_s_i_o_n function to display version information (see _s_h_o_w___v_e_r_s_i_o_n function to display version information (see
show_version below). The conversation function may also be 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. used to display additional error message to the user.
settings settings
@@ -653,17 +685,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
the form of "name=value" strings. The vector is terminated by the form of "name=value" strings. The vector is terminated by
a NULL pointer. a NULL pointer.
1.8.0a1 March 19, 2010 10
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
When parsing _u_s_e_r___i_n_f_o, the plugin should split on the ffiirrsstt When parsing _u_s_e_r___i_n_f_o, the plugin should split on the ffiirrsstt
equal sign ('=') since the _n_a_m_e field will never include one equal sign ('=') since the _n_a_m_e field will never include one
itself but the _v_a_l_u_e might. itself but the _v_a_l_u_e might.
@@ -697,6 +718,18 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
of errno set by the _e_x_e_c_v_e(2) system call. If the command was of errno set by the _e_x_e_c_v_e(2) system call. If the command was
successfully executed, the value of error is 0. 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 show_version
int (*show_version)(int verbose); int (*show_version)(int verbose);
@@ -718,18 +751,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
The function arguments are as follows: 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. buf The buffer containing user input.
len The length of _b_u_f in bytes. len The length of _b_u_f in bytes.
@@ -757,6 +778,24 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
SSuuddoo iimmpplleemmeennttaattiioonn ddeettaaiillss SSuuddoo iimmpplleemmeennttaattiioonn ddeettaaiillss
Version macros: 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_MAJOR(v) ((v) >> 16)
#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ #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

View File

@@ -139,7 +139,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "SUDO_PLUGIN @mansectsu@" .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 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents. .\" way too many mistakes in technical documents.
.if n .ad l .if n .ad l
@@ -295,6 +295,15 @@ the user wishes to preserve the environment.
.IX Item "login_shell=bool" .IX Item "login_shell=bool"
Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that 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. 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 .IP "preserve_groups=bool" 4
.IX Item "preserve_groups=bool" .IX Item "preserve_groups=bool"
Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that

View 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 Set to true if the user specified the C<-i> flag, indicating that
the user wishes to run a login shell. 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 =item preserve_groups=bool
Set to true if the user specified the C<-P> flag, indicating that Set to true if the user specified the C<-P> flag, indicating that

View File

@@ -262,12 +262,6 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
/* Set login class if applicable. */ /* Set login class if applicable. */
set_loginclass(sudo_user.pw); 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 */ /* XXX */
user_env = envp; /* stash for later */ user_env = envp; /* stash for later */
@@ -305,11 +299,17 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
return -1; 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 *)); NewArgv = emalloc2(argc + 1, sizeof(char *));
memcpy(NewArgv, argv, argc * sizeof(char *)); memcpy(NewArgv, argv, argc * sizeof(char *));
NewArgv[argc] = NULL; NewArgv[argc] = NULL;
NewArgc = argc; NewArgc = argc;
if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
NewArgv[0] = runas_pw->pw_shell;
/* Set environ to contents of user_env. */ /* Set environ to contents of user_env. */
env_init(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)) if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
def_preserve_groups = TRUE; 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) { if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
/* XXX - error message */ rval = -2; /* usage error */
goto done; goto done;
} }
@@ -447,7 +447,7 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
goto done; goto done;
} else if (cmnd_status == NOT_FOUND) { } else if (cmnd_status == NOT_FOUND) {
//audit_failure(NewArgv, "%s: command not found", user_cmnd); //audit_failure(NewArgv, "%s: command not found", user_cmnd);
warningx("command not found", user_cmnd); warningx("%s: command not found", user_cmnd);
goto done; goto done;
} }
@@ -622,12 +622,6 @@ init_vars(char * const envp[])
(void) tzset(); /* set the timezone if applicable */ (void) tzset(); /* set the timezone if applicable */
#endif /* HAVE_TZSET */ #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++) { for (ep = envp; *ep; ep++) {
/* XXX - don't fill in if empty string */ /* XXX - don't fill in if empty string */
switch (**ep) { switch (**ep) {
@@ -644,9 +638,7 @@ init_vars(char * const envp[])
user_path = *ep + 5; user_path = *ep + 5;
break; break;
case 'S': case 'S':
if (strncmp("SHELL=", *ep, 6) == 0) if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
user_shell = *ep + 6;
else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
user_prompt = *ep + 12; user_prompt = *ep + 12;
else if (strncmp("SUDO_USER=", *ep, 10) == 0) else if (strncmp("SUDO_USER=", *ep, 10) == 0)
prev_user = *ep + 10; prev_user = *ep + 10;
@@ -683,8 +675,6 @@ init_vars(char * const envp[])
#ifdef HAVE_MBR_CHECK_MEMBERSHIP #ifdef HAVE_MBR_CHECK_MEMBERSHIP
mbr_uid_to_uuid(user_uid, user_uuid); mbr_uid_to_uuid(user_uid, user_uuid);
#endif #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() */ /* It is now safe to use log_error() and set_perms() */
@@ -692,43 +682,6 @@ init_vars(char * const envp[])
/* may call log_error() */ /* may call log_error() */
set_fqdn(); 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; rval = FOUND;
user_stat = emalloc(sizeof(struct stat)); 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 (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) { if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
set_perms(PERM_RUNAS); set_perms(PERM_RUNAS);
@@ -766,16 +723,9 @@ set_cmnd(sudo_mode)
char *to, **from; char *to, **from;
size_t size, n; 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. */ /* Alloc and build up user_args. */
for (size = 0, from = NewArgv + 1; *from; from++)
size += strlen(*from) + 1;
user_args = emalloc(size); user_args = emalloc(size);
for (to = user_args, from = NewArgv + 1; *from; from++) { for (to = user_args, from = NewArgv + 1; *from; from++) {
n = strlcpy(to, *from, size - (to - user_args)); n = strlcpy(to, *from, size - (to - user_args));
@@ -1197,6 +1147,11 @@ deserialize_info(char * const settings[], char * const user_info[])
} }
continue; 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=")) { if (MATCHES(*cur, "preserve_groups=")) {
SET(flags, MODE_PRESERVE_GROUPS); SET(flags, MODE_PRESERVE_GROUPS);
continue; continue;

View File

@@ -48,7 +48,6 @@ struct sudo_user {
struct stat *cmnd_stat; struct stat *cmnd_stat;
char *name; char *name;
char *path; char *path;
char *shell;
char *tty; char *tty;
char *ttypath; char *ttypath;
char *host; char *host;
@@ -156,7 +155,6 @@ struct sudo_user {
#define user_passwd (sudo_user.pw->pw_passwd) #define user_passwd (sudo_user.pw->pw_passwd)
#define user_uuid (sudo_user.uuid) #define user_uuid (sudo_user.uuid)
#define user_dir (sudo_user.pw->pw_dir) #define user_dir (sudo_user.pw->pw_dir)
#define user_shell (sudo_user.shell)
#define user_ngroups (sudo_user.ngroups) #define user_ngroups (sudo_user.ngroups)
#define user_groups (sudo_user.groups) #define user_groups (sudo_user.groups)
#define user_tty (sudo_user.tty) #define user_tty (sudo_user.tty)

View File

@@ -66,7 +66,6 @@ const char *list_user, *runas_user, *runas_group;
/* /*
* Local functions. * Local functions.
*/ */
static void usage(int) __attribute__((__noreturn__));
static void usage_excl(int) __attribute__((__noreturn__)); static void usage_excl(int) __attribute__((__noreturn__));
/* /*
@@ -102,7 +101,9 @@ static struct sudo_settings {
{ "runas_user" }, { "runas_user" },
#define ARG_PROGNAME 12 #define ARG_PROGNAME 12
{ "progname" }, { "progname" },
#define NUM_SETTINGS 13 #define ARG_IMPLIED_SHELL 13
{ "implied_shell" },
#define NUM_SETTINGS 14
{ NULL } { NULL }
}; };
@@ -295,13 +296,13 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
} }
} }
*nargc = argc - optind; argc -= optind;
*nargv = argv + optind; argv += optind;
if (!mode) { if (!mode) {
/* Defer -k mode setting until we know whether it is a flag or not */ /* Defer -k mode setting until we know whether it is a flag or not */
if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) { if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) {
if (*nargc == 0) { if (argc == 0) {
mode = MODE_INVALIDATE; /* -k by itself */ mode = MODE_INVALIDATE; /* -k by itself */
sudo_settings[ARG_IGNORE_TICKET].value = NULL; sudo_settings[ARG_IGNORE_TICKET].value = NULL;
valid_flags = 0; 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 */ mode = MODE_RUN; /* running a command */
} }
if (*nargc > 0 && mode == MODE_LIST) if (argc > 0 && mode == MODE_LIST)
mode = MODE_CHECK; mode = MODE_CHECK;
if (ISSET(flags, MODE_LOGIN_SHELL)) { 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"); warningx("the `-A' and `-S' options may not be used together");
usage(1); usage(1);
} }
if ((*nargc == 0 && mode == MODE_EDIT) || if ((argc == 0 && mode == MODE_EDIT) ||
(*nargc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK))) (argc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
usage(1); 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)); SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
sudo_settings[ARG_IMPLIED_SHELL].value = "true";
}
if (mode == MODE_HELP) if (mode == MODE_HELP)
usage(0); 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. * Format setting_pairs into settings array.
*/ */
@@ -375,6 +416,8 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
*settingsp = settings; *settingsp = settings;
*env_addp = env_add; *env_addp = env_add;
*nargc = argc;
*nargv = argv;
return(mode | flags); return(mode | flags);
} }
@@ -388,7 +431,7 @@ usage_out(const char *buf)
* Give usage message and exit. * Give usage message and exit.
* The actual usage strings are in sudo_usage.h for configure substitution. * The actual usage strings are in sudo_usage.h for configure substitution.
*/ */
static void void
usage(int exit_val) usage(int exit_val)
{ {
struct lbuf lbuf; struct lbuf lbuf;

View File

@@ -224,8 +224,11 @@ main(int argc, char *argv[], char *envp[])
ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add, ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add,
&command_info, &argv_out, &user_env_out); &command_info, &argv_out, &user_env_out);
sudo_debug(8, "policy plugin returns %d", ok); sudo_debug(8, "policy plugin returns %d", ok);
if (ok != TRUE) if (ok != TRUE) {
exit(ok); /* plugin printed error message */ if (ok == -2)
usage(1);
exit(1); /* plugin printed error message */
}
command_info_to_details(command_info, &command_details); command_info_to_details(command_info, &command_details);
/* Restore coredumpsize resource limit before running. */ /* Restore coredumpsize resource limit before running. */
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
@@ -330,6 +333,12 @@ get_user_info(struct user_details *ud)
errorx(1, "unable to allocate memory"); errorx(1, "unable to allocate memory");
ud->username = user_info[i] + sizeof("user=") - 1; 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], "uid=%lu", (unsigned long)ud->uid);
easprintf(&user_info[++i], "euid=%lu", (unsigned long)ud->euid); easprintf(&user_info[++i], "euid=%lu", (unsigned long)ud->euid);
easprintf(&user_info[++i], "gid=%lu", (unsigned long)ud->gid); easprintf(&user_info[++i], "gid=%lu", (unsigned long)ud->gid);

View File

@@ -117,6 +117,7 @@ struct user_details {
const char *cwd; const char *cwd;
const char *tty; const char *tty;
const char *host; const char *host;
const char *shell;
GETGROUPS_T *groups; GETGROUPS_T *groups;
int ngroups; int ngroups;
int ts_cols; int ts_cols;
@@ -210,6 +211,9 @@ int exec_setup(struct command_details *details);
extern int debug_level; extern int debug_level;
extern struct plugin_container_list io_plugins; extern struct plugin_container_list io_plugins;
/* parse_args.c */
void usage(int) __attribute__((__noreturn__));
#ifndef errno #ifndef errno
extern int errno; extern int errno;
#endif #endif