-1.8.0a1 May 17, 2010 1
+1.8.0a1 May 24, 2010 1
-1.8.0a1 May 17, 2010 2
+1.8.0a1 May 24, 2010 2
-1.8.0a1 May 17, 2010 3
+1.8.0a1 May 24, 2010 3
error if the plugin does not support _\bs_\bu_\bd_\bo_\be_\bd_\bi_\bt. For more
information, see the _\bc_\bh_\be_\bc_\bk_\b__\bp_\bo_\bl_\bi_\bc_\by section.
+ closefrom=number
+ If specified, the user has requested via the -C flag that
+ s\bsu\bud\bdo\bo close all files descriptors with a value of _\bn_\bu_\bm_\bb_\be_\br or
+ higher. The plugin may optionally pass this, or another
+ value, back in the _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b__\bi_\bn_\bf_\bo list.
+
Additional settings may be added in the future so the plugin
should silently ignore settings that it does not recognize.
the form of "name=value" strings. The vector is terminated by
a NULL pointer.
- 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.
-
- user=string
- The name of the user invoking s\bsu\bud\bdo\bo.
-1.8.0a1 May 17, 2010 4
+1.8.0a1 May 24, 2010 4
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.
+
+ user=string
+ The name of the user invoking s\bsu\bud\bdo\bo.
+
uid=uid_t
The real user ID of the user invoking s\bsu\bud\bdo\bo.
The function arguments are as follows:
- exit_status
- The command's exit status, as returned by the _\bw_\ba_\bi_\bt(2) system
- call. The value of exit_status is undefined if error is non-
- zero.
-
-
-
-1.8.0a1 May 17, 2010 5
+1.8.0a1 May 24, 2010 5
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
+ exit_status
+ The command's exit status, as returned by the _\bw_\ba_\bi_\bt(2) system
+ call. The value of exit_status is undefined if error is non-
+ zero.
+
error
If the command could not be executed, this is set to the value
of errno set by the _\be_\bx_\be_\bc_\bv_\be(2) system call. The plugin is
The function arguments are as follows:
- argc
- The number of elements in _\ba_\br_\bg_\bv, not counting the final NULL
- pointer.
-
-
-1.8.0a1 May 17, 2010 6
+1.8.0a1 May 24, 2010 6
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
+ argc
+ The number of elements in _\ba_\br_\bg_\bv, not counting the final NULL
+ pointer.
+
argv
The argument vector describing the command the user wishes to
run, in the same form as what would be passed to the _\be_\bx_\be_\bc_\bv_\be_\b(_\b)
nice value (optional). This option is only set on systems
that support login classes.
- preserve_groups=bool
- If set, s\bsu\bud\bdo\bo will preserve the user's group vector instead
- of initializing the group vector based on runas_user.
-
-1.8.0a1 May 17, 2010 7
+1.8.0a1 May 24, 2010 7
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
+ preserve_groups=bool
+ If set, s\bsu\bud\bdo\bo will preserve the user's group vector instead
+ of initializing the group vector based on runas_user.
+
cwd=string
The current working directory to change to when executing
the command.
transparently enable _\bs_\bu_\bd_\bo_\be_\bd_\bi_\bt when the user attempts to run
an editor.
+ closefrom=number
+ If specified, s\bsu\bud\bdo\bo will close all files descriptors with a
+ value of _\bn_\bu_\bm_\bb_\be_\br or higher.
+
Unsupported values will be ignored.
argv_out
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 or plugin_printf function with
-
-1.8.0a1 May 17, 2010 8
+1.8.0a1 May 24, 2010 8
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
+ 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 or plugin_printf function with
SUDO_CONF_ERROR_MSG to present additional error information to the
user.
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 May 24, 2010 9
-1.8.0a1 May 17, 2010 9
+SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
-SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
+ 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
If the plugin needs to interact with the user, it may do so via the
conversation function. A plugin should not attempt to read directly
needed and supports standard _\bp_\br_\bi_\bn_\bt_\bf_\b(_\b) escape sequences.
See the sample plugin for an example of the conversation function
- usage.
-
- I\bI/\b/O\bO P\bPl\blu\bug\bgi\bin\bn A\bAP\bPI\bI
-
-
-
-
-
-1.8.0a1 May 17, 2010 10
+1.8.0a1 May 24, 2010 10
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
struct io_plugin {
#define SUDO_IO_PLUGIN 2
unsigned int type; /* always SUDO_IO_PLUGIN */
char * const user_info[], int argc, char * const argv[],
char * const user_env[]);
- The _\bo_\bp_\be_\bn function is run before the _\bl_\bo_\bg_\b__\bi_\bn_\bp_\bu_\bt, _\bl_\bo_\bg_\b__\bo_\bu_\bt_\bp_\bu_\bt or
- _\bs_\bh_\bo_\bw_\b__\bv_\be_\br_\bs_\bi_\bo_\bn functions are called. It is only called if the
-
-1.8.0a1 May 17, 2010 11
+1.8.0a1 May 24, 2010 11
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
+ The _\bo_\bp_\be_\bn function is run before the _\bl_\bo_\bg_\b__\bi_\bn_\bp_\bu_\bt, _\bl_\bo_\bg_\b__\bo_\bu_\bt_\bp_\bu_\bt or
+ _\bs_\bh_\bo_\bw_\b__\bv_\be_\br_\bs_\bi_\bo_\bn functions are called. It is only called if the
version is being requested or the _\bc_\bh_\be_\bc_\bk_\b__\bp_\bo_\bl_\bi_\bc_\by function has
returned successfully. It returns 1 on success, 0 on failure, -1
if a general error occurred, or -2 if there was a usage error. In
-
-
-1.8.0a1 May 17, 2010 12
+1.8.0a1 May 24, 2010 12
-1.8.0a1 May 17, 2010 13
+1.8.0a1 May 24, 2010 13
-1.8.0a1 May 17, 2010 14
+1.8.0a1 May 24, 2010 14
Hey! T\bTh\bhe\be a\bab\bbo\bov\bve\be d\bdo\boc\bcu\bum\bme\ben\bnt\bt h\bha\bad\bd s\bso\bom\bme\be c\bco\bod\bdi\bin\bng\bg e\ber\brr\bro\bor\brs\bs,\b, w\bwh\bhi\bic\bch\bh a\bar\bre\be e\bex\bxp\bpl\bla\bai\bin\bne\bed\bd
b\bbe\bel\blo\bow\bw:\b:
- Around line 597:
+ Around line 609:
You forgot a '=back' before '=head3'
-1.8.0a1 May 17, 2010 15
+1.8.0a1 May 24, 2010 15
.\" ========================================================================
.\"
.IX Title "SUDO_PLUGIN @mansectsu@"
-.TH SUDO_PLUGIN @mansectsu@ "May 17, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
+.TH SUDO_PLUGIN @mansectsu@ "May 24, 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
in the \fIcheck_policy\fR function or return \f(CW\*(C`\-2\*(C'\fR with a usage error
if the plugin does not support \fIsudoedit\fR. For more information,
see the \fIcheck_policy\fR section.
+.IP "closefrom=number" 4
+.IX Item "closefrom=number"
+If specified, the user has requested via the \f(CW\*(C`\-C\*(C'\fR flag that \fBsudo\fR
+close all files descriptors with a value of \fInumber\fR or higher.
+The plugin may optionally pass this, or another value, back in the
+\&\fIcommand_info\fR list.
.RE
.RS 4
.Sp
\&\fIsudoedit\fR mode even if \fBsudo\fR was not invoked as \fBsudoedit\fR.
This allows the plugin to perform command substitution and transparently
enable \fIsudoedit\fR when the user attempts to run an editor.
+.IP "closefrom=number" 4
+.IX Item "closefrom=number"
+If specified, \fBsudo\fR will close all files descriptors with a value
+of \fInumber\fR or higher.
.RE
.RS 4
.Sp
.SH "POD ERRORS"
.IX Header "POD ERRORS"
Hey! \fBThe above document had some coding errors, which are explained below:\fR
-.IP "Around line 597:" 4
-.IX Item "Around line 597:"
+.IP "Around line 609:" 4
+.IX Item "Around line 609:"
You forgot a '=back' before '=head3'
if the plugin does not support I<sudoedit>. For more information,
see the I<check_policy> section.
+=item closefrom=number
+
+If specified, the user has requested via the C<-C> flag that B<sudo>
+close all files descriptors with a value of I<number> or higher.
+The plugin may optionally pass this, or another value, back in the
+I<command_info> list.
+
=back
Additional settings may be added in the future so the plugin should
This allows the plugin to perform command substitution and transparently
enable I<sudoedit> when the user attempts to run an editor.
+=item closefrom=number
+
+If specified, B<sudo> will close all files descriptors with a value
+of I<number> or higher.
+
=back
Unsupported values will be ignored.
int info_len = 0;
int rval = FALSE;
- /* refactor so list can use it too */
-
/* Is root even allowed to run sudo? */
if (user_uid == 0 && !def_root_sudo) {
warningx("sudoers specifies that root is not allowed to sudo");
goto done;
}
+ /* Check for -C overriding def_closefrom. */
+ if (user_closefrom >= 0 && user_closefrom != def_closefrom) {
+ if (!def_closefrom_override) {
+ warningx("you are not permitted to use the -C option");
+ goto done;
+ }
+ def_closefrom = user_closefrom;
+ }
+
if (sigsetjmp(error_jmp, 1)) {
/* error recovery via error(), errorx() or log_error() */
rewind_perms();
}
command_info[info_len++] = gid_list;
}
+ if (def_closefrom >= 0)
+ easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
/* Must audit before uid change. */
audit_success(NewArgv);
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0)
/* Parse command line settings. */
+ user_closefrom = -1;
for (cur = settings; *cur != NULL; cur++) {
+ if (MATCHES(*cur, "closefrom=")) {
+ user_closefrom = atoi(*cur + sizeof("closefrom=") - 1);
+ continue;
+ }
if (MATCHES(*cur, "debug_level=")) {
debug_level = atoi(*cur + sizeof("debug_level=") - 1);
continue;
char *krb5_ccname;
char *display;
char *askpass;
+ int closefrom;
int ngroups;
uid_t uid;
uid_t gid;
#define runas_gr (sudo_user._runas_gr)
#define user_role (sudo_user.role)
#define user_type (sudo_user.type)
+#define user_closefrom (sudo_user.closefrom)
/*
* We used to use the system definition of PASS_MAX or _PASSWD_LEN,
/* XXX - better home for these and extern in header file */
int tgetpass_flags;
-int user_closefrom = -1;
const char *list_user, *runas_user, *runas_group;
/*
{ "noninteractive" },
#define ARG_SUDOEDIT 16
{ "sudoedit" },
-#define NUM_SETTINGS 17
+#define ARG_CLOSEFROM 17
+ { "closefrom" },
+#define NUM_SETTINGS 18
{ NULL }
};
SET(flags, MODE_BACKGROUND);
break;
case 'C':
- if ((user_closefrom = atoi(optarg)) < 3) {
+ if (atoi(optarg) < 3) {
warningx("the argument to -C must be at least 3");
usage(1);
}
+ sudo_settings[ARG_CLOSEFROM].value = optarg;
break;
#ifdef HAVE_LOGIN_CAP_H
case 'c':
static void flush_output(struct io_buffer *iobufs);
static int perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw);
static void handler(int s);
-static int script_child(const char *path, char *argv[], char *envp[], int, int);
-static void script_run(const char *path, char *argv[], char *envp[], int);
+static int my_execve(const char *path, char *const argv[],
+ char *const envp[]);
+static int script_child(struct command_details *details, char *argv[],
+ char *envp[], int, int);
+static void script_run(struct command_details *detail, char *argv[],
+ char *envp[], int);
static void sigwinch(int s);
static void sync_ttysize(int src, int dst);
static void deliver_signal(pid_t pid, int signo);
/*
* Like execve(2) but falls back to running through /bin/sh
- * like execvp(3) if we get ENOEXEC.
+ * ala execvp(3) if we get ENOEXEC.
*/
static int
my_execve(const char *path, char *const argv[], char *const envp[])
/* child */
close(sv[0]);
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
+ /* XXX - defer call to exec_setup() until my_execve()? */
if (exec_setup(details) == 0) {
/* headed for execve() */
if (log_io) {
close(io_pipe[STDOUT_FILENO][0]);
if (io_pipe[STDERR_FILENO][0])
close(io_pipe[STDERR_FILENO][0]);
- script_child(details->command, argv, envp, sv[1], rbac_enabled);
+ script_child(details, argv, envp, sv[1], rbac_enabled);
} else {
+ if (details->closefrom >= 0)
+ closefrom(details->closefrom);
#ifdef HAVE_SELINUX
if (rbac_enabled)
selinux_execve(details->command, argv, envp);
* Returns an error if fork(2) fails, else calls _exit(2).
*/
int
-script_child(const char *path, char *argv[], char *envp[], int backchannel, int rbac)
+script_child(struct command_details *details, char *argv[], char *envp[],
+ int backchannel, int rbac)
{
struct command_status cstat;
struct timeval tv;
fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
/* setup tty and exec command */
- script_run(path, argv, envp, rbac);
+ script_run(details, argv, envp, rbac);
cstat.type = CMD_ERRNO;
cstat.val = errno;
write(errpipe[1], &cstat, sizeof(cstat));
* Returns only if execve() fails.
*/
static void
-script_run(const char *path, char *argv[], char *envp[], int rbac_enabled)
+script_run(struct command_details *details, char *argv[], char *envp[],
+ int rbac_enabled)
{
pid_t self = getpid();
if (script_fds[SFD_STDERR] != script_fds[SFD_SLAVE])
close(script_fds[SFD_STDERR]);
+ if (details->closefrom >= 0)
+ closefrom(details->closefrom);
#ifdef HAVE_SELINUX
if (rbac_enabled)
- selinux_execve(path, argv, envp);
+ selinux_execve(details->command, argv, envp);
else
#endif
- my_execve(path, argv, envp);
+ my_execve(details->command, argv, envp);
}
/*
}
void
-selinux_execv(char *path, char **argv)
+selinux_execve(const char *path, char *argv[], char *envp[])
{
if (setexeccon(new_context)) {
warning("unable to set exec context to %s", new_context);
#endif
/* We use the "spare" slot in argv to store sesh. */
+ /* XXX - no longer can do this XXX */
--argv;
argv[0] = *argv[1] == '-' ? "-sesh" : "sesh";
- argv[1] = path;
+ argv[1] = (char *)path;
- execv(_PATH_SUDO_SESH, argv);
+ execve(_PATH_SUDO_SESH, argv, envp);
warning("%s", path);
}
char *cp, *ep;
memset(details, 0, sizeof(*details));
+ details->closefrom = -1;
#define SET_STRING(s, n) \
if (strncmp(s, info[i], sizeof(s) - 1) == 0 && info[i][sizeof(s) - 1]) { \
SET_STRING("chroot=", chroot)
SET_STRING("command=", command)
SET_STRING("cwd=", cwd)
+ if (strncmp("closefrom=", info[i], sizeof("closefrom=") - 1) == 0) {
+ cp = info[i] + sizeof("closefrom=") - 1;
+ if (*cp == '\0')
+ break;
+ errno = 0;
+ lval = strtol(cp, &ep, 0);
+ if (*cp != '\0' && *ep == '\0' &&
+ !(errno == ERANGE &&
+ (lval == LONG_MAX || lval == LONG_MIN)) &&
+ lval < INT_MAX && lval > INT_MIN) {
+ details->closefrom = (int)lval;
+ }
+ break;
+ }
break;
case 'l':
SET_STRING("login_class=", login_class)
int priority;
int timeout;
int ngroups;
+ int closefrom;
GETGROUPS_T *groups;
const char *command;
const char *cwd;