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)
{
struct plugin_info *info;
const char *name, *path;
size_t namelen;
const char *name, *path, *cp, *ep;
char **args = NULL;
size_t namelen, pathlen;
unsigned int nargs;
/* Parse Plugin line */
name = entry;
@@ -215,10 +217,35 @@ set_plugin(const char *entry)
namelen = (size_t)(path - name);
while (isblank((unsigned char)*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->symbol_name = estrndup(name, namelen);
info->path = estrdup(path);
info->path = estrndup(path, pathlen);
info->args = args;
info->prev = info;
info->next = NULL;
tq_append(&sudo_conf_data.plugins, info);

View File

@@ -2,7 +2,7 @@
# Sample /etc/sudo.conf file
#
# Format:
# Plugin plugin_name plugin_path
# 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
@@ -13,6 +13,7 @@
# 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.
#
# The sudoers plugin is used by default if no Plugin lines are present.
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
#
# Format:
# Plugin plugin_name plugin_path
# 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
@@ -431,6 +431,7 @@ which corresponds to the following F<@sysconfdir@/sudo.conf> file.
# 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
@@ -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>
may be fully qualified or relative. If not fully qualified it is
relative to the F<@prefix@/libexec> directory. Any additional
parameters after the I<path> are ignored. Lines that don't begin
with C<Plugin> or C<Path> are silently ignored
parameters after the I<path> are passed as arguments to the plugin's
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.

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>
may be fully qualified or relative. If not fully qualified it is
relative to the F<@prefix@/libexec> directory. Any additional
parameters after the I<path> are ignored. Lines that don't begin
with C<Plugin> or C<Path> are silently ignored.
parameters after the I<path> are passed as arguments to the plugin's
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
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
#
# Format:
# Plugin plugin_name plugin_path
# Plugin plugin_name plugin_path optional_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 sudoers_policy 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 */
int (*open)(unsigned int version, sudo_conv_t conversation,
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);
int (*show_version)(int verbose);
int (*check_policy)(int argc, char * const argv[],
@@ -118,7 +124,8 @@ built against.
int (*open)(unsigned int version, sudo_conv_t conversation,
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,
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
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
=item close
@@ -762,7 +782,7 @@ error information to the user.
int (*open)(unsigned int version, sudo_conv_t conversation
sudo_printf_t plugin_printf, char * const settings[],
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 */
int (*show_version)(int verbose);
int (*log_ttyin)(const char *buf, unsigned int len);
@@ -811,7 +831,7 @@ built against.
int (*open)(unsigned int version, sudo_conv_t conversation
sudo_printf_t plugin_printf, char * const settings[],
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>
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
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
=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
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.
=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>
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
ESCAPES> section at the end of this manual. This flag is I<off> by default.
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.
=item path_info
@@ -1594,10 +1594,166 @@ is displayed when B<sudo> is run by root with the I<-V> option.
=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
=over 24
=item F<@sysconfdir@/sudo.conf>
Sudo front end configuration
=item F<@sysconfdir@/sudoers>
List of who can run what
@@ -1810,6 +1966,8 @@ for encapsulating in a shell script.
=head1 SECURITY NOTES
=head2 Limitations of the '!' operator
It is generally not effective to "subtract" commands from C<ALL>
using the '!' operator. A user can trivially circumvent this
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
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
(aka wildcard) characters. This is because the C library's
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
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
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
B<sudoedit>.
=head1 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 SECURITY NOTES
=head2 Time stamp file checks
I<sudoers> will check the ownership of its time stamp directory
(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
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
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 */
const char *path;
const char *symbol_name;
char * const * args;
};
TQ_DECLARE(plugin_info)

View File

@@ -19,7 +19,7 @@
/* API version major/minor */
#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_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 */
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[]);
char * const user_info[], char * const user_env[],
char * const plugin_args[]);
void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose);
int (*check_policy)(int argc, char * const argv[],
@@ -84,7 +85,8 @@ struct io_plugin {
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[]);
int argc, char * const argv[], char * const user_env[],
char * const plugin_args[]);
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);

View File

@@ -111,7 +111,7 @@ fmt_string(const char *var, const char *val)
static int
policy_open(unsigned int version, sudo_conv_t conversation,
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;
struct passwd *pw;
@@ -422,7 +422,7 @@ static int
io_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[])
int argc, char * const argv[], char * const user_env[], char * const args[])
{
int fd;
char path[PATH_MAX];

View File

@@ -417,7 +417,7 @@ static int
sudoers_io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[],
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;
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 int cb_runas_default(const char *);
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 void create_admin_success_flag(void);
@@ -135,13 +136,17 @@ sigjmp_buf error_jmp;
static int
sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
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;
sigaction_t sa;
struct sudo_nss *nss;
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)
sudo_conv = conversation;
if (!sudo_printf)
@@ -178,8 +183,8 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
/* Setup defaults data structures. */
init_defaults();
/* Parse settings and user_info */
sudo_mode = deserialize_info(settings, user_info);
/* Parse args, settings and user_info */
sudo_mode = deserialize_info(args, settings, user_info);
init_vars(envp); /* XXX - move this later? */
@@ -1181,7 +1186,7 @@ sudoers_policy_version(int verbose)
}
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;
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)
/* 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. */
user_closefrom = -1;
for (cur = settings; *cur != NULL; cur++) {
@@ -1294,23 +1322,6 @@ deserialize_info(char * const settings[], char * const user_info[])
set_interfaces(interfaces_string);
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++) {

View File

@@ -81,7 +81,7 @@ int sudolineno;
int last_token;
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;
mode_t sudoers_mode = SUDOERS_MODE;
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->name = info->symbol_name;
policy_plugin->args = info->args;
policy_plugin->u.generic = plugin;
} else if (plugin->type == SUDO_IO_PLUGIN) {
container = emalloc(sizeof(*container));
@@ -138,6 +139,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
container->next = NULL;
container->handle = handle;
container->name = info->symbol_name;
container->args = info->args;
container->u.generic = plugin;
tq_append(io_plugins, container);
}

View File

@@ -1056,9 +1056,24 @@ static int
policy_open(struct plugin_container *plugin, char * const settings[],
char * const user_info[], char * const user_env[])
{
int rval;
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
@@ -1141,7 +1156,7 @@ iolog_open(struct plugin_container *plugin, char * const settings[],
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) {
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,
user_env);
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:
rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, command_info, argc, argv,
user_env);
_sudo_printf, settings, user_info, command_info,
argc, argv, user_env, plugin->args);
}
debug_return_bool(rval);
}

View File

@@ -29,6 +29,23 @@ struct generic_plugin {
/*
* 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 {
unsigned int type;
unsigned int version;
@@ -44,6 +61,21 @@ struct io_plugin_1_0 {
int (*log_stdout)(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.
@@ -52,12 +84,15 @@ struct plugin_container {
struct plugin_container *prev; /* required */
struct plugin_container *next; /* required */
const char *name;
char * const *args;
void *handle;
union {
struct generic_plugin *generic;
struct policy_plugin *policy;
struct policy_plugin_1_0 *policy_1_0;
struct io_plugin *io;
struct io_plugin_1_0 *io_1_0;
struct io_plugin_1_1 *io_1_1;
} u;
};
TQ_DECLARE(plugin_container)