Add support for plugin args at the end of a Plugin line in sudo.conf.

Bump the minor number accordingly and update the documentation.  A
plugin must check the sudo front end's version before using the
plugin_args parameter since it is only supported for API version
1.2 and higher.
This commit is contained in:
Todd C. Miller
2012-03-02 11:04:09 -05:00
parent c623857fc9
commit a16dee915b
14 changed files with 354 additions and 150 deletions

View File

@@ -204,8 +204,10 @@ static bool
set_plugin(const char *entry) set_plugin(const char *entry)
{ {
struct plugin_info *info; struct plugin_info *info;
const char *name, *path; const char *name, *path, *cp, *ep;
size_t namelen; char **args = NULL;
size_t namelen, pathlen;
unsigned int nargs;
/* Parse Plugin line */ /* Parse Plugin line */
name = entry; name = entry;
@@ -215,10 +217,35 @@ set_plugin(const char *entry)
namelen = (size_t)(path - name); namelen = (size_t)(path - name);
while (isblank((unsigned char)*path)) while (isblank((unsigned char)*path))
path++; path++;
if ((cp = strpbrk(path, " \t")) != NULL) {
/* Convert extra args to an array. */
pathlen = (size_t)(cp - path);
while (isblank((unsigned char)*cp))
cp++;
/* Count number of args and allocate array. */
for (ep = cp, nargs = 1; (ep = strpbrk(ep, " \t")) != NULL; nargs++) {
while (isblank((unsigned char)*ep))
ep++;
}
args = emalloc2(nargs + 1, sizeof(*args));
/* Fill in args array, there is at least one element. */
for (nargs = 0; (ep = strpbrk(cp, " \t")) != NULL; ) {
args[nargs++] = estrndup(cp, (size_t)(ep - cp));
while (isblank((unsigned char)*ep))
ep++;
cp = ep;
}
args[nargs++] = estrdup(cp);
args[nargs] = NULL;
} else {
/* No extra args. */
pathlen = strlen(path);
}
info = emalloc(sizeof(*info)); info = emalloc(sizeof(*info));
info->symbol_name = estrndup(name, namelen); info->symbol_name = estrndup(name, namelen);
info->path = estrdup(path); info->path = estrndup(path, pathlen);
info->args = args;
info->prev = info; info->prev = info;
info->next = NULL; info->next = NULL;
tq_append(&sudo_conf_data.plugins, info); tq_append(&sudo_conf_data.plugins, info);

View File

@@ -2,7 +2,7 @@
# Sample /etc/sudo.conf file # Sample /etc/sudo.conf file
# #
# Format: # Format:
# Plugin plugin_name plugin_path # Plugin plugin_name plugin_path plugin_args ...
# Path askpass /path/to/askpass # Path askpass /path/to/askpass
# Path noexec /path/to/noexec.so # Path noexec /path/to/noexec.so
# Debug sudo /var/log/sudo_debug all@warn # Debug sudo /var/log/sudo_debug all@warn
@@ -13,6 +13,7 @@
# The plugin_path is relative to ${prefix}/libexec unless fully qualified. # The plugin_path is relative to ${prefix}/libexec unless fully qualified.
# The plugin_name corresponds to a global symbol in the plugin # The plugin_name corresponds to a global symbol in the plugin
# that contains the plugin interface structure. # that contains the plugin interface structure.
# The plugin_args are optional.
# #
# The sudoers plugin is used by default if no Plugin lines are present. # The sudoers plugin is used by default if no Plugin lines are present.
Plugin sudoers_policy sudoers.so Plugin sudoers_policy sudoers.so

View File

@@ -421,7 +421,7 @@ which corresponds to the following F<@sysconfdir@/sudo.conf> file.
# Default @sysconfdir@/sudo.conf file # Default @sysconfdir@/sudo.conf file
# #
# Format: # Format:
# Plugin plugin_name plugin_path # Plugin plugin_name plugin_path plugin_args ...
# Path askpass /path/to/askpass # Path askpass /path/to/askpass
# Path noexec /path/to/noexec.so # Path noexec /path/to/noexec.so
# Debug sudo /var/log/sudo_debug all@warn # Debug sudo /var/log/sudo_debug all@warn
@@ -431,6 +431,7 @@ which corresponds to the following F<@sysconfdir@/sudo.conf> file.
# fully qualified. # fully qualified.
# The plugin_name corresponds to a global symbol in the plugin # The plugin_name corresponds to a global symbol in the plugin
# that contains the plugin interface structure. # that contains the plugin interface structure.
# The plugin_args are optional.
# #
Plugin policy_plugin sudoers.so Plugin policy_plugin sudoers.so
Plugin io_plugin sudoers.so Plugin io_plugin sudoers.so
@@ -441,8 +442,9 @@ plugin. The I<symbol_name> is the name of the C<struct policy_plugin>
or C<struct io_plugin> in the plugin shared object. The I<path> or C<struct io_plugin> in the plugin shared object. The I<path>
may be fully qualified or relative. If not fully qualified it is may be fully qualified or relative. If not fully qualified it is
relative to the F<@prefix@/libexec> directory. Any additional relative to the F<@prefix@/libexec> directory. Any additional
parameters after the I<path> are ignored. Lines that don't begin parameters after the I<path> are passed as arguments to the plugin's
with C<Plugin> or C<Path> are silently ignored I<open> function. Lines that don't begin with C<Plugin>, C<Path>,
C<Debug> or C<Set> are silently ignored.
For more information, see the L<sudo_plugin(8)> manual. For more information, see the L<sudo_plugin(8)> manual.

View File

@@ -48,8 +48,9 @@ plugin. The I<symbol_name> is the name of the C<struct policy_plugin>
or C<struct io_plugin> in the plugin shared object. The I<path> or C<struct io_plugin> in the plugin shared object. The I<path>
may be fully qualified or relative. If not fully qualified it is may be fully qualified or relative. If not fully qualified it is
relative to the F<@prefix@/libexec> directory. Any additional relative to the F<@prefix@/libexec> directory. Any additional
parameters after the I<path> are ignored. Lines that don't begin parameters after the I<path> are passed as arguments to the plugin's
with C<Plugin> or C<Path> are silently ignored. I<open> function. Lines that don't begin with C<Plugin>, C<Path>,
C<Debug> or C<Set> are silently ignored.
The same shared object may contain multiple plugins, each with a The same shared object may contain multiple plugins, each with a
different symbol name. The shared object file must be owned by uid different symbol name. The shared object file must be owned by uid
@@ -61,13 +62,17 @@ This limitation does not apply to I/O plugins.
# Default @sysconfdir@/sudo.conf file # Default @sysconfdir@/sudo.conf file
# #
# Format: # Format:
# Plugin plugin_name plugin_path # Plugin plugin_name plugin_path optional_args
# Path askpass /path/to/askpass # Path askpass /path/to/askpass
# Path noexec /path/to/noexec.so
# Debug sudo /var/log/sudo_debug all@warn
# Set disable_coredump true
# #
# The plugin_path is relative to @prefix@/libexec unless # The plugin_path is relative to @prefix@/libexec unless
# fully qualified. # fully qualified.
# The plugin_name corresponds to a global symbol in the plugin # The plugin_name corresponds to a global symbol in the plugin
# that contains the plugin interface structure. # that contains the plugin interface structure.
# The plugin_args are optional.
# #
Plugin sudoers_policy sudoers.so Plugin sudoers_policy sudoers.so
Plugin sudoers_io sudoers.so Plugin sudoers_io sudoers.so
@@ -86,7 +91,8 @@ so that B<sudo> can load it.
unsigned int version; /* always SUDO_API_VERSION */ unsigned int version; /* always SUDO_API_VERSION */
int (*open)(unsigned int version, sudo_conv_t conversation, int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[], sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const user_env[]); char * const user_info[], char * const user_env[],
char * const plugin_args[]);
void (*close)(int exit_status, int error); void (*close)(int exit_status, int error);
int (*show_version)(int verbose); int (*show_version)(int verbose);
int (*check_policy)(int argc, char * const argv[], int (*check_policy)(int argc, char * const argv[],
@@ -118,7 +124,8 @@ built against.
int (*open)(unsigned int version, sudo_conv_t conversation, int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[], sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const user_env[]); char * const user_info[], char * const user_env[],
char * const plugin_args[]);
Returns 1 on success, 0 on failure, -1 if a general error occurred, Returns 1 on success, 0 on failure, -1 if a general error occurred,
or -2 if there was a usage error. In the latter case, B<sudo> will or -2 if there was a usage error. In the latter case, B<sudo> will
@@ -369,6 +376,19 @@ When parsing I<user_env>, the plugin should split on the B<first>
equal sign ('=') since the I<name> field will never include one equal sign ('=') since the I<name> field will never include one
itself but the I<value> might. itself but the I<value> might.
=item plugin_args
Any (non-comment) strings immediately after the plugin path are
treated as arguments to the plugin. These arguments are split on
a whitespace boundary and are passed to the plugin in the form of
a C<NULL>-terminated array of strings. If no arguments were
specified, I<plugin_args> will be the NULL pointer.
NOTE: the I<plugin_args> parameter is only available starting with
API version 1.2. A plugin B<must> check the API version specified
by the B<sudo> front end before using I<plugin_args>. Failure to
do so may result in a crash.
=back =back
=item close =item close
@@ -762,7 +782,7 @@ error information to the user.
int (*open)(unsigned int version, sudo_conv_t conversation int (*open)(unsigned int version, sudo_conv_t conversation
sudo_printf_t plugin_printf, char * const settings[], sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], int argc, char * const argv[], char * const user_info[], int argc, char * const argv[],
char * const user_env[]); char * const user_env[], char * const plugin_args[]);
void (*close)(int exit_status, int error); /* wait status or error */ void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose); int (*show_version)(int verbose);
int (*log_ttyin)(const char *buf, unsigned int len); int (*log_ttyin)(const char *buf, unsigned int len);
@@ -811,7 +831,7 @@ built against.
int (*open)(unsigned int version, sudo_conv_t conversation int (*open)(unsigned int version, sudo_conv_t conversation
sudo_printf_t plugin_printf, char * const settings[], sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], int argc, char * const argv[], char * const user_info[], int argc, char * const argv[],
char * const user_env[]); char * const user_env[], char * const plugin_args[]);
The I<open> function is run before the I<log_input>, I<log_output> The I<open> function is run before the I<log_input>, I<log_output>
or I<show_version> functions are called. It is only called if the or I<show_version> functions are called. It is only called if the
@@ -895,6 +915,19 @@ When parsing I<user_env>, the plugin should split on the B<first>
equal sign ('=') since the I<name> field will never include one equal sign ('=') since the I<name> field will never include one
itself but the I<value> might. itself but the I<value> might.
=item plugin_args
Any (non-comment) strings immediately after the plugin path are
treated as arguments to the plugin. These arguments are split on
a whitespace boundary and are passed to the plugin in the form of
a C<NULL>-terminated array of strings. If no arguments were
specified, I<plugin_args> will be the NULL pointer.
NOTE: the I<plugin_args> parameter is only available starting with
API version 1.2. A plugin B<must> check the API version specified
by the B<sudo> front end before using I<plugin_args>. Failure to
do so may result in a crash.
=back =back
=item close =item close

View File

@@ -540,7 +540,7 @@ and F</usr/bin/vi> but shell escapes will be disabled.
aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
See the L<PREVENTING SHELL ESCAPES> section below for more details See the L<Preventing Shell Escapes> section below for more details
on how C<NOEXEC> works and whether or not it will work on your system. on how C<NOEXEC> works and whether or not it will work on your system.
=head3 SETENV and NOSETENV =head3 SETENV and NOSETENV
@@ -940,8 +940,8 @@ by default.
If set, all commands run via B<sudo> will behave as if the C<NOEXEC> If set, all commands run via B<sudo> will behave as if the C<NOEXEC>
tag has been set, unless overridden by a C<EXEC> tag. See the tag has been set, unless overridden by a C<EXEC> tag. See the
description of I<NOEXEC and EXEC> below as well as the L<PREVENTING SHELL description of I<NOEXEC and EXEC> below as well as the L<Preventing Shell
ESCAPES> section at the end of this manual. This flag is I<off> by default. Escapes> section at the end of this manual. This flag is I<off> by default.
=item path_info =item path_info
@@ -1594,10 +1594,166 @@ is displayed when B<sudo> is run by root with the I<-V> option.
=back =back
=head1 SUDO.CONF
The F<@sysconfdir@/sudo.conf> file determines which plugins the
B<sudo> front end will load. If no F<@sysconfdir@/sudo.conf> file
is present, or it contains no C<Plugin> lines, B<sudo> will use the
I<sudoers> security policy and I/O logging, which corresponds to
the following F<@sysconfdir@/sudo.conf> file.
#
# Default @sysconfdir@/sudo.conf file
#
# Format:
# Plugin plugin_name plugin_path plugin_args ...
# Path askpass /path/to/askpass
# Path noexec /path/to/noexec.so
# Debug sudo /var/log/sudo_debug all@warn
# Set disable_coredump true
#
# The plugin_path is relative to @prefix@/libexec unless
# fully qualified.
# The plugin_name corresponds to a global symbol in the plugin
# that contains the plugin interface structure.
# The plugin_args are optional.
#
Plugin policy_plugin sudoers.so
Plugin io_plugin sudoers.so
=head2 PLUGIN OPTIONS
Starting with B<sudo> 1.8.5 it is possible to pass options to the
I<sudoers> plugin. Options may be listed after the path to the
plugin (i.e. after F<sudoers.so>); multiple options should be
space-separated. For example:
Plugin sudoers_policy sudoers.so sudoers_file=/etc/sudoers sudoers_uid=0 sudoers_gid=0 sudoers_mode=0440
The following plugin options are supported:
=over 10
=item sudoers_file=pathname
The I<sudoers_file> option can be used to override the default path
to the I<sudoers> file.
=item sudoers_uid=uid
The I<sudoers_uid> option can be used to override the default owner
of the sudoers file. It should be specified as a numeric user ID.
=item sudoers_gid=gid
The I<sudoers_gid> option can be used to override the default group
of the sudoers file. It should be specified as a numeric group ID.
=item sudoers_mode=mode
The I<sudoers_mode> option can be used to override the default file
mode for the sudoers file. It should be specified as an octal value.
=back
=head2 DEBUG FLAGS
Versions 1.8.4 and higher of the I<sudoers> plugin supports a
debugging framework that can help track down what the plugin is
doing internally if there is a problem. This can be configured in
the F<@sysconfdir@/sudo.conf> file as described in L<sudo(8)>.
The I<sudoers> plugin uses the same debug flag format as B<sudo>
itself: I<subsystem>@I<priority>.
The priorities used by I<sudoers>, in order of decreasing severity,
are: I<crit>, I<err>, I<warn>, I<notice>, I<diag>, I<info>, I<trace>
and I<debug>. Each priority, when specified, also includes all
priorities higher than it. For example, a priority of I<notice>
would include debug messages logged at I<notice> and higher.
The following subsystems are used by I<sudoers>:
=over 10
=item I<alias>
C<User_Alias>, C<Runas_Alias>, C<Host_Alias> and C<Cmnd_Alias> processing
=item I<all>
matches every subsystem
=item I<audit>
BSM and Linux audit code
=item I<auth>
user authentication
=item I<defaults>
I<sudoers> I<Defaults> settings
=item I<env>
environment handling
=item I<ldap>
LDAP-based sudoers
=item I<logging>
logging support
=item I<match>
matching of users, groups, hosts and netgroups in I<sudoers>
=item I<netif>
network interface handling
=item I<nss>
network service switch handling in I<sudoers>
=item I<parser>
I<sudoers> file parsing
=item I<perms>
permission setting
=item I<plugin>
The equivalent of I<main> for the plugin.
=item I<pty>
pseudo-tty related code
=item I<rbtree>
redblack tree internals
=item I<util>
utility functions
=back
=head1 FILES =head1 FILES
=over 24 =over 24
=item F<@sysconfdir@/sudo.conf>
Sudo front end configuration
=item F<@sysconfdir@/sudoers> =item F<@sysconfdir@/sudoers>
List of who can run what List of who can run what
@@ -1810,6 +1966,8 @@ for encapsulating in a shell script.
=head1 SECURITY NOTES =head1 SECURITY NOTES
=head2 Limitations of the '!' operator
It is generally not effective to "subtract" commands from C<ALL> It is generally not effective to "subtract" commands from C<ALL>
using the '!' operator. A user can trivially circumvent this using the '!' operator. A user can trivially circumvent this
by copying the desired command to a different name and then by copying the desired command to a different name and then
@@ -1823,7 +1981,14 @@ different name, or use a shell escape from an editor or other
program. Therefore, these kind of restrictions should be considered program. Therefore, these kind of restrictions should be considered
advisory at best (and reinforced by policy). advisory at best (and reinforced by policy).
Furthermore, if the I<fast_glob> option is in use, it is not possible In general, if a user has sudo C<ALL> there is nothing to prevent
them from creating their own program that gives them a root shell
(or making their own copy of a shell) regardless of any '!' elements
in the user specification.
=head2 Security implications of I<fast_glob>
If the I<fast_glob> option is in use, it is not possible
to reliably negate commands where the path name includes globbing to reliably negate commands where the path name includes globbing
(aka wildcard) characters. This is because the C library's (aka wildcard) characters. This is because the C library's
L<fnmatch(3)> function cannot resolve relative paths. While this L<fnmatch(3)> function cannot resolve relative paths. While this
@@ -1839,7 +2004,7 @@ For example, given the following I<sudoers> entry:
User B<john> can still run C</usr/bin/passwd root> if I<fast_glob> is User B<john> can still run C</usr/bin/passwd root> if I<fast_glob> is
enabled by changing to F</usr/bin> and running C<./passwd root> instead. enabled by changing to F</usr/bin> and running C<./passwd root> instead.
=head1 PREVENTING SHELL ESCAPES =head2 Preventing Shell Escapes
Once B<sudo> executes a program, that program is free to do whatever Once B<sudo> executes a program, that program is free to do whatever
it pleases, including run other programs. This can be a security it pleases, including run other programs. This can be a security
@@ -1903,97 +2068,7 @@ to unintended privilege escalation. In the specific case of an
editor, a safer approach is to give the user permission to run editor, a safer approach is to give the user permission to run
B<sudoedit>. B<sudoedit>.
=head1 DEBUG FLAGS =head2 Time stamp file checks
Versions 1.8.4 and higher of the I<sudoers> plugin supports a
debugging framework that can help track down what the plugin is
doing internally if there is a problem. This can be configured in
the F<@sysconfdir@/sudo.conf> file as described in L<sudo(8)>.
The I<sudoers> plugin uses the same debug flag format as B<sudo>
itself: I<subsystem>@I<priority>.
The priorities used by I<sudoers>, in order of decreasing severity,
are: I<crit>, I<err>, I<warn>, I<notice>, I<diag>, I<info>, I<trace>
and I<debug>. Each priority, when specified, also includes all
priorities higher than it. For example, a priority of I<notice>
would include debug messages logged at I<notice> and higher.
The following subsystems are used by I<sudoers>:
=over 10
=item I<alias>
C<User_Alias>, C<Runas_Alias>, C<Host_Alias> and C<Cmnd_Alias> processing
=item I<all>
matches every subsystem
=item I<audit>
BSM and Linux audit code
=item I<auth>
user authentication
=item I<defaults>
I<sudoers> I<Defaults> settings
=item I<env>
environment handling
=item I<ldap>
LDAP-based sudoers
=item I<logging>
logging support
=item I<match>
matching of users, groups, hosts and netgroups in I<sudoers>
=item I<netif>
network interface handling
=item I<nss>
network service switch handling in I<sudoers>
=item I<parser>
I<sudoers> file parsing
=item I<perms>
permission setting
=item I<plugin>
The equivalent of I<main> for the plugin.
=item I<pty>
pseudo-tty related code
=item I<rbtree>
redblack tree internals
=item I<util>
utility functions
=back
=head1 SECURITY NOTES
I<sudoers> will check the ownership of its time stamp directory I<sudoers> will check the ownership of its time stamp directory
(F<@timedir@> by default) and ignore the directory's contents if (F<@timedir@> by default) and ignore the directory's contents if
@@ -2034,11 +2109,6 @@ created (such as Mac OS X), I<sudoers> is able to determine when a
tty-based time stamp file is stale and will ignore it. Administrators tty-based time stamp file is stale and will ignore it. Administrators
should not rely on this feature as it is not universally available. should not rely on this feature as it is not universally available.
If users have sudo C<ALL> there is nothing to prevent them from
creating their own program that gives them a root shell (or making
their own copy of a shell) regardless of any '!' elements in the
user specification.
=head1 SEE ALSO =head1 SEE ALSO
L<rsh(1)>, L<su(1)>, L<fnmatch(3)>, L<glob(3)>, L<mktemp(3)>, L<strftime(3)>, L<rsh(1)>, L<su(1)>, L<fnmatch(3)>, L<glob(3)>, L<mktemp(3)>, L<strftime(3)>,

View File

@@ -24,6 +24,7 @@ struct plugin_info {
struct plugin_info *next; /* required */ struct plugin_info *next; /* required */
const char *path; const char *path;
const char *symbol_name; const char *symbol_name;
char * const * args;
}; };
TQ_DECLARE(plugin_info) TQ_DECLARE(plugin_info)

View File

@@ -19,7 +19,7 @@
/* API version major/minor */ /* API version major/minor */
#define SUDO_API_VERSION_MAJOR 1 #define SUDO_API_VERSION_MAJOR 1
#define SUDO_API_VERSION_MINOR 1 #define SUDO_API_VERSION_MINOR 2
#define SUDO_API_MKVERSION(x, y) ((x << 16) | y) #define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR) #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR)
@@ -63,7 +63,8 @@ struct policy_plugin {
unsigned int version; /* always SUDO_API_VERSION */ unsigned int version; /* always SUDO_API_VERSION */
int (*open)(unsigned int version, sudo_conv_t conversation, int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const user_env[]); char * const user_info[], char * const user_env[],
char * const plugin_args[]);
void (*close)(int exit_status, int error); /* wait status or error */ void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose); int (*show_version)(int verbose);
int (*check_policy)(int argc, char * const argv[], int (*check_policy)(int argc, char * const argv[],
@@ -84,7 +85,8 @@ struct io_plugin {
int (*open)(unsigned int version, sudo_conv_t conversation, int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const command_info[], char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[]); int argc, char * const argv[], char * const user_env[],
char * const plugin_args[]);
void (*close)(int exit_status, int error); /* wait status or error */ void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose); int (*show_version)(int verbose);
int (*log_ttyin)(const char *buf, unsigned int len); int (*log_ttyin)(const char *buf, unsigned int len);

View File

@@ -111,7 +111,7 @@ fmt_string(const char *var, const char *val)
static int static int
policy_open(unsigned int version, sudo_conv_t conversation, policy_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const user_env[]) char * const user_info[], char * const user_env[], char * const args[])
{ {
char * const *ui; char * const *ui;
struct passwd *pw; struct passwd *pw;
@@ -422,7 +422,7 @@ static int
io_open(unsigned int version, sudo_conv_t conversation, io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const command_info[], char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[]) int argc, char * const argv[], char * const user_env[], char * const args[])
{ {
int fd; int fd;
char path[PATH_MAX]; char path[PATH_MAX];

View File

@@ -417,7 +417,7 @@ static int
sudoers_io_open(unsigned int version, sudo_conv_t conversation, sudoers_io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[], sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const command_info[], char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[]) int argc, char * const argv[], char * const user_env[], char * const args[])
{ {
struct iolog_details details; struct iolog_details details;
char pathbuf[PATH_MAX], sessid[7]; char pathbuf[PATH_MAX], sessid[7];

View File

@@ -96,7 +96,8 @@ static void set_runaspw(const char *);
static void set_runasgr(const char *); static void set_runasgr(const char *);
static int cb_runas_default(const char *); static int cb_runas_default(const char *);
static int sudoers_policy_version(int verbose); static int sudoers_policy_version(int verbose);
static int deserialize_info(char * const settings[], char * const user_info[]); static int deserialize_info(char * const args[], char * const settings[],
char * const user_info[]);
static char *find_editor(int nfiles, char **files, char ***argv_out); static char *find_editor(int nfiles, char **files, char ***argv_out);
static void create_admin_success_flag(void); static void create_admin_success_flag(void);
@@ -135,13 +136,17 @@ sigjmp_buf error_jmp;
static int static int
sudoers_policy_open(unsigned int version, sudo_conv_t conversation, sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[], sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const envp[]) char * const user_info[], char * const envp[], char * const args[])
{ {
volatile int sources = 0; volatile int sources = 0;
sigaction_t sa; sigaction_t sa;
struct sudo_nss *nss; struct sudo_nss *nss;
debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN) debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN)
/* Plugin args are only specified for API version 1.2 and higher. */
if (version < SUDO_API_MKVERSION(1, 2))
args = NULL;
if (!sudo_conv) if (!sudo_conv)
sudo_conv = conversation; sudo_conv = conversation;
if (!sudo_printf) if (!sudo_printf)
@@ -178,8 +183,8 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
/* Setup defaults data structures. */ /* Setup defaults data structures. */
init_defaults(); init_defaults();
/* Parse settings and user_info */ /* Parse args, settings and user_info */
sudo_mode = deserialize_info(settings, user_info); sudo_mode = deserialize_info(args, settings, user_info);
init_vars(envp); /* XXX - move this later? */ init_vars(envp); /* XXX - move this later? */
@@ -1181,7 +1186,7 @@ sudoers_policy_version(int verbose)
} }
static int static int
deserialize_info(char * const settings[], char * const user_info[]) deserialize_info(char * const args[], char * const settings[], char * const user_info[])
{ {
char * const *cur; char * const *cur;
const char *p, *groups = NULL; const char *p, *groups = NULL;
@@ -1191,6 +1196,29 @@ deserialize_info(char * const settings[], char * const user_info[])
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0) #define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0)
/* Parse sudo.conf plugin args. */
if (args != NULL) {
for (cur = args; *cur != NULL; cur++) {
if (MATCHES(*cur, "sudoers_file=")) {
sudoers_file = *cur + sizeof("sudoers_file=") - 1;
continue;
}
if (MATCHES(*cur, "sudoers_uid=")) {
sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1);
continue;
}
if (MATCHES(*cur, "sudoers_gid=")) {
sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1);
continue;
}
if (MATCHES(*cur, "sudoers_mode=")) {
sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1,
NULL, 8);
continue;
}
}
}
/* Parse command line settings. */ /* Parse command line settings. */
user_closefrom = -1; user_closefrom = -1;
for (cur = settings; *cur != NULL; cur++) { for (cur = settings; *cur != NULL; cur++) {
@@ -1294,23 +1322,6 @@ deserialize_info(char * const settings[], char * const user_info[])
set_interfaces(interfaces_string); set_interfaces(interfaces_string);
continue; continue;
} }
if (MATCHES(*cur, "sudoers_file=")) {
sudoers_file = *cur + sizeof("sudoers_file=") - 1;
continue;
}
if (MATCHES(*cur, "sudoers_uid=")) {
sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1);
continue;
}
if (MATCHES(*cur, "sudoers_gid=")) {
sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1);
continue;
}
if (MATCHES(*cur, "sudoers_mode=")) {
sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1,
NULL, 8);
continue;
}
} }
for (cur = user_info; *cur != NULL; cur++) { for (cur = user_info; *cur != NULL; cur++) {

View File

@@ -81,7 +81,7 @@ int sudolineno;
int last_token; int last_token;
char *sudoers; char *sudoers;
/* Default sudoers path, mode and owner */ /* Default sudoers path, mode and owner (may be set via sudo.conf) */
const char *sudoers_file = _PATH_SUDOERS; const char *sudoers_file = _PATH_SUDOERS;
mode_t sudoers_mode = SUDOERS_MODE; mode_t sudoers_mode = SUDOERS_MODE;
uid_t sudoers_uid = SUDOERS_UID; uid_t sudoers_uid = SUDOERS_UID;

View File

@@ -131,6 +131,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
} }
policy_plugin->handle = handle; policy_plugin->handle = handle;
policy_plugin->name = info->symbol_name; policy_plugin->name = info->symbol_name;
policy_plugin->args = info->args;
policy_plugin->u.generic = plugin; policy_plugin->u.generic = plugin;
} else if (plugin->type == SUDO_IO_PLUGIN) { } else if (plugin->type == SUDO_IO_PLUGIN) {
container = emalloc(sizeof(*container)); container = emalloc(sizeof(*container));
@@ -138,6 +139,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
container->next = NULL; container->next = NULL;
container->handle = handle; container->handle = handle;
container->name = info->symbol_name; container->name = info->symbol_name;
container->args = info->args;
container->u.generic = plugin; container->u.generic = plugin;
tq_append(io_plugins, container); tq_append(io_plugins, container);
} }

View File

@@ -1056,9 +1056,24 @@ static int
policy_open(struct plugin_container *plugin, char * const settings[], policy_open(struct plugin_container *plugin, char * const settings[],
char * const user_info[], char * const user_env[]) char * const user_info[], char * const user_env[])
{ {
int rval;
debug_decl(policy_open, SUDO_DEBUG_PCOMM) debug_decl(policy_open, SUDO_DEBUG_PCOMM)
debug_return_bool(plugin->u.policy->open(SUDO_API_VERSION,
sudo_conversation, _sudo_printf, settings, user_info, user_env)); /*
* Backwards compatibility for older API versions
*/
switch (plugin->u.generic->version) {
case SUDO_API_MKVERSION(1, 0):
case SUDO_API_MKVERSION(1, 1):
rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version,
sudo_conversation, _sudo_printf, settings, user_info, user_env);
break;
default:
rval = plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, user_env, plugin->args);
}
debug_return_bool(rval);
} }
static void static void
@@ -1141,7 +1156,7 @@ iolog_open(struct plugin_container *plugin, char * const settings[],
debug_decl(iolog_open, SUDO_DEBUG_PCOMM) debug_decl(iolog_open, SUDO_DEBUG_PCOMM)
/* /*
* Backwards compatibility for API major 1, minor 0 * Backwards compatibility for older API versions
*/ */
switch (plugin->u.generic->version) { switch (plugin->u.generic->version) {
case SUDO_API_MKVERSION(1, 0): case SUDO_API_MKVERSION(1, 0):
@@ -1149,10 +1164,15 @@ iolog_open(struct plugin_container *plugin, char * const settings[],
sudo_conversation, _sudo_printf, settings, user_info, argc, argv, sudo_conversation, _sudo_printf, settings, user_info, argc, argv,
user_env); user_env);
break; break;
case SUDO_API_MKVERSION(1, 1):
rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version,
sudo_conversation, _sudo_printf, settings, user_info,
command_info, argc, argv, user_env);
break;
default: default:
rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation, rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, command_info, argc, argv, _sudo_printf, settings, user_info, command_info,
user_env); argc, argv, user_env, plugin->args);
} }
debug_return_bool(rval); debug_return_bool(rval);
} }

View File

@@ -29,6 +29,23 @@ struct generic_plugin {
/* /*
* Backwards-compatible structures for API bumps. * Backwards-compatible structures for API bumps.
*/ */
struct policy_plugin_1_0 {
unsigned int type;
unsigned int version;
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const user_env[]);
void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose);
int (*check_policy)(int argc, char * const argv[],
char *env_add[], char **command_info[],
char **argv_out[], char **user_env_out[]);
int (*list)(int argc, char * const argv[], int verbose,
const char *list_user);
int (*validate)(void);
void (*invalidate)(int remove);
int (*init_session)(struct passwd *pwd);
};
struct io_plugin_1_0 { struct io_plugin_1_0 {
unsigned int type; unsigned int type;
unsigned int version; unsigned int version;
@@ -44,6 +61,21 @@ struct io_plugin_1_0 {
int (*log_stdout)(const char *buf, unsigned int len); int (*log_stdout)(const char *buf, unsigned int len);
int (*log_stderr)(const char *buf, unsigned int len); int (*log_stderr)(const char *buf, unsigned int len);
}; };
struct io_plugin_1_1 {
unsigned int type;
unsigned int version;
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[]);
void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose);
int (*log_ttyin)(const char *buf, unsigned int len);
int (*log_ttyout)(const char *buf, unsigned int len);
int (*log_stdin)(const char *buf, unsigned int len);
int (*log_stdout)(const char *buf, unsigned int len);
int (*log_stderr)(const char *buf, unsigned int len);
};
/* /*
* Sudo plugin internals. * Sudo plugin internals.
@@ -52,12 +84,15 @@ struct plugin_container {
struct plugin_container *prev; /* required */ struct plugin_container *prev; /* required */
struct plugin_container *next; /* required */ struct plugin_container *next; /* required */
const char *name; const char *name;
char * const *args;
void *handle; void *handle;
union { union {
struct generic_plugin *generic; struct generic_plugin *generic;
struct policy_plugin *policy; struct policy_plugin *policy;
struct policy_plugin_1_0 *policy_1_0;
struct io_plugin *io; struct io_plugin *io;
struct io_plugin_1_0 *io_1_0; struct io_plugin_1_0 *io_1_0;
struct io_plugin_1_1 *io_1_1;
} u; } u;
}; };
TQ_DECLARE(plugin_container) TQ_DECLARE(plugin_container)