File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / doc / sudo_plugin.pod
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:23:02 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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>