]> git.gag.com Git - debian/sudo/blobdiff - doc/sudo_plugin.pod
Merge tag 'debian/1.8.5p2-1' into squeeze
[debian/sudo] / doc / sudo_plugin.pod
diff --git a/doc/sudo_plugin.pod b/doc/sudo_plugin.pod
new file mode 100644 (file)
index 0000000..d24de9d
--- /dev/null
@@ -0,0 +1,1617 @@
+Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=pod
+
+=head1 NAME
+
+sudo_plugin - Sudo Plugin API
+
+=head1 DESCRIPTION
+
+Starting with version 1.8, B<sudo> supports a plugin API
+for policy and session logging.  By default, the I<sudoers> policy
+plugin and an associated I/O logging plugin are used.  Via the plugin
+API, B<sudo> can be configured to use alternate policy and/or I/O
+logging plugins provided by third parties.  The plugins to be used
+are specified via the F<@sysconfdir@/sudo.conf> file.
+
+The API is versioned with a major and minor number.  The minor
+version number is incremented when additions are made.  The major
+number is incremented when incompatible changes are made.  A plugin
+should be check the version passed to it and make sure that the
+major version matches.
+
+The plugin API is defined by the C<sudo_plugin.h> header file.
+
+=head2 The sudo.conf File
+
+The F<@sysconfdir@/sudo.conf> file contains plugin configuration directives.
+Currently, the only supported keyword is the C<Plugin> directive,
+which causes a plugin plugin to be loaded.
+
+A C<Plugin> line consists of the C<Plugin> keyword, followed by the
+I<symbol_name> and the I<path> to the shared object containing the
+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 passed as options 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
+0 and only writable by its owner.  Because of ambiguities that arise
+from composite policies, only a single policy plugin may be specified.
+This limitation does not apply to I/O plugins.
+
+ #
+ # Default @sysconfdir@/sudo.conf file
+ #
+ # Format:
+ #   Plugin plugin_name plugin_path plugin_options ...
+ #   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
+ #   fully qualified.
+ # The plugin_name corresponds to a global symbol in the plugin
+ #   that contains the plugin interface structure.
+ # The plugin_options are optional.
+ #
+ Plugin sudoers_policy sudoers.so
+ Plugin sudoers_io sudoers.so
+
+=head2 Policy Plugin API
+
+A policy plugin must declare and populate a C<policy_plugin> struct
+in the global scope.  This structure contains pointers to the functions
+that implement the B<sudo> policy checks.  The name of the symbol should
+be specified in F<@sysconfdir@/sudo.conf> along with a path to the plugin
+so that B<sudo> can load it.
+
+ struct policy_plugin {
+ #define SUDO_POLICY_PLUGIN    1
+     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[],
+                 char * const plugin_options[]);
+     void (*close)(int exit_status, int 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, 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:
+
+=over 4
+
+=item type
+
+The C<type> field should always be set to SUDO_POLICY_PLUGIN.
+
+=item version
+
+The C<version> field should be set to SUDO_API_VERSION.
+
+This allows B<sudo> to determine the API version the plugin was
+built against.
+
+=item open
+
+ 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 plugin_options[]);
+
+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
+print a usage message before it exits.  If an error occurs, the
+plugin may optionally call the conversation or plugin_printf function
+with C<SUDO_CONF_ERROR_MSG> to present additional error information
+to the user.
+
+The function arguments are as follows:
+
+=over 4
+
+=item version
+
+The version passed in by B<sudo> allows the plugin to determine the
+major and minor version number of the plugin API supported by
+B<sudo>.
+
+=item conversation
+
+A pointer to the conversation function that can be used by the
+plugin to interact with the user (see below).
+Returns 0 on success and -1 on failure.
+
+=item plugin_printf
+
+A pointer to a printf-style function that may be used to display
+informational or error messages (see below).
+Returns the number of characters printed on success and -1 on failure.
+
+=item settings
+
+A vector of user-supplied B<sudo> settings in the form of "name=value"
+strings.  The vector is terminated by a C<NULL> pointer.  These
+settings correspond to flags the user specified when running B<sudo>.
+As such, they will only be present when the corresponding flag has
+been specified on the command line.
+
+When parsing I<settings>, 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.
+
+=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
+
+This setting has been deprecated in favor of I<debug_flags>.
+
+=item runas_user=string
+
+The user name or uid to to run the command as, if specified via the
+C<-u> flag.
+
+=item runas_group=string
+
+The group name or gid to to run the command as, if specified via
+the C<-g> flag.
+
+=item prompt=string
+
+The prompt to use when requesting a password, if specified via
+the C<-p> flag.
+
+=item set_home=bool
+
+Set to true if the user specified the C<-H> flag.  If true, set the
+C<HOME> environment variable to the target user's home directory.
+
+=item preserve_environment=bool
+
+Set to true if the user specified the C<-E> flag, indicating that
+the user wishes to preserve the environment.
+
+=item run_shell=bool
+
+Set to true if the user specified the C<-s> flag, indicating that
+the user wishes to run a shell.
+
+=item login_shell=bool
+
+Set to true if the user specified the C<-i> flag, indicating that
+the user wishes to run a login shell.
+
+=item implied_shell=bool
+
+If the user does not specify a program on the command line, B<sudo>
+will pass the plugin the path to the user's shell and set
+I<implied_shell> to true.  This allows B<sudo> with no arguments
+to be used similarly to L<su(1)>.  If the plugin does not to support
+this usage, it may return a value of -2 from the C<check_policy>
+function, which will cause B<sudo> to print a usage message and
+exit.
+
+=item preserve_groups=bool
+
+Set to true if the user specified the C<-P> flag, indicating that
+the user wishes to preserve the group vector instead of setting it
+based on the runas user.
+
+=item ignore_ticket=bool
+
+Set to true if the user specified the C<-k> flag along with a
+command, indicating that the user wishes to ignore any cached
+authentication credentials.
+
+=item noninteractive=bool
+
+Set to true if the user specified the C<-n> flag, indicating that
+B<sudo> should operate in non-interactive mode.  The plugin may
+reject a command run in non-interactive mode if user interaction
+is required.
+
+=item login_class=string
+
+BSD login class to use when setting resource limits and nice value,
+if specified by the C<-c> flag.
+
+=item selinux_role=string
+
+SELinux role to use when executing the command, if specified by
+the C<-r> flag.
+
+=item selinux_type=string
+
+SELinux type to use when executing the command, if specified by
+the C<-t> flag.
+
+=item bsdauth_type=string
+
+Authentication type, if specified by the C<-a> flag, to use on
+systems where BSD authentication is supported.
+
+=item network_addrs=list
+
+A space-separated list of IP network addresses and netmasks in the
+form "addr/netmask", e.g. "192.168.1.2/255.255.255.0".  The address
+and netmask pairs may be either IPv4 or IPv6, depending on what the
+operating system supports.  If the address contains a colon (':'),
+it is an IPv6 address, else it is IPv4.
+
+=item progname=string
+
+The command name that sudo was run as, typically "sudo" or "sudoedit".
+
+=item sudoedit=bool
+
+Set to true when the C<-e> flag is is specified or if invoked as
+B<sudoedit>.  The plugin shall substitute an editor into I<argv>
+in the I<check_policy> function or return C<-2> with a usage error
+if the plugin does not support I<sudoedit>.  For more information,
+see the I<check_policy> section.
+
+=item closefrom=number
+
+If specified, the user has requested via the C<-C> flag that B<sudo>
+close all files descriptors with a value of I<number> or higher.
+The plugin may optionally pass this, or another value, back in the
+I<command_info> list.
+
+=back
+
+Additional settings may be added in the future so the plugin should
+silently ignore settings that it does not recognize.
+
+=item user_info
+
+A vector of information about the user running the command in the form of
+"name=value" strings.  The vector is terminated by a C<NULL> pointer.
+
+When parsing I<user_info>, 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.
+
+=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
+
+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
+
+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
+
+The real group ID of the user invoking B<sudo>.
+
+=item groups=list
+
+The user's supplementary group list formatted as a string of
+comma-separated group IDs.
+
+=item cwd=string
+
+The user's current working directory.
+
+=item tty=string
+
+The path to the user's terminal device.  If the user has no terminal
+device associated with the session, the value will be empty, as in
+C<tty=>.
+
+=item host=string
+
+The local machine's hostname as returned by the C<gethostname()>
+system call.
+
+=item lines=int
+
+The number of lines the user's terminal supports.  If there is
+no terminal device available, a default value of 24 is used.
+
+=item cols=int
+
+The number of columns the user's terminal supports.  If there is
+no terminal device available, a default value of 80 is used.
+
+=back
+
+=item user_env
+
+The user's environment in the form of a C<NULL>-terminated vector of
+"name=value" strings.
+
+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_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
+
+=item close
+
+ void (*close)(int exit_status, int error);
+
+The C<close> function is called when the command being run by B<sudo>
+finishes.
+
+The function arguments are as follows:
+
+=over 4
+
+=item exit_status
+
+The command's exit status, as returned by the wait(2) system call.
+The value of C<exit_status> is undefined if C<error> is non-zero.
+
+=item error
+
+If the command could not be executed, this is set to the value of
+C<errno> set by the execve(2) system call.  The plugin is responsible
+for displaying error information via the conversation or plugin_printf
+function.  If the command was successfully executed, the value of
+C<error> is 0.
+
+=back
+
+=item show_version
+
+ int (*show_version)(int verbose);
+
+The C<show_version> function is called by B<sudo> when the user specifies
+the C<-V> option.  The plugin may display its version information
+to the user via the conversation or plugin_printf function using
+C<SUDO_CONV_INFO_MSG>.  If the user requests detailed version
+information, the verbose flag will be set.
+
+=item check_policy
+
+ int (*check_policy)(int argc, char * const argv[]
+                     char *env_add[], char **command_info[],
+                     char **argv_out[], char **user_env_out[]);
+
+The I<check_policy> function is called by B<sudo> to determine
+whether the user is allowed to run the specified commands.
+
+If the I<sudoedit> option was enabled in the I<settings> array
+passed to the I<open> function, the user has requested I<sudoedit>
+mode.  I<sudoedit> is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges.  B<sudo> achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete.  If
+the plugin supports B<sudoedit>, it should choose the editor to be
+used, potentially from a variable in the user's environment, such
+as C<EDITOR>, and include it in I<argv_out> (note that environment
+variables may include command line flags).  The files to be edited
+should be copied from I<argv> into I<argv_out>, separated from the
+editor and its arguments by a C<"--"> element.  The C<"--"> will
+be removed by B<sudo> before the editor is executed.  The plugin
+should also set I<sudoedit=true> in the I<command_info> list.
+
+The I<check_policy> function returns 1 if the command is allowed,
+0 if not allowed, -1 for a general error, or -2 for a usage error
+or if B<sudoedit> was specified but is unsupported by the plugin.
+In the latter case, B<sudo> will print a usage message before it
+exits.  If an error occurs, the plugin may optionally call the
+conversation or plugin_printf function with C<SUDO_CONF_ERROR_MSG>
+to present additional error information to the user.
+
+The function arguments are as follows:
+
+=over 4
+
+=item argc
+
+The number of elements in I<argv>, not counting the final C<NULL>
+pointer.
+
+=item argv
+
+The argument vector describing the command the user wishes to run,
+in the same form as what would be passed to the execve() system
+call.  The vector is terminated by a C<NULL> pointer.
+
+=item env_add
+
+Additional environment variables specified by the user on the command
+line in the form of a C<NULL>-terminated vector of "name=value"
+strings.  The plugin may reject the command if one or more variables
+are not allowed to be set, or it may silently ignore such variables.
+
+When parsing I<env_add>, 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 command_info
+
+Information about the command being run in the form of "name=value"
+strings.  These values are used by B<sudo> to set the execution
+environment when running a command.  The plugin is responsible for
+creating and populating the vector, which must be terminated with
+a C<NULL> pointer.  The following values are recognized by B<sudo>:
+
+=over 4
+
+=item command=string
+
+Fully qualified path to the command to be executed.
+
+=item runas_uid=uid
+
+User ID to run the command as.
+
+=item runas_euid=uid
+
+Effective user ID to run the command as.
+If not specified, the value of I<runas_uid> is used.
+
+=item runas_gid=gid
+
+Group ID to run the command as.
+
+=item runas_egid=gid
+
+Effective group ID to run the command as.
+If not specified, the value of I<runas_gid> is used.
+
+=item runas_groups=list
+
+The supplementary group vector to use for the command in the form
+of a comma-separated list of group IDs.  If I<preserve_groups>
+is set, this option is ignored.
+
+=item login_class=string
+
+BSD login class to use when setting resource limits and nice value
+(optional).  This option is only set on systems that support login
+classes.
+
+=item preserve_groups=bool
+
+If set, B<sudo> will preserve the user's group vector instead of
+initializing the group vector based on C<runas_user>.
+
+=item cwd=string
+
+The current working directory to change to when executing the command.
+
+=item noexec=bool
+
+If set, prevent the command from executing other programs.
+
+=item chroot=string
+
+The root directory to use when running the command.
+
+=item nice=int
+
+Nice value (priority) to use when executing the command.  The nice
+value, if specified, overrides the priority associated with the
+I<login_class> on BSD systems.
+
+=item umask=octal
+
+The file creation mask to use when executing the command.
+
+=item selinux_role=string
+
+SELinux role to use when executing the command.
+
+=item selinux_type=string
+
+SELinux type to use when executing the command.
+
+=item timeout=int
+
+Command timeout.  If non-zero then when the timeout expires the
+command will be killed.
+
+=item sudoedit=bool
+
+Set to true when in I<sudoedit> mode.  The plugin may enable
+I<sudoedit> mode even if B<sudo> was not invoked as B<sudoedit>.
+This allows the plugin to perform command substitution and transparently
+enable I<sudoedit> when the user attempts to run an editor.
+
+=item closefrom=number
+
+If specified, B<sudo> will close all files descriptors with a value
+of I<number> or higher.
+
+=item iolog_compress=bool
+
+Set to true if the I/O logging plugins, if any, should compress the
+log data.  This is a hint to the I/O logging plugin which may choose
+to ignore it.
+
+=item iolog_path=string
+
+Fully qualified path to the file or directory in which I/O log is
+to be stored.  This is a hint to the I/O logging plugin which may
+choose to ignore it.  If no I/O logging plugin is loaded, this
+setting has no effect.
+
+=item iolog_stdin=bool
+
+Set to true if the I/O logging plugins, if any, should log the
+standard input if it is not connected to a terminal device.  This
+is a hint to the I/O logging plugin which may choose to ignore it.
+
+=item iolog_stdout=bool
+
+Set to true if the I/O logging plugins, if any, should log the
+standard output if it is not connected to a terminal device.  This
+is a hint to the I/O logging plugin which may choose to ignore it.
+
+=item iolog_stderr=bool
+
+Set to true if the I/O logging plugins, if any, should log the
+standard error if it is not connected to a terminal device.  This
+is a hint to the I/O logging plugin which may choose to ignore it.
+
+=item iolog_ttyin=bool
+
+Set to true if the I/O logging plugins, if any, should log all
+terminal input.  This only includes input typed by the user and not
+from a pipe or redirected from a file.  This is a hint to the I/O
+logging plugin which may choose to ignore it.
+
+=item iolog_ttyout=bool
+
+Set to true if the I/O logging plugins, if any, should log all
+terminal output.  This only includes output to the screen, not
+output to a pipe or file.  This is a hint to the I/O logging plugin
+which may choose to ignore it.
+
+=item use_pty=bool
+
+Allocate a pseudo-tty to run the command in, regardless of whether
+or not I/O logging is in use.  By default, B<sudo> will only run
+the command in a pty when an I/O log plugin is loaded.
+
+=item set_utmp=bool
+
+Create a utmp (or utmpx) entry when a pseudo-tty is allocated.  By
+default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type and pid fields updated.
+
+=item utmp_user=string
+
+User name to use when constructing a new utmp (or utmpx) entry when
+I<set_utmp> is enabled.  This option can be used to set the user
+field in the utmp entry to the user the command runs as rather than
+the invoking user.  If not set, B<sudo> will base the new entry on
+the invoking user's existing entry.
+
+=back
+
+Unsupported values will be ignored.
+
+=item argv_out
+
+The C<NULL>-terminated argument vector to pass to the execve()
+system call when executing the command.  The plugin is responsible
+for allocating and populating the vector.
+
+=item user_env_out
+
+The C<NULL>-terminated environment vector to use when executing the
+command.  The plugin is responsible for allocating and populating
+the vector.
+
+=back
+
+=item list
+
+ int (*list)(int verbose, const char *list_user,
+             int argc, char * const argv[]);
+
+List available privileges for the invoking user.  Returns 1 on
+success, 0 on failure and -1 on error.  On error, the plugin may
+optionally call the conversation or plugin_printf function with
+C<SUDO_CONF_ERROR_MSG> to present additional error information to
+the user.
+
+Privileges should be output via the conversation or plugin_printf
+function using C<SUDO_CONV_INFO_MSG>.
+
+=over 4
+
+=item verbose
+
+Flag indicating whether to list in verbose mode or not.
+
+=item list_user
+
+The name of a different user to list privileges for if the policy
+allows it.  If C<NULL>, the plugin should list the privileges of
+the invoking user.
+
+=item argc
+
+The number of elements in I<argv>, not counting the final C<NULL>
+pointer.
+
+=item argv
+
+If non-C<NULL>, an argument vector describing a command the user
+wishes to check against the policy in the same form as what would
+be passed to the execve() system call.  If the command is permitted
+by the policy, the fully-qualified path to the command should be
+displayed along with any command line arguments.
+
+=back
+
+=item validate
+
+ int (*validate)(void);
+
+The C<validate> function is called when B<sudo> is run with the
+C<-v> flag.  For policy plugins such as I<sudoers> that cache
+authentication credentials, this function will validate and cache
+the credentials.
+
+The C<validate> function should be C<NULL> if the plugin does not
+support credential caching.
+
+Returns 1 on success, 0 on failure and -1 on error.
+On error, the plugin may optionally call the conversation or plugin_printf
+function with C<SUDO_CONF_ERROR_MSG> to present additional
+error information to the user.
+
+=item invalidate
+
+ void (*invalidate)(int remove);
+
+The C<invalidate> function is called when B<sudo> is called with
+the C<-k> or C<-K> flag.  For policy plugins such as I<sudoers> that
+cache authentication credentials, this function will invalidate the
+credentials.  If the I<remove> flag is set, the plugin may remove
+the credentials instead of simply invalidating them.
+
+The C<invalidate> function should be C<NULL> if the plugin does not
+support credential caching.
+
+=item init_session
+
+ int (*init_session)(struct passwd *pwd, char **user_envp[);
+
+The C<init_session> function is called before B<sudo> sets up the
+execution environment for the command.  It is run in the parent
+B<sudo> process and before any uid or gid changes.  This can be used
+to perform session setup that is not supported by I<command_info>,
+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
+command will be run as if the uid the command will run as was found
+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.
+On error, the plugin may optionally call the conversation or plugin_printf
+function with C<SUDO_CONF_ERROR_MSG> to present additional
+error information to the user.
+
+=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
+
+=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_MINOR(v) ((v) & 0xffff)
+ #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
+     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
+ } while(0)
+ #define SUDO_VERSION_SET_MINOR(vp, n) do { \
+     *(vp) = (*(vp) & 0xffff0000) | (n); \
+ } while(0)
+
+=head2 I/O Plugin API
+
+ struct io_plugin {
+ #define SUDO_IO_PLUGIN                2
+     unsigned int type; /* always SUDO_IO_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[], int argc, char * const argv[],
+                 char * const user_env[], char * const plugin_options[]);
+     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);
+     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.
+This makes it possible to log the input and output from the user's
+session.  If any of the standard input, standard output or standard
+error do not correspond to a tty, B<sudo> will open a pipe to capture
+the I/O for logging before passing it on.
+
+The log_ttyin function receives the raw user input from the terminal
+device (note that this will include input even when echo is disabled,
+such as when a password is read). The log_ttyout function receives
+output from the pseudo-tty that is suitable for replaying the user's
+session at a later time.  The log_stdin, log_stdout and log_stderr
+functions are only called if the standard input, standard output
+or standard error respectively correspond to something other than
+a tty.
+
+Any of the logging functions may be set to the NULL
+pointer if no logging is to be performed.  If the open function
+returns C<0>, no I/O will be sent to the plugin.
+
+The io_plugin struct has the following fields:
+
+=over 4
+
+=item type
+
+The C<type> field should always be set to SUDO_IO_PLUGIN
+
+=item version
+
+The C<version> field should be set to SUDO_API_VERSION.
+
+This allows B<sudo> to determine the API version the plugin was
+built against.
+
+=item open
+
+ 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 plugin_options[]);
+
+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
+version is being requested or the I<check_policy> function has
+returned successfully.  It 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 print a usage message before it exits.
+If an error occurs, the plugin may optionally call the conversation
+or plugin_printf function with C<SUDO_CONF_ERROR_MSG> to present
+additional error information to the user.
+
+The function arguments are as follows:
+
+=over 4
+
+=item version
+
+The version passed in by B<sudo> allows the plugin to determine the
+major and minor version number of the plugin API supported by
+B<sudo>.
+
+=item conversation
+
+A pointer to the conversation function that may be used by the
+I<show_version> function to display version information (see
+show_version below).  The conversation function may also be used
+to display additional error message to the user.
+The conversation function returns 0 on success and -1 on failure.
+
+=item plugin_printf
+
+A pointer to a printf-style function that may be used by the
+I<show_version> function to display version information (see
+show_version below).  The plugin_printf function may also be used
+to display additional error message to the user.
+The plugin_printf function returns number of characters printed on
+success and -1 on failure.
+
+=item settings
+
+A vector of user-supplied B<sudo> settings in the form of "name=value"
+strings.  The vector is terminated by a C<NULL> pointer.  These
+settings correspond to flags the user specified when running B<sudo>.
+As such, they will only be present when the corresponding flag has
+been specified on the command line.
+
+When parsing I<settings>, 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.
+
+See the L<Policy Plugin API> section for a list of all possible settings.
+
+=item user_info
+
+A vector of information about the user running the command in the form of
+"name=value" strings.  The vector is terminated by a C<NULL> pointer.
+
+When parsing I<user_info>, 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.
+
+See the L<Policy Plugin API> section for a list of all possible strings.
+
+=item argc
+
+The number of elements in I<argv>, not counting the final C<NULL>
+pointer.
+
+=item argv
+
+If non-C<NULL>, an argument vector describing a command the user
+wishes to run in the same form as what would be passed to the
+execve() system call.
+
+=item user_env
+
+The user's environment in the form of a C<NULL>-terminated vector of
+"name=value" strings.
+
+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_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
+
+=item close
+
+ void (*close)(int exit_status, int error);
+
+The C<close> function is called when the command being run by B<sudo>
+finishes.
+
+The function arguments are as follows:
+
+=over 4
+
+=item exit_status
+
+The command's exit status, as returned by the wait(2) system call.
+The value of C<exit_status> is undefined if C<error> is non-zero.
+
+=item error
+
+If the command could not be executed, this is set to the value of
+C<errno> set by the execve(2) system call.  If the command was
+successfully executed, the value of C<error> is 0.
+
+=back
+
+=item show_version
+
+ int (*show_version)(int verbose);
+
+The C<show_version> function is called by B<sudo> when the user specifies
+the C<-V> option.  The plugin may display its version information
+to the user via the conversation or plugin_printf function using
+C<SUDO_CONV_INFO_MSG>.  If the user requests detailed version
+information, the verbose flag will be set.
+
+=item log_ttyin
+
+ int (*log_ttyin)(const char *buf, unsigned int len);
+
+The I<log_ttyin> function is called whenever data can be read from
+the user but before it is passed to the running command.  This
+allows the plugin to reject data if it chooses to (for instance
+if the input contains banned content).  Returns C<1> if the data
+should be passed to the command, C<0> if the data is rejected
+(which will terminate the command) or C<-1> if an error occurred.
+
+The function arguments are as follows:
+
+=over 4
+
+=item buf
+
+The buffer containing user input.
+
+=item len
+
+The length of I<buf> in bytes.
+
+=back
+
+=item log_ttyout
+
+ int (*log_ttyout)(const char *buf, unsigned int len);
+
+The I<log_ttyout> function is called whenever data can be read from
+the command but before it is written to the user's terminal.  This
+allows the plugin to reject data if it chooses to (for instance
+if the output contains banned content).  Returns C<1> if the data
+should be passed to the user, C<0> if the data is rejected
+(which will terminate the command) or C<-1> if an error occurred.
+
+The function arguments are as follows:
+
+=over 4
+
+=item buf
+
+The buffer containing command output.
+
+=item len
+
+The length of I<buf> in bytes.
+
+=back
+
+=item log_stdin
+
+ int (*log_stdin)(const char *buf, unsigned int len);
+
+The I<log_stdin> function is only used if the standard input does
+not correspond to a tty device.  It is called whenever data can be
+read from the standard input but before it is passed to the running
+command.  This allows the plugin to reject data if it chooses to
+(for instance if the input contains banned content).  Returns C<1>
+if the data should be passed to the command, C<0> if the data is
+rejected (which will terminate the command) or C<-1> if an error
+occurred.
+
+The function arguments are as follows:
+
+=over 4
+
+=item buf
+
+The buffer containing user input.
+
+=item len
+
+The length of I<buf> in bytes.
+
+=back
+
+=item log_stdout
+
+ int (*log_stdout)(const char *buf, unsigned int len);
+
+The I<log_stdout> function is only used if the standard output does
+not correspond to a tty device.  It is called whenever data can be
+read from the command but before it is written to the standard
+output.  This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).  Returns C<1>
+if the data should be passed to the user, C<0> if the data is
+rejected (which will terminate the command) or C<-1> if an error
+occurred.
+
+The function arguments are as follows:
+
+=over 4
+
+=item buf
+
+The buffer containing command output.
+
+=item len
+
+The length of I<buf> in bytes.
+
+=back
+
+=item log_stderr
+
+ int (*log_stderr)(const char *buf, unsigned int len);
+
+The I<log_stderr> function is only used if the standard error does
+not correspond to a tty device.  It is called whenever data can be
+read from the command but before it is written to the standard
+error.  This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).  Returns C<1>
+if the data should be passed to the user, C<0> if the data is
+rejected (which will terminate the command) or C<-1> if an error
+occurred.
+
+The function arguments are as follows:
+
+=over 4
+
+=item buf
+
+The buffer containing command output.
+
+=item len
+
+The length of I<buf> in bytes.
+
+=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
+
+=head3 I/O Plugin Version Macros
+
+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
+
+If the plugin needs to interact with the user, it may do so via the
+conversation function.  A plugin should not attempt to read directly
+from the standard input or the user's tty (neither of which are
+guaranteed to exist).  The caller must include a trailing newline
+in C<msg> if one is to be printed.
+
+A printf-style function is also available that can be used to display
+informational or error messages to the user, which is usually more
+convenient for simple messages where no use input is required.
+
+ struct sudo_conv_message {
+ #define SUDO_CONV_PROMPT_ECHO_OFF  0x0001 /* do not echo user input */
+ #define SUDO_CONV_PROMPT_ECHO_ON   0x0002 /* echo user input */
+ #define SUDO_CONV_ERROR_MSG       0x0003 /* error message */
+ #define SUDO_CONV_INFO_MSG        0x0004 /* informational message */
+ #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 */
+     int msg_type;
+     int timeout;
+     const char *msg;
+ };
+
+ struct sudo_conv_reply {
+     char *reply;
+ };
+
+ typedef int (*sudo_conv_t)(int num_msgs,
+             const struct sudo_conv_message msgs[],
+              struct sudo_conv_reply replies[]);
+
+ typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
+
+Pointers to the conversation and printf-style functions are passed
+in to the plugin's C<open> function when the plugin is initialized.
+
+To use the conversation function, the plugin must pass an array of
+C<sudo_conv_message> and C<sudo_conv_reply> structures.  There must
+be a C<struct sudo_conv_message> and C<struct sudo_conv_reply> for
+each message in the conversation.  The plugin is responsible for
+freeing the reply buffer filled in to the C<struct sudo_conv_reply>,
+if any.
+
+The printf-style function uses the same underlying mechanism as the
+conversation function but only supports C<SUDO_CONV_INFO_MSG>,
+C<SUDO_CONV_ERROR_MSG> and C<SUDO_CONV_DEBUG_MSG> for the I<msg_type>
+parameter.  It can be more convenient than using the conversation
+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.
+
+=head2 Sudoers Group Plugin API
+
+The I<sudoers> module supports a plugin interface to allow non-Unix
+group lookups.  This can be used to query a group source other than
+the standard Unix group database.  A sample group plugin is bundled
+with B<sudo> that implements file-based lookups.  Third party group
+plugins include a QAS AD plugin available from Quest Software.
+
+A group plugin must declare and populate a C<sudoers_group_plugin>
+struct in the global scope.  This structure contains pointers to
+the functions that implement plugin initialization, cleanup and
+group lookup.
+
+ struct sudoers_group_plugin {
+    unsigned int version;
+    int (*init)(int version, sudo_printf_t sudo_printf,
+                char *const argv[]);
+    void (*cleanup)(void);
+    int (*query)(const char *user, const char *group,
+                 const struct passwd *pwd);
+};
+
+The C<sudoers_group_plugin> struct has the following fields:
+
+=over 4
+
+=item version
+
+The C<version> field should be set to GROUP_API_VERSION.
+
+This allows I<sudoers> to determine the API version the group plugin
+was built against.
+
+=item init
+
+ int (*init)(int version, sudo_printf_t plugin_printf,
+             char *const argv[]);
+
+The I<init> function is called after I<sudoers> has been parsed but
+before any policy checks.  It returns 1 on success, 0 on failure
+(or if the plugin is not configured), and -1 if a error occurred.
+If an error occurs, the plugin may call the plugin_printf function
+with C<SUDO_CONF_ERROR_MSG> to present additional error information
+to the user.
+
+The function arguments are as follows:
+
+=over 4
+
+=item version
+
+The version passed in by I<sudoers> allows the plugin to determine the
+major and minor version number of the group plugin API supported by
+I<sudoers>.
+
+=item plugin_printf
+
+A pointer to a printf-style function that may be used to display
+informational or error message to the user.
+Returns the number of characters printed on success and -1 on failure.
+
+=item argv
+
+A NULL-terminated array of arguments generated from the I<group_plugin>
+option in I<sudoers>.  If no arguments were given, I<argv> will be
+NULL.
+
+=back
+
+=item cleanup
+
+ void (*cleanup)();
+
+The I<cleanup> function is called when I<sudoers> has finished its
+group checks.  The plugin should free any memory it has allocated
+and close open file handles.
+
+=item query
+
+ int (*query)(const char *user, const char *group,
+              const struct passwd *pwd);
+
+The I<query> function is used to ask the group plugin whether I<user>
+is a member of I<group>.
+
+The function arguments are as follows:
+
+=over 4
+
+=item user
+
+The name of the user being looked up in the external group database.
+
+=item group
+
+The name of the group being queried.
+
+=item pwd
+
+The password database entry for I<user>, if any.  If I<user> is not
+present in the password database, I<pwd> will be C<NULL>.
+
+=back
+
+=back
+
+=head3 Group API Version Macros
+
+ /* Sudoers group plugin version major/minor */
+ #define GROUP_API_VERSION_MAJOR 1
+ #define GROUP_API_VERSION_MINOR 0
+ #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \
+                            GROUP_API_VERSION_MINOR)
+
+ /* Getters and setters for group version */
+ #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+ #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+ #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \
+     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
+ } while(0)
+ #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \
+     *(vp) = (*(vp) & 0xffff0000) | (n); \
+ } 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
+
+L<sudoers(5)>, L<sudo(8)>
+
+=head1 BUGS
+
+If you feel you have found a bug in B<sudo>, please submit a bug report
+at http://www.sudo.ws/sudo/bugs/
+
+=head1 SUPPORT
+
+Limited free support is available via the sudo-workers mailing list,
+see http://www.sudo.ws/mailman/listinfo/sudo-workers to subscribe or
+search the archives.
+
+=head1 DISCLAIMER
+
+B<sudo> is provided ``AS IS'' and any express or implied warranties,
+including, but not limited to, the implied warranties of merchantability
+and fitness for a particular purpose are disclaimed.  See the LICENSE
+file distributed with B<sudo> or http://www.sudo.ws/sudo/license.html
+for complete details.