Instead, sudo will set sudoedit=true in the settings array.
The plugin should check for this and modify argv_out as appropriate
in check_policy.
.\" ========================================================================
.\"
.IX Title "SUDO_PLUGIN @mansectsu@"
-.TH SUDO_PLUGIN @mansectsu@ "May 14, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
+.TH SUDO_PLUGIN @mansectsu@ "May 17, 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
\& const char *list_user);
\& int (*validate)(void);
\& void (*invalidate)(int remove);
-\& int (*check_sudoedit)(int argc, char * const argv[],
-\& char *env_add[], char **command_info[],
-\& char **argv_out[], char **user_env_out[]);
\& };
.Ve
.PP
.IP "progname=string" 4
.IX Item "progname=string"
The command name that sudo was run as, typically \*(L"sudo\*(R" or \*(L"sudoedit\*(R".
+.IP "sudoedit=bool" 4
+.IX Item "sudoedit=bool"
+Set to true when the \f(CW\*(C`\-e\*(C'\fR flag is is specified or if invoked as
+\&\fBsudoedit\fR. The plugin shall substitute an editor into \fIargv\fR
+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.
.RE
.RS 4
.Sp
.Ve
.Sp
The \fIcheck_policy\fR function is called by \fBsudo\fR to determine
-whether the user is allowed to run the specified commands. Returns
-1 if the command is allowed, 0 if not allowed, \-1 for a general
-error, or \-2 for a usage error. In the latter case, \fBsudo\fR will
-print a usage message before it exits. If an error occurs, the
-plugin may optionally call the conversation or plugin_printf function
-with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information
-to the user.
+whether the user is allowed to run the specified commands.
+.Sp
+If the \fIsudoedit\fR option was enabled in the \fIsettings\fR array
+passed to the \fIopen\fR function, the user has requested \fIsudoedit\fR
+mode. \fIsudoedit\fR is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges. \fBsudo\fR achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete. If
+the plugin supports \fBsudoedit\fR, it should choose the editor to be
+used, potentially from a variable in the user's environment, such
+as \f(CW\*(C`EDITOR\*(C'\fR, and include it in \fIargv_out\fR (note that environment
+variables may include command line flags). The files to be edited
+should be copied from \fIargv\fR into \fIargv_out\fR, separated from the
+editor and its arguments by a \f(CW"\-\-"\fR element. The \f(CW"\-\-"\fR will
+be removed by \fBsudo\fR before the editor is executed. The plugin
+should also set \fIsudoedit=true\fR in the \fIcommand_info\fR list.
+.Sp
+The \fIcheck_policy\fR function returns 1 if the command is allowed,
+0 if not allowed, \-1 for a general error, or \-2 for a usage error
+or if \fBsudoedit\fR was specified but is unsupported by the plugin.
+In the latter case, \fBsudo\fR will print a usage message before it
+exits. If an error occurs, the plugin may optionally call the
+conversation or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR
+to present additional error information to the user.
.Sp
The function arguments are as follows:
.RS 4
.IX Item "timeout=int"
Command timeout. If non-zero then when the timeout expires the
command will be killed.
+.IP "sudoedit=bool" 4
+.IX Item "sudoedit=bool"
+Set to true when in \fIsudoedit\fR mode. The plugin may enable
+\&\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.
.RE
.RS 4
.Sp
.Sp
The \f(CW\*(C`invalidate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not
support credential caching.
-.IP "check_sudoedit" 4
-.IX Item "check_sudoedit"
-.Vb 3
-\& int (*check_sudoedit)(int argc, char * const argv[]
-\& char *env_add[], char **command_info[],
-\& char **argv_out[], char **user_env_out[]);
-.Ve
-.Sp
-The \fIcheck_sudoedit\fR function is called instead of \fIcheck_policy\fR
-when \fBsudo\fR is invoked as \fBsudoedit\fR or when the \f(CW\*(C`\-e\*(C'\fR flag is
-specified. \fBsudoedit\fR is a mechanism for editing one or more files
-where an editor is run with the user's credentials instead of with
-elevated privileges. \fBsudo\fR achieves this by creating user-writable
-temporary copies of the files to be edited and then overwriting the
-originals with the temporary copies after editing is complete.
-.Sp
-The plugin should choose the editor to be used, potentially from a
-variable in the user's environment, such as \f(CW\*(C`EDITOR\*(C'\fR, and include
-it in \fIargv_out\fR. The files to be edited should be copied from
-\&\fIargv\fR into \fIargv_out\fR, separated from the editor and its arguments
-by a \f(CW"\-\-"\fR element. The \f(CW"\-\-"\fR will be removed by \fBsudo\fR before
-the editor is executed.
-.Sp
-Returns 1 if the command is allowed, 0 if not allowed, \-1 for a
-general error, or \-2 for a usage error. In the latter case, \fBsudo\fR
-will print a usage message before it exits. If an error occurs,
-the plugin may optionally call the conversation or plugin_printf
-function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error
-information to the user.
-.Sp
-The function arguments are the same as for \fIcheck_policy\fR, except
-that \fIargv[0]\fR will always be the string \*(L"sudoedit\*(R".
.PP
\fIConversation \s-1API\s0\fR
.IX Subsection "Conversation API"
\& struct io_plugin io;
\& };
.Ve
+.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:"
+You forgot a '=back' before '=head3'
const char *list_user);
int (*validate)(void);
void (*invalidate)(int remove);
- int (*check_sudoedit)(int argc, char * const argv[],
- char *env_add[], char **command_info[],
- char **argv_out[], char **user_env_out[]);
};
The policy_plugin struct has the following fields:
The command name that sudo was run as, typically "sudo" or "sudoedit".
+=item sudoedit=bool
+
+Set to true when the C<-e> flag is is specified or if invoked as
+B<sudoedit>. The plugin shall substitute an editor into I<argv>
+in the I<check_policy> function or return C<-2> with a usage error
+if the plugin does not support I<sudoedit>. For more information,
+see the I<check_policy> section.
+
=back
Additional settings may be added in the future so the plugin should
char **argv_out[], char **user_env_out[]);
The I<check_policy> function is called by B<sudo> to determine
-whether the user is allowed to run the specified commands. Returns
-1 if the command is allowed, 0 if not allowed, -1 for a general
-error, or -2 for a usage error. In the latter case, B<sudo> will
-print a usage message before it exits. If an error occurs, the
-plugin may optionally call the conversation or plugin_printf function
-with C<SUDO_CONF_ERROR_MSG> to present additional error information
-to the user.
+whether the user is allowed to run the specified commands.
+
+If the I<sudoedit> option was enabled in the I<settings> array
+passed to the I<open> function, the user has requested I<sudoedit>
+mode. I<sudoedit> is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges. B<sudo> achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete. If
+the plugin supports B<sudoedit>, it should choose the editor to be
+used, potentially from a variable in the user's environment, such
+as C<EDITOR>, and include it in I<argv_out> (note that environment
+variables may include command line flags). The files to be edited
+should be copied from I<argv> into I<argv_out>, separated from the
+editor and its arguments by a C<"--"> element. The C<"--"> will
+be removed by B<sudo> before the editor is executed. The plugin
+should also set I<sudoedit=true> in the I<command_info> list.
+
+The I<check_policy> function returns 1 if the command is allowed,
+0 if not allowed, -1 for a general error, or -2 for a usage error
+or if B<sudoedit> was specified but is unsupported by the plugin.
+In the latter case, B<sudo> will print a usage message before it
+exits. If an error occurs, the plugin may optionally call the
+conversation or plugin_printf function with C<SUDO_CONF_ERROR_MSG>
+to present additional error information to the user.
The function arguments are as follows:
Command timeout. If non-zero then when the timeout expires the
command will be killed.
+=item sudoedit=bool
+
+Set to true when in I<sudoedit> mode. The plugin may enable
+I<sudoedit> mode even if B<sudo> was not invoked as B<sudoedit>.
+This allows the plugin to perform command substitution and transparently
+enable I<sudoedit> when the user attempts to run an editor.
+
=back
Unsupported values will be ignored.
The C<invalidate> function should be C<NULL> if the plugin does not
support credential caching.
-=item check_sudoedit
-
- int (*check_sudoedit)(int argc, char * const argv[]
- char *env_add[], char **command_info[],
- char **argv_out[], char **user_env_out[]);
-
-The I<check_sudoedit> function is called instead of I<check_policy>
-when B<sudo> is invoked as B<sudoedit> or when the C<-e> flag is
-specified. B<sudoedit> is a mechanism for editing one or more files
-where an editor is run with the user's credentials instead of with
-elevated privileges. B<sudo> achieves this by creating user-writable
-temporary copies of the files to be edited and then overwriting the
-originals with the temporary copies after editing is complete.
-
-The plugin should choose the editor to be used, potentially from a
-variable in the user's environment, such as C<EDITOR>, and include
-it in I<argv_out>. The files to be edited should be copied from
-I<argv> into I<argv_out>, separated from the editor and its arguments
-by a C<"--"> element. The C<"--"> will be removed by B<sudo> before
-the editor is executed.
-
-Returns 1 if the command is allowed, 0 if not allowed, -1 for a
-general error, or -2 for a usage error. In the latter case, B<sudo>
-will print a usage message before it exits. If an error occurs,
-the plugin may optionally call the conversation or plugin_printf
-function with C<SUDO_CONF_ERROR_MSG> to present additional error
-information to the user.
-
-The function arguments are the same as for I<check_policy>, except
-that I<argv[0]> will always be the string "sudoedit".
-
-=back
-
=head3 Conversation API
If the plugin needs to interact with the user, it may do so via the
const char *list_user);
int (*validate)(void);
void (*invalidate)(int remove);
- int (*check_sudoedit)(int argc, char * const argv[],
- char *env_add[], char **command_info[],
- char **argv_out[], char **user_env_out[]);
};
/* I/O plugin type and defines */
static FILE *input, *output;
static uid_t runas_uid = ROOT_UID;
static gid_t runas_gid = -1;
+static int use_sudoedit = FALSE;
/*
* Allocate storage for a name=value string and return it.
setprogname(*ui + sizeof("progname=") - 1);
}
#endif
+ /* Check to see if sudo was called as sudoedit or with -e flag. */
+ if (strncmp(*ui, "sudoedit=", sizeof("sudoedit=") - 1) == 0) {
+ if (strcasecmp(*ui + sizeof("sudoedit=") - 1, "true") == 0)
+ use_sudoedit = TRUE;
+ }
}
if (runas_user != NULL) {
if ((pw = getpwnam(runas_user)) == NULL) {
}
static char **
-build_command_info(char *command, int sudoedit)
+build_command_info(char *command)
{
static char **command_info;
int i = 0;
return NULL;
}
}
- if (sudoedit) {
+ if (use_sudoedit) {
command_info[i] = strdup("sudoedit=true");
if (command_info[i++] == NULL)
return NULL;
return FALSE;
}
- /*
- * If "sudo vi" is run, auto-convert to sudoedit.
- */
- if (strcmp(command, _PATH_VI) == 0) {
+ /* If "sudo vi" is run, auto-convert to sudoedit. */
+ if (strcmp(command, _PATH_VI) == 0)
+ use_sudoedit = TRUE;
+
+ if (use_sudoedit) {
/* Rebuild argv using editor */
command = find_editor(argc - 1, argv + 1, argv_out);
if (command == NULL) {
sudo_log(SUDO_CONV_ERROR_MSG, "unable to find valid editor\n");
return ERROR;
}
+ use_sudoedit = TRUE;
} else {
- /* No changes to argv */
+ /* No changes needd to argv */
*argv_out = (char **)argv;
}
*user_env_out = plugin_state.envp;
/* Setup command info. */
- *command_info_out = build_command_info(command, *argv_out != argv);
- if (*command_info_out == NULL) {
- sudo_log(SUDO_CONV_ERROR_MSG, "out of memory\n");
- return ERROR;
- }
-
- return TRUE;
-}
-
-/*
- * Plugin policy edit function.
- * Simple example that prompts for a password, hard-coded to "test".
- */
-static int
-policy_edit(int argc, char * const argv[],
- char *env_add[], char **command_info_out[],
- char **argv_out[], char **user_env_out[])
-{
- char *editor;
-
- if (!check_passwd())
- return FALSE;
-
- /* Rebuild argv using editor */
- editor = find_editor(argc - 1, argv + 1, argv_out);
- if (editor == NULL) {
- sudo_log(SUDO_CONV_ERROR_MSG, "unable to find valid editor\n");
- return ERROR;
- }
-
- /* No changes to envp */
- *user_env_out = plugin_state.envp;
-
- /* Setup command info. */
- *command_info_out = build_command_info(editor, TRUE);
+ *command_info_out = build_command_info(command);
if (*command_info_out == NULL) {
sudo_log(SUDO_CONV_ERROR_MSG, "out of memory\n");
return ERROR;
policy_check,
policy_list,
NULL, /* validate */
- NULL, /* invalidate */
- policy_edit
+ NULL /* invalidate */
};
/*
if (!editor)
goto done;
command_info[info_len++] = fmt_string("command", editor);
+ command_info[info_len++] = estrdup("sudoedit=true");
} else {
command_info[info_len++] = fmt_string("command", safe_cmnd);
}
argv_out, user_env_out);
}
-static int
-sudoers_policy_sudoedit(int argc, char * const argv[], char *env_add[],
- char **command_infop[], char **argv_out[], char **user_env_out[])
-{
- SET(sudo_mode, MODE_EDIT);
-
- return sudoers_policy_main(argc, argv, 0, env_add, command_infop,
- argv_out, user_env_out);
-}
-
static int
sudoers_policy_validate(void)
{
SET(flags, MODE_IGNORE_TICKET);
continue;
}
+ if (MATCHES(*cur, "sudoedit=")) {
+ if (atobool(*cur + sizeof("sudoedit=") - 1) == TRUE)
+ SET(flags, MODE_EDIT);
+ continue;
+ }
if (MATCHES(*cur, "login_class=")) {
login_class = *cur + sizeof("login_class=") - 1;
def_use_loginclass = TRUE;
sudoers_policy_check,
sudoers_policy_list,
sudoers_policy_validate,
- sudoers_policy_invalidate,
- sudoers_policy_sudoedit
+ sudoers_policy_invalidate
};
struct io_plugin sudoers_io = {
{ "preserve_groups" },
#define ARG_NONINTERACTIVE 15
{ "noninteractive" },
-#define NUM_SETTINGS 16
+#define ARG_SUDOEDIT 16
+ { "sudoedit" },
+#define NUM_SETTINGS 17
{ NULL }
};
sudo_settings[ARG_PROGNAME].value = getprogname();
/* First, check to see if we were invoked as "sudoedit". */
- if (strcmp(getprogname(), "sudoedit") == 0)
+ if (strcmp(getprogname(), "sudoedit") == 0) {
mode = MODE_EDIT;
+ sudo_settings[ARG_SUDOEDIT].value = "true";
+ }
/* Returns true if the last option string was "--" */
#define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \
if (mode && mode != MODE_EDIT)
usage_excl(1);
mode = MODE_EDIT;
+ sudo_settings[ARG_SUDOEDIT].value = "true";
valid_flags = MODE_NONINTERACTIVE;
break;
case 'g':
}
exit(ok != TRUE);
case MODE_EDIT:
- if (!policy_plugin.u.policy->check_sudoedit)
- errorx(1, "policy plugin %s does not support sudoedit",
- policy_plugin.name);
- /* FALLTHROUGH */
case MODE_RUN:
- if (sudo_mode & MODE_EDIT) {
- /* XXX - must be able to tell which are the files in argv */
- /* as opposed to editor flags; could use original argv */
- /* and only use argv_out for the command path + args */
- ok = policy_plugin.u.policy->check_sudoedit(nargc, nargv,
- env_add, &command_info, &argv_out, &user_env_out);
- } else {
- ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add,
- &command_info, &argv_out, &user_env_out);
- }
+ ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add,
+ &command_info, &argv_out, &user_env_out);
sudo_debug(8, "policy plugin returns %d", ok);
if (ok != TRUE) {
if (ok == -2)
}
}
command_info_to_details(command_info, &command_details);
- if (ISSET(sudo_mode, MODE_EDIT))
- SET(command_details.flags, CD_SUDOEDIT);
/* Restore coredumpsize resource limit before running. */
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
(void) setrlimit(RLIMIT_CORE, &corelimit);
else
editor_argc++;
}
- if (nfiles == 0)
+ if (nfiles == 0) {
+ warningx("plugin error: missing file list for sudoedit");
return 1;
+ }
/*
* For each file specified by the user, make a temporary version