]> granicus.if.org Git - sudo/commitdiff
Add support for plugin args at the end of a Plugin line in sudo.conf.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Mar 2012 16:04:09 +0000 (11:04 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Mar 2012 16:04:09 +0000 (11:04 -0500)
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.

14 files changed:
common/sudo_conf.c
doc/sample.sudo.conf
doc/sudo.pod
doc/sudo_plugin.pod
doc/sudoers.pod
include/sudo_conf.h
include/sudo_plugin.h
plugins/sample/sample_plugin.c
plugins/sudoers/iolog.c
plugins/sudoers/sudoers.c
plugins/sudoers/toke.l
src/load_plugins.c
src/sudo.c
src/sudo_plugin_int.h

index 74b90407d674148398b751555c029c61674a8712..3cdf9056ab69cceea95bc067f74c9a397b521cbc 100644 (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);
index 529602fb10fe2827a7606f3923891dae86309fb3..c6b2d38cf9c15286e91158d751cbdc2a8aaa0739 100644 (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
index 13b1b84af76c1a89d817b647ba65c56df54b8a92..d69b5b6d95200153f30ff4880787df6c5bd4d31c 100644 (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.
 
index 3513cae0a27d03a67304451a6317c529010e04f2..8627556d71b255c8beed683642ca974fc04f77fe 100644 (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
@@ -85,8 +90,9 @@ so that B<sudo> can load it.
      unsigned int type; /* always SUDO_POLICY_PLUGIN */
      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[]);
+                 sudo_printf_t plugin_printf, char * const settings[],
+                 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
index 32c39bce2f02edf9719205ebc552e2de263554bc..144c8f8a167face253b9fb5f569d7369df4daaed 100644 (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)>,
index 6efc302f8064795a2594b3ea8202cafa1effbb69..9e0ea14bbbb9c2e43eb8fb0c280d75f3750b434e 100644 (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)
 
index 6fd3e6794b7d3c205ee7bb052357722931e5bdf8..1eed2a294ee77b7dc5e431015e0c7a59140b19a1 100644 (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);
index 51ec2451a41b09d1f6a490694ccbb1a6468dadfd..c95ffd60eccbee8c825bf3b7a91c8b8d9971d8c2 100644 (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];
index 11622cb5e12aee189699ff8d22ff2407f18ea5d3..1f591e924fea262916ea313d5fe024fd22ebf159 100644 (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];
index 28707ab503ad6b7f45e46bbcac63c70f865e77e5..936298990da7fc504d32e8862533042c5c067725 100644 (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++) {
index f48fb2842faaf62a87a658fc6792a91294a6cb48..967de07fd3f65cbf6d3596f331f274c6fbaffeea 100644 (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;
index e86c1432c391521b55169647f100302ef56dea47..7b0f5e50eacf1dfad838f01e92d5fafa5f1fc18d 100644 (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);
        }
index eb006a088f720b049c41932a0cf67edba932fe78..7721f4aa7641b2c06bda18142976d35f163f5e63 100644 (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);
 }
index 135c1234467acef69102fb7e18e9f43af41a0dfa..a3c77313c7c14b11ad088d3d78f4118045cd2808 100644 (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)