Annotation of embedaddon/sudo/doc/sudo_plugin.pod, revision 1.1

1.1     ! misho       1: Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com>
        !             2: 
        !             3: Permission to use, copy, modify, and distribute this software for any
        !             4: purpose with or without fee is hereby granted, provided that the above
        !             5: copyright notice and this permission notice appear in all copies.
        !             6: 
        !             7: THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !             8: WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !             9: MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            10: ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            11: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            12: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            13: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            14: ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            15: 
        !            16: =pod
        !            17: 
        !            18: =head1 NAME
        !            19: 
        !            20: sudo_plugin - Sudo Plugin API
        !            21: 
        !            22: =head1 DESCRIPTION
        !            23: 
        !            24: Starting with version 1.8, B<sudo> supports a plugin API
        !            25: for policy and session logging.  By default, the I<sudoers> policy
        !            26: plugin and an associated I/O logging plugin are used.  Via the plugin
        !            27: API, B<sudo> can be configured to use alternate policy and/or I/O
        !            28: logging plugins provided by third parties.  The plugins to be used
        !            29: are specified via the F<@sysconfdir@/sudo.conf> file.
        !            30: 
        !            31: The API is versioned with a major and minor number.  The minor
        !            32: version number is incremented when additions are made.  The major
        !            33: number is incremented when incompatible changes are made.  A plugin
        !            34: should be check the version passed to it and make sure that the
        !            35: major version matches.
        !            36: 
        !            37: The plugin API is defined by the C<sudo_plugin.h> header file.
        !            38: 
        !            39: =head2 The sudo.conf File
        !            40: 
        !            41: The F<@sysconfdir@/sudo.conf> file contains plugin configuration directives.
        !            42: Currently, the only supported keyword is the C<Plugin> directive,
        !            43: which causes a plugin plugin to be loaded.
        !            44: 
        !            45: A C<Plugin> line consists of the C<Plugin> keyword, followed by the
        !            46: I<symbol_name> and the I<path> to the shared object containing the
        !            47: plugin.  The I<symbol_name> is the name of the C<struct policy_plugin>
        !            48: or C<struct io_plugin> in the plugin shared object.  The I<path>
        !            49: may be fully qualified or relative.  If not fully qualified it is
        !            50: relative to the F<@prefix@/libexec> directory.  Any additional
        !            51: parameters after the I<path> are ignored.  Lines that don't begin
        !            52: with C<Plugin> or C<Path> are silently ignored.
        !            53: 
        !            54: The same shared object may contain multiple plugins, each with a
        !            55: different symbol name.  The shared object file must be owned by uid
        !            56: 0 and only writable by its owner.  Because of ambiguities that arise
        !            57: from composite policies, only a single policy plugin may be specified.
        !            58: This limitation does not apply to I/O plugins.
        !            59: 
        !            60:  #
        !            61:  # Default @sysconfdir@/sudo.conf file
        !            62:  #
        !            63:  # Format:
        !            64:  #   Plugin plugin_name plugin_path
        !            65:  #   Path askpass /path/to/askpass
        !            66:  #
        !            67:  # The plugin_path is relative to @prefix@/libexec unless
        !            68:  #   fully qualified.
        !            69:  # The plugin_name corresponds to a global symbol in the plugin
        !            70:  #   that contains the plugin interface structure.
        !            71:  #
        !            72:  Plugin sudoers_policy sudoers.so
        !            73:  Plugin sudoers_io sudoers.so
        !            74: 
        !            75: =head2 Policy Plugin API
        !            76: 
        !            77: A policy plugin must declare and populate a C<policy_plugin> struct
        !            78: in the global scope.  This structure contains pointers to the functions
        !            79: that implement the B<sudo> policy checks.  The name of the symbol should
        !            80: be specified in F<@sysconfdir@/sudo.conf> along with a path to the plugin
        !            81: so that B<sudo> can load it.
        !            82: 
        !            83:  struct policy_plugin {
        !            84:  #define SUDO_POLICY_PLUGIN    1
        !            85:      unsigned int type; /* always SUDO_POLICY_PLUGIN */
        !            86:      unsigned int version; /* always SUDO_API_VERSION */
        !            87:      int (*open)(unsigned int version, sudo_conv_t conversation,
        !            88:                 sudo_printf_t plugin_printf, char * const settings[],
        !            89:                 char * const user_info[], char * const user_env[]);
        !            90:      void (*close)(int exit_status, int error);
        !            91:      int (*show_version)(int verbose);
        !            92:      int (*check_policy)(int argc, char * const argv[],
        !            93:                          char *env_add[], char **command_info[],
        !            94:                          char **argv_out[], char **user_env_out[]);
        !            95:      int (*list)(int argc, char * const argv[], int verbose,
        !            96:                  const char *list_user);
        !            97:      int (*validate)(void);
        !            98:      void (*invalidate)(int remove);
        !            99:      int (*init_session)(struct passwd *pwd);
        !           100:  };
        !           101: 
        !           102: The policy_plugin struct has the following fields:
        !           103: 
        !           104: =over 4
        !           105: 
        !           106: =item type
        !           107: 
        !           108: The C<type> field should always be set to SUDO_POLICY_PLUGIN.
        !           109: 
        !           110: =item version
        !           111: 
        !           112: The C<version> field should be set to SUDO_API_VERSION.
        !           113: 
        !           114: This allows B<sudo> to determine the API version the plugin was
        !           115: built against.
        !           116: 
        !           117: =item open
        !           118: 
        !           119:  int (*open)(unsigned int version, sudo_conv_t conversation,
        !           120:              sudo_printf_t plugin_printf, char * const settings[],
        !           121:              char * const user_info[], char * const user_env[]);
        !           122: 
        !           123: Returns 1 on success, 0 on failure, -1 if a general error occurred,
        !           124: or -2 if there was a usage error.  In the latter case, B<sudo> will
        !           125: print a usage message before it exits.  If an error occurs, the
        !           126: plugin may optionally call the conversation or plugin_printf function
        !           127: with C<SUDO_CONF_ERROR_MSG> to present additional error information
        !           128: to the user.
        !           129: 
        !           130: The function arguments are as follows:
        !           131: 
        !           132: =over 4
        !           133: 
        !           134: =item version
        !           135: 
        !           136: The version passed in by B<sudo> allows the plugin to determine the
        !           137: major and minor version number of the plugin API supported by
        !           138: B<sudo>.
        !           139: 
        !           140: =item conversation
        !           141: 
        !           142: A pointer to the conversation function that can be used by the
        !           143: plugin to interact with the user (see below).
        !           144: Returns 0 on success and -1 on failure.
        !           145: 
        !           146: =item plugin_printf
        !           147: 
        !           148: A pointer to a printf-style function that may be used to display
        !           149: informational or error messages (see below).
        !           150: Returns the number of characters printed on success and -1 on failure.
        !           151: 
        !           152: =item settings
        !           153: 
        !           154: A vector of user-supplied B<sudo> settings in the form of "name=value"
        !           155: strings.  The vector is terminated by a C<NULL> pointer.  These
        !           156: settings correspond to flags the user specified when running B<sudo>.
        !           157: As such, they will only be present when the corresponding flag has
        !           158: been specified on the command line.
        !           159: 
        !           160: When parsing I<settings>, the plugin should split on the B<first>
        !           161: equal sign ('=') since the I<name> field will never include one
        !           162: itself but the I<value> might.
        !           163: 
        !           164: =over 4
        !           165: 
        !           166: =item debug_level=number
        !           167: 
        !           168: A numeric debug level, from 1-9, if specified via the C<-D> flag.
        !           169: 
        !           170: =item runas_user=string
        !           171: 
        !           172: The user name or uid to to run the command as, if specified via the
        !           173: C<-u> flag.
        !           174: 
        !           175: =item runas_group=string
        !           176: 
        !           177: The group name or gid to to run the command as, if specified via
        !           178: the C<-g> flag.
        !           179: 
        !           180: =item prompt=string
        !           181: 
        !           182: The prompt to use when requesting a password, if specified via
        !           183: the C<-p> flag.
        !           184: 
        !           185: =item set_home=bool
        !           186: 
        !           187: Set to true if the user specified the C<-H> flag.  If true, set the
        !           188: C<HOME> environment variable to the target user's home directory.
        !           189: 
        !           190: =item preserve_environment=bool
        !           191: 
        !           192: Set to true if the user specified the C<-E> flag, indicating that
        !           193: the user wishes to preserve the environment.
        !           194: 
        !           195: =item run_shell=bool
        !           196: 
        !           197: Set to true if the user specified the C<-s> flag, indicating that
        !           198: the user wishes to run a shell.
        !           199: 
        !           200: =item login_shell=bool
        !           201: 
        !           202: Set to true if the user specified the C<-i> flag, indicating that
        !           203: the user wishes to run a login shell.
        !           204: 
        !           205: =item implied_shell=bool
        !           206: 
        !           207: If the user does not specify a program on the command line, B<sudo>
        !           208: will pass the plugin the path to the user's shell and set
        !           209: I<implied_shell> to true.  This allows B<sudo> with no arguments
        !           210: to be used similarly to L<su(1)>.  If the plugin does not to support
        !           211: this usage, it may return a value of -2 from the C<check_policy>
        !           212: function, which will cause B<sudo> to print a usage message and
        !           213: exit.
        !           214: 
        !           215: =item preserve_groups=bool
        !           216: 
        !           217: Set to true if the user specified the C<-P> flag, indicating that
        !           218: the user wishes to preserve the group vector instead of setting it
        !           219: based on the runas user.
        !           220: 
        !           221: =item ignore_ticket=bool
        !           222: 
        !           223: Set to true if the user specified the C<-k> flag along with a
        !           224: command, indicating that the user wishes to ignore any cached
        !           225: authentication credentials.
        !           226: 
        !           227: =item noninteractive=bool
        !           228: 
        !           229: Set to true if the user specified the C<-n> flag, indicating that
        !           230: B<sudo> should operate in non-interactive mode.  The plugin may
        !           231: reject a command run in non-interactive mode if user interaction
        !           232: is required.
        !           233: 
        !           234: =item login_class=string
        !           235: 
        !           236: BSD login class to use when setting resource limits and nice value,
        !           237: if specified by the C<-c> flag.
        !           238: 
        !           239: =item selinux_role=string
        !           240: 
        !           241: SELinux role to use when executing the command, if specified by
        !           242: the C<-r> flag.
        !           243: 
        !           244: =item selinux_type=string
        !           245: 
        !           246: SELinux type to use when executing the command, if specified by
        !           247: the C<-t> flag.
        !           248: 
        !           249: =item bsdauth_type=string
        !           250: 
        !           251: Authentication type, if specified by the C<-a> flag, to use on
        !           252: systems where BSD authentication is supported.
        !           253: 
        !           254: =item network_addrs=list
        !           255: 
        !           256: A space-separated list of IP network addresses and netmasks in the
        !           257: form "addr/netmask", e.g. "192.168.1.2/255.255.255.0".  The address
        !           258: and netmask pairs may be either IPv4 or IPv6, depending on what the
        !           259: operating system supports.  If the address contains a colon (':'),
        !           260: it is an IPv6 address, else it is IPv4.
        !           261: 
        !           262: =item progname=string
        !           263: 
        !           264: The command name that sudo was run as, typically "sudo" or "sudoedit".
        !           265: 
        !           266: =item sudoedit=bool
        !           267: 
        !           268: Set to true when the C<-e> flag is is specified or if invoked as
        !           269: B<sudoedit>.  The plugin shall substitute an editor into I<argv>
        !           270: in the I<check_policy> function or return C<-2> with a usage error
        !           271: if the plugin does not support I<sudoedit>.  For more information,
        !           272: see the I<check_policy> section.
        !           273: 
        !           274: =item closefrom=number
        !           275: 
        !           276: If specified, the user has requested via the C<-C> flag that B<sudo>
        !           277: close all files descriptors with a value of I<number> or higher.
        !           278: The plugin may optionally pass this, or another value, back in the
        !           279: I<command_info> list.
        !           280: 
        !           281: =back
        !           282: 
        !           283: Additional settings may be added in the future so the plugin should
        !           284: silently ignore settings that it does not recognize.
        !           285: 
        !           286: =item user_info
        !           287: 
        !           288: A vector of information about the user running the command in the form of
        !           289: "name=value" strings.  The vector is terminated by a C<NULL> pointer.
        !           290: 
        !           291: When parsing I<user_info>, the plugin should split on the B<first>
        !           292: equal sign ('=') since the I<name> field will never include one
        !           293: itself but the I<value> might.
        !           294: 
        !           295: =over 4
        !           296: 
        !           297: =item user=string
        !           298: 
        !           299: The name of the user invoking B<sudo>.
        !           300: 
        !           301: =item uid=uid_t
        !           302: 
        !           303: The real user ID of the user invoking B<sudo>.
        !           304: 
        !           305: =item gid=gid_t
        !           306: 
        !           307: The real group ID of the user invoking B<sudo>.
        !           308: 
        !           309: =item groups=list
        !           310: 
        !           311: The user's supplementary group list formatted as a string of
        !           312: comma-separated group IDs.
        !           313: 
        !           314: =item cwd=string
        !           315: 
        !           316: The user's current working directory.
        !           317: 
        !           318: =item tty=string
        !           319: 
        !           320: The path to the user's terminal device.  If the user has no terminal
        !           321: device associated with the session, the value will be empty, as in
        !           322: C<tty=>.
        !           323: 
        !           324: =item host=string
        !           325: 
        !           326: The local machine's hostname as returned by the C<gethostname()>
        !           327: system call.
        !           328: 
        !           329: =item lines=int
        !           330: 
        !           331: The number of lines the user's terminal supports.  If there is
        !           332: no terminal device available, a default value of 24 is used.
        !           333: 
        !           334: =item cols=int
        !           335: 
        !           336: The number of columns the user's terminal supports.  If there is
        !           337: no terminal device available, a default value of 80 is used.
        !           338: 
        !           339: =back
        !           340: 
        !           341: =item user_env
        !           342: 
        !           343: The user's environment in the form of a C<NULL>-terminated vector of
        !           344: "name=value" strings.
        !           345: 
        !           346: When parsing I<user_env>, the plugin should split on the B<first>
        !           347: equal sign ('=') since the I<name> field will never include one
        !           348: itself but the I<value> might.
        !           349: 
        !           350: =back
        !           351: 
        !           352: =item close
        !           353: 
        !           354:  void (*close)(int exit_status, int error);
        !           355: 
        !           356: The C<close> function is called when the command being run by B<sudo>
        !           357: finishes.
        !           358: 
        !           359: The function arguments are as follows:
        !           360: 
        !           361: =over 4
        !           362: 
        !           363: =item exit_status
        !           364: 
        !           365: The command's exit status, as returned by the wait(2) system call.
        !           366: The value of C<exit_status> is undefined if C<error> is non-zero.
        !           367: 
        !           368: =item error
        !           369: 
        !           370: If the command could not be executed, this is set to the value of
        !           371: C<errno> set by the execve(2) system call.  The plugin is responsible
        !           372: for displaying error information via the conversation or plugin_printf
        !           373: function.  If the command was successfully executed, the value of
        !           374: C<error> is 0.
        !           375: 
        !           376: =back
        !           377: 
        !           378: =item show_version
        !           379: 
        !           380:  int (*show_version)(int verbose);
        !           381: 
        !           382: The C<show_version> function is called by B<sudo> when the user specifies
        !           383: the C<-V> option.  The plugin may display its version information
        !           384: to the user via the conversation or plugin_printf function using
        !           385: C<SUDO_CONV_INFO_MSG>.  If the user requests detailed version
        !           386: information, the verbose flag will be set.
        !           387: 
        !           388: =item check_policy
        !           389: 
        !           390:  int (*check_policy)(int argc, char * const argv[]
        !           391:                      char *env_add[], char **command_info[],
        !           392:                      char **argv_out[], char **user_env_out[]);
        !           393: 
        !           394: The I<check_policy> function is called by B<sudo> to determine
        !           395: whether the user is allowed to run the specified commands.
        !           396: 
        !           397: If the I<sudoedit> option was enabled in the I<settings> array
        !           398: passed to the I<open> function, the user has requested I<sudoedit>
        !           399: mode.  I<sudoedit> is a mechanism for editing one or more files
        !           400: where an editor is run with the user's credentials instead of with
        !           401: elevated privileges.  B<sudo> achieves this by creating user-writable
        !           402: temporary copies of the files to be edited and then overwriting the
        !           403: originals with the temporary copies after editing is complete.  If
        !           404: the plugin supports B<sudoedit>, it should choose the editor to be
        !           405: used, potentially from a variable in the user's environment, such
        !           406: as C<EDITOR>, and include it in I<argv_out> (note that environment
        !           407: variables may include command line flags).  The files to be edited
        !           408: should be copied from I<argv> into I<argv_out>, separated from the
        !           409: editor and its arguments by a C<"--"> element.  The C<"--"> will
        !           410: be removed by B<sudo> before the editor is executed.  The plugin
        !           411: should also set I<sudoedit=true> in the I<command_info> list.
        !           412: 
        !           413: The I<check_policy> function returns 1 if the command is allowed,
        !           414: 0 if not allowed, -1 for a general error, or -2 for a usage error
        !           415: or if B<sudoedit> was specified but is unsupported by the plugin.
        !           416: In the latter case, B<sudo> will print a usage message before it
        !           417: exits.  If an error occurs, the plugin may optionally call the
        !           418: conversation or plugin_printf function with C<SUDO_CONF_ERROR_MSG>
        !           419: to present additional error information to the user.
        !           420: 
        !           421: The function arguments are as follows:
        !           422: 
        !           423: =over 4
        !           424: 
        !           425: =item argc
        !           426: 
        !           427: The number of elements in I<argv>, not counting the final C<NULL>
        !           428: pointer.
        !           429: 
        !           430: =item argv
        !           431: 
        !           432: The argument vector describing the command the user wishes to run,
        !           433: in the same form as what would be passed to the execve() system
        !           434: call.  The vector is terminated by a C<NULL> pointer.
        !           435: 
        !           436: =item env_add
        !           437: 
        !           438: Additional environment variables specified by the user on the command
        !           439: line in the form of a C<NULL>-terminated vector of "name=value"
        !           440: strings.  The plugin may reject the command if one or more variables
        !           441: are not allowed to be set, or it may silently ignore such variables.
        !           442: 
        !           443: When parsing I<env_add>, the plugin should split on the B<first>
        !           444: equal sign ('=') since the I<name> field will never include one
        !           445: itself but the I<value> might.
        !           446: 
        !           447: =item command_info
        !           448: 
        !           449: Information about the command being run in the form of "name=value"
        !           450: strings.  These values are used by B<sudo> to set the execution
        !           451: environment when running a command.  The plugin is responsible for
        !           452: creating and populating the vector, which must be terminated with
        !           453: a C<NULL> pointer.  The following values are recognized by B<sudo>:
        !           454: 
        !           455: =over 4
        !           456: 
        !           457: =item command=string
        !           458: 
        !           459: Fully qualified path to the command to be executed.
        !           460: 
        !           461: =item runas_uid=uid
        !           462: 
        !           463: User ID to run the command as.
        !           464: 
        !           465: =item runas_euid=uid
        !           466: 
        !           467: Effective user ID to run the command as.
        !           468: If not specified, the value of I<runas_uid> is used.
        !           469: 
        !           470: =item runas_gid=gid
        !           471: 
        !           472: Group ID to run the command as.
        !           473: 
        !           474: =item runas_egid=gid
        !           475: 
        !           476: Effective group ID to run the command as.
        !           477: If not specified, the value of I<runas_gid> is used.
        !           478: 
        !           479: =item runas_groups=list
        !           480: 
        !           481: The supplementary group vector to use for the command in the form
        !           482: of a comma-separated list of group IDs.  If I<preserve_groups>
        !           483: is set, this option is ignored.
        !           484: 
        !           485: =item login_class=string
        !           486: 
        !           487: BSD login class to use when setting resource limits and nice value
        !           488: (optional).  This option is only set on systems that support login
        !           489: classes.
        !           490: 
        !           491: =item preserve_groups=bool
        !           492: 
        !           493: If set, B<sudo> will preserve the user's group vector instead of
        !           494: initializing the group vector based on C<runas_user>.
        !           495: 
        !           496: =item cwd=string
        !           497: 
        !           498: The current working directory to change to when executing the command.
        !           499: 
        !           500: =item noexec=bool
        !           501: 
        !           502: If set, prevent the command from executing other programs.
        !           503: 
        !           504: =item chroot=string
        !           505: 
        !           506: The root directory to use when running the command.
        !           507: 
        !           508: =item nice=int
        !           509: 
        !           510: Nice value (priority) to use when executing the command.  The nice
        !           511: value, if specified, overrides the priority associated with the
        !           512: I<login_class> on BSD systems.
        !           513: 
        !           514: =item umask=octal
        !           515: 
        !           516: The file creation mask to use when executing the command.
        !           517: 
        !           518: =item selinux_role=string
        !           519: 
        !           520: SELinux role to use when executing the command.
        !           521: 
        !           522: =item selinux_type=string
        !           523: 
        !           524: SELinux type to use when executing the command.
        !           525: 
        !           526: =item timeout=int
        !           527: 
        !           528: Command timeout.  If non-zero then when the timeout expires the
        !           529: command will be killed.
        !           530: 
        !           531: =item sudoedit=bool
        !           532: 
        !           533: Set to true when in I<sudoedit> mode.  The plugin may enable
        !           534: I<sudoedit> mode even if B<sudo> was not invoked as B<sudoedit>.
        !           535: This allows the plugin to perform command substitution and transparently
        !           536: enable I<sudoedit> when the user attempts to run an editor.
        !           537: 
        !           538: =item closefrom=number
        !           539: 
        !           540: If specified, B<sudo> will close all files descriptors with a value
        !           541: of I<number> or higher.
        !           542: 
        !           543: =item iolog_compress=bool
        !           544: 
        !           545: Set to true if the I/O logging plugins, if any, should compress the
        !           546: log data.  This is a hint to the I/O logging plugin which may choose
        !           547: to ignore it.
        !           548: 
        !           549: =item iolog_path=string
        !           550: 
        !           551: Fully qualified path to the file or directory in which I/O log is
        !           552: to be stored.  This is a hint to the I/O logging plugin which may
        !           553: choose to ignore it.  If no I/O logging plugin is loaded, this
        !           554: setting has no effect.
        !           555: 
        !           556: =item iolog_stdin=bool
        !           557: 
        !           558: Set to true if the I/O logging plugins, if any, should log the
        !           559: standard input if it is not connected to a terminal device.  This
        !           560: is a hint to the I/O logging plugin which may choose to ignore it.
        !           561: 
        !           562: =item iolog_stdout=bool
        !           563: 
        !           564: Set to true if the I/O logging plugins, if any, should log the
        !           565: standard output if it is not connected to a terminal device.  This
        !           566: is a hint to the I/O logging plugin which may choose to ignore it.
        !           567: 
        !           568: =item iolog_stderr=bool
        !           569: 
        !           570: Set to true if the I/O logging plugins, if any, should log the
        !           571: standard error if it is not connected to a terminal device.  This
        !           572: is a hint to the I/O logging plugin which may choose to ignore it.
        !           573: 
        !           574: =item iolog_ttyin=bool
        !           575: 
        !           576: Set to true if the I/O logging plugins, if any, should log all
        !           577: terminal input.  This only includes input typed by the user and not
        !           578: from a pipe or redirected from a file.  This is a hint to the I/O
        !           579: logging plugin which may choose to ignore it.
        !           580: 
        !           581: =item iolog_ttyout=bool
        !           582: 
        !           583: Set to true if the I/O logging plugins, if any, should log all
        !           584: terminal output.  This only includes output to the screen, not
        !           585: output to a pipe or file.  This is a hint to the I/O logging plugin
        !           586: which may choose to ignore it.
        !           587: 
        !           588: =item use_pty=bool
        !           589: 
        !           590: Allocate a pseudo-tty to run the command in, regardless of whether
        !           591: or not I/O logging is in use.  By default, B<sudo> will only run
        !           592: the command in a pty when an I/O log plugin is loaded.
        !           593: 
        !           594: =item set_utmp=bool
        !           595: 
        !           596: Create a utmp (or utmpx) entry when a pseudo-tty is allocated.  By
        !           597: default, the new entry will be a copy of the user's existing utmp
        !           598: entry (if any), with the tty, time, type and pid fields updated.
        !           599: 
        !           600: =item utmp_user=string
        !           601: 
        !           602: User name to use when constructing a new utmp (or utmpx) entry when
        !           603: I<set_utmp> is enabled.  This option can be used to set the user
        !           604: field in the utmp entry to the user the command runs as rather than
        !           605: the invoking user.  If not set, B<sudo> will base the new entry on
        !           606: the invoking user's existing entry.
        !           607: 
        !           608: =back
        !           609: 
        !           610: Unsupported values will be ignored.
        !           611: 
        !           612: =item argv_out
        !           613: 
        !           614: The C<NULL>-terminated argument vector to pass to the execve()
        !           615: system call when executing the command.  The plugin is responsible
        !           616: for allocating and populating the vector.
        !           617: 
        !           618: =item user_env_out
        !           619: 
        !           620: The C<NULL>-terminated environment vector to use when executing the
        !           621: command.  The plugin is responsible for allocating and populating
        !           622: the vector.
        !           623: 
        !           624: =back
        !           625: 
        !           626: =item list
        !           627: 
        !           628:  int (*list)(int verbose, const char *list_user,
        !           629:              int argc, char * const argv[]);
        !           630: 
        !           631: List available privileges for the invoking user.  Returns 1 on
        !           632: success, 0 on failure and -1 on error.  On error, the plugin may
        !           633: optionally call the conversation or plugin_printf function with
        !           634: C<SUDO_CONF_ERROR_MSG> to present additional error information to
        !           635: the user.
        !           636: 
        !           637: Privileges should be output via the conversation or plugin_printf
        !           638: function using C<SUDO_CONV_INFO_MSG>.
        !           639: 
        !           640: =over 4
        !           641: 
        !           642: =item verbose
        !           643: 
        !           644: Flag indicating whether to list in verbose mode or not.
        !           645: 
        !           646: =item list_user
        !           647: 
        !           648: The name of a different user to list privileges for if the policy
        !           649: allows it.  If C<NULL>, the plugin should list the privileges of
        !           650: the invoking user.
        !           651: 
        !           652: =item argc
        !           653: 
        !           654: The number of elements in I<argv>, not counting the final C<NULL>
        !           655: pointer.
        !           656: 
        !           657: =item argv
        !           658: 
        !           659: If non-C<NULL>, an argument vector describing a command the user
        !           660: wishes to check against the policy in the same form as what would
        !           661: be passed to the execve() system call.  If the command is permitted
        !           662: by the policy, the fully-qualified path to the command should be
        !           663: displayed along with any command line arguments.
        !           664: 
        !           665: =back
        !           666: 
        !           667: =item validate
        !           668: 
        !           669:  int (*validate)(void);
        !           670: 
        !           671: The C<validate> function is called when B<sudo> is run with the
        !           672: C<-v> flag.  For policy plugins such as I<sudoers> that cache
        !           673: authentication credentials, this function will validate and cache
        !           674: the credentials.
        !           675: 
        !           676: The C<validate> function should be C<NULL> if the plugin does not
        !           677: support credential caching.
        !           678: 
        !           679: Returns 1 on success, 0 on failure and -1 on error.
        !           680: On error, the plugin may optionally call the conversation or plugin_printf
        !           681: function with C<SUDO_CONF_ERROR_MSG> to present additional
        !           682: error information to the user.
        !           683: 
        !           684: =item invalidate
        !           685: 
        !           686:  void (*invalidate)(int remove);
        !           687: 
        !           688: The C<invalidate> function is called when B<sudo> is called with
        !           689: the C<-k> or C<-K> flag.  For policy plugins such as I<sudoers> that
        !           690: cache authentication credentials, this function will invalidate the
        !           691: credentials.  If the I<remove> flag is set, the plugin may remove
        !           692: the credentials instead of simply invalidating them.
        !           693: 
        !           694: The C<invalidate> function should be C<NULL> if the plugin does not
        !           695: support credential caching.
        !           696: 
        !           697: =item init_session
        !           698: 
        !           699:  int (*init_session)(struct passwd *pwd);
        !           700: 
        !           701: The C<init_session> function is called when B<sudo> sets up the
        !           702: execution environment for the command, immediately before the
        !           703: contents of the I<command_info> list are applied (before the uid
        !           704: changes).  This can be used to do session setup that is not supported
        !           705: by I<command_info>, such as opening the PAM session.
        !           706: 
        !           707: The I<pwd> argument points to a passwd struct for the user the
        !           708: command will be run as if the uid the command will run as was found
        !           709: in the password database, otherwise it will be NULL.
        !           710: 
        !           711: Returns 1 on success, 0 on failure and -1 on error.
        !           712: On error, the plugin may optionally call the conversation or plugin_printf
        !           713: function with C<SUDO_CONF_ERROR_MSG> to present additional
        !           714: error information to the user.
        !           715: 
        !           716: =back
        !           717: 
        !           718: =head3 Version macros
        !           719: 
        !           720:  #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
        !           721:  #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
        !           722:  #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
        !           723:      *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
        !           724:  } while(0)
        !           725:  #define SUDO_VERSION_SET_MINOR(vp, n) do { \
        !           726:      *(vp) = (*(vp) & 0xffff0000) | (n); \
        !           727:  } while(0)
        !           728: 
        !           729:  #define SUDO_API_VERSION_MAJOR 1
        !           730:  #define SUDO_API_VERSION_MINOR 0
        !           731:  #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \
        !           732:                            SUDO_API_VERSION_MINOR)
        !           733: 
        !           734: =head2 I/O Plugin API
        !           735: 
        !           736:  struct io_plugin {
        !           737:  #define SUDO_IO_PLUGIN                2
        !           738:      unsigned int type; /* always SUDO_IO_PLUGIN */
        !           739:      unsigned int version; /* always SUDO_API_VERSION */
        !           740:      int (*open)(unsigned int version, sudo_conv_t conversation
        !           741:                  sudo_printf_t plugin_printf, char * const settings[],
        !           742:                  char * const user_info[], int argc, char * const argv[],
        !           743:                  char * const user_env[]);
        !           744:      void (*close)(int exit_status, int error); /* wait status or error */
        !           745:      int (*show_version)(int verbose);
        !           746:      int (*log_ttyin)(const char *buf, unsigned int len);
        !           747:      int (*log_ttyout)(const char *buf, unsigned int len);
        !           748:      int (*log_stdin)(const char *buf, unsigned int len);
        !           749:      int (*log_stdout)(const char *buf, unsigned int len);
        !           750:      int (*log_stderr)(const char *buf, unsigned int len);
        !           751:  };
        !           752: 
        !           753: When an I/O plugin is loaded, B<sudo> runs the command in a pseudo-tty.
        !           754: This makes it possible to log the input and output from the user's
        !           755: session.  If any of the standard input, standard output or standard
        !           756: error do not correspond to a tty, B<sudo> will open a pipe to capture
        !           757: the I/O for logging before passing it on.
        !           758: 
        !           759: The log_ttyin function receives the raw user input from the terminal
        !           760: device (note that this will include input even when echo is disabled,
        !           761: such as when a password is read). The log_ttyout function receives
        !           762: output from the pseudo-tty that is suitable for replaying the user's
        !           763: session at a later time.  The log_stdin, log_stdout and log_stderr
        !           764: functions are only called if the standard input, standard output
        !           765: or standard error respectively correspond to something other than
        !           766: a tty.
        !           767: 
        !           768: Any of the logging functions may be set to the NULL
        !           769: pointer if no logging is to be performed.  If the open function
        !           770: returns C<0>, no I/O will be sent to the plugin.
        !           771: 
        !           772: The io_plugin struct has the following fields:
        !           773: 
        !           774: =over 4
        !           775: 
        !           776: =item type
        !           777: 
        !           778: The C<type> field should always be set to SUDO_IO_PLUGIN
        !           779: 
        !           780: =item version
        !           781: 
        !           782: The C<version> field should be set to SUDO_API_VERSION.
        !           783: 
        !           784: This allows B<sudo> to determine the API version the plugin was
        !           785: built against.
        !           786: 
        !           787: =item open
        !           788: 
        !           789:  int (*open)(unsigned int version, sudo_conv_t conversation
        !           790:              sudo_printf_t plugin_printf, char * const settings[],
        !           791:              char * const user_info[], int argc, char * const argv[],
        !           792:              char * const user_env[]);
        !           793: 
        !           794: The I<open> function is run before the I<log_input>, I<log_output>
        !           795: or I<show_version> functions are called.  It is only called if the
        !           796: version is being requested or the I<check_policy> function has
        !           797: returned successfully.  It returns 1 on success, 0 on failure, -1
        !           798: if a general error occurred, or -2 if there was a usage error.  In
        !           799: the latter case, B<sudo> will print a usage message before it exits.
        !           800: If an error occurs, the plugin may optionally call the conversation
        !           801: or plugin_printf function with C<SUDO_CONF_ERROR_MSG> to present
        !           802: additional error information to the user.
        !           803: 
        !           804: The function arguments are as follows:
        !           805: 
        !           806: =over 4
        !           807: 
        !           808: =item version
        !           809: 
        !           810: The version passed in by B<sudo> allows the plugin to determine the
        !           811: major and minor version number of the plugin API supported by
        !           812: B<sudo>.
        !           813: 
        !           814: =item conversation
        !           815: 
        !           816: A pointer to the conversation function that may be used by the
        !           817: I<show_version> function to display version information (see
        !           818: show_version below).  The conversation function may also be used
        !           819: to display additional error message to the user.
        !           820: The conversation function returns 0 on success and -1 on failure.
        !           821: 
        !           822: =item plugin_printf
        !           823: 
        !           824: A pointer to a printf-style function that may be used by the
        !           825: I<show_version> function to display version information (see
        !           826: show_version below).  The plugin_printf function may also be used
        !           827: to display additional error message to the user.
        !           828: The plugin_printf function returns number of characters printed on
        !           829: success and -1 on failure.
        !           830: 
        !           831: =item settings
        !           832: 
        !           833: A vector of user-supplied B<sudo> settings in the form of "name=value"
        !           834: strings.  The vector is terminated by a C<NULL> pointer.  These
        !           835: settings correspond to flags the user specified when running B<sudo>.
        !           836: As such, they will only be present when the corresponding flag has
        !           837: been specified on the command line.
        !           838: 
        !           839: When parsing I<settings>, the plugin should split on the B<first>
        !           840: equal sign ('=') since the I<name> field will never include one
        !           841: itself but the I<value> might.
        !           842: 
        !           843: See the L<Policy Plugin API> section for a list of all possible settings.
        !           844: 
        !           845: =item user_info
        !           846: 
        !           847: A vector of information about the user running the command in the form of
        !           848: "name=value" strings.  The vector is terminated by a C<NULL> pointer.
        !           849: 
        !           850: When parsing I<user_info>, the plugin should split on the B<first>
        !           851: equal sign ('=') since the I<name> field will never include one
        !           852: itself but the I<value> might.
        !           853: 
        !           854: See the L<Policy Plugin API> section for a list of all possible strings.
        !           855: 
        !           856: =item argc
        !           857: 
        !           858: The number of elements in I<argv>, not counting the final C<NULL>
        !           859: pointer.
        !           860: 
        !           861: =item argv
        !           862: 
        !           863: If non-C<NULL>, an argument vector describing a command the user
        !           864: wishes to run in the same form as what would be passed to the
        !           865: execve() system call.
        !           866: 
        !           867: =item user_env
        !           868: 
        !           869: The user's environment in the form of a C<NULL>-terminated vector of
        !           870: "name=value" strings.
        !           871: 
        !           872: When parsing I<user_env>, the plugin should split on the B<first>
        !           873: equal sign ('=') since the I<name> field will never include one
        !           874: itself but the I<value> might.
        !           875: 
        !           876: =back
        !           877: 
        !           878: =item close
        !           879: 
        !           880:  void (*close)(int exit_status, int error);
        !           881: 
        !           882: The C<close> function is called when the command being run by B<sudo>
        !           883: finishes.
        !           884: 
        !           885: The function arguments are as follows:
        !           886: 
        !           887: =over 4
        !           888: 
        !           889: =item exit_status
        !           890: 
        !           891: The command's exit status, as returned by the wait(2) system call.
        !           892: The value of C<exit_status> is undefined if C<error> is non-zero.
        !           893: 
        !           894: =item error
        !           895: 
        !           896: If the command could not be executed, this is set to the value of
        !           897: C<errno> set by the execve(2) system call.  If the command was
        !           898: successfully executed, the value of C<error> is 0.
        !           899: 
        !           900: =back
        !           901: 
        !           902: =item show_version
        !           903: 
        !           904:  int (*show_version)(int verbose);
        !           905: 
        !           906: The C<show_version> function is called by B<sudo> when the user specifies
        !           907: the C<-V> option.  The plugin may display its version information
        !           908: to the user via the conversation or plugin_printf function using
        !           909: C<SUDO_CONV_INFO_MSG>.  If the user requests detailed version
        !           910: information, the verbose flag will be set.
        !           911: 
        !           912: =item log_ttyin
        !           913: 
        !           914:  int (*log_ttyin)(const char *buf, unsigned int len);
        !           915: 
        !           916: The I<log_ttyin> function is called whenever data can be read from
        !           917: the user but before it is passed to the running command.  This
        !           918: allows the plugin to reject data if it chooses to (for instance
        !           919: if the input contains banned content).  Returns C<1> if the data
        !           920: should be passed to the command, C<0> if the data is rejected
        !           921: (which will terminate the command) or C<-1> if an error occurred.
        !           922: 
        !           923: The function arguments are as follows:
        !           924: 
        !           925: =over 4
        !           926: 
        !           927: =item buf
        !           928: 
        !           929: The buffer containing user input.
        !           930: 
        !           931: =item len
        !           932: 
        !           933: The length of I<buf> in bytes.
        !           934: 
        !           935: =back
        !           936: 
        !           937: =item log_ttyout
        !           938: 
        !           939:  int (*log_ttyout)(const char *buf, unsigned int len);
        !           940: 
        !           941: The I<log_ttyout> function is called whenever data can be read from
        !           942: the command but before it is written to the user's terminal.  This
        !           943: allows the plugin to reject data if it chooses to (for instance
        !           944: if the output contains banned content).  Returns C<1> if the data
        !           945: should be passed to the user, C<0> if the data is rejected
        !           946: (which will terminate the command) or C<-1> if an error occurred.
        !           947: 
        !           948: The function arguments are as follows:
        !           949: 
        !           950: =over 4
        !           951: 
        !           952: =item buf
        !           953: 
        !           954: The buffer containing command output.
        !           955: 
        !           956: =item len
        !           957: 
        !           958: The length of I<buf> in bytes.
        !           959: 
        !           960: =back
        !           961: 
        !           962: =item log_stdin
        !           963: 
        !           964:  int (*log_stdin)(const char *buf, unsigned int len);
        !           965: 
        !           966: The I<log_stdin> function is only used if the standard input does
        !           967: not correspond to a tty device.  It is called whenever data can be
        !           968: read from the standard input but before it is passed to the running
        !           969: command.  This allows the plugin to reject data if it chooses to
        !           970: (for instance if the input contains banned content).  Returns C<1>
        !           971: if the data should be passed to the command, C<0> if the data is
        !           972: rejected (which will terminate the command) or C<-1> if an error
        !           973: occurred.
        !           974: 
        !           975: The function arguments are as follows:
        !           976: 
        !           977: =over 4
        !           978: 
        !           979: =item buf
        !           980: 
        !           981: The buffer containing user input.
        !           982: 
        !           983: =item len
        !           984: 
        !           985: The length of I<buf> in bytes.
        !           986: 
        !           987: =back
        !           988: 
        !           989: =item log_stdout
        !           990: 
        !           991:  int (*log_stdout)(const char *buf, unsigned int len);
        !           992: 
        !           993: The I<log_stdout> function is only used if the standard output does
        !           994: not correspond to a tty device.  It is called whenever data can be
        !           995: read from the command but before it is written to the standard
        !           996: output.  This allows the plugin to reject data if it chooses to
        !           997: (for instance if the output contains banned content).  Returns C<1>
        !           998: if the data should be passed to the user, C<0> if the data is
        !           999: rejected (which will terminate the command) or C<-1> if an error
        !          1000: occurred.
        !          1001: 
        !          1002: The function arguments are as follows:
        !          1003: 
        !          1004: =over 4
        !          1005: 
        !          1006: =item buf
        !          1007: 
        !          1008: The buffer containing command output.
        !          1009: 
        !          1010: =item len
        !          1011: 
        !          1012: The length of I<buf> in bytes.
        !          1013: 
        !          1014: =back
        !          1015: 
        !          1016: =item log_stderr
        !          1017: 
        !          1018:  int (*log_stderr)(const char *buf, unsigned int len);
        !          1019: 
        !          1020: The I<log_stderr> function is only used if the standard error does
        !          1021: not correspond to a tty device.  It is called whenever data can be
        !          1022: read from the command but before it is written to the standard
        !          1023: error.  This allows the plugin to reject data if it chooses to
        !          1024: (for instance if the output contains banned content).  Returns C<1>
        !          1025: if the data should be passed to the user, C<0> if the data is
        !          1026: rejected (which will terminate the command) or C<-1> if an error
        !          1027: occurred.
        !          1028: 
        !          1029: The function arguments are as follows:
        !          1030: 
        !          1031: =over 4
        !          1032: 
        !          1033: =item buf
        !          1034: 
        !          1035: The buffer containing command output.
        !          1036: 
        !          1037: =item len
        !          1038: 
        !          1039: The length of I<buf> in bytes.
        !          1040: 
        !          1041: =back
        !          1042: 
        !          1043: =back
        !          1044: 
        !          1045: =head3 Version macros
        !          1046: 
        !          1047: Same as for the L<Policy Plugin API>.
        !          1048: 
        !          1049: =head2 Conversation API
        !          1050: 
        !          1051: If the plugin needs to interact with the user, it may do so via the
        !          1052: conversation function.  A plugin should not attempt to read directly
        !          1053: from the standard input or the user's tty (neither of which are
        !          1054: guaranteed to exist).  The caller must include a trailing newline
        !          1055: in C<msg> if one is to be printed.
        !          1056: 
        !          1057: A printf-style function is also available that can be used to display
        !          1058: informational or error messages to the user, which is usually more
        !          1059: convenient for simple messages where no use input is required.
        !          1060: 
        !          1061:  struct sudo_conv_message {
        !          1062:  #define SUDO_CONV_PROMPT_ECHO_OFF  0x0001 /* do not echo user input */
        !          1063:  #define SUDO_CONV_PROMPT_ECHO_ON   0x0002 /* echo user input */
        !          1064:  #define SUDO_CONV_ERROR_MSG       0x0003 /* error message */
        !          1065:  #define SUDO_CONV_INFO_MSG        0x0004 /* informational message */
        !          1066:  #define SUDO_CONV_PROMPT_MASK     0x0005 /* mask user input */
        !          1067:  #define SUDO_CONV_PROMPT_ECHO_OK   0x1000 /* flag: allow echo if no tty */
        !          1068:      int msg_type;
        !          1069:      int timeout;
        !          1070:      const char *msg;
        !          1071:  };
        !          1072: 
        !          1073:  struct sudo_conv_reply {
        !          1074:      char *reply;
        !          1075:  };
        !          1076: 
        !          1077:  typedef int (*sudo_conv_t)(int num_msgs,
        !          1078:              const struct sudo_conv_message msgs[],
        !          1079:               struct sudo_conv_reply replies[]);
        !          1080: 
        !          1081:  typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
        !          1082: 
        !          1083: Pointers to the conversation and printf-style functions are passed
        !          1084: in to the plugin's C<open> function when the plugin is initialized.
        !          1085: 
        !          1086: To use the conversation function, the plugin must pass an array of
        !          1087: C<sudo_conv_message> and C<sudo_conv_reply> structures.  There must
        !          1088: be a C<struct sudo_conv_message> and C<struct sudo_conv_reply> for
        !          1089: each message in the conversation.  The plugin is responsible for
        !          1090: freeing the reply buffer filled in to the C<struct sudo_conv_reply>,
        !          1091: if any.
        !          1092: 
        !          1093: The printf-style function uses the same underlying mechanism as the
        !          1094: conversation function but only supports C<SUDO_CONV_INFO_MSG> and
        !          1095: C<SUDO_CONV_ERROR_MSG> for the I<msg_type> parameter.  It can be
        !          1096: more convenient than using the conversation function if no user
        !          1097: reply is needed and supports standard printf() escape sequences.
        !          1098: 
        !          1099: See the sample plugin for an example of the conversation function usage.
        !          1100: 
        !          1101: =head2 Sudoers Group Plugin API
        !          1102: 
        !          1103: The I<sudoers> module supports a plugin interface to allow non-Unix
        !          1104: group lookups.  This can be used to query a group source other than
        !          1105: the standard Unix group database.  A sample group plugin is bundled
        !          1106: with B<sudo> that implements file-based lookups.  Third party group
        !          1107: plugins include a QAS AD plugin available from Quest Software.
        !          1108: 
        !          1109: A group plugin must declare and populate a C<sudoers_group_plugin>
        !          1110: struct in the global scope.  This structure contains pointers to
        !          1111: the functions that implement plugin initialization, cleanup and
        !          1112: group lookup.
        !          1113: 
        !          1114:  struct sudoers_group_plugin {
        !          1115:     unsigned int version;
        !          1116:     int (*init)(int version, sudo_printf_t sudo_printf,
        !          1117:                 char *const argv[]);
        !          1118:     void (*cleanup)(void);
        !          1119:     int (*query)(const char *user, const char *group,
        !          1120:                  const struct passwd *pwd);
        !          1121: };
        !          1122: 
        !          1123: The C<sudoers_group_plugin> struct has the following fields:
        !          1124: 
        !          1125: =over 4
        !          1126: 
        !          1127: =item version
        !          1128: 
        !          1129: The C<version> field should be set to GROUP_API_VERSION.
        !          1130: 
        !          1131: This allows I<sudoers> to determine the API version the group plugin
        !          1132: was built against.
        !          1133: 
        !          1134: =item init
        !          1135: 
        !          1136:  int (*init)(int version, sudo_printf_t plugin_printf,
        !          1137:              char *const argv[]);
        !          1138: 
        !          1139: The I<init> function is called after I<sudoers> has been parsed but
        !          1140: before any policy checks.  It returns 1 on success, 0 on failure
        !          1141: (or if the plugin is not configured), and -1 if a error occurred.
        !          1142: If an error occurs, the plugin may call the plugin_printf function
        !          1143: with C<SUDO_CONF_ERROR_MSG> to present additional error information
        !          1144: to the user.
        !          1145: 
        !          1146: The function arguments are as follows:
        !          1147: 
        !          1148: =over 4
        !          1149: 
        !          1150: =item version
        !          1151: 
        !          1152: The version passed in by I<sudoers> allows the plugin to determine the
        !          1153: major and minor version number of the group plugin API supported by
        !          1154: I<sudoers>.
        !          1155: 
        !          1156: =item plugin_printf
        !          1157: 
        !          1158: A pointer to a printf-style function that may be used to display
        !          1159: informational or error message to the user.
        !          1160: Returns the number of characters printed on success and -1 on failure.
        !          1161: 
        !          1162: =item argv
        !          1163: 
        !          1164: A NULL-terminated array of arguments generated from the I<group_plugin>
        !          1165: option in I<sudoers>.  If no arguments were given, I<argv> will be
        !          1166: NULL.
        !          1167: 
        !          1168: =back
        !          1169: 
        !          1170: =item cleanup
        !          1171: 
        !          1172:  void (*cleanup)();
        !          1173: 
        !          1174: The I<cleanup> function is called when I<sudoers> has finished its
        !          1175: group checks.  The plugin should free any memory it has allocated
        !          1176: and close open file handles.
        !          1177: 
        !          1178: =item query
        !          1179: 
        !          1180:  int (*query)(const char *user, const char *group,
        !          1181:               const struct passwd *pwd);
        !          1182: 
        !          1183: The I<query> function is used to ask the group plugin whether I<user>
        !          1184: is a member of I<group>.
        !          1185: 
        !          1186: The function arguments are as follows:
        !          1187: 
        !          1188: =over 4
        !          1189: 
        !          1190: =item user
        !          1191: 
        !          1192: The name of the user being looked up in the external group database.
        !          1193: 
        !          1194: =item group
        !          1195: 
        !          1196: The name of the group being queried.
        !          1197: 
        !          1198: =item pwd
        !          1199: 
        !          1200: The password database entry for I<user>, if any.  If I<user> is not
        !          1201: present in the password database, I<pwd> will be C<NULL>.
        !          1202: 
        !          1203: =back
        !          1204: 
        !          1205: =back
        !          1206: 
        !          1207: =head3 Version Macros
        !          1208: 
        !          1209:  /* Sudoers group plugin version major/minor */
        !          1210:  #define GROUP_API_VERSION_MAJOR 1
        !          1211:  #define GROUP_API_VERSION_MINOR 0
        !          1212:  #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \
        !          1213:                             GROUP_API_VERSION_MINOR)
        !          1214: 
        !          1215:  /* Getters and setters for group version */
        !          1216:  #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
        !          1217:  #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
        !          1218:  #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \
        !          1219:      *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
        !          1220:  } while(0)
        !          1221:  #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \
        !          1222:      *(vp) = (*(vp) & 0xffff0000) | (n); \
        !          1223:  } while(0)
        !          1224: 
        !          1225: =head1 SEE ALSO
        !          1226: 
        !          1227: L<sudoers(5)>, L<sudo(8)>
        !          1228: 
        !          1229: =head1 BUGS
        !          1230: 
        !          1231: If you feel you have found a bug in B<sudo>, please submit a bug report
        !          1232: at http://www.sudo.ws/sudo/bugs/
        !          1233: 
        !          1234: =head1 SUPPORT
        !          1235: 
        !          1236: Limited free support is available via the sudo-workers mailing list,
        !          1237: see http://www.sudo.ws/mailman/listinfo/sudo-workers to subscribe or
        !          1238: search the archives.
        !          1239: 
        !          1240: =head1 DISCLAIMER
        !          1241: 
        !          1242: B<sudo> is provided ``AS IS'' and any express or implied warranties,
        !          1243: including, but not limited to, the implied warranties of merchantability
        !          1244: and fitness for a particular purpose are disclaimed.  See the LICENSE
        !          1245: file distributed with B<sudo> or http://www.sudo.ws/sudo/license.html
        !          1246: for complete details.

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