Diff for /embedaddon/sudo/doc/sudo_plugin.pod between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 16:23:02 version 1.1.1.2, 2012/05/29 12:26:49
Line 1 Line 1
Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com>Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
   
 Permission to use, copy, modify, and distribute this software for any  Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above  purpose with or without fee is hereby granted, provided that the above
Line 48  plugin.  The I<symbol_name> is the name of the C<struc Line 48  plugin.  The I<symbol_name> is the name of the C<struc
 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 beginparameters after the I<path> are passed as options 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
Line 61  This limitation does not apply to I/O plugins. Line 62  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 plugin_options ...
  #   Path askpass /path/to/askpass   #   Path askpass /path/to/askpass
    #   Path noexec /path/to/sudo_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_options are optional.
  #   #
  Plugin sudoers_policy sudoers.so   Plugin sudoers_policy sudoers.so
  Plugin sudoers_io sudoers.so   Plugin sudoers_io sudoers.so
Line 85  so that B<sudo> can load it. Line 90  so that B<sudo> can load it.
      unsigned int type; /* always SUDO_POLICY_PLUGIN */       unsigned int type; /* always SUDO_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 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_options[]);
      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[],
Line 96  so that B<sudo> can load it. Line 102  so that B<sudo> can load it.
                  const char *list_user);                   const char *list_user);
      int (*validate)(void);       int (*validate)(void);
      void (*invalidate)(int remove);       void (*invalidate)(int remove);
     int (*init_session)(struct passwd *pwd);     int (*init_session)(struct passwd *pwd, char **user_env[]);
      void (*register_hooks)(int version,
         int (*register_hook)(struct sudo_hook *hook));
      void (*deregister_hooks)(int version,
         int (*deregister_hook)(struct sudo_hook *hook));
  };   };
   
 The policy_plugin struct has the following fields:  The policy_plugin struct has the following fields:
Line 118  built against. Line 128  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_options[]);
   
 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
Line 163  itself but the I<value> might. Line 174  itself but the I<value> might.
   
 =over 4  =over 4
   
   =item debug_flags=string
   
   A comma-separated list of debug flags that correspond to B<sudo>'s
   C<Debug> entry in F<@sysconfdir@/sudo.conf>, if there is one.  The
   flags are passed to the plugin as they appear in F<@sysconfdir@/sudo.conf>.
   The syntax used by B<sudo> and the I<sudoers> plugin is
   I<subsystem>@I<priority> but the plugin is free to use a different
   format so long as it does not include a command C<,>.
   
   For reference, the priorities supported by the B<sudo> front end and
   I<sudoers> are: I<crit>, I<err>, I<warn>, I<notice>, I<diag>,
   I<info>, I<trace> and I<debug>.
   
   The following subsystems are defined: I<main>, I<memory>, I<args>,
   I<exec>, I<pty>, I<utmp>, I<conv>, I<pcomm>, I<util>, I<list>,
   I<netif>, I<audit>, I<edit>, I<selinux>, I<ldap>, I<match>, I<parser>,
   I<alias>, I<defaults>, I<auth>, I<env>, I<logging>, I<nss>, I<rbtree>,
   I<perms>, I<plugin>.  The subsystem I<all> includes every subsystem.
   
   There is not currently a way to specify a set of debug flags specific
   to the plugin--the flags are shared by B<sudo> and the plugin.
   
 =item debug_level=number  =item debug_level=number
   
A numeric debug level, from 1-9, if specified via the C<-D> flag.This setting has been deprecated in favor of I<debug_flags>.
   
 =item runas_user=string  =item runas_user=string
   
Line 294  itself but the I<value> might. Line 327  itself but the I<value> might.
   
 =over 4  =over 4
   
   =item pid=int
   
   The process ID of the running B<sudo> process.
   Only available starting with API version 1.2
   
   =item ppid=int
   
   The parent process ID of the running B<sudo> process.
   Only available starting with API version 1.2
   
   =item sid=int
   
   The session ID of the running B<sudo> process or 0 if B<sudo> is
   not part of a POSIX job control session.
   Only available starting with API version 1.2
   
   =item pgid=int
   
   The ID of the process group that the running B<sudo> process belongs
   to.
   Only available starting with API version 1.2
   
   =item tcpgid=int
   
   The ID of the forground process group associated with the terminal
   device associcated with the B<sudo> process or -1 if there is no
   terminal present.
   Only available starting with API version 1.2
   
 =item user=string  =item user=string
   
 The name of the user invoking B<sudo>.  The name of the user invoking B<sudo>.
   
   =item euid=uid_t
   
   The effective user ID of the user invoking B<sudo>.
   
 =item uid=uid_t  =item uid=uid_t
   
 The real user ID of the user invoking B<sudo>.  The real user ID of the user invoking B<sudo>.
   
   =item egid=gid_t
   
   The effective group ID of the user invoking B<sudo>.
   
 =item gid=gid_t  =item gid=gid_t
   
 The real group ID of the user invoking B<sudo>.  The real group ID of the user invoking B<sudo>.
Line 347  When parsing I<user_env>, the plugin should split on t Line 417  When parsing I<user_env>, the plugin should split on t
 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_options
   
   Any (non-comment) strings immediately after the plugin path are
   treated as arguments to the plugin.  These arguments are split on
   a white space 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_options> will be the NULL pointer.
   
   NOTE: the I<plugin_options> 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_options>.  Failure to
   do so may result in a crash.
   
 =back  =back
   
 =item close  =item close
Line 696  support credential caching. Line 779  support credential caching.
   
 =item init_session  =item init_session
   
 int (*init_session)(struct passwd *pwd); int (*init_session)(struct passwd *pwd, char **user_envp[);
   
The C<init_session> function is called when B<sudo> sets up theThe C<init_session> function is called before B<sudo> sets up the
execution environment for the command, immediately before theexecution environment for the command.  It is run in the parent
contents of the I<command_info> list are applied (before the uidB<sudo> process and before any uid or gid changes.  This can be used
changes).  This can be used to do session setup that is not supportedto perform session setup that is not supported by I<command_info>,
by I<command_info>, such as opening the PAM session.such as opening the PAM session.  The C<close> function can be
 used to tear down the session that was opened by C<init_session>.
   
 The I<pwd> argument points to a passwd struct for the user the  The I<pwd> argument points to a passwd struct for the user the
 command will be run as if the uid the command will run as was found  command will be run as if the uid the command will run as was found
 in the password database, otherwise it will be NULL.  in the password database, otherwise it will be NULL.
   
   The I<user_env> argument points to the environment the command will
   run in, in the form of a C<NULL>-terminated vector of "name=value"
   strings.  This is the same string passed back to the front end via
   the Policy Plugin's I<user_env_out> parameter.  If the C<init_session>
   function needs to modify the user environment, it should update the
   pointer stored in I<user_env>.  The expected use case is to merge
   the contents of the PAM environment (if any) with the contents of
   I<user_env>.  NOTE: the I<user_env> 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<user_env>.
   Failure to do so may result in a crash.
   
 Returns 1 on success, 0 on failure and -1 on error.  Returns 1 on success, 0 on failure and -1 on error.
 On error, the plugin may optionally call the conversation or plugin_printf  On error, the plugin may optionally call the conversation or plugin_printf
 function with C<SUDO_CONF_ERROR_MSG> to present additional  function with C<SUDO_CONF_ERROR_MSG> to present additional
 error information to the user.  error information to the user.
   
   =item register_hooks
   
    void (*register_hooks)(int version,
       int (*register_hook)(struct sudo_hook *hook));
   
   The C<register_hooks> function is called by the sudo front end to
   register any hooks the plugin needs.  If the plugin does not support
   hooks, C<register_hooks> should be set to the NULL pointer.
   
   The I<version> argument describes the version of the hooks API
   supported by the B<sudo> front end.
   
   The C<register_hook> function should be used to register any supported
   hooks the plugin needs.  It returns 0 on success, 1 if the hook
   type is not supported and -1 if the major version in C<struct hook>
   does not match the front end's major hook API version.
   
   See the L<Hook Function API> section below for more information
   about hooks.
   
   NOTE: the C<register_hooks> function is only available starting
   with API version 1.2.  If the B<sudo> front end doesn't support API
   version 1.2 or higher, C<register_hooks> will not be called.
   
   =item deregister_hooks
   
    void (*deregister_hooks)(int version,
       int (*deregister_hook)(struct sudo_hook *hook));
   
   The C<deregister_hooks> function is called by the sudo front end
   to deregister any hooks the plugin has registered.  If the plugin
   does not support hooks, C<deregister_hooks> should be set to the
   NULL pointer.
   
   The I<version> argument describes the version of the hooks API
   supported by the B<sudo> front end.
   
   The C<deregister_hook> function should be used to deregister any
   hooks that were put in place by the C<register_hook> function.  If
   the plugin tries to deregister a hook that the front end does not
   support, C<deregister_hook> will return an error.
   
   See the L<Hook Function API> section below for more information
   about hooks.
   
   NOTE: the C<deregister_hooks> function is only available starting
   with API version 1.2.  If the B<sudo> front end doesn't support API
   version 1.2 or higher, C<deregister_hooks> will not be called.
   
 =back  =back
   
=head3 Version macros=head3 Policy Plugin Version Macros
   
    /* Plugin API version major/minor. */
    #define SUDO_API_VERSION_MAJOR 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)
   
    /* Getters and setters for API version */
  #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)   #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
  #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)   #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
  #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \   #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
Line 726  error information to the user. Line 879  error information to the user.
      *(vp) = (*(vp) & 0xffff0000) | (n); \       *(vp) = (*(vp) & 0xffff0000) | (n); \
  } while(0)   } while(0)
   
  #define SUDO_API_VERSION_MAJOR 1  
  #define SUDO_API_VERSION_MINOR 0  
  #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \  
                            SUDO_API_VERSION_MINOR)  
   
 =head2 I/O Plugin API  =head2 I/O Plugin API
   
  struct io_plugin {   struct io_plugin {
Line 740  error information to the user. Line 888  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_options[]);
      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);
Line 748  error information to the user. Line 896  error information to the user.
      int (*log_stdin)(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_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);
        void (*register_hooks)(int version,
           int (*register_hook)(struct sudo_hook *hook));
        void (*deregister_hooks)(int version,
           int (*deregister_hook)(struct sudo_hook *hook));
  };   };
   
 When an I/O plugin is loaded, B<sudo> runs the command in a pseudo-tty.  When an I/O plugin is loaded, B<sudo> runs the command in a pseudo-tty.
Line 789  built against. Line 941  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_options[]);
   
 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
Line 873  When parsing I<user_env>, the plugin should split on t Line 1025  When parsing I<user_env>, the plugin should split on t
 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_options
   
   Any (non-comment) strings immediately after the plugin path are
   treated as arguments to the plugin.  These arguments are split on
   a white space 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_options> will be the NULL pointer.
   
   NOTE: the I<plugin_options> 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_options>.  Failure to
   do so may result in a crash.
   
 =back  =back
   
 =item close  =item close
Line 1040  The length of I<buf> in bytes. Line 1205  The length of I<buf> in bytes.
   
 =back  =back
   
   =item register_hooks
   
   See the L<Policy Plugin API> section for a description of
   C<register_hooks>.
   
   =item deregister_hooks
   
   See the L<Policy Plugin API> section for a description of
   C<deregister_hooks>.
   
 =back  =back
   
=head3 Version macros=head3 I/O Plugin Version Macros
   
 Same as for the L<Policy Plugin API>.  Same as for the L<Policy Plugin API>.
   
   =head2 Hook Function API
   
   Beginning with plugin API version 1.2, it is possible to install
   hooks for certain functions called by the B<sudo> front end.
   
   Currently, the only supported hooks relate to the handling of
   environment variables.  Hooks can be used to intercept attempts to
   get, set, or remove environment variables so that these changes can
   be reflected in the version of the environment that is used to
   execute a command.  A future version of the API will support
   hooking internal B<sudo> front end functions as well.
   
   =head3 Hook structure
   
   Hooks in B<sudo> are described by the following structure:
   
    typedef int (*sudo_hook_fn_t)();
   
    struct sudo_hook {
        int hook_version;
        int hook_type;
        sudo_hook_fn_t hook_fn;
        void *closure;
    };
   
   The C<sudo_hook> structure has the following fields:
   
   =over 4
   
   =item hook_version
   
   The C<hook_version> field should be set to SUDO_HOOK_VERSION.
   
   =item hook_type
   
   The C<hook_type> field may be one of the following supported hook types:
   
   =over 4
   
   =item SUDO_HOOK_SETENV
   
   The C library C<setenv()> function.  Any registered hooks will run
   before the C library implementation.  The C<hook_fn> field should
   be a function that matches the following typedef:
   
    typedef int (*sudo_hook_fn_setenv_t)(const char *name,
       const char *value, int overwrite, void *closure);
   
   If the registered hook does not match the typedef the results are
   unspecified.
   
   =item SUDO_HOOK_UNSETENV
   
   The C library C<unsetenv()> function.  Any registered hooks will run
   before the C library implementation.  The C<hook_fn> field should
   be a function that matches the following typedef:
   
    typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
       void *closure);
   
   =item SUDO_HOOK_GETENV
   
   The C library C<getenv()> function.  Any registered hooks will run
   before the C library implementation.  The C<hook_fn> field should
   be a function that matches the following typedef:
   
    typedef int (*sudo_hook_fn_getenv_t)(const char *name,
       char **value, void *closure);
   
   If the registered hook does not match the typedef the results are
   unspecified.
   
   =item SUDO_HOOK_PUTENV
   
   The C library C<putenv()> function.  Any registered hooks will run
   before the C library implementation.  The C<hook_fn> field should
   be a function that matches the following typedef:
   
    typedef int (*sudo_hook_fn_putenv_t)(char *string,
       void *closure);
   
   If the registered hook does not match the typedef the results are
   unspecified.
   
   =back
   
   =item hook_fn
   
    sudo_hook_fn_t hook_fn;
   
   The C<hook_fn> field should be set to the plugin's hook implementation.
   The actual function arguments will vary depending on the C<hook_type>
   (see C<hook_type> above).  In all cases, the C<closure> field of
   C<struct sudo_hook> is passed as the last function parameter.  This
   can be used to pass arbitrary data to the plugin's hook implementation.
   
   The function return value may be one of the following:
   
   =over 4
   
   =item SUDO_HOOK_RET_ERROR
   
   The hook function encountered an error.
   
   =item SUDO_HOOK_RET_NEXT
   
   The hook completed without error, go on to the next hook (including
   the native implementation if applicable).  For example, a C<getenv>
   hook might return C<SUDO_HOOK_RET_NEXT> if the specified variable
   was not found in the private copy of the environment.
   
   =item SUDO_HOOK_RET_STOP
   
   The hook completed without error, stop processing hooks for this
   invocation.  This can be used to replace the native implementation.
   For example, a C<setenv> hook that operates on a private copy of
   the environment but leaves C<environ> unchanged.
   
   =back
   
   =back
   
   Note that it is very easy to create an infinite loop when hooking
   C library functions.  For example, a C<getenv> hook that calls the
   C<snprintf> function may create a loop if the C<snprintf> implementation
   calls C<getenv> to check the locale.  To prevent this, you may wish
   to use a static variable in the hook function to guard against
   nested calls.  E.g.
   
    static int in_progress = 0; /* avoid recursion */
    if (in_progress)
        return SUDO_HOOK_RET_NEXT;
    in_progress = 1;
    ...
    in_progress = 0;
    return SUDO_HOOK_RET_STOP;
   
   =head3 Hook API Version Macros
   
    /* Hook API version major/minor */
    #define SUDO_HOOK_VERSION_MAJOR 1
    #define SUDO_HOOK_VERSION_MINOR 0
    #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y)
    #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\
                                                  SUDO_HOOK_VERSION_MINOR)
   
    /* Getters and setters for hook API version */
    #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16)
    #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff)
    #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \
        *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
    } while(0)
    #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \
        *(vp) = (*(vp) & 0xffff0000) | (n); \
    } while(0)
   
 =head2 Conversation API  =head2 Conversation API
   
 If the plugin needs to interact with the user, it may do so via the  If the plugin needs to interact with the user, it may do so via the
Line 1064  convenient for simple messages where no use input is r Line 1395  convenient for simple messages where no use input is r
  #define SUDO_CONV_ERROR_MSG        0x0003 /* error message */   #define SUDO_CONV_ERROR_MSG        0x0003 /* error message */
  #define SUDO_CONV_INFO_MSG         0x0004 /* informational message */   #define SUDO_CONV_INFO_MSG         0x0004 /* informational message */
  #define SUDO_CONV_PROMPT_MASK      0x0005 /* mask user input */   #define SUDO_CONV_PROMPT_MASK      0x0005 /* mask user input */
    #define SUDO_CONV_DEBUG_MSG        0x0006 /* debugging message */
  #define SUDO_CONV_PROMPT_ECHO_OK   0x1000 /* flag: allow echo if no tty */   #define SUDO_CONV_PROMPT_ECHO_OK   0x1000 /* flag: allow echo if no tty */
      int msg_type;       int msg_type;
      int timeout;       int timeout;
Line 1091  freeing the reply buffer filled in to the C<struct sud Line 1423  freeing the reply buffer filled in to the C<struct sud
 if any.  if any.
   
 The printf-style function uses the same underlying mechanism as the  The printf-style function uses the same underlying mechanism as the
conversation function but only supports C<SUDO_CONV_INFO_MSG> andconversation function but only supports C<SUDO_CONV_INFO_MSG>,
C<SUDO_CONV_ERROR_MSG> for the I<msg_type> parameter.  It can beC<SUDO_CONV_ERROR_MSG> and C<SUDO_CONV_DEBUG_MSG> for the I<msg_type>
more convenient than using the conversation function if no userparameter.  It can be more convenient than using the conversation
reply is needed and supports standard printf() escape sequences.function if no user reply is needed and supports standard printf()
 escape sequences.
   
   Unlike, C<SUDO_CONV_INFO_MSG> and C<SUDO_CONV_ERROR_MSG>, messages
   sent with the <SUDO_CONV_DEBUG_MSG> I<msg_type> are not directly
   user-visible.  Instead, they are logged to the file specified in
   the C<Debug> statement (if any) in the F<@sysconfdir@/sudo.conf>
   file.  This allows a plugin to log debugging information and is
   intended to be used in conjunction with the I<debug_flags> setting.
   
 See the sample plugin for an example of the conversation function usage.  See the sample plugin for an example of the conversation function usage.
   
 =head2 Sudoers Group Plugin API  =head2 Sudoers Group Plugin API
Line 1204  present in the password database, I<pwd> will be C<NUL Line 1544  present in the password database, I<pwd> will be C<NUL
   
 =back  =back
   
=head3 Version Macros=head3 Group API Version Macros
   
  /* Sudoers group plugin version major/minor */   /* Sudoers group plugin version major/minor */
  #define GROUP_API_VERSION_MAJOR 1   #define GROUP_API_VERSION_MAJOR 1
Line 1221  present in the password database, I<pwd> will be C<NUL Line 1561  present in the password database, I<pwd> will be C<NUL
  #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \   #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \
      *(vp) = (*(vp) & 0xffff0000) | (n); \       *(vp) = (*(vp) & 0xffff0000) | (n); \
  } while(0)   } while(0)
   
   =head1 PLUGIN API CHANGELOG
   
   The following revisions have been made to the Sudo Plugin API.
   
   =over 4
   
   =item Version 1.0
   
   Initial API version.
   
   =item Version 1.1
   
   The I/O logging plugin's C<open> function was modified to take the
   C<command_info> list as an argument.
   
   =item Version 1.2
   
   The Policy and I/O logging plugins' C<open> functions are now passed
   a list of plugin options if any are specified in F<@sysconfdir@/sudo.conf>.
   
   A simple hooks API has been introduced to allow plugins to hook in to the
   system's environment handling functions.
   
   The C<init_session> Policy plugin function is now passed a pointer
   to the user environment which can be updated as needed.  This can
   be used to merge in environment variables stored in the PAM handle
   before a command is run.
   
   =back
   
   
 =head1 SEE ALSO  =head1 SEE ALSO
   

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>