File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / doc / sudo_plugin.man.in
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:26:49 2012 UTC (12 years, 2 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_5p1, HEAD
sudo 1.8.5p1

    1: .\" Copyright (c) 2009-2012 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: .\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
   17: .\"
   18: .\" Standard preamble:
   19: .\" ========================================================================
   20: .de Sp \" Vertical space (when we can't use .PP)
   21: .if t .sp .5v
   22: .if n .sp
   23: ..
   24: .de Vb \" Begin verbatim text
   25: .ft CW
   26: .nf
   27: .ne \\$1
   28: ..
   29: .de Ve \" End verbatim text
   30: .ft R
   31: .fi
   32: ..
   33: .\" Set up some character translations and predefined strings.  \*(-- will
   34: .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
   35: .\" double quote, and \*(R" will give a right double quote.  \*(C+ will
   36: .\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
   37: .\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
   38: .\" nothing in troff, for use with C<>.
   39: .tr \(*W-
   40: .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
   41: .ie n \{\
   42: .    ds -- \(*W-
   43: .    ds PI pi
   44: .    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
   45: .    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
   46: .    ds L" ""
   47: .    ds R" ""
   48: .    ds C` 
   49: .    ds C' 
   50: 'br\}
   51: .el\{\
   52: .    ds -- \|\(em\|
   53: .    ds PI \(*p
   54: .    ds L" ``
   55: .    ds R" ''
   56: 'br\}
   57: .\"
   58: .\" Escape single quotes in literal strings from groff's Unicode transform.
   59: .ie \n(.g .ds Aq \(aq
   60: .el       .ds Aq '
   61: .\"
   62: .\" If the F register is turned on, we'll generate index entries on stderr for
   63: .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
   64: .\" entries marked with X<> in POD.  Of course, you'll have to process the
   65: .\" output yourself in some meaningful fashion.
   66: .ie \nF \{\
   67: .    de IX
   68: .    tm Index:\\$1\t\\n%\t"\\$2"
   69: ..
   70: .    nr % 0
   71: .    rr F
   72: .\}
   73: .el \{\
   74: .    de IX
   75: ..
   76: .\}
   77: .\"
   78: .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
   79: .\" Fear.  Run.  Save yourself.  No user-serviceable parts.
   80: .    \" fudge factors for nroff and troff
   81: .if n \{\
   82: .    ds #H 0
   83: .    ds #V .8m
   84: .    ds #F .3m
   85: .    ds #[ \f1
   86: .    ds #] \fP
   87: .\}
   88: .if t \{\
   89: .    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
   90: .    ds #V .6m
   91: .    ds #F 0
   92: .    ds #[ \&
   93: .    ds #] \&
   94: .\}
   95: .    \" simple accents for nroff and troff
   96: .if n \{\
   97: .    ds ' \&
   98: .    ds ` \&
   99: .    ds ^ \&
  100: .    ds , \&
  101: .    ds ~ ~
  102: .    ds /
  103: .\}
  104: .if t \{\
  105: .    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
  106: .    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
  107: .    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
  108: .    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
  109: .    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
  110: .    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
  111: .\}
  112: .    \" troff and (daisy-wheel) nroff accents
  113: .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
  114: .ds 8 \h'\*(#H'\(*b\h'-\*(#H'
  115: .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
  116: .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
  117: .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
  118: .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
  119: .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
  120: .ds ae a\h'-(\w'a'u*4/10)'e
  121: .ds Ae A\h'-(\w'A'u*4/10)'E
  122: .    \" corrections for vroff
  123: .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
  124: .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
  125: .    \" for low resolution devices (crt and lpr)
  126: .if \n(.H>23 .if \n(.V>19 \
  127: \{\
  128: .    ds : e
  129: .    ds 8 ss
  130: .    ds o a
  131: .    ds d- d\h'-1'\(ga
  132: .    ds D- D\h'-1'\(hy
  133: .    ds th \o'bp'
  134: .    ds Th \o'LP'
  135: .    ds ae ae
  136: .    ds Ae AE
  137: .\}
  138: .rm #[ #] #H #V #F C
  139: .\" ========================================================================
  140: .\"
  141: .IX Title "SUDO_PLUGIN @mansectsu@"
  142: .TH SUDO_PLUGIN @mansectsu@ "April 23, 2012" "1.8.5" "MAINTENANCE COMMANDS"
  143: .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
  144: .\" way too many mistakes in technical documents.
  145: .if n .ad l
  146: .nh
  147: .SH "NAME"
  148: sudo_plugin \- Sudo Plugin API
  149: .SH "DESCRIPTION"
  150: .IX Header "DESCRIPTION"
  151: Starting with version 1.8, \fBsudo\fR supports a plugin \s-1API\s0
  152: for policy and session logging.  By default, the \fIsudoers\fR policy
  153: plugin and an associated I/O logging plugin are used.  Via the plugin
  154: \&\s-1API\s0, \fBsudo\fR can be configured to use alternate policy and/or I/O
  155: logging plugins provided by third parties.  The plugins to be used
  156: are specified via the \fI@sysconfdir@/sudo.conf\fR file.
  157: .PP
  158: The \s-1API\s0 is versioned with a major and minor number.  The minor
  159: version number is incremented when additions are made.  The major
  160: number is incremented when incompatible changes are made.  A plugin
  161: should be check the version passed to it and make sure that the
  162: major version matches.
  163: .PP
  164: The plugin \s-1API\s0 is defined by the \f(CW\*(C`sudo_plugin.h\*(C'\fR header file.
  165: .SS "The sudo.conf File"
  166: .IX Subsection "The sudo.conf File"
  167: The \fI@sysconfdir@/sudo.conf\fR file contains plugin configuration directives.
  168: Currently, the only supported keyword is the \f(CW\*(C`Plugin\*(C'\fR directive,
  169: which causes a plugin plugin to be loaded.
  170: .PP
  171: A \f(CW\*(C`Plugin\*(C'\fR line consists of the \f(CW\*(C`Plugin\*(C'\fR keyword, followed by the
  172: \&\fIsymbol_name\fR and the \fIpath\fR to the shared object containing the
  173: plugin.  The \fIsymbol_name\fR is the name of the \f(CW\*(C`struct policy_plugin\*(C'\fR
  174: or \f(CW\*(C`struct io_plugin\*(C'\fR in the plugin shared object.  The \fIpath\fR
  175: may be fully qualified or relative.  If not fully qualified it is
  176: relative to the \fI@prefix@/libexec\fR directory.  Any additional
  177: parameters after the \fIpath\fR are passed as options to the plugin's
  178: \&\fIopen\fR function.  Lines that don't begin with \f(CW\*(C`Plugin\*(C'\fR, \f(CW\*(C`Path\*(C'\fR,
  179: \&\f(CW\*(C`Debug\*(C'\fR or \f(CW\*(C`Set\*(C'\fR are silently ignored.
  180: .PP
  181: The same shared object may contain multiple plugins, each with a
  182: different symbol name.  The shared object file must be owned by uid
  183: 0 and only writable by its owner.  Because of ambiguities that arise
  184: from composite policies, only a single policy plugin may be specified.
  185: This limitation does not apply to I/O plugins.
  186: .PP
  187: .Vb 10
  188: \& #
  189: \& # Default @sysconfdir@/sudo.conf file
  190: \& #
  191: \& # Format:
  192: \& #   Plugin plugin_name plugin_path plugin_options ...
  193: \& #   Path askpass /path/to/askpass
  194: \& #   Path noexec /path/to/sudo_noexec.so
  195: \& #   Debug sudo /var/log/sudo_debug all@warn
  196: \& #   Set disable_coredump true
  197: \& #
  198: \& # The plugin_path is relative to @prefix@/libexec unless
  199: \& #   fully qualified.
  200: \& # The plugin_name corresponds to a global symbol in the plugin
  201: \& #   that contains the plugin interface structure.
  202: \& # The plugin_options are optional.
  203: \& #
  204: \& Plugin sudoers_policy sudoers.so
  205: \& Plugin sudoers_io sudoers.so
  206: .Ve
  207: .SS "Policy Plugin \s-1API\s0"
  208: .IX Subsection "Policy Plugin API"
  209: A policy plugin must declare and populate a \f(CW\*(C`policy_plugin\*(C'\fR struct
  210: in the global scope.  This structure contains pointers to the functions
  211: that implement the \fBsudo\fR policy checks.  The name of the symbol should
  212: be specified in \fI@sysconfdir@/sudo.conf\fR along with a path to the plugin
  213: so that \fBsudo\fR can load it.
  214: .PP
  215: .Vb 10
  216: \& struct policy_plugin {
  217: \& #define SUDO_POLICY_PLUGIN     1
  218: \&     unsigned int type; /* always SUDO_POLICY_PLUGIN */
  219: \&     unsigned int version; /* always SUDO_API_VERSION */
  220: \&     int (*open)(unsigned int version, sudo_conv_t conversation,
  221: \&                 sudo_printf_t plugin_printf, char * const settings[],
  222: \&                 char * const user_info[], char * const user_env[],
  223: \&                 char * const plugin_options[]);
  224: \&     void (*close)(int exit_status, int error);
  225: \&     int (*show_version)(int verbose);
  226: \&     int (*check_policy)(int argc, char * const argv[],
  227: \&                         char *env_add[], char **command_info[],
  228: \&                         char **argv_out[], char **user_env_out[]);
  229: \&     int (*list)(int argc, char * const argv[], int verbose,
  230: \&                 const char *list_user);
  231: \&     int (*validate)(void);
  232: \&     void (*invalidate)(int remove);
  233: \&     int (*init_session)(struct passwd *pwd, char **user_env[]);
  234: \&     void (*register_hooks)(int version,
  235: \&        int (*register_hook)(struct sudo_hook *hook));
  236: \&     void (*deregister_hooks)(int version,
  237: \&        int (*deregister_hook)(struct sudo_hook *hook));
  238: \& };
  239: .Ve
  240: .PP
  241: The policy_plugin struct has the following fields:
  242: .IP "type" 4
  243: .IX Item "type"
  244: The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_POLICY_PLUGIN\s0.
  245: .IP "version" 4
  246: .IX Item "version"
  247: The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0.
  248: .Sp
  249: This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was
  250: built against.
  251: .IP "open" 4
  252: .IX Item "open"
  253: .Vb 4
  254: \& int (*open)(unsigned int version, sudo_conv_t conversation,
  255: \&             sudo_printf_t plugin_printf, char * const settings[],
  256: \&             char * const user_info[], char * const user_env[],
  257: \&             char * const plugin_options[]);
  258: .Ve
  259: .Sp
  260: Returns 1 on success, 0 on failure, \-1 if a general error occurred,
  261: or \-2 if there was a usage error.  In the latter case, \fBsudo\fR will
  262: print a usage message before it exits.  If an error occurs, the
  263: plugin may optionally call the conversation or plugin_printf function
  264: with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information
  265: to the user.
  266: .Sp
  267: The function arguments are as follows:
  268: .RS 4
  269: .IP "version" 4
  270: .IX Item "version"
  271: The version passed in by \fBsudo\fR allows the plugin to determine the
  272: major and minor version number of the plugin \s-1API\s0 supported by
  273: \&\fBsudo\fR.
  274: .IP "conversation" 4
  275: .IX Item "conversation"
  276: A pointer to the conversation function that can be used by the
  277: plugin to interact with the user (see below).
  278: Returns 0 on success and \-1 on failure.
  279: .IP "plugin_printf" 4
  280: .IX Item "plugin_printf"
  281: A pointer to a printf-style function that may be used to display
  282: informational or error messages (see below).
  283: Returns the number of characters printed on success and \-1 on failure.
  284: .IP "settings" 4
  285: .IX Item "settings"
  286: A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R"
  287: strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.  These
  288: settings correspond to flags the user specified when running \fBsudo\fR.
  289: As such, they will only be present when the corresponding flag has
  290: been specified on the command line.
  291: .Sp
  292: When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR
  293: equal sign ('=') since the \fIname\fR field will never include one
  294: itself but the \fIvalue\fR might.
  295: .RS 4
  296: .IP "debug_flags=string" 4
  297: .IX Item "debug_flags=string"
  298: A comma-separated list of debug flags that correspond to \fBsudo\fR's
  299: \&\f(CW\*(C`Debug\*(C'\fR entry in \fI@sysconfdir@/sudo.conf\fR, if there is one.  The
  300: flags are passed to the plugin as they appear in \fI@sysconfdir@/sudo.conf\fR.
  301: The syntax used by \fBsudo\fR and the \fIsudoers\fR plugin is
  302: \&\fIsubsystem\fR@\fIpriority\fR but the plugin is free to use a different
  303: format so long as it does not include a command \f(CW\*(C`,\*(C'\fR.
  304: .Sp
  305: For reference, the priorities supported by the \fBsudo\fR front end and
  306: \&\fIsudoers\fR are: \fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR,
  307: \&\fIinfo\fR, \fItrace\fR and \fIdebug\fR.
  308: .Sp
  309: The following subsystems are defined: \fImain\fR, \fImemory\fR, \fIargs\fR,
  310: \&\fIexec\fR, \fIpty\fR, \fIutmp\fR, \fIconv\fR, \fIpcomm\fR, \fIutil\fR, \fIlist\fR,
  311: \&\fInetif\fR, \fIaudit\fR, \fIedit\fR, \fIselinux\fR, \fIldap\fR, \fImatch\fR, \fIparser\fR,
  312: \&\fIalias\fR, \fIdefaults\fR, \fIauth\fR, \fIenv\fR, \fIlogging\fR, \fInss\fR, \fIrbtree\fR,
  313: \&\fIperms\fR, \fIplugin\fR.  The subsystem \fIall\fR includes every subsystem.
  314: .Sp
  315: There is not currently a way to specify a set of debug flags specific
  316: to the plugin\*(--the flags are shared by \fBsudo\fR and the plugin.
  317: .IP "debug_level=number" 4
  318: .IX Item "debug_level=number"
  319: This setting has been deprecated in favor of \fIdebug_flags\fR.
  320: .IP "runas_user=string" 4
  321: .IX Item "runas_user=string"
  322: The user name or uid to to run the command as, if specified via the
  323: \&\f(CW\*(C`\-u\*(C'\fR flag.
  324: .IP "runas_group=string" 4
  325: .IX Item "runas_group=string"
  326: The group name or gid to to run the command as, if specified via
  327: the \f(CW\*(C`\-g\*(C'\fR flag.
  328: .IP "prompt=string" 4
  329: .IX Item "prompt=string"
  330: The prompt to use when requesting a password, if specified via
  331: the \f(CW\*(C`\-p\*(C'\fR flag.
  332: .IP "set_home=bool" 4
  333: .IX Item "set_home=bool"
  334: Set to true if the user specified the \f(CW\*(C`\-H\*(C'\fR flag.  If true, set the
  335: \&\f(CW\*(C`HOME\*(C'\fR environment variable to the target user's home directory.
  336: .IP "preserve_environment=bool" 4
  337: .IX Item "preserve_environment=bool"
  338: Set to true if the user specified the \f(CW\*(C`\-E\*(C'\fR flag, indicating that
  339: the user wishes to preserve the environment.
  340: .IP "run_shell=bool" 4
  341: .IX Item "run_shell=bool"
  342: Set to true if the user specified the \f(CW\*(C`\-s\*(C'\fR flag, indicating that
  343: the user wishes to run a shell.
  344: .IP "login_shell=bool" 4
  345: .IX Item "login_shell=bool"
  346: Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that
  347: the user wishes to run a login shell.
  348: .IP "implied_shell=bool" 4
  349: .IX Item "implied_shell=bool"
  350: If the user does not specify a program on the command line, \fBsudo\fR
  351: will pass the plugin the path to the user's shell and set
  352: \&\fIimplied_shell\fR to true.  This allows \fBsudo\fR with no arguments
  353: to be used similarly to \fIsu\fR\|(1).  If the plugin does not to support
  354: this usage, it may return a value of \-2 from the \f(CW\*(C`check_policy\*(C'\fR
  355: function, which will cause \fBsudo\fR to print a usage message and
  356: exit.
  357: .IP "preserve_groups=bool" 4
  358: .IX Item "preserve_groups=bool"
  359: Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that
  360: the user wishes to preserve the group vector instead of setting it
  361: based on the runas user.
  362: .IP "ignore_ticket=bool" 4
  363: .IX Item "ignore_ticket=bool"
  364: Set to true if the user specified the \f(CW\*(C`\-k\*(C'\fR flag along with a
  365: command, indicating that the user wishes to ignore any cached
  366: authentication credentials.
  367: .IP "noninteractive=bool" 4
  368: .IX Item "noninteractive=bool"
  369: Set to true if the user specified the \f(CW\*(C`\-n\*(C'\fR flag, indicating that
  370: \&\fBsudo\fR should operate in non-interactive mode.  The plugin may
  371: reject a command run in non-interactive mode if user interaction
  372: is required.
  373: .IP "login_class=string" 4
  374: .IX Item "login_class=string"
  375: \&\s-1BSD\s0 login class to use when setting resource limits and nice value,
  376: if specified by the \f(CW\*(C`\-c\*(C'\fR flag.
  377: .IP "selinux_role=string" 4
  378: .IX Item "selinux_role=string"
  379: SELinux role to use when executing the command, if specified by
  380: the \f(CW\*(C`\-r\*(C'\fR flag.
  381: .IP "selinux_type=string" 4
  382: .IX Item "selinux_type=string"
  383: SELinux type to use when executing the command, if specified by
  384: the \f(CW\*(C`\-t\*(C'\fR flag.
  385: .IP "bsdauth_type=string" 4
  386: .IX Item "bsdauth_type=string"
  387: Authentication type, if specified by the \f(CW\*(C`\-a\*(C'\fR flag, to use on
  388: systems where \s-1BSD\s0 authentication is supported.
  389: .IP "network_addrs=list" 4
  390: .IX Item "network_addrs=list"
  391: A space-separated list of \s-1IP\s0 network addresses and netmasks in the
  392: form \*(L"addr/netmask\*(R", e.g. \*(L"192.168.1.2/255.255.255.0\*(R".  The address
  393: and netmask pairs may be either IPv4 or IPv6, depending on what the
  394: operating system supports.  If the address contains a colon (':'),
  395: it is an IPv6 address, else it is IPv4.
  396: .IP "progname=string" 4
  397: .IX Item "progname=string"
  398: The command name that sudo was run as, typically \*(L"sudo\*(R" or \*(L"sudoedit\*(R".
  399: .IP "sudoedit=bool" 4
  400: .IX Item "sudoedit=bool"
  401: Set to true when the \f(CW\*(C`\-e\*(C'\fR flag is is specified or if invoked as
  402: \&\fBsudoedit\fR.  The plugin shall substitute an editor into \fIargv\fR
  403: in the \fIcheck_policy\fR function or return \f(CW\*(C`\-2\*(C'\fR with a usage error
  404: if the plugin does not support \fIsudoedit\fR.  For more information,
  405: see the \fIcheck_policy\fR section.
  406: .IP "closefrom=number" 4
  407: .IX Item "closefrom=number"
  408: If specified, the user has requested via the \f(CW\*(C`\-C\*(C'\fR flag that \fBsudo\fR
  409: close all files descriptors with a value of \fInumber\fR or higher.
  410: The plugin may optionally pass this, or another value, back in the
  411: \&\fIcommand_info\fR list.
  412: .RE
  413: .RS 4
  414: .Sp
  415: Additional settings may be added in the future so the plugin should
  416: silently ignore settings that it does not recognize.
  417: .RE
  418: .IP "user_info" 4
  419: .IX Item "user_info"
  420: A vector of information about the user running the command in the form of
  421: \&\*(L"name=value\*(R" strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.
  422: .Sp
  423: When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR
  424: equal sign ('=') since the \fIname\fR field will never include one
  425: itself but the \fIvalue\fR might.
  426: .RS 4
  427: .IP "pid=int" 4
  428: .IX Item "pid=int"
  429: The process \s-1ID\s0 of the running \fBsudo\fR process.
  430: Only available starting with \s-1API\s0 version 1.2
  431: .IP "ppid=int" 4
  432: .IX Item "ppid=int"
  433: The parent process \s-1ID\s0 of the running \fBsudo\fR process.
  434: Only available starting with \s-1API\s0 version 1.2
  435: .IP "sid=int" 4
  436: .IX Item "sid=int"
  437: The session \s-1ID\s0 of the running \fBsudo\fR process or 0 if \fBsudo\fR is
  438: not part of a \s-1POSIX\s0 job control session.
  439: Only available starting with \s-1API\s0 version 1.2
  440: .IP "pgid=int" 4
  441: .IX Item "pgid=int"
  442: The \s-1ID\s0 of the process group that the running \fBsudo\fR process belongs
  443: to.
  444: Only available starting with \s-1API\s0 version 1.2
  445: .IP "tcpgid=int" 4
  446: .IX Item "tcpgid=int"
  447: The \s-1ID\s0 of the forground process group associated with the terminal
  448: device associcated with the \fBsudo\fR process or \-1 if there is no
  449: terminal present.
  450: Only available starting with \s-1API\s0 version 1.2
  451: .IP "user=string" 4
  452: .IX Item "user=string"
  453: The name of the user invoking \fBsudo\fR.
  454: .IP "euid=uid_t" 4
  455: .IX Item "euid=uid_t"
  456: The effective user \s-1ID\s0 of the user invoking \fBsudo\fR.
  457: .IP "uid=uid_t" 4
  458: .IX Item "uid=uid_t"
  459: The real user \s-1ID\s0 of the user invoking \fBsudo\fR.
  460: .IP "egid=gid_t" 4
  461: .IX Item "egid=gid_t"
  462: The effective group \s-1ID\s0 of the user invoking \fBsudo\fR.
  463: .IP "gid=gid_t" 4
  464: .IX Item "gid=gid_t"
  465: The real group \s-1ID\s0 of the user invoking \fBsudo\fR.
  466: .IP "groups=list" 4
  467: .IX Item "groups=list"
  468: The user's supplementary group list formatted as a string of
  469: comma-separated group IDs.
  470: .IP "cwd=string" 4
  471: .IX Item "cwd=string"
  472: The user's current working directory.
  473: .IP "tty=string" 4
  474: .IX Item "tty=string"
  475: The path to the user's terminal device.  If the user has no terminal
  476: device associated with the session, the value will be empty, as in
  477: \&\f(CW\*(C`tty=\*(C'\fR.
  478: .IP "host=string" 4
  479: .IX Item "host=string"
  480: The local machine's hostname as returned by the \f(CW\*(C`gethostname()\*(C'\fR
  481: system call.
  482: .IP "lines=int" 4
  483: .IX Item "lines=int"
  484: The number of lines the user's terminal supports.  If there is
  485: no terminal device available, a default value of 24 is used.
  486: .IP "cols=int" 4
  487: .IX Item "cols=int"
  488: The number of columns the user's terminal supports.  If there is
  489: no terminal device available, a default value of 80 is used.
  490: .RE
  491: .RS 4
  492: .RE
  493: .IP "user_env" 4
  494: .IX Item "user_env"
  495: The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of
  496: \&\*(L"name=value\*(R" strings.
  497: .Sp
  498: When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR
  499: equal sign ('=') since the \fIname\fR field will never include one
  500: itself but the \fIvalue\fR might.
  501: .IP "plugin_options" 4
  502: .IX Item "plugin_options"
  503: Any (non-comment) strings immediately after the plugin path are
  504: treated as arguments to the plugin.  These arguments are split on
  505: a white space boundary and are passed to the plugin in the form of
  506: a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings.  If no arguments were
  507: specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer.
  508: .Sp
  509: \&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with
  510: \&\s-1API\s0 version 1.2.  A plugin \fBmust\fR check the \s-1API\s0 version specified
  511: by the \fBsudo\fR front end before using \fIplugin_options\fR.  Failure to
  512: do so may result in a crash.
  513: .RE
  514: .RS 4
  515: .RE
  516: .IP "close" 4
  517: .IX Item "close"
  518: .Vb 1
  519: \& void (*close)(int exit_status, int error);
  520: .Ve
  521: .Sp
  522: The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR
  523: finishes.
  524: .Sp
  525: The function arguments are as follows:
  526: .RS 4
  527: .IP "exit_status" 4
  528: .IX Item "exit_status"
  529: The command's exit status, as returned by the \fIwait\fR\|(2) system call.
  530: The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero.
  531: .IP "error" 4
  532: .IX Item "error"
  533: If the command could not be executed, this is set to the value of
  534: \&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call.  The plugin is responsible
  535: for displaying error information via the conversation or plugin_printf
  536: function.  If the command was successfully executed, the value of
  537: \&\f(CW\*(C`error\*(C'\fR is 0.
  538: .RE
  539: .RS 4
  540: .RE
  541: .IP "show_version" 4
  542: .IX Item "show_version"
  543: .Vb 1
  544: \& int (*show_version)(int verbose);
  545: .Ve
  546: .Sp
  547: The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies
  548: the \f(CW\*(C`\-V\*(C'\fR option.  The plugin may display its version information
  549: to the user via the conversation or plugin_printf function using
  550: \&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR.  If the user requests detailed version
  551: information, the verbose flag will be set.
  552: .IP "check_policy" 4
  553: .IX Item "check_policy"
  554: .Vb 3
  555: \& int (*check_policy)(int argc, char * const argv[]
  556: \&                     char *env_add[], char **command_info[],
  557: \&                     char **argv_out[], char **user_env_out[]);
  558: .Ve
  559: .Sp
  560: The \fIcheck_policy\fR function is called by \fBsudo\fR to determine
  561: whether the user is allowed to run the specified commands.
  562: .Sp
  563: If the \fIsudoedit\fR option was enabled in the \fIsettings\fR array
  564: passed to the \fIopen\fR function, the user has requested \fIsudoedit\fR
  565: mode.  \fIsudoedit\fR is a mechanism for editing one or more files
  566: where an editor is run with the user's credentials instead of with
  567: elevated privileges.  \fBsudo\fR achieves this by creating user-writable
  568: temporary copies of the files to be edited and then overwriting the
  569: originals with the temporary copies after editing is complete.  If
  570: the plugin supports \fBsudoedit\fR, it should choose the editor to be
  571: used, potentially from a variable in the user's environment, such
  572: as \f(CW\*(C`EDITOR\*(C'\fR, and include it in \fIargv_out\fR (note that environment
  573: variables may include command line flags).  The files to be edited
  574: should be copied from \fIargv\fR into \fIargv_out\fR, separated from the
  575: editor and its arguments by a \f(CW"\-\-"\fR element.  The \f(CW"\-\-"\fR will
  576: be removed by \fBsudo\fR before the editor is executed.  The plugin
  577: should also set \fIsudoedit=true\fR in the \fIcommand_info\fR list.
  578: .Sp
  579: The \fIcheck_policy\fR function returns 1 if the command is allowed,
  580: 0 if not allowed, \-1 for a general error, or \-2 for a usage error
  581: or if \fBsudoedit\fR was specified but is unsupported by the plugin.
  582: In the latter case, \fBsudo\fR will print a usage message before it
  583: exits.  If an error occurs, the plugin may optionally call the
  584: conversation or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR
  585: to present additional error information to the user.
  586: .Sp
  587: The function arguments are as follows:
  588: .RS 4
  589: .IP "argc" 4
  590: .IX Item "argc"
  591: The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR
  592: pointer.
  593: .IP "argv" 4
  594: .IX Item "argv"
  595: The argument vector describing the command the user wishes to run,
  596: in the same form as what would be passed to the \fIexecve()\fR system
  597: call.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.
  598: .IP "env_add" 4
  599: .IX Item "env_add"
  600: Additional environment variables specified by the user on the command
  601: line in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R"
  602: strings.  The plugin may reject the command if one or more variables
  603: are not allowed to be set, or it may silently ignore such variables.
  604: .Sp
  605: When parsing \fIenv_add\fR, the plugin should split on the \fBfirst\fR
  606: equal sign ('=') since the \fIname\fR field will never include one
  607: itself but the \fIvalue\fR might.
  608: .IP "command_info" 4
  609: .IX Item "command_info"
  610: Information about the command being run in the form of \*(L"name=value\*(R"
  611: strings.  These values are used by \fBsudo\fR to set the execution
  612: environment when running a command.  The plugin is responsible for
  613: creating and populating the vector, which must be terminated with
  614: a \f(CW\*(C`NULL\*(C'\fR pointer.  The following values are recognized by \fBsudo\fR:
  615: .RS 4
  616: .IP "command=string" 4
  617: .IX Item "command=string"
  618: Fully qualified path to the command to be executed.
  619: .IP "runas_uid=uid" 4
  620: .IX Item "runas_uid=uid"
  621: User \s-1ID\s0 to run the command as.
  622: .IP "runas_euid=uid" 4
  623: .IX Item "runas_euid=uid"
  624: Effective user \s-1ID\s0 to run the command as.
  625: If not specified, the value of \fIrunas_uid\fR is used.
  626: .IP "runas_gid=gid" 4
  627: .IX Item "runas_gid=gid"
  628: Group \s-1ID\s0 to run the command as.
  629: .IP "runas_egid=gid" 4
  630: .IX Item "runas_egid=gid"
  631: Effective group \s-1ID\s0 to run the command as.
  632: If not specified, the value of \fIrunas_gid\fR is used.
  633: .IP "runas_groups=list" 4
  634: .IX Item "runas_groups=list"
  635: The supplementary group vector to use for the command in the form
  636: of a comma-separated list of group IDs.  If \fIpreserve_groups\fR
  637: is set, this option is ignored.
  638: .IP "login_class=string" 4
  639: .IX Item "login_class=string"
  640: \&\s-1BSD\s0 login class to use when setting resource limits and nice value
  641: (optional).  This option is only set on systems that support login
  642: classes.
  643: .IP "preserve_groups=bool" 4
  644: .IX Item "preserve_groups=bool"
  645: If set, \fBsudo\fR will preserve the user's group vector instead of
  646: initializing the group vector based on \f(CW\*(C`runas_user\*(C'\fR.
  647: .IP "cwd=string" 4
  648: .IX Item "cwd=string"
  649: The current working directory to change to when executing the command.
  650: .IP "noexec=bool" 4
  651: .IX Item "noexec=bool"
  652: If set, prevent the command from executing other programs.
  653: .IP "chroot=string" 4
  654: .IX Item "chroot=string"
  655: The root directory to use when running the command.
  656: .IP "nice=int" 4
  657: .IX Item "nice=int"
  658: Nice value (priority) to use when executing the command.  The nice
  659: value, if specified, overrides the priority associated with the
  660: \&\fIlogin_class\fR on \s-1BSD\s0 systems.
  661: .IP "umask=octal" 4
  662: .IX Item "umask=octal"
  663: The file creation mask to use when executing the command.
  664: .IP "selinux_role=string" 4
  665: .IX Item "selinux_role=string"
  666: SELinux role to use when executing the command.
  667: .IP "selinux_type=string" 4
  668: .IX Item "selinux_type=string"
  669: SELinux type to use when executing the command.
  670: .IP "timeout=int" 4
  671: .IX Item "timeout=int"
  672: Command timeout.  If non-zero then when the timeout expires the
  673: command will be killed.
  674: .IP "sudoedit=bool" 4
  675: .IX Item "sudoedit=bool"
  676: Set to true when in \fIsudoedit\fR mode.  The plugin may enable
  677: \&\fIsudoedit\fR mode even if \fBsudo\fR was not invoked as \fBsudoedit\fR.
  678: This allows the plugin to perform command substitution and transparently
  679: enable \fIsudoedit\fR when the user attempts to run an editor.
  680: .IP "closefrom=number" 4
  681: .IX Item "closefrom=number"
  682: If specified, \fBsudo\fR will close all files descriptors with a value
  683: of \fInumber\fR or higher.
  684: .IP "iolog_compress=bool" 4
  685: .IX Item "iolog_compress=bool"
  686: Set to true if the I/O logging plugins, if any, should compress the
  687: log data.  This is a hint to the I/O logging plugin which may choose
  688: to ignore it.
  689: .IP "iolog_path=string" 4
  690: .IX Item "iolog_path=string"
  691: Fully qualified path to the file or directory in which I/O log is
  692: to be stored.  This is a hint to the I/O logging plugin which may
  693: choose to ignore it.  If no I/O logging plugin is loaded, this
  694: setting has no effect.
  695: .IP "iolog_stdin=bool" 4
  696: .IX Item "iolog_stdin=bool"
  697: Set to true if the I/O logging plugins, if any, should log the
  698: standard input if it is not connected to a terminal device.  This
  699: is a hint to the I/O logging plugin which may choose to ignore it.
  700: .IP "iolog_stdout=bool" 4
  701: .IX Item "iolog_stdout=bool"
  702: Set to true if the I/O logging plugins, if any, should log the
  703: standard output if it is not connected to a terminal device.  This
  704: is a hint to the I/O logging plugin which may choose to ignore it.
  705: .IP "iolog_stderr=bool" 4
  706: .IX Item "iolog_stderr=bool"
  707: Set to true if the I/O logging plugins, if any, should log the
  708: standard error if it is not connected to a terminal device.  This
  709: is a hint to the I/O logging plugin which may choose to ignore it.
  710: .IP "iolog_ttyin=bool" 4
  711: .IX Item "iolog_ttyin=bool"
  712: Set to true if the I/O logging plugins, if any, should log all
  713: terminal input.  This only includes input typed by the user and not
  714: from a pipe or redirected from a file.  This is a hint to the I/O
  715: logging plugin which may choose to ignore it.
  716: .IP "iolog_ttyout=bool" 4
  717: .IX Item "iolog_ttyout=bool"
  718: Set to true if the I/O logging plugins, if any, should log all
  719: terminal output.  This only includes output to the screen, not
  720: output to a pipe or file.  This is a hint to the I/O logging plugin
  721: which may choose to ignore it.
  722: .IP "use_pty=bool" 4
  723: .IX Item "use_pty=bool"
  724: Allocate a pseudo-tty to run the command in, regardless of whether
  725: or not I/O logging is in use.  By default, \fBsudo\fR will only run
  726: the command in a pty when an I/O log plugin is loaded.
  727: .IP "set_utmp=bool" 4
  728: .IX Item "set_utmp=bool"
  729: Create a utmp (or utmpx) entry when a pseudo-tty is allocated.  By
  730: default, the new entry will be a copy of the user's existing utmp
  731: entry (if any), with the tty, time, type and pid fields updated.
  732: .IP "utmp_user=string" 4
  733: .IX Item "utmp_user=string"
  734: User name to use when constructing a new utmp (or utmpx) entry when
  735: \&\fIset_utmp\fR is enabled.  This option can be used to set the user
  736: field in the utmp entry to the user the command runs as rather than
  737: the invoking user.  If not set, \fBsudo\fR will base the new entry on
  738: the invoking user's existing entry.
  739: .RE
  740: .RS 4
  741: .Sp
  742: Unsupported values will be ignored.
  743: .RE
  744: .IP "argv_out" 4
  745: .IX Item "argv_out"
  746: The \f(CW\*(C`NULL\*(C'\fR\-terminated argument vector to pass to the \fIexecve()\fR
  747: system call when executing the command.  The plugin is responsible
  748: for allocating and populating the vector.
  749: .IP "user_env_out" 4
  750: .IX Item "user_env_out"
  751: The \f(CW\*(C`NULL\*(C'\fR\-terminated environment vector to use when executing the
  752: command.  The plugin is responsible for allocating and populating
  753: the vector.
  754: .RE
  755: .RS 4
  756: .RE
  757: .IP "list" 4
  758: .IX Item "list"
  759: .Vb 2
  760: \& int (*list)(int verbose, const char *list_user,
  761: \&             int argc, char * const argv[]);
  762: .Ve
  763: .Sp
  764: List available privileges for the invoking user.  Returns 1 on
  765: success, 0 on failure and \-1 on error.  On error, the plugin may
  766: optionally call the conversation or plugin_printf function with
  767: \&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to
  768: the user.
  769: .Sp
  770: Privileges should be output via the conversation or plugin_printf
  771: function using \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR.
  772: .RS 4
  773: .IP "verbose" 4
  774: .IX Item "verbose"
  775: Flag indicating whether to list in verbose mode or not.
  776: .IP "list_user" 4
  777: .IX Item "list_user"
  778: The name of a different user to list privileges for if the policy
  779: allows it.  If \f(CW\*(C`NULL\*(C'\fR, the plugin should list the privileges of
  780: the invoking user.
  781: .IP "argc" 4
  782: .IX Item "argc"
  783: The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR
  784: pointer.
  785: .IP "argv" 4
  786: .IX Item "argv"
  787: If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user
  788: wishes to check against the policy in the same form as what would
  789: be passed to the \fIexecve()\fR system call.  If the command is permitted
  790: by the policy, the fully-qualified path to the command should be
  791: displayed along with any command line arguments.
  792: .RE
  793: .RS 4
  794: .RE
  795: .IP "validate" 4
  796: .IX Item "validate"
  797: .Vb 1
  798: \& int (*validate)(void);
  799: .Ve
  800: .Sp
  801: The \f(CW\*(C`validate\*(C'\fR function is called when \fBsudo\fR is run with the
  802: \&\f(CW\*(C`\-v\*(C'\fR flag.  For policy plugins such as \fIsudoers\fR that cache
  803: authentication credentials, this function will validate and cache
  804: the credentials.
  805: .Sp
  806: The \f(CW\*(C`validate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not
  807: support credential caching.
  808: .Sp
  809: Returns 1 on success, 0 on failure and \-1 on error.
  810: On error, the plugin may optionally call the conversation or plugin_printf
  811: function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional
  812: error information to the user.
  813: .IP "invalidate" 4
  814: .IX Item "invalidate"
  815: .Vb 1
  816: \& void (*invalidate)(int remove);
  817: .Ve
  818: .Sp
  819: The \f(CW\*(C`invalidate\*(C'\fR function is called when \fBsudo\fR is called with
  820: the \f(CW\*(C`\-k\*(C'\fR or \f(CW\*(C`\-K\*(C'\fR flag.  For policy plugins such as \fIsudoers\fR that
  821: cache authentication credentials, this function will invalidate the
  822: credentials.  If the \fIremove\fR flag is set, the plugin may remove
  823: the credentials instead of simply invalidating them.
  824: .Sp
  825: The \f(CW\*(C`invalidate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not
  826: support credential caching.
  827: .IP "init_session" 4
  828: .IX Item "init_session"
  829: .Vb 1
  830: \& int (*init_session)(struct passwd *pwd, char **user_envp[);
  831: .Ve
  832: .Sp
  833: The \f(CW\*(C`init_session\*(C'\fR function is called before \fBsudo\fR sets up the
  834: execution environment for the command.  It is run in the parent
  835: \&\fBsudo\fR process and before any uid or gid changes.  This can be used
  836: to perform session setup that is not supported by \fIcommand_info\fR,
  837: such as opening the \s-1PAM\s0 session.  The \f(CW\*(C`close\*(C'\fR function can be
  838: used to tear down the session that was opened by \f(CW\*(C`init_session\*(C'\fR.
  839: .Sp
  840: The \fIpwd\fR argument points to a passwd struct for the user the
  841: command will be run as if the uid the command will run as was found
  842: in the password database, otherwise it will be \s-1NULL\s0.
  843: .Sp
  844: The \fIuser_env\fR argument points to the environment the command will
  845: run in, in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R"
  846: strings.  This is the same string passed back to the front end via
  847: the Policy Plugin's \fIuser_env_out\fR parameter.  If the \f(CW\*(C`init_session\*(C'\fR
  848: function needs to modify the user environment, it should update the
  849: pointer stored in \fIuser_env\fR.  The expected use case is to merge
  850: the contents of the \s-1PAM\s0 environment (if any) with the contents of
  851: \&\fIuser_env\fR.  \s-1NOTE:\s0 the \fIuser_env\fR parameter is only available
  852: starting with \s-1API\s0 version 1.2.  A plugin \fBmust\fR check the \s-1API\s0
  853: version specified by the \fBsudo\fR front end before using \fIuser_env\fR.
  854: Failure to do so may result in a crash.
  855: .Sp
  856: Returns 1 on success, 0 on failure and \-1 on error.
  857: On error, the plugin may optionally call the conversation or plugin_printf
  858: function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional
  859: error information to the user.
  860: .IP "register_hooks" 4
  861: .IX Item "register_hooks"
  862: .Vb 2
  863: \& void (*register_hooks)(int version,
  864: \&    int (*register_hook)(struct sudo_hook *hook));
  865: .Ve
  866: .Sp
  867: The \f(CW\*(C`register_hooks\*(C'\fR function is called by the sudo front end to
  868: register any hooks the plugin needs.  If the plugin does not support
  869: hooks, \f(CW\*(C`register_hooks\*(C'\fR should be set to the \s-1NULL\s0 pointer.
  870: .Sp
  871: The \fIversion\fR argument describes the version of the hooks \s-1API\s0
  872: supported by the \fBsudo\fR front end.
  873: .Sp
  874: The \f(CW\*(C`register_hook\*(C'\fR function should be used to register any supported
  875: hooks the plugin needs.  It returns 0 on success, 1 if the hook
  876: type is not supported and \-1 if the major version in \f(CW\*(C`struct hook\*(C'\fR
  877: does not match the front end's major hook \s-1API\s0 version.
  878: .Sp
  879: See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information
  880: about hooks.
  881: .Sp
  882: \&\s-1NOTE:\s0 the \f(CW\*(C`register_hooks\*(C'\fR function is only available starting
  883: with \s-1API\s0 version 1.2.  If the \fBsudo\fR front end doesn't support \s-1API\s0
  884: version 1.2 or higher, \f(CW\*(C`register_hooks\*(C'\fR will not be called.
  885: .IP "deregister_hooks" 4
  886: .IX Item "deregister_hooks"
  887: .Vb 2
  888: \& void (*deregister_hooks)(int version,
  889: \&    int (*deregister_hook)(struct sudo_hook *hook));
  890: .Ve
  891: .Sp
  892: The \f(CW\*(C`deregister_hooks\*(C'\fR function is called by the sudo front end
  893: to deregister any hooks the plugin has registered.  If the plugin
  894: does not support hooks, \f(CW\*(C`deregister_hooks\*(C'\fR should be set to the
  895: \&\s-1NULL\s0 pointer.
  896: .Sp
  897: The \fIversion\fR argument describes the version of the hooks \s-1API\s0
  898: supported by the \fBsudo\fR front end.
  899: .Sp
  900: The \f(CW\*(C`deregister_hook\*(C'\fR function should be used to deregister any
  901: hooks that were put in place by the \f(CW\*(C`register_hook\*(C'\fR function.  If
  902: the plugin tries to deregister a hook that the front end does not
  903: support, \f(CW\*(C`deregister_hook\*(C'\fR will return an error.
  904: .Sp
  905: See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information
  906: about hooks.
  907: .Sp
  908: \&\s-1NOTE:\s0 the \f(CW\*(C`deregister_hooks\*(C'\fR function is only available starting
  909: with \s-1API\s0 version 1.2.  If the \fBsudo\fR front end doesn't support \s-1API\s0
  910: version 1.2 or higher, \f(CW\*(C`deregister_hooks\*(C'\fR will not be called.
  911: .PP
  912: \fIPolicy Plugin Version Macros\fR
  913: .IX Subsection "Policy Plugin Version Macros"
  914: .PP
  915: .Vb 6
  916: \& /* Plugin API version major/minor. */
  917: \& #define SUDO_API_VERSION_MAJOR 1
  918: \& #define SUDO_API_VERSION_MINOR 2
  919: \& #define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
  920: \& #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
  921: \&                                             SUDO_API_VERSION_MINOR)
  922: \&
  923: \& /* Getters and setters for API version */
  924: \& #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
  925: \& #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
  926: \& #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
  927: \&     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
  928: \& } while(0)
  929: \& #define SUDO_VERSION_SET_MINOR(vp, n) do { \e
  930: \&     *(vp) = (*(vp) & 0xffff0000) | (n); \e
  931: \& } while(0)
  932: .Ve
  933: .SS "I/O Plugin \s-1API\s0"
  934: .IX Subsection "I/O Plugin API"
  935: .Vb 10
  936: \& struct io_plugin {
  937: \& #define SUDO_IO_PLUGIN         2
  938: \&     unsigned int type; /* always SUDO_IO_PLUGIN */
  939: \&     unsigned int version; /* always SUDO_API_VERSION */
  940: \&     int (*open)(unsigned int version, sudo_conv_t conversation
  941: \&                 sudo_printf_t plugin_printf, char * const settings[],
  942: \&                 char * const user_info[], int argc, char * const argv[],
  943: \&                 char * const user_env[], char * const plugin_options[]);
  944: \&     void (*close)(int exit_status, int error); /* wait status or error */
  945: \&     int (*show_version)(int verbose);
  946: \&     int (*log_ttyin)(const char *buf, unsigned int len);
  947: \&     int (*log_ttyout)(const char *buf, unsigned int len);
  948: \&     int (*log_stdin)(const char *buf, unsigned int len);
  949: \&     int (*log_stdout)(const char *buf, unsigned int len);
  950: \&     int (*log_stderr)(const char *buf, unsigned int len);
  951: \&     void (*register_hooks)(int version,
  952: \&        int (*register_hook)(struct sudo_hook *hook));
  953: \&     void (*deregister_hooks)(int version,
  954: \&        int (*deregister_hook)(struct sudo_hook *hook));
  955: \& };
  956: .Ve
  957: .PP
  958: When an I/O plugin is loaded, \fBsudo\fR runs the command in a pseudo-tty.
  959: This makes it possible to log the input and output from the user's
  960: session.  If any of the standard input, standard output or standard
  961: error do not correspond to a tty, \fBsudo\fR will open a pipe to capture
  962: the I/O for logging before passing it on.
  963: .PP
  964: The log_ttyin function receives the raw user input from the terminal
  965: device (note that this will include input even when echo is disabled,
  966: such as when a password is read). The log_ttyout function receives
  967: output from the pseudo-tty that is suitable for replaying the user's
  968: session at a later time.  The log_stdin, log_stdout and log_stderr
  969: functions are only called if the standard input, standard output
  970: or standard error respectively correspond to something other than
  971: a tty.
  972: .PP
  973: Any of the logging functions may be set to the \s-1NULL\s0
  974: pointer if no logging is to be performed.  If the open function
  975: returns \f(CW0\fR, no I/O will be sent to the plugin.
  976: .PP
  977: The io_plugin struct has the following fields:
  978: .IP "type" 4
  979: .IX Item "type"
  980: The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_IO_PLUGIN\s0
  981: .IP "version" 4
  982: .IX Item "version"
  983: The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0.
  984: .Sp
  985: This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was
  986: built against.
  987: .IP "open" 4
  988: .IX Item "open"
  989: .Vb 4
  990: \& int (*open)(unsigned int version, sudo_conv_t conversation
  991: \&             sudo_printf_t plugin_printf, char * const settings[],
  992: \&             char * const user_info[], int argc, char * const argv[],
  993: \&             char * const user_env[], char * const plugin_options[]);
  994: .Ve
  995: .Sp
  996: The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR
  997: or \fIshow_version\fR functions are called.  It is only called if the
  998: version is being requested or the \fIcheck_policy\fR function has
  999: returned successfully.  It returns 1 on success, 0 on failure, \-1
 1000: if a general error occurred, or \-2 if there was a usage error.  In
 1001: the latter case, \fBsudo\fR will print a usage message before it exits.
 1002: If an error occurs, the plugin may optionally call the conversation
 1003: or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present
 1004: additional error information to the user.
 1005: .Sp
 1006: The function arguments are as follows:
 1007: .RS 4
 1008: .IP "version" 4
 1009: .IX Item "version"
 1010: The version passed in by \fBsudo\fR allows the plugin to determine the
 1011: major and minor version number of the plugin \s-1API\s0 supported by
 1012: \&\fBsudo\fR.
 1013: .IP "conversation" 4
 1014: .IX Item "conversation"
 1015: A pointer to the conversation function that may be used by the
 1016: \&\fIshow_version\fR function to display version information (see
 1017: show_version below).  The conversation function may also be used
 1018: to display additional error message to the user.
 1019: The conversation function returns 0 on success and \-1 on failure.
 1020: .IP "plugin_printf" 4
 1021: .IX Item "plugin_printf"
 1022: A pointer to a printf-style function that may be used by the
 1023: \&\fIshow_version\fR function to display version information (see
 1024: show_version below).  The plugin_printf function may also be used
 1025: to display additional error message to the user.
 1026: The plugin_printf function returns number of characters printed on
 1027: success and \-1 on failure.
 1028: .IP "settings" 4
 1029: .IX Item "settings"
 1030: A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R"
 1031: strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.  These
 1032: settings correspond to flags the user specified when running \fBsudo\fR.
 1033: As such, they will only be present when the corresponding flag has
 1034: been specified on the command line.
 1035: .Sp
 1036: When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR
 1037: equal sign ('=') since the \fIname\fR field will never include one
 1038: itself but the \fIvalue\fR might.
 1039: .Sp
 1040: See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible settings.
 1041: .IP "user_info" 4
 1042: .IX Item "user_info"
 1043: A vector of information about the user running the command in the form of
 1044: \&\*(L"name=value\*(R" strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.
 1045: .Sp
 1046: When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR
 1047: equal sign ('=') since the \fIname\fR field will never include one
 1048: itself but the \fIvalue\fR might.
 1049: .Sp
 1050: See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible strings.
 1051: .IP "argc" 4
 1052: .IX Item "argc"
 1053: The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR
 1054: pointer.
 1055: .IP "argv" 4
 1056: .IX Item "argv"
 1057: If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user
 1058: wishes to run in the same form as what would be passed to the
 1059: \&\fIexecve()\fR system call.
 1060: .IP "user_env" 4
 1061: .IX Item "user_env"
 1062: The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of
 1063: \&\*(L"name=value\*(R" strings.
 1064: .Sp
 1065: When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR
 1066: equal sign ('=') since the \fIname\fR field will never include one
 1067: itself but the \fIvalue\fR might.
 1068: .IP "plugin_options" 4
 1069: .IX Item "plugin_options"
 1070: Any (non-comment) strings immediately after the plugin path are
 1071: treated as arguments to the plugin.  These arguments are split on
 1072: a white space boundary and are passed to the plugin in the form of
 1073: a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings.  If no arguments were
 1074: specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer.
 1075: .Sp
 1076: \&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with
 1077: \&\s-1API\s0 version 1.2.  A plugin \fBmust\fR check the \s-1API\s0 version specified
 1078: by the \fBsudo\fR front end before using \fIplugin_options\fR.  Failure to
 1079: do so may result in a crash.
 1080: .RE
 1081: .RS 4
 1082: .RE
 1083: .IP "close" 4
 1084: .IX Item "close"
 1085: .Vb 1
 1086: \& void (*close)(int exit_status, int error);
 1087: .Ve
 1088: .Sp
 1089: The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR
 1090: finishes.
 1091: .Sp
 1092: The function arguments are as follows:
 1093: .RS 4
 1094: .IP "exit_status" 4
 1095: .IX Item "exit_status"
 1096: The command's exit status, as returned by the \fIwait\fR\|(2) system call.
 1097: The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero.
 1098: .IP "error" 4
 1099: .IX Item "error"
 1100: If the command could not be executed, this is set to the value of
 1101: \&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call.  If the command was
 1102: successfully executed, the value of \f(CW\*(C`error\*(C'\fR is 0.
 1103: .RE
 1104: .RS 4
 1105: .RE
 1106: .IP "show_version" 4
 1107: .IX Item "show_version"
 1108: .Vb 1
 1109: \& int (*show_version)(int verbose);
 1110: .Ve
 1111: .Sp
 1112: The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies
 1113: the \f(CW\*(C`\-V\*(C'\fR option.  The plugin may display its version information
 1114: to the user via the conversation or plugin_printf function using
 1115: \&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR.  If the user requests detailed version
 1116: information, the verbose flag will be set.
 1117: .IP "log_ttyin" 4
 1118: .IX Item "log_ttyin"
 1119: .Vb 1
 1120: \& int (*log_ttyin)(const char *buf, unsigned int len);
 1121: .Ve
 1122: .Sp
 1123: The \fIlog_ttyin\fR function is called whenever data can be read from
 1124: the user but before it is passed to the running command.  This
 1125: allows the plugin to reject data if it chooses to (for instance
 1126: if the input contains banned content).  Returns \f(CW1\fR if the data
 1127: should be passed to the command, \f(CW0\fR if the data is rejected
 1128: (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred.
 1129: .Sp
 1130: The function arguments are as follows:
 1131: .RS 4
 1132: .IP "buf" 4
 1133: .IX Item "buf"
 1134: The buffer containing user input.
 1135: .IP "len" 4
 1136: .IX Item "len"
 1137: The length of \fIbuf\fR in bytes.
 1138: .RE
 1139: .RS 4
 1140: .RE
 1141: .IP "log_ttyout" 4
 1142: .IX Item "log_ttyout"
 1143: .Vb 1
 1144: \& int (*log_ttyout)(const char *buf, unsigned int len);
 1145: .Ve
 1146: .Sp
 1147: The \fIlog_ttyout\fR function is called whenever data can be read from
 1148: the command but before it is written to the user's terminal.  This
 1149: allows the plugin to reject data if it chooses to (for instance
 1150: if the output contains banned content).  Returns \f(CW1\fR if the data
 1151: should be passed to the user, \f(CW0\fR if the data is rejected
 1152: (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred.
 1153: .Sp
 1154: The function arguments are as follows:
 1155: .RS 4
 1156: .IP "buf" 4
 1157: .IX Item "buf"
 1158: The buffer containing command output.
 1159: .IP "len" 4
 1160: .IX Item "len"
 1161: The length of \fIbuf\fR in bytes.
 1162: .RE
 1163: .RS 4
 1164: .RE
 1165: .IP "log_stdin" 4
 1166: .IX Item "log_stdin"
 1167: .Vb 1
 1168: \& int (*log_stdin)(const char *buf, unsigned int len);
 1169: .Ve
 1170: .Sp
 1171: The \fIlog_stdin\fR function is only used if the standard input does
 1172: not correspond to a tty device.  It is called whenever data can be
 1173: read from the standard input but before it is passed to the running
 1174: command.  This allows the plugin to reject data if it chooses to
 1175: (for instance if the input contains banned content).  Returns \f(CW1\fR
 1176: if the data should be passed to the command, \f(CW0\fR if the data is
 1177: rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error
 1178: occurred.
 1179: .Sp
 1180: The function arguments are as follows:
 1181: .RS 4
 1182: .IP "buf" 4
 1183: .IX Item "buf"
 1184: The buffer containing user input.
 1185: .IP "len" 4
 1186: .IX Item "len"
 1187: The length of \fIbuf\fR in bytes.
 1188: .RE
 1189: .RS 4
 1190: .RE
 1191: .IP "log_stdout" 4
 1192: .IX Item "log_stdout"
 1193: .Vb 1
 1194: \& int (*log_stdout)(const char *buf, unsigned int len);
 1195: .Ve
 1196: .Sp
 1197: The \fIlog_stdout\fR function is only used if the standard output does
 1198: not correspond to a tty device.  It is called whenever data can be
 1199: read from the command but before it is written to the standard
 1200: output.  This allows the plugin to reject data if it chooses to
 1201: (for instance if the output contains banned content).  Returns \f(CW1\fR
 1202: if the data should be passed to the user, \f(CW0\fR if the data is
 1203: rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error
 1204: occurred.
 1205: .Sp
 1206: The function arguments are as follows:
 1207: .RS 4
 1208: .IP "buf" 4
 1209: .IX Item "buf"
 1210: The buffer containing command output.
 1211: .IP "len" 4
 1212: .IX Item "len"
 1213: The length of \fIbuf\fR in bytes.
 1214: .RE
 1215: .RS 4
 1216: .RE
 1217: .IP "log_stderr" 4
 1218: .IX Item "log_stderr"
 1219: .Vb 1
 1220: \& int (*log_stderr)(const char *buf, unsigned int len);
 1221: .Ve
 1222: .Sp
 1223: The \fIlog_stderr\fR function is only used if the standard error does
 1224: not correspond to a tty device.  It is called whenever data can be
 1225: read from the command but before it is written to the standard
 1226: error.  This allows the plugin to reject data if it chooses to
 1227: (for instance if the output contains banned content).  Returns \f(CW1\fR
 1228: if the data should be passed to the user, \f(CW0\fR if the data is
 1229: rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error
 1230: occurred.
 1231: .Sp
 1232: The function arguments are as follows:
 1233: .RS 4
 1234: .IP "buf" 4
 1235: .IX Item "buf"
 1236: The buffer containing command output.
 1237: .IP "len" 4
 1238: .IX Item "len"
 1239: The length of \fIbuf\fR in bytes.
 1240: .RE
 1241: .RS 4
 1242: .RE
 1243: .IP "register_hooks" 4
 1244: .IX Item "register_hooks"
 1245: See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of
 1246: \&\f(CW\*(C`register_hooks\*(C'\fR.
 1247: .IP "deregister_hooks" 4
 1248: .IX Item "deregister_hooks"
 1249: See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of
 1250: \&\f(CW\*(C`deregister_hooks\*(C'\fR.
 1251: .PP
 1252: \fII/O Plugin Version Macros\fR
 1253: .IX Subsection "I/O Plugin Version Macros"
 1254: .PP
 1255: Same as for the \*(L"Policy Plugin \s-1API\s0\*(R".
 1256: .SS "Hook Function \s-1API\s0"
 1257: .IX Subsection "Hook Function API"
 1258: Beginning with plugin \s-1API\s0 version 1.2, it is possible to install
 1259: hooks for certain functions called by the \fBsudo\fR front end.
 1260: .PP
 1261: Currently, the only supported hooks relate to the handling of
 1262: environment variables.  Hooks can be used to intercept attempts to
 1263: get, set, or remove environment variables so that these changes can
 1264: be reflected in the version of the environment that is used to
 1265: execute a command.  A future version of the \s-1API\s0 will support
 1266: hooking internal \fBsudo\fR front end functions as well.
 1267: .PP
 1268: \fIHook structure\fR
 1269: .IX Subsection "Hook structure"
 1270: .PP
 1271: Hooks in \fBsudo\fR are described by the following structure:
 1272: .PP
 1273: .Vb 1
 1274: \& typedef int (*sudo_hook_fn_t)();
 1275: \&
 1276: \& struct sudo_hook {
 1277: \&     int hook_version;
 1278: \&     int hook_type;
 1279: \&     sudo_hook_fn_t hook_fn;
 1280: \&     void *closure;
 1281: \& };
 1282: .Ve
 1283: .PP
 1284: The \f(CW\*(C`sudo_hook\*(C'\fR structure has the following fields:
 1285: .IP "hook_version" 4
 1286: .IX Item "hook_version"
 1287: The \f(CW\*(C`hook_version\*(C'\fR field should be set to \s-1SUDO_HOOK_VERSION\s0.
 1288: .IP "hook_type" 4
 1289: .IX Item "hook_type"
 1290: The \f(CW\*(C`hook_type\*(C'\fR field may be one of the following supported hook types:
 1291: .RS 4
 1292: .IP "\s-1SUDO_HOOK_SETENV\s0" 4
 1293: .IX Item "SUDO_HOOK_SETENV"
 1294: The C library \f(CW\*(C`setenv()\*(C'\fR function.  Any registered hooks will run
 1295: before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
 1296: be a function that matches the following typedef:
 1297: .Sp
 1298: .Vb 2
 1299: \& typedef int (*sudo_hook_fn_setenv_t)(const char *name,
 1300: \&    const char *value, int overwrite, void *closure);
 1301: .Ve
 1302: .Sp
 1303: If the registered hook does not match the typedef the results are
 1304: unspecified.
 1305: .IP "\s-1SUDO_HOOK_UNSETENV\s0" 4
 1306: .IX Item "SUDO_HOOK_UNSETENV"
 1307: The C library \f(CW\*(C`unsetenv()\*(C'\fR function.  Any registered hooks will run
 1308: before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
 1309: be a function that matches the following typedef:
 1310: .Sp
 1311: .Vb 2
 1312: \& typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
 1313: \&    void *closure);
 1314: .Ve
 1315: .IP "\s-1SUDO_HOOK_GETENV\s0" 4
 1316: .IX Item "SUDO_HOOK_GETENV"
 1317: The C library \f(CW\*(C`getenv()\*(C'\fR function.  Any registered hooks will run
 1318: before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
 1319: be a function that matches the following typedef:
 1320: .Sp
 1321: .Vb 2
 1322: \& typedef int (*sudo_hook_fn_getenv_t)(const char *name,
 1323: \&    char **value, void *closure);
 1324: .Ve
 1325: .Sp
 1326: If the registered hook does not match the typedef the results are
 1327: unspecified.
 1328: .IP "\s-1SUDO_HOOK_PUTENV\s0" 4
 1329: .IX Item "SUDO_HOOK_PUTENV"
 1330: The C library \f(CW\*(C`putenv()\*(C'\fR function.  Any registered hooks will run
 1331: before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
 1332: be a function that matches the following typedef:
 1333: .Sp
 1334: .Vb 2
 1335: \& typedef int (*sudo_hook_fn_putenv_t)(char *string,
 1336: \&    void *closure);
 1337: .Ve
 1338: .Sp
 1339: If the registered hook does not match the typedef the results are
 1340: unspecified.
 1341: .RE
 1342: .RS 4
 1343: .RE
 1344: .IP "hook_fn" 4
 1345: .IX Item "hook_fn"
 1346: .Vb 1
 1347: \& sudo_hook_fn_t hook_fn;
 1348: .Ve
 1349: .Sp
 1350: The \f(CW\*(C`hook_fn\*(C'\fR field should be set to the plugin's hook implementation.
 1351: The actual function arguments will vary depending on the \f(CW\*(C`hook_type\*(C'\fR
 1352: (see \f(CW\*(C`hook_type\*(C'\fR above).  In all cases, the \f(CW\*(C`closure\*(C'\fR field of
 1353: \&\f(CW\*(C`struct sudo_hook\*(C'\fR is passed as the last function parameter.  This
 1354: can be used to pass arbitrary data to the plugin's hook implementation.
 1355: .Sp
 1356: The function return value may be one of the following:
 1357: .RS 4
 1358: .IP "\s-1SUDO_HOOK_RET_ERROR\s0" 4
 1359: .IX Item "SUDO_HOOK_RET_ERROR"
 1360: The hook function encountered an error.
 1361: .IP "\s-1SUDO_HOOK_RET_NEXT\s0" 4
 1362: .IX Item "SUDO_HOOK_RET_NEXT"
 1363: The hook completed without error, go on to the next hook (including
 1364: the native implementation if applicable).  For example, a \f(CW\*(C`getenv\*(C'\fR
 1365: hook might return \f(CW\*(C`SUDO_HOOK_RET_NEXT\*(C'\fR if the specified variable
 1366: was not found in the private copy of the environment.
 1367: .IP "\s-1SUDO_HOOK_RET_STOP\s0" 4
 1368: .IX Item "SUDO_HOOK_RET_STOP"
 1369: The hook completed without error, stop processing hooks for this
 1370: invocation.  This can be used to replace the native implementation.
 1371: For example, a \f(CW\*(C`setenv\*(C'\fR hook that operates on a private copy of
 1372: the environment but leaves \f(CW\*(C`environ\*(C'\fR unchanged.
 1373: .RE
 1374: .RS 4
 1375: .RE
 1376: .PP
 1377: Note that it is very easy to create an infinite loop when hooking
 1378: C library functions.  For example, a \f(CW\*(C`getenv\*(C'\fR hook that calls the
 1379: \&\f(CW\*(C`snprintf\*(C'\fR function may create a loop if the \f(CW\*(C`snprintf\*(C'\fR implementation
 1380: calls \f(CW\*(C`getenv\*(C'\fR to check the locale.  To prevent this, you may wish
 1381: to use a static variable in the hook function to guard against
 1382: nested calls.  E.g.
 1383: .PP
 1384: .Vb 7
 1385: \& static int in_progress = 0; /* avoid recursion */
 1386: \& if (in_progress)
 1387: \&     return SUDO_HOOK_RET_NEXT;
 1388: \& in_progress = 1;
 1389: \& ...
 1390: \& in_progress = 0;
 1391: \& return SUDO_HOOK_RET_STOP;
 1392: .Ve
 1393: .PP
 1394: \fIHook \s-1API\s0 Version Macros\fR
 1395: .IX Subsection "Hook API Version Macros"
 1396: .PP
 1397: .Vb 6
 1398: \& /* Hook API version major/minor */
 1399: \& #define SUDO_HOOK_VERSION_MAJOR 1
 1400: \& #define SUDO_HOOK_VERSION_MINOR 0
 1401: \& #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y)
 1402: \& #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
 1403: \&                                               SUDO_HOOK_VERSION_MINOR)
 1404: \&
 1405: \& /* Getters and setters for hook API version */
 1406: \& #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16)
 1407: \& #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff)
 1408: \& #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \e
 1409: \&     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
 1410: \& } while(0)
 1411: \& #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \e
 1412: \&     *(vp) = (*(vp) & 0xffff0000) | (n); \e
 1413: \& } while(0)
 1414: .Ve
 1415: .SS "Conversation \s-1API\s0"
 1416: .IX Subsection "Conversation API"
 1417: If the plugin needs to interact with the user, it may do so via the
 1418: conversation function.  A plugin should not attempt to read directly
 1419: from the standard input or the user's tty (neither of which are
 1420: guaranteed to exist).  The caller must include a trailing newline
 1421: in \f(CW\*(C`msg\*(C'\fR if one is to be printed.
 1422: .PP
 1423: A printf-style function is also available that can be used to display
 1424: informational or error messages to the user, which is usually more
 1425: convenient for simple messages where no use input is required.
 1426: .PP
 1427: .Vb 12
 1428: \& struct sudo_conv_message {
 1429: \& #define SUDO_CONV_PROMPT_ECHO_OFF  0x0001 /* do not echo user input */
 1430: \& #define SUDO_CONV_PROMPT_ECHO_ON   0x0002 /* echo user input */
 1431: \& #define SUDO_CONV_ERROR_MSG        0x0003 /* error message */
 1432: \& #define SUDO_CONV_INFO_MSG         0x0004 /* informational message */
 1433: \& #define SUDO_CONV_PROMPT_MASK      0x0005 /* mask user input */
 1434: \& #define SUDO_CONV_DEBUG_MSG        0x0006 /* debugging message */
 1435: \& #define SUDO_CONV_PROMPT_ECHO_OK   0x1000 /* flag: allow echo if no tty */
 1436: \&     int msg_type;
 1437: \&     int timeout;
 1438: \&     const char *msg;
 1439: \& };
 1440: \&
 1441: \& struct sudo_conv_reply {
 1442: \&     char *reply;
 1443: \& };
 1444: \&
 1445: \& typedef int (*sudo_conv_t)(int num_msgs,
 1446: \&              const struct sudo_conv_message msgs[],
 1447: \&              struct sudo_conv_reply replies[]);
 1448: \&
 1449: \& typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
 1450: .Ve
 1451: .PP
 1452: Pointers to the conversation and printf-style functions are passed
 1453: in to the plugin's \f(CW\*(C`open\*(C'\fR function when the plugin is initialized.
 1454: .PP
 1455: To use the conversation function, the plugin must pass an array of
 1456: \&\f(CW\*(C`sudo_conv_message\*(C'\fR and \f(CW\*(C`sudo_conv_reply\*(C'\fR structures.  There must
 1457: be a \f(CW\*(C`struct sudo_conv_message\*(C'\fR and \f(CW\*(C`struct sudo_conv_reply\*(C'\fR for
 1458: each message in the conversation.  The plugin is responsible for
 1459: freeing the reply buffer filled in to the \f(CW\*(C`struct sudo_conv_reply\*(C'\fR,
 1460: if any.
 1461: .PP
 1462: The printf-style function uses the same underlying mechanism as the
 1463: conversation function but only supports \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR,
 1464: \&\f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_DEBUG_MSG\*(C'\fR for the \fImsg_type\fR
 1465: parameter.  It can be more convenient than using the conversation
 1466: function if no user reply is needed and supports standard \fIprintf()\fR
 1467: escape sequences.
 1468: .PP
 1469: Unlike, \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR, messages
 1470: sent with the <\s-1SUDO_CONV_DEBUG_MSG\s0> \fImsg_type\fR are not directly
 1471: user-visible.  Instead, they are logged to the file specified in
 1472: the \f(CW\*(C`Debug\*(C'\fR statement (if any) in the \fI@sysconfdir@/sudo.conf\fR
 1473: file.  This allows a plugin to log debugging information and is
 1474: intended to be used in conjunction with the \fIdebug_flags\fR setting.
 1475: .PP
 1476: See the sample plugin for an example of the conversation function usage.
 1477: .SS "Sudoers Group Plugin \s-1API\s0"
 1478: .IX Subsection "Sudoers Group Plugin API"
 1479: The \fIsudoers\fR module supports a plugin interface to allow non-Unix
 1480: group lookups.  This can be used to query a group source other than
 1481: the standard Unix group database.  A sample group plugin is bundled
 1482: with \fBsudo\fR that implements file-based lookups.  Third party group
 1483: plugins include a \s-1QAS\s0 \s-1AD\s0 plugin available from Quest Software.
 1484: .PP
 1485: A group plugin must declare and populate a \f(CW\*(C`sudoers_group_plugin\*(C'\fR
 1486: struct in the global scope.  This structure contains pointers to
 1487: the functions that implement plugin initialization, cleanup and
 1488: group lookup.
 1489: .PP
 1490: .Vb 8
 1491: \& struct sudoers_group_plugin {
 1492: \&    unsigned int version;
 1493: \&    int (*init)(int version, sudo_printf_t sudo_printf,
 1494: \&                char *const argv[]);
 1495: \&    void (*cleanup)(void);
 1496: \&    int (*query)(const char *user, const char *group,
 1497: \&                 const struct passwd *pwd);
 1498: \&};
 1499: .Ve
 1500: .PP
 1501: The \f(CW\*(C`sudoers_group_plugin\*(C'\fR struct has the following fields:
 1502: .IP "version" 4
 1503: .IX Item "version"
 1504: The \f(CW\*(C`version\*(C'\fR field should be set to \s-1GROUP_API_VERSION\s0.
 1505: .Sp
 1506: This allows \fIsudoers\fR to determine the \s-1API\s0 version the group plugin
 1507: was built against.
 1508: .IP "init" 4
 1509: .IX Item "init"
 1510: .Vb 2
 1511: \& int (*init)(int version, sudo_printf_t plugin_printf,
 1512: \&             char *const argv[]);
 1513: .Ve
 1514: .Sp
 1515: The \fIinit\fR function is called after \fIsudoers\fR has been parsed but
 1516: before any policy checks.  It returns 1 on success, 0 on failure
 1517: (or if the plugin is not configured), and \-1 if a error occurred.
 1518: If an error occurs, the plugin may call the plugin_printf function
 1519: with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information
 1520: to the user.
 1521: .Sp
 1522: The function arguments are as follows:
 1523: .RS 4
 1524: .IP "version" 4
 1525: .IX Item "version"
 1526: The version passed in by \fIsudoers\fR allows the plugin to determine the
 1527: major and minor version number of the group plugin \s-1API\s0 supported by
 1528: \&\fIsudoers\fR.
 1529: .IP "plugin_printf" 4
 1530: .IX Item "plugin_printf"
 1531: A pointer to a printf-style function that may be used to display
 1532: informational or error message to the user.
 1533: Returns the number of characters printed on success and \-1 on failure.
 1534: .IP "argv" 4
 1535: .IX Item "argv"
 1536: A NULL-terminated array of arguments generated from the \fIgroup_plugin\fR
 1537: option in \fIsudoers\fR.  If no arguments were given, \fIargv\fR will be
 1538: \&\s-1NULL\s0.
 1539: .RE
 1540: .RS 4
 1541: .RE
 1542: .IP "cleanup" 4
 1543: .IX Item "cleanup"
 1544: .Vb 1
 1545: \& void (*cleanup)();
 1546: .Ve
 1547: .Sp
 1548: The \fIcleanup\fR function is called when \fIsudoers\fR has finished its
 1549: group checks.  The plugin should free any memory it has allocated
 1550: and close open file handles.
 1551: .IP "query" 4
 1552: .IX Item "query"
 1553: .Vb 2
 1554: \& int (*query)(const char *user, const char *group,
 1555: \&              const struct passwd *pwd);
 1556: .Ve
 1557: .Sp
 1558: The \fIquery\fR function is used to ask the group plugin whether \fIuser\fR
 1559: is a member of \fIgroup\fR.
 1560: .Sp
 1561: The function arguments are as follows:
 1562: .RS 4
 1563: .IP "user" 4
 1564: .IX Item "user"
 1565: The name of the user being looked up in the external group database.
 1566: .IP "group" 4
 1567: .IX Item "group"
 1568: The name of the group being queried.
 1569: .IP "pwd" 4
 1570: .IX Item "pwd"
 1571: The password database entry for \fIuser\fR, if any.  If \fIuser\fR is not
 1572: present in the password database, \fIpwd\fR will be \f(CW\*(C`NULL\*(C'\fR.
 1573: .RE
 1574: .RS 4
 1575: .RE
 1576: .PP
 1577: \fIGroup \s-1API\s0 Version Macros\fR
 1578: .IX Subsection "Group API Version Macros"
 1579: .PP
 1580: .Vb 5
 1581: \& /* Sudoers group plugin version major/minor */
 1582: \& #define GROUP_API_VERSION_MAJOR 1
 1583: \& #define GROUP_API_VERSION_MINOR 0
 1584: \& #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
 1585: \&                            GROUP_API_VERSION_MINOR)
 1586: \&
 1587: \& /* Getters and setters for group version */
 1588: \& #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
 1589: \& #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
 1590: \& #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \e
 1591: \&     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
 1592: \& } while(0)
 1593: \& #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \e
 1594: \&     *(vp) = (*(vp) & 0xffff0000) | (n); \e
 1595: \& } while(0)
 1596: .Ve
 1597: .SH "PLUGIN API CHANGELOG"
 1598: .IX Header "PLUGIN API CHANGELOG"
 1599: The following revisions have been made to the Sudo Plugin \s-1API\s0.
 1600: .IP "Version 1.0" 4
 1601: .IX Item "Version 1.0"
 1602: Initial \s-1API\s0 version.
 1603: .IP "Version 1.1" 4
 1604: .IX Item "Version 1.1"
 1605: The I/O logging plugin's \f(CW\*(C`open\*(C'\fR function was modified to take the
 1606: \&\f(CW\*(C`command_info\*(C'\fR list as an argument.
 1607: .IP "Version 1.2" 4
 1608: .IX Item "Version 1.2"
 1609: The Policy and I/O logging plugins' \f(CW\*(C`open\*(C'\fR functions are now passed
 1610: a list of plugin options if any are specified in \fI@sysconfdir@/sudo.conf\fR.
 1611: .Sp
 1612: A simple hooks \s-1API\s0 has been introduced to allow plugins to hook in to the
 1613: system's environment handling functions.
 1614: .Sp
 1615: The \f(CW\*(C`init_session\*(C'\fR Policy plugin function is now passed a pointer
 1616: to the user environment which can be updated as needed.  This can
 1617: be used to merge in environment variables stored in the \s-1PAM\s0 handle
 1618: before a command is run.
 1619: .SH "SEE ALSO"
 1620: .IX Header "SEE ALSO"
 1621: \&\fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@)
 1622: .SH "BUGS"
 1623: .IX Header "BUGS"
 1624: If you feel you have found a bug in \fBsudo\fR, please submit a bug report
 1625: at http://www.sudo.ws/sudo/bugs/
 1626: .SH "SUPPORT"
 1627: .IX Header "SUPPORT"
 1628: Limited free support is available via the sudo-workers mailing list,
 1629: see http://www.sudo.ws/mailman/listinfo/sudo\-workers to subscribe or
 1630: search the archives.
 1631: .SH "DISCLAIMER"
 1632: .IX Header "DISCLAIMER"
 1633: \&\fBsudo\fR is provided ``\s-1AS\s0 \s-1IS\s0'' and any express or implied warranties,
 1634: including, but not limited to, the implied warranties of merchantability
 1635: and fitness for a particular purpose are disclaimed.  See the \s-1LICENSE\s0
 1636: file distributed with \fBsudo\fR or http://www.sudo.ws/sudo/license.html
 1637: for complete details.

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