version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.4, 2013/07/22 10:46:12
|
Line 1
|
Line 1
|
.\" Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com> | .\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER! |
.\" | .\" IT IS GENERATED AUTOMATICALLY FROM sudo_plugin.mdoc.in |
| .\" |
| .\" Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
| .\" |
.\" Permission to use, copy, modify, and distribute this software for any |
.\" Permission to use, copy, modify, and distribute this software for any |
.\" purpose with or without fee is hereby granted, provided that the above |
.\" purpose with or without fee is hereby granted, provided that the above |
.\" copyright notice and this permission notice appear in all copies. |
.\" copyright notice and this permission notice appear in all copies. |
.\" | .\" |
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
Line 12
|
Line 15
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
.\" |
|
.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) |
|
.\" |
.\" |
.\" Standard preamble: | .TH "SUDO_PLUGIN" "5" "March 5, 2013" "Sudo @PACKAGE_VERSION@" "OpenBSD Programmer's Manual" |
.\" ======================================================================== | |
.de Sp \" Vertical space (when we can't use .PP) | |
.if t .sp .5v | |
.if n .sp | |
.. | |
.de Vb \" Begin verbatim text | |
.ft CW | |
.nf | |
.ne \\$1 | |
.. | |
.de Ve \" End verbatim text | |
.ft R | |
.fi | |
.. | |
.\" Set up some character translations and predefined strings. \*(-- will | |
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left | |
.\" double quote, and \*(R" will give a right double quote. \*(C+ will | |
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and | |
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, | |
.\" nothing in troff, for use with C<>. | |
.tr \(*W- | |
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' | |
.ie n \{\ | |
. ds -- \(*W- | |
. ds PI pi | |
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch | |
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch | |
. ds L" "" | |
. ds R" "" | |
. ds C` | |
. ds C' | |
'br\} | |
.el\{\ | |
. ds -- \|\(em\| | |
. ds PI \(*p | |
. ds L" `` | |
. ds R" '' | |
'br\} | |
.\" | |
.\" Escape single quotes in literal strings from groff's Unicode transform. | |
.ie \n(.g .ds Aq \(aq | |
.el .ds Aq ' | |
.\" | |
.\" If the F register is turned on, we'll generate index entries on stderr for | |
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index | |
.\" entries marked with X<> in POD. Of course, you'll have to process the | |
.\" output yourself in some meaningful fashion. | |
.ie \nF \{\ | |
. de IX | |
. tm Index:\\$1\t\\n%\t"\\$2" | |
.. | |
. nr % 0 | |
. rr F | |
.\} | |
.el \{\ | |
. de IX | |
.. | |
.\} | |
.\" | |
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). | |
.\" Fear. Run. Save yourself. No user-serviceable parts. | |
. \" fudge factors for nroff and troff | |
.if n \{\ | |
. ds #H 0 | |
. ds #V .8m | |
. ds #F .3m | |
. ds #[ \f1 | |
. ds #] \fP | |
.\} | |
.if t \{\ | |
. ds #H ((1u-(\\\\n(.fu%2u))*.13m) | |
. ds #V .6m | |
. ds #F 0 | |
. ds #[ \& | |
. ds #] \& | |
.\} | |
. \" simple accents for nroff and troff | |
.if n \{\ | |
. ds ' \& | |
. ds ` \& | |
. ds ^ \& | |
. ds , \& | |
. ds ~ ~ | |
. ds / | |
.\} | |
.if t \{\ | |
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" | |
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' | |
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' | |
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' | |
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' | |
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' | |
.\} | |
. \" troff and (daisy-wheel) nroff accents | |
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' | |
.ds 8 \h'\*(#H'\(*b\h'-\*(#H' | |
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] | |
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' | |
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' | |
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] | |
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] | |
.ds ae a\h'-(\w'a'u*4/10)'e | |
.ds Ae A\h'-(\w'A'u*4/10)'E | |
. \" corrections for vroff | |
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' | |
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' | |
. \" for low resolution devices (crt and lpr) | |
.if \n(.H>23 .if \n(.V>19 \ | |
\{\ | |
. ds : e | |
. ds 8 ss | |
. ds o a | |
. ds d- d\h'-1'\(ga | |
. ds D- D\h'-1'\(hy | |
. ds th \o'bp' | |
. ds Th \o'LP' | |
. ds ae ae | |
. ds Ae AE | |
.\} | |
.rm #[ #] #H #V #F C | |
.\" ======================================================================== | |
.\" | |
.IX Title "SUDO_PLUGIN @mansectsu@" | |
.TH SUDO_PLUGIN @mansectsu@ "April 23, 2012" "1.8.5" "MAINTENANCE COMMANDS" | |
.\" For nroff, turn off justification. Always turn off hyphenation; it makes | |
.\" way too many mistakes in technical documents. | |
.if n .ad l | |
.nh |
.nh |
|
.if n .ad l |
.SH "NAME" |
.SH "NAME" |
sudo_plugin \- Sudo Plugin API | \fBsudo_plugin\fR |
| \- Sudo Plugin API |
.SH "DESCRIPTION" |
.SH "DESCRIPTION" |
.IX Header "DESCRIPTION" | Starting with version 1.8, |
Starting with version 1.8, \fBsudo\fR supports a plugin \s-1API\s0 | \fBsudo\fR |
for policy and session logging. By default, the \fIsudoers\fR policy | supports a plugin API |
plugin and an associated I/O logging plugin are used. Via the plugin | for policy and session logging. |
\&\s-1API\s0, \fBsudo\fR can be configured to use alternate policy and/or I/O | By default, the |
logging plugins provided by third parties. The plugins to be used | \fBsudoers\fR |
are specified via the \fI@sysconfdir@/sudo.conf\fR file. | policy plugin and an associated I/O logging plugin are used. |
| Via the plugin API, |
| \fBsudo\fR |
| can be configured to use alternate policy and/or I/O logging plugins |
| provided by third parties. |
| The plugins to be used are specified in the |
| sudo.conf(@mansectform@) |
| file. |
.PP |
.PP |
The \s-1API\s0 is versioned with a major and minor number. The minor | The API is versioned with a major and minor number. |
version number is incremented when additions are made. The major | The minor version number is incremented when additions are made. |
number is incremented when incompatible changes are made. A plugin | The major number is incremented when incompatible changes are made. |
should be check the version passed to it and make sure that the | A plugin should be check the version passed to it and make sure that the |
major version matches. |
major version matches. |
.PP |
.PP |
The plugin \s-1API\s0 is defined by the \f(CW\*(C`sudo_plugin.h\*(C'\fR header file. | The plugin API is defined by the |
.SS "The sudo.conf File" | \fRsudo_plugin.h\fR |
.IX Subsection "The sudo.conf File" | header file. |
The \fI@sysconfdir@/sudo.conf\fR file contains plugin configuration directives. | .SS "Policy plugin API" |
Currently, the only supported keyword is the \f(CW\*(C`Plugin\*(C'\fR directive, | A policy plugin must declare and populate a |
which causes a plugin plugin to be loaded. | \fRpolicy_plugin\fR |
| struct in the global scope. |
| This structure contains pointers to the functions that implement the |
| \fBsudo\fR |
| policy checks. |
| The name of the symbol should be specified in |
| sudo.conf(@mansectform@) |
| along with a path to the plugin so that |
| \fBsudo\fR |
| can load it. |
| .nf |
| .sp |
| .RS 0n |
| struct policy_plugin { |
| #define SUDO_POLICY_PLUGIN 1 |
| unsigned int type; /* always SUDO_POLICY_PLUGIN */ |
| unsigned int version; /* always SUDO_API_VERSION */ |
| int (*open)(unsigned int version, sudo_conv_t conversation, |
| sudo_printf_t plugin_printf, char * const settings[], |
| char * const user_info[], char * const user_env[], |
| char * const plugin_options[]); |
| void (*close)(int exit_status, int error); |
| int (*show_version)(int verbose); |
| int (*check_policy)(int argc, char * const argv[], |
| char *env_add[], char **command_info[], |
| char **argv_out[], char **user_env_out[]); |
| int (*list)(int argc, char * const argv[], int verbose, |
| const char *list_user); |
| int (*validate)(void); |
| void (*invalidate)(int remove); |
| int (*init_session)(struct passwd *pwd, char **user_env[]); |
| void (*register_hooks)(int version, |
| int (*register_hook)(struct sudo_hook *hook)); |
| void (*deregister_hooks)(int version, |
| int (*deregister_hook)(struct sudo_hook *hook)); |
| }; |
| .RE |
| .fi |
.PP |
.PP |
A \f(CW\*(C`Plugin\*(C'\fR line consists of the \f(CW\*(C`Plugin\*(C'\fR keyword, followed by the |
|
\&\fIsymbol_name\fR and the \fIpath\fR to the shared object containing the |
|
plugin. The \fIsymbol_name\fR is the name of the \f(CW\*(C`struct policy_plugin\*(C'\fR |
|
or \f(CW\*(C`struct io_plugin\*(C'\fR in the plugin shared object. The \fIpath\fR |
|
may be fully qualified or relative. If not fully qualified it is |
|
relative to the \fI@prefix@/libexec\fR directory. Any additional |
|
parameters after the \fIpath\fR are passed as options to the plugin's |
|
\&\fIopen\fR function. Lines that don't begin with \f(CW\*(C`Plugin\*(C'\fR, \f(CW\*(C`Path\*(C'\fR, |
|
\&\f(CW\*(C`Debug\*(C'\fR or \f(CW\*(C`Set\*(C'\fR are silently ignored. |
|
.PP |
|
The same shared object may contain multiple plugins, each with a |
|
different symbol name. The shared object file must be owned by uid |
|
0 and only writable by its owner. Because of ambiguities that arise |
|
from composite policies, only a single policy plugin may be specified. |
|
This limitation does not apply to I/O plugins. |
|
.PP |
|
.Vb 10 |
|
\& # |
|
\& # Default @sysconfdir@/sudo.conf file |
|
\& # |
|
\& # Format: |
|
\& # Plugin plugin_name plugin_path plugin_options ... |
|
\& # Path askpass /path/to/askpass |
|
\& # Path noexec /path/to/sudo_noexec.so |
|
\& # Debug sudo /var/log/sudo_debug all@warn |
|
\& # Set disable_coredump true |
|
\& # |
|
\& # The plugin_path is relative to @prefix@/libexec unless |
|
\& # fully qualified. |
|
\& # The plugin_name corresponds to a global symbol in the plugin |
|
\& # that contains the plugin interface structure. |
|
\& # The plugin_options are optional. |
|
\& # |
|
\& Plugin sudoers_policy sudoers.so |
|
\& Plugin sudoers_io sudoers.so |
|
.Ve |
|
.SS "Policy Plugin \s-1API\s0" |
|
.IX Subsection "Policy Plugin API" |
|
A policy plugin must declare and populate a \f(CW\*(C`policy_plugin\*(C'\fR struct |
|
in the global scope. This structure contains pointers to the functions |
|
that implement the \fBsudo\fR policy checks. The name of the symbol should |
|
be specified in \fI@sysconfdir@/sudo.conf\fR along with a path to the plugin |
|
so that \fBsudo\fR can load it. |
|
.PP |
|
.Vb 10 |
|
\& struct policy_plugin { |
|
\& #define SUDO_POLICY_PLUGIN 1 |
|
\& unsigned int type; /* always SUDO_POLICY_PLUGIN */ |
|
\& unsigned int version; /* always SUDO_API_VERSION */ |
|
\& int (*open)(unsigned int version, sudo_conv_t conversation, |
|
\& sudo_printf_t plugin_printf, char * const settings[], |
|
\& char * const user_info[], char * const user_env[], |
|
\& char * const plugin_options[]); |
|
\& void (*close)(int exit_status, int error); |
|
\& int (*show_version)(int verbose); |
|
\& int (*check_policy)(int argc, char * const argv[], |
|
\& char *env_add[], char **command_info[], |
|
\& char **argv_out[], char **user_env_out[]); |
|
\& int (*list)(int argc, char * const argv[], int verbose, |
|
\& const char *list_user); |
|
\& int (*validate)(void); |
|
\& void (*invalidate)(int remove); |
|
\& int (*init_session)(struct passwd *pwd, char **user_env[]); |
|
\& void (*register_hooks)(int version, |
|
\& int (*register_hook)(struct sudo_hook *hook)); |
|
\& void (*deregister_hooks)(int version, |
|
\& int (*deregister_hook)(struct sudo_hook *hook)); |
|
\& }; |
|
.Ve |
|
.PP |
|
The policy_plugin struct has the following fields: |
The policy_plugin struct has the following fields: |
.IP "type" 4 | .TP 6n |
.IX Item "type" | type |
The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_POLICY_PLUGIN\s0. | The |
.IP "version" 4 | \fRtype\fR |
.IX Item "version" | field should always be set to SUDO_POLICY_PLUGIN. |
The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0. | .TP 6n |
.Sp | version |
This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was | The |
| \fRversion\fR |
| field should be set to |
| \fRSUDO_API_VERSION\fR. |
| .sp |
| This allows |
| \fBsudo\fR |
| to determine the API version the plugin was |
built against. |
built against. |
.IP "open" 4 | .TP 6n |
.IX Item "open" | open |
.Vb 4 | .RS |
\& int (*open)(unsigned int version, sudo_conv_t conversation, | .nf |
\& sudo_printf_t plugin_printf, char * const settings[], | .RS 0n |
\& char * const user_info[], char * const user_env[], | int (*open)(unsigned int version, sudo_conv_t conversation, |
\& char * const plugin_options[]); | sudo_printf_t plugin_printf, char * const settings[], |
.Ve | char * const user_info[], char * const user_env[], |
.Sp | char * const plugin_options[]); |
| .RE |
| .fi |
| .sp |
Returns 1 on success, 0 on failure, \-1 if a general error occurred, |
Returns 1 on success, 0 on failure, \-1 if a general error occurred, |
or \-2 if there was a usage error. In the latter case, \fBsudo\fR will | or \-2 if there was a usage error. |
print a usage message before it exits. If an error occurs, the | In the latter case, |
plugin may optionally call the conversation or plugin_printf function | \fBsudo\fR |
with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information | will print a usage message before it exits. |
to the user. | If an error occurs, the plugin may optionally call the |
.Sp | \fBconversation\fR() |
| or |
| \fBplugin_printf\fR() |
| function with |
| \fRSUDO_CONF_ERROR_MSG\fR |
| to present additional error information to the user. |
| .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .TP 6n |
.IP "version" 4 | version |
.IX Item "version" | The version passed in by |
The version passed in by \fBsudo\fR allows the plugin to determine the | \fBsudo\fR |
major and minor version number of the plugin \s-1API\s0 supported by | allows the plugin to determine the |
\&\fBsudo\fR. | major and minor version number of the plugin API supported by |
.IP "conversation" 4 | \fBsudo\fR. |
.IX Item "conversation" | .TP 6n |
A pointer to the conversation function that can be used by the | conversation |
plugin to interact with the user (see below). | A pointer to the |
| \fBconversation\fR() |
| function that can be used by the plugin to interact with the user (see below). |
Returns 0 on success and \-1 on failure. |
Returns 0 on success and \-1 on failure. |
.IP "plugin_printf" 4 | .TP 6n |
.IX Item "plugin_printf" | plugin_printf |
A pointer to a printf-style function that may be used to display | A pointer to a |
informational or error messages (see below). | \fBprintf\fR()-style |
| function that may be used to display informational or error messages |
| (see below). |
Returns the number of characters printed on success and \-1 on failure. |
Returns the number of characters printed on success and \-1 on failure. |
.IP "settings" 4 | .TP 6n |
.IX Item "settings" | settings |
A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R" | A vector of user-supplied |
strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. These | \fBsudo\fR |
settings correspond to flags the user specified when running \fBsudo\fR. | settings in the form of |
| ``name=value'' |
| strings. |
| The vector is terminated by a |
| \fRNULL\fR |
| pointer. |
| These settings correspond to flags the user specified when running |
| \fBsudo\fR. |
As such, they will only be present when the corresponding flag has |
As such, they will only be present when the corresponding flag has |
been specified on the command line. |
been specified on the command line. |
.Sp | .sp |
When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR | When parsing |
equal sign ('=') since the \fIname\fR field will never include one | \fIsettings\fR, |
itself but the \fIvalue\fR might. | the plugin should split on the |
.RS 4 | \fBfirst\fR |
.IP "debug_flags=string" 4 | equal sign |
.IX Item "debug_flags=string" | (`=') |
A comma-separated list of debug flags that correspond to \fBsudo\fR's | since the |
\&\f(CW\*(C`Debug\*(C'\fR entry in \fI@sysconfdir@/sudo.conf\fR, if there is one. The | \fIname\fR |
flags are passed to the plugin as they appear in \fI@sysconfdir@/sudo.conf\fR. | field will never include one |
The syntax used by \fBsudo\fR and the \fIsudoers\fR plugin is | itself but the |
\&\fIsubsystem\fR@\fIpriority\fR but the plugin is free to use a different | \fIvalue\fR |
format so long as it does not include a command \f(CW\*(C`,\*(C'\fR. | might. |
.Sp | .RS |
For reference, the priorities supported by the \fBsudo\fR front end and | .TP 6n |
\&\fIsudoers\fR are: \fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, | bsdauth_type=string |
\&\fIinfo\fR, \fItrace\fR and \fIdebug\fR. | Authentication type, if specified by the |
.Sp | \fB\-a\fR |
The following subsystems are defined: \fImain\fR, \fImemory\fR, \fIargs\fR, | flag, to use on |
\&\fIexec\fR, \fIpty\fR, \fIutmp\fR, \fIconv\fR, \fIpcomm\fR, \fIutil\fR, \fIlist\fR, | systems where BSD authentication is supported. |
\&\fInetif\fR, \fIaudit\fR, \fIedit\fR, \fIselinux\fR, \fIldap\fR, \fImatch\fR, \fIparser\fR, | .TP 6n |
\&\fIalias\fR, \fIdefaults\fR, \fIauth\fR, \fIenv\fR, \fIlogging\fR, \fInss\fR, \fIrbtree\fR, | closefrom=number |
\&\fIperms\fR, \fIplugin\fR. The subsystem \fIall\fR includes every subsystem. | If specified, the user has requested via the |
.Sp | \fB\-C\fR |
| flag that |
| \fBsudo\fR |
| close all files descriptors with a value of |
| \fInumber\fR |
| or higher. |
| The plugin may optionally pass this, or another value, back in the |
| \fIcommand_info\fR |
| list. |
| .TP 6n |
| debug_flags=string |
| A comma-separated list of debug flags that correspond to |
| \fBsudo\fR's |
| \fRDebug\fR |
| entry in |
| sudo.conf(@mansectform@), |
| if there is one. |
| The flags are passed to the plugin as they appear in |
| sudo.conf(@mansectform@). |
| The syntax used by |
| \fBsudo\fR |
| and the |
| \fBsudoers\fR |
| plugin is |
| \fIsubsystem\fR@\fIpriority\fR |
| but the plugin is free to use a different |
| format so long as it does not include a comma |
| (`,\&'). |
There is not currently a way to specify a set of debug flags specific |
There is not currently a way to specify a set of debug flags specific |
to the plugin\*(--the flags are shared by \fBsudo\fR and the plugin. | to the plugin--the flags are shared by |
.IP "debug_level=number" 4 | \fBsudo\fR |
.IX Item "debug_level=number" | and the plugin. |
This setting has been deprecated in favor of \fIdebug_flags\fR. | .TP 6n |
.IP "runas_user=string" 4 | debug_level=number |
.IX Item "runas_user=string" | This setting has been deprecated in favor of |
The user name or uid to to run the command as, if specified via the | \fIdebug_flags\fR. |
\&\f(CW\*(C`\-u\*(C'\fR flag. | .TP 6n |
.IP "runas_group=string" 4 | ignore_ticket=bool |
.IX Item "runas_group=string" | Set to true if the user specified the |
The group name or gid to to run the command as, if specified via | \fB\-k\fR |
the \f(CW\*(C`\-g\*(C'\fR flag. | flag along with a |
.IP "prompt=string" 4 | command, indicating that the user wishes to ignore any cached |
.IX Item "prompt=string" | authentication credentials. |
The prompt to use when requesting a password, if specified via | \fIimplied_shell\fR |
the \f(CW\*(C`\-p\*(C'\fR flag. | to true. |
.IP "set_home=bool" 4 | This allows |
.IX Item "set_home=bool" | \fBsudo\fR |
Set to true if the user specified the \f(CW\*(C`\-H\*(C'\fR flag. If true, set the | with no arguments |
\&\f(CW\*(C`HOME\*(C'\fR environment variable to the target user's home directory. | to be used similarly to |
.IP "preserve_environment=bool" 4 | su(1). |
.IX Item "preserve_environment=bool" | If the plugin does not to support this usage, it may return a value of \-2 |
Set to true if the user specified the \f(CW\*(C`\-E\*(C'\fR flag, indicating that | from the |
the user wishes to preserve the environment. | \fBcheck_policy\fR() |
.IP "run_shell=bool" 4 | function, which will cause |
.IX Item "run_shell=bool" | \fBsudo\fR |
Set to true if the user specified the \f(CW\*(C`\-s\*(C'\fR flag, indicating that | to print a usage message and |
the user wishes to run a shell. | |
.IP "login_shell=bool" 4 | |
.IX Item "login_shell=bool" | |
Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that | |
the user wishes to run a login shell. | |
.IP "implied_shell=bool" 4 | |
.IX Item "implied_shell=bool" | |
If the user does not specify a program on the command line, \fBsudo\fR | |
will pass the plugin the path to the user's shell and set | |
\&\fIimplied_shell\fR to true. This allows \fBsudo\fR with no arguments | |
to be used similarly to \fIsu\fR\|(1). If the plugin does not to support | |
this usage, it may return a value of \-2 from the \f(CW\*(C`check_policy\*(C'\fR | |
function, which will cause \fBsudo\fR to print a usage message and | |
exit. |
exit. |
.IP "preserve_groups=bool" 4 | .TP 6n |
.IX Item "preserve_groups=bool" | implied_shell=bool |
Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that | If the user does not specify a program on the command line, |
| \fBsudo\fR |
| will pass the plugin the path to the user's shell and set |
| .TP 6n |
| login_class=string |
| BSD login class to use when setting resource limits and nice value, |
| if specified by the |
| \fB\-c\fR |
| flag. |
| .TP 6n |
| login_shell=bool |
| Set to true if the user specified the |
| \fB\-i\fR |
| flag, indicating that |
| the user wishes to run a login shell. |
| .TP 6n |
| max_groups=int |
| The maximum number of groups a user may belong to. |
| This will only be present if there is a corresponding setting in |
| sudo.conf(@mansectform@). |
| .TP 6n |
| network_addrs=list |
| A space-separated list of IP network addresses and netmasks in the |
| form |
| ``addr/netmask'', |
| e.g.\& |
| ``192.168.1.2/255.255.255.0''. |
| The address and netmask pairs may be either IPv4 or IPv6, depending on |
| what the operating system supports. |
| If the address contains a colon |
| (`:\&'), |
| it is an IPv6 address, else it is IPv4. |
| .TP 6n |
| noninteractive=bool |
| Set to true if the user specified the |
| \fB\-n\fR |
| flag, indicating that |
| \fBsudo\fR |
| should operate in non-interactive mode. |
| The plugin may reject a command run in non-interactive mode if user |
| interaction is required. |
| .TP 6n |
| plugin_dir=string |
| The default plugin directory used by the |
| \fBsudo\fR |
| front end. |
| This is the default directory set at compile time and may not |
| correspond to the directory the running plugin was loaded from. |
| It may be used by a plugin to locate support files. |
| .TP 6n |
| preserve_environment=bool |
| Set to true if the user specified the |
| \fB\-E\fR |
| flag, indicating that |
| the user wishes to preserve the environment. |
| .TP 6n |
| preserve_groups=bool |
| Set to true if the user specified the |
| \fB\-P\fR |
| flag, indicating that |
the user wishes to preserve the group vector instead of setting it |
the user wishes to preserve the group vector instead of setting it |
based on the runas user. |
based on the runas user. |
.IP "ignore_ticket=bool" 4 | .TP 6n |
.IX Item "ignore_ticket=bool" | progname=string |
Set to true if the user specified the \f(CW\*(C`\-k\*(C'\fR flag along with a | The command name that sudo was run as, typically |
command, indicating that the user wishes to ignore any cached | ``sudo'' |
authentication credentials. | or |
.IP "noninteractive=bool" 4 | ``sudoedit''. |
.IX Item "noninteractive=bool" | .TP 6n |
Set to true if the user specified the \f(CW\*(C`\-n\*(C'\fR flag, indicating that | prompt=string |
\&\fBsudo\fR should operate in non-interactive mode. The plugin may | The prompt to use when requesting a password, if specified via |
reject a command run in non-interactive mode if user interaction | the |
is required. | \fB\-p\fR |
.IP "login_class=string" 4 | flag. |
.IX Item "login_class=string" | .TP 6n |
\&\s-1BSD\s0 login class to use when setting resource limits and nice value, | run_shell=bool |
if specified by the \f(CW\*(C`\-c\*(C'\fR flag. | Set to true if the user specified the |
.IP "selinux_role=string" 4 | \fB\-s\fR |
.IX Item "selinux_role=string" | flag, indicating that |
| the user wishes to run a shell. |
| .TP 6n |
| runas_group=string |
| The group name or gid to to run the command as, if specified via |
| the |
| \fB\-g\fR |
| flag. |
| .TP 6n |
| runas_user=string |
| The user name or uid to to run the command as, if specified via the |
| \fB\-u\fR |
| flag. |
| .TP 6n |
| selinux_role=string |
SELinux role to use when executing the command, if specified by |
SELinux role to use when executing the command, if specified by |
the \f(CW\*(C`\-r\*(C'\fR flag. | the |
.IP "selinux_type=string" 4 | \fB\-r\fR |
.IX Item "selinux_type=string" | flag. |
| .TP 6n |
| selinux_type=string |
SELinux type to use when executing the command, if specified by |
SELinux type to use when executing the command, if specified by |
the \f(CW\*(C`\-t\*(C'\fR flag. | the |
.IP "bsdauth_type=string" 4 | \fB\-t\fR |
.IX Item "bsdauth_type=string" | flag. |
Authentication type, if specified by the \f(CW\*(C`\-a\*(C'\fR flag, to use on | .TP 6n |
systems where \s-1BSD\s0 authentication is supported. | set_home=bool |
.IP "network_addrs=list" 4 | Set to true if the user specified the |
.IX Item "network_addrs=list" | \fB\-H\fR |
A space-separated list of \s-1IP\s0 network addresses and netmasks in the | flag. |
form \*(L"addr/netmask\*(R", e.g. \*(L"192.168.1.2/255.255.255.0\*(R". The address | If true, set the |
and netmask pairs may be either IPv4 or IPv6, depending on what the | \fRHOME\fR |
operating system supports. If the address contains a colon (':'), | environment variable to the target user's home directory. |
it is an IPv6 address, else it is IPv4. | .TP 6n |
.IP "progname=string" 4 | sudoedit=bool |
.IX Item "progname=string" | Set to true when the |
The command name that sudo was run as, typically \*(L"sudo\*(R" or \*(L"sudoedit\*(R". | \fB\-e\fR |
.IP "sudoedit=bool" 4 | flag is is specified or if invoked as |
.IX Item "sudoedit=bool" | \fBsudoedit\fR. |
Set to true when the \f(CW\*(C`\-e\*(C'\fR flag is is specified or if invoked as | The plugin shall substitute an editor into |
\&\fBsudoedit\fR. The plugin shall substitute an editor into \fIargv\fR | \fIargv\fR |
in the \fIcheck_policy\fR function or return \f(CW\*(C`\-2\*(C'\fR with a usage error | in the |
if the plugin does not support \fIsudoedit\fR. For more information, | \fBcheck_policy\fR() |
see the \fIcheck_policy\fR section. | function or return \-2 with a usage error |
.IP "closefrom=number" 4 | if the plugin does not support |
.IX Item "closefrom=number" | \fIsudoedit\fR. |
If specified, the user has requested via the \f(CW\*(C`\-C\*(C'\fR flag that \fBsudo\fR | For more information, see the |
close all files descriptors with a value of \fInumber\fR or higher. | \fIcheck_policy\fR |
The plugin may optionally pass this, or another value, back in the | section. |
\&\fIcommand_info\fR list. | .PP |
.RE | |
.RS 4 | |
.Sp | |
Additional settings may be added in the future so the plugin should |
Additional settings may be added in the future so the plugin should |
silently ignore settings that it does not recognize. |
silently ignore settings that it does not recognize. |
|
.PP |
.RE |
.RE |
.IP "user_info" 4 | .PD 0 |
.IX Item "user_info" | .TP 6n |
| user_info |
A vector of information about the user running the command in the form of |
A vector of information about the user running the command in the form of |
\&\*(L"name=value\*(R" strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. | ``name=value'' |
.Sp | strings. |
When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR | The vector is terminated by a |
equal sign ('=') since the \fIname\fR field will never include one | \fRNULL\fR |
itself but the \fIvalue\fR might. | pointer. |
.RS 4 | .sp |
.IP "pid=int" 4 | When parsing |
.IX Item "pid=int" | \fIuser_info\fR, |
The process \s-1ID\s0 of the running \fBsudo\fR process. | the plugin should split on the |
Only available starting with \s-1API\s0 version 1.2 | \fBfirst\fR |
.IP "ppid=int" 4 | equal sign |
.IX Item "ppid=int" | (`=') |
The parent process \s-1ID\s0 of the running \fBsudo\fR process. | since the |
Only available starting with \s-1API\s0 version 1.2 | \fIname\fR |
.IP "sid=int" 4 | field will never include one |
.IX Item "sid=int" | itself but the |
The session \s-1ID\s0 of the running \fBsudo\fR process or 0 if \fBsudo\fR is | \fIvalue\fR |
not part of a \s-1POSIX\s0 job control session. | might. |
Only available starting with \s-1API\s0 version 1.2 | .RS |
.IP "pgid=int" 4 | .PD |
.IX Item "pgid=int" | .TP 6n |
The \s-1ID\s0 of the process group that the running \fBsudo\fR process belongs | cols=int |
to. | The number of columns the user's terminal supports. |
Only available starting with \s-1API\s0 version 1.2 | If there is no terminal device available, a default value of 80 is used. |
.IP "tcpgid=int" 4 | .TP 6n |
.IX Item "tcpgid=int" | cwd=string |
The \s-1ID\s0 of the forground process group associated with the terminal | The user's current working directory. |
device associcated with the \fBsudo\fR process or \-1 if there is no | .TP 6n |
terminal present. | egid=gid_t |
Only available starting with \s-1API\s0 version 1.2 | The effective group ID of the user invoking |
.IP "user=string" 4 | \fBsudo\fR. |
.IX Item "user=string" | .TP 6n |
The name of the user invoking \fBsudo\fR. | euid=uid_t |
.IP "euid=uid_t" 4 | The effective user ID of the user invoking |
.IX Item "euid=uid_t" | \fBsudo\fR. |
The effective user \s-1ID\s0 of the user invoking \fBsudo\fR. | .TP 6n |
.IP "uid=uid_t" 4 | gid=gid_t |
.IX Item "uid=uid_t" | The real group ID of the user invoking |
The real user \s-1ID\s0 of the user invoking \fBsudo\fR. | \fBsudo\fR. |
.IP "egid=gid_t" 4 | .TP 6n |
.IX Item "egid=gid_t" | groups=list |
The effective group \s-1ID\s0 of the user invoking \fBsudo\fR. | |
.IP "gid=gid_t" 4 | |
.IX Item "gid=gid_t" | |
The real group \s-1ID\s0 of the user invoking \fBsudo\fR. | |
.IP "groups=list" 4 | |
.IX Item "groups=list" | |
The user's supplementary group list formatted as a string of |
The user's supplementary group list formatted as a string of |
comma-separated group IDs. |
comma-separated group IDs. |
.IP "cwd=string" 4 | .TP 6n |
.IX Item "cwd=string" | host=string |
The user's current working directory. | The local machine's hostname as returned by the |
.IP "tty=string" 4 | gethostname(2) |
.IX Item "tty=string" | |
The path to the user's terminal device. If the user has no terminal | |
device associated with the session, the value will be empty, as in | |
\&\f(CW\*(C`tty=\*(C'\fR. | |
.IP "host=string" 4 | |
.IX Item "host=string" | |
The local machine's hostname as returned by the \f(CW\*(C`gethostname()\*(C'\fR | |
system call. |
system call. |
.IP "lines=int" 4 | .TP 6n |
.IX Item "lines=int" | lines=int |
The number of lines the user's terminal supports. If there is | The number of lines the user's terminal supports. |
| If there is |
no terminal device available, a default value of 24 is used. |
no terminal device available, a default value of 24 is used. |
.IP "cols=int" 4 | .TP 6n |
.IX Item "cols=int" | pgid=int |
The number of columns the user's terminal supports. If there is | The ID of the process group that the running |
no terminal device available, a default value of 80 is used. | \fBsudo\fR |
.RE | process is a member of. |
.RS 4 | Only available starting with API version 1.2 |
.RE | .TP 6n |
.IP "user_env" 4 | pid=int |
.IX Item "user_env" | The process ID of the running |
The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of | \fBsudo\fR |
\&\*(L"name=value\*(R" strings. | process. |
.Sp | Only available starting with API version 1.2 |
When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR | .TP 6n |
equal sign ('=') since the \fIname\fR field will never include one | plugin_options |
itself but the \fIvalue\fR might. | |
.IP "plugin_options" 4 | |
.IX Item "plugin_options" | |
Any (non-comment) strings immediately after the plugin path are |
Any (non-comment) strings immediately after the plugin path are |
treated as arguments to the plugin. These arguments are split on | passed as arguments to the plugin. |
a white space boundary and are passed to the plugin in the form of | These arguments are split on a white space boundary and are passed to |
a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings. If no arguments were | the plugin in the form of a |
specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer. | \fRNULL\fR-terminated |
.Sp | array of strings. |
\&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with | If no arguments were |
\&\s-1API\s0 version 1.2. A plugin \fBmust\fR check the \s-1API\s0 version specified | specified, |
by the \fBsudo\fR front end before using \fIplugin_options\fR. Failure to | \fIplugin_options\fR |
do so may result in a crash. | will be the |
| \fRNULL\fR |
| pointer. |
| .sp |
| NOTE: the |
| \fIplugin_options\fR |
| parameter is only available starting with |
| API version 1.2. |
| A plugin |
| \fBmust\fR |
| check the API version specified |
| by the |
| \fBsudo\fR |
| front end before using |
| \fIplugin_options\fR. |
| Failure to do so may result in a crash. |
| .TP 6n |
| ppid=int |
| The parent process ID of the running |
| \fBsudo\fR |
| process. |
| Only available starting with API version 1.2 |
| .TP 6n |
| sid=int |
| The session ID of the running |
| \fBsudo\fR |
| process or 0 if |
| \fBsudo\fR |
| is not part of a POSIX job control session. |
| Only available starting with API version 1.2 |
| .TP 6n |
| tcpgid=int |
| The ID of the foreground process group associated with the terminal |
| device associated with the |
| \fBsudo\fR |
| process or \-1 if there is no |
| terminal present. |
| Only available starting with API version 1.2 |
| .TP 6n |
| tty=string |
| The path to the user's terminal device. |
| If the user has no terminal device associated with the session, |
| the value will be empty, as in |
| ``\fRtty=\fR''. |
| .TP 6n |
| uid=uid_t |
| The real user ID of the user invoking |
| \fBsudo\fR. |
| .TP 6n |
| user=string |
| The name of the user invoking |
| \fBsudo\fR. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| user_env |
| The user's environment in the form of a |
| \fRNULL\fR-terminated vector of |
| ``name=value'' |
| strings. |
| .sp |
| When parsing |
| \fIuser_env\fR, |
| the plugin should split on the |
| \fBfirst\fR |
| equal sign |
| (`=') |
| since the |
| \fIname\fR |
| field will never include one |
| itself but the |
| \fIvalue\fR |
| might. |
| .PD |
| .PP |
.RE |
.RE |
.IP "close" 4 | .PD 0 |
.IX Item "close" | .TP 6n |
.Vb 1 | close |
\& void (*close)(int exit_status, int error); | .br |
.Ve | .RS |
.Sp | .nf |
The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR | .RS 0n |
| void (*close)(int exit_status, int error); |
| .RE |
| .fi |
| .sp |
| The |
| \fBclose\fR() |
| function is called when the command being run by |
| \fBsudo\fR |
finishes. |
finishes. |
.Sp | .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "exit_status" 4 | .TP 6n |
.IX Item "exit_status" | exit_status |
The command's exit status, as returned by the \fIwait\fR\|(2) system call. | The command's exit status, as returned by the |
The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero. | wait(2) |
.IP "error" 4 | system call. |
.IX Item "error" | The value of |
| \fRexit_status\fR |
| is undefined if |
| \fRerror\fR |
| is non-zero. |
| .TP 6n |
| error |
| .br |
If the command could not be executed, this is set to the value of |
If the command could not be executed, this is set to the value of |
\&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call. The plugin is responsible | \fRerrno\fR |
for displaying error information via the conversation or plugin_printf | set by the |
function. If the command was successfully executed, the value of | execve(2) |
\&\f(CW\*(C`error\*(C'\fR is 0. | system call. |
| The plugin is responsible for displaying error information via the |
| \fBconversation\fR() |
| or |
| \fBplugin_printf\fR() |
| function. |
| If the command was successfully executed, the value of |
| \fRerror\fR |
| is 0. |
| .PP |
| If no |
| \fBclose\fR() |
| function is defined, no I/O logging plugins are loaded, |
| and neither the |
| \fItimeout\fR |
| not |
| \fIuse_pty\fR |
| options are set in the |
| \fRcommand_info\fR |
| list, the |
| \fBsudo\fR |
| front end may execute the command directly instead of running |
| it as a child process. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| show_version |
| .RS |
| .nf |
| .RS 0n |
| int (*show_version)(int verbose); |
.RE |
.RE |
.IP "show_version" 4 | .fi |
.IX Item "show_version" | .sp |
.Vb 1 | The |
\& int (*show_version)(int verbose); | \fBshow_version\fR() |
.Ve | function is called by |
.Sp | \fBsudo\fR |
The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies | when the user specifies |
the \f(CW\*(C`\-V\*(C'\fR option. The plugin may display its version information | the |
to the user via the conversation or plugin_printf function using | \fB\-V\fR |
\&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR. If the user requests detailed version | option. |
information, the verbose flag will be set. | The plugin may display its version information to the user via the |
.IP "check_policy" 4 | \fBconversation\fR() |
.IX Item "check_policy" | or |
.Vb 3 | \fBplugin_printf\fR() |
\& int (*check_policy)(int argc, char * const argv[] | function using |
\& char *env_add[], char **command_info[], | \fRSUDO_CONV_INFO_MSG\fR. |
\& char **argv_out[], char **user_env_out[]); | If the user requests detailed version information, the verbose flag will be set. |
.Ve | .PD |
.Sp | .PP |
The \fIcheck_policy\fR function is called by \fBsudo\fR to determine | .RE |
| .PD 0 |
| .TP 6n |
| check_policy |
| .RS |
| .nf |
| .RS 0n |
| int (*check_policy)(int argc, char * const argv[] |
| char *env_add[], char **command_info[], |
| char **argv_out[], char **user_env_out[]); |
| .RE |
| .fi |
| .sp |
| The |
| \fBcheck_policy\fR() |
| function is called by |
| \fBsudo\fR |
| to determine |
whether the user is allowed to run the specified commands. |
whether the user is allowed to run the specified commands. |
.Sp | .sp |
If the \fIsudoedit\fR option was enabled in the \fIsettings\fR array | If the |
passed to the \fIopen\fR function, the user has requested \fIsudoedit\fR | \fIsudoedit\fR |
mode. \fIsudoedit\fR is a mechanism for editing one or more files | option was enabled in the |
| \fIsettings\fR |
| array |
| passed to the |
| \fBopen\fR() |
| function, the user has requested |
| \fIsudoedit\fR |
| mode. |
| \fIsudoedit\fR |
| is a mechanism for editing one or more files |
where an editor is run with the user's credentials instead of with |
where an editor is run with the user's credentials instead of with |
elevated privileges. \fBsudo\fR achieves this by creating user-writable | elevated privileges. |
| \fBsudo\fR |
| achieves this by creating user-writable |
temporary copies of the files to be edited and then overwriting the |
temporary copies of the files to be edited and then overwriting the |
originals with the temporary copies after editing is complete. If | originals with the temporary copies after editing is complete. |
the plugin supports \fBsudoedit\fR, it should choose the editor to be | If the plugin supports |
used, potentially from a variable in the user's environment, such | \fIsudoedit\fR, |
as \f(CW\*(C`EDITOR\*(C'\fR, and include it in \fIargv_out\fR (note that environment | it should choose the editor to be used, potentially from a variable |
variables may include command line flags). The files to be edited | in the user's environment, such as |
should be copied from \fIargv\fR into \fIargv_out\fR, separated from the | \fREDITOR\fR, |
editor and its arguments by a \f(CW"\-\-"\fR element. The \f(CW"\-\-"\fR will | and include it in |
be removed by \fBsudo\fR before the editor is executed. The plugin | \fIargv_out\fR |
should also set \fIsudoedit=true\fR in the \fIcommand_info\fR list. | (note that environment |
.Sp | variables may include command line flags). |
The \fIcheck_policy\fR function returns 1 if the command is allowed, | The files to be edited should be copied from |
| \fIargv\fR |
| into |
| \fIargv_out\fR, |
| separated from the |
| editor and its arguments by a |
| ``\fR--\fR'' |
| element. |
| The |
| ``\fR--\fR'' |
| will |
| be removed by |
| \fBsudo\fR |
| before the editor is executed. |
| The plugin should also set |
| \fIsudoedit=true\fR |
| in the |
| \fIcommand_info\fR |
| list. |
| .sp |
| The |
| \fBcheck_policy\fR() |
| function returns 1 if the command is allowed, |
0 if not allowed, \-1 for a general error, or \-2 for a usage error |
0 if not allowed, \-1 for a general error, or \-2 for a usage error |
or if \fBsudoedit\fR was specified but is unsupported by the plugin. | or if |
In the latter case, \fBsudo\fR will print a usage message before it | \fIsudoedit\fR |
exits. If an error occurs, the plugin may optionally call the | was specified but is unsupported by the plugin. |
conversation or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR | In the latter case, |
| \fBsudo\fR |
| will print a usage message before it |
| exits. |
| If an error occurs, the plugin may optionally call the |
| \fBconversation\fR() |
| or |
| \fBplugin_printf\fR() |
| function with |
| \fRSUDO_CONF_ERROR_MSG\fR |
to present additional error information to the user. |
to present additional error information to the user. |
.Sp | .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "argc" 4 | .TP 6n |
.IX Item "argc" | argc |
The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR | The number of elements in |
| \fIargv\fR, |
| not counting the final |
| \fRNULL\fR |
pointer. |
pointer. |
.IP "argv" 4 | .TP 6n |
.IX Item "argv" | argv |
The argument vector describing the command the user wishes to run, |
The argument vector describing the command the user wishes to run, |
in the same form as what would be passed to the \fIexecve()\fR system | in the same form as what would be passed to the |
call. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. | execve(2) |
.IP "env_add" 4 | system call. |
.IX Item "env_add" | The vector is terminated by a |
| \fRNULL\fR |
| pointer. |
| .TP 6n |
| env_add |
Additional environment variables specified by the user on the command |
Additional environment variables specified by the user on the command |
line in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R" | line in the form of a |
strings. The plugin may reject the command if one or more variables | \fRNULL\fR-terminated |
| vector of |
| ``name=value'' |
| strings. |
| The plugin may reject the command if one or more variables |
are not allowed to be set, or it may silently ignore such variables. |
are not allowed to be set, or it may silently ignore such variables. |
.Sp | .sp |
When parsing \fIenv_add\fR, the plugin should split on the \fBfirst\fR | When parsing |
equal sign ('=') since the \fIname\fR field will never include one | \fIenv_add\fR, |
itself but the \fIvalue\fR might. | the plugin should split on the |
.IP "command_info" 4 | \fBfirst\fR |
.IX Item "command_info" | equal sign |
Information about the command being run in the form of \*(L"name=value\*(R" | (`=') |
strings. These values are used by \fBsudo\fR to set the execution | since the |
environment when running a command. The plugin is responsible for | \fIname\fR |
creating and populating the vector, which must be terminated with | field will never include one |
a \f(CW\*(C`NULL\*(C'\fR pointer. The following values are recognized by \fBsudo\fR: | itself but the |
.RS 4 | \fIvalue\fR |
.IP "command=string" 4 | might. |
.IX Item "command=string" | .TP 6n |
| command_info |
| Information about the command being run in the form of |
| ``name=value'' |
| strings. |
| These values are used by |
| \fBsudo\fR |
| to set the execution |
| environment when running a command. |
| The plugin is responsible for creating and populating the vector, |
| which must be terminated with a |
| \fRNULL\fR |
| pointer. |
| The following values are recognized by |
| \fBsudo\fR: |
| .RS |
| .TP 6n |
| chroot=string |
| The root directory to use when running the command. |
| .TP 6n |
| closefrom=number |
| If specified, |
| \fBsudo\fR |
| will close all files descriptors with a value |
| of |
| \fInumber\fR |
| or higher. |
| .TP 6n |
| command=string |
Fully qualified path to the command to be executed. |
Fully qualified path to the command to be executed. |
.IP "runas_uid=uid" 4 | .TP 6n |
.IX Item "runas_uid=uid" | cwd=string |
User \s-1ID\s0 to run the command as. | |
.IP "runas_euid=uid" 4 | |
.IX Item "runas_euid=uid" | |
Effective user \s-1ID\s0 to run the command as. | |
If not specified, the value of \fIrunas_uid\fR is used. | |
.IP "runas_gid=gid" 4 | |
.IX Item "runas_gid=gid" | |
Group \s-1ID\s0 to run the command as. | |
.IP "runas_egid=gid" 4 | |
.IX Item "runas_egid=gid" | |
Effective group \s-1ID\s0 to run the command as. | |
If not specified, the value of \fIrunas_gid\fR is used. | |
.IP "runas_groups=list" 4 | |
.IX Item "runas_groups=list" | |
The supplementary group vector to use for the command in the form | |
of a comma-separated list of group IDs. If \fIpreserve_groups\fR | |
is set, this option is ignored. | |
.IP "login_class=string" 4 | |
.IX Item "login_class=string" | |
\&\s-1BSD\s0 login class to use when setting resource limits and nice value | |
(optional). This option is only set on systems that support login | |
classes. | |
.IP "preserve_groups=bool" 4 | |
.IX Item "preserve_groups=bool" | |
If set, \fBsudo\fR will preserve the user's group vector instead of | |
initializing the group vector based on \f(CW\*(C`runas_user\*(C'\fR. | |
.IP "cwd=string" 4 | |
.IX Item "cwd=string" | |
The current working directory to change to when executing the command. |
The current working directory to change to when executing the command. |
.IP "noexec=bool" 4 | .TP 6n |
.IX Item "noexec=bool" | exec_background=bool |
If set, prevent the command from executing other programs. | By default, |
.IP "chroot=string" 4 | \fBsudo\fR |
.IX Item "chroot=string" | runs a command as the foreground process as long as |
The root directory to use when running the command. | \fBsudo\fR |
.IP "nice=int" 4 | itself is running in the foreground. |
.IX Item "nice=int" | When |
Nice value (priority) to use when executing the command. The nice | \fIexec_background\fR |
value, if specified, overrides the priority associated with the | is enabled and the command is being run in a pty (due to I/O logging |
\&\fIlogin_class\fR on \s-1BSD\s0 systems. | or the |
.IP "umask=octal" 4 | \fIuse_pty\fR |
.IX Item "umask=octal" | setting), the command will be run as a background process. |
The file creation mask to use when executing the command. | Attempts to read from the controlling terminal (or to change terminal |
.IP "selinux_role=string" 4 | settings) will result in the command being suspended with the |
.IX Item "selinux_role=string" | \fRSIGTTIN\fR |
SELinux role to use when executing the command. | signal (or |
.IP "selinux_type=string" 4 | \fRSIGTTOU\fR |
.IX Item "selinux_type=string" | in the case of terminal settings). |
SELinux type to use when executing the command. | If this happens when |
.IP "timeout=int" 4 | \fBsudo\fR |
.IX Item "timeout=int" | is a foreground process, the command will be granted the controlling terminal |
Command timeout. If non-zero then when the timeout expires the | and resumed in the foreground with no user intervention required. |
command will be killed. | The advantage of initially running the command in the background is that |
.IP "sudoedit=bool" 4 | \fBsudo\fR |
.IX Item "sudoedit=bool" | need not read from the terminal unless the command explicitly requests it. |
Set to true when in \fIsudoedit\fR mode. The plugin may enable | Otherwise, any terminal input must be passed to the command, whether it |
\&\fIsudoedit\fR mode even if \fBsudo\fR was not invoked as \fBsudoedit\fR. | has required it or not (the kernel buffers terminals so it is not possible |
This allows the plugin to perform command substitution and transparently | to tell whether the command really wants the input). |
enable \fIsudoedit\fR when the user attempts to run an editor. | This is different from historic |
.IP "closefrom=number" 4 | \fIsudo\fR |
.IX Item "closefrom=number" | behavior or when the command is not being run in a pty. |
If specified, \fBsudo\fR will close all files descriptors with a value | .sp |
of \fInumber\fR or higher. | For this to work seamlessly, the operating system must support the |
.IP "iolog_compress=bool" 4 | automatic restarting of system calls. |
.IX Item "iolog_compress=bool" | Unfortunately, not all operating systems do this by default, |
| and even those that do may have bugs. |
| For example, Mac OS X fails to restart the |
| \fBtcgetattr\fR() |
| and |
| \fBtcsetattr\fR() |
| system calls (this is a bug in Mac OS X). |
| Furthermore, because this behavior depends on the command stopping with the |
| \fRSIGTTIN\fR |
| or |
| \fRSIGTTOU\fR |
| signals, programs that catch these signals and suspend themselves |
| with a different signal (usually |
| \fRSIGTOP\fR) |
| will not be automatically foregrounded. |
| Some versions of the linux |
| su(1) |
| command behave this way. |
| Because of this, a plugin should not set |
| \fIexec_background\fR |
| unless it is explicitly enabled by the administrator and there should |
| be a way to enabled or disable it on a per-command basis. |
| .sp |
| This setting has no effect unless I/O logging is enabled or |
| \fIuse_pty\fR |
| is enabled. |
| .TP 6n |
| iolog_compress=bool |
Set to true if the I/O logging plugins, if any, should compress the |
Set to true if the I/O logging plugins, if any, should compress the |
log data. This is a hint to the I/O logging plugin which may choose | log data. |
to ignore it. | This is a hint to the I/O logging plugin which may choose to ignore it. |
.IP "iolog_path=string" 4 | .TP 6n |
.IX Item "iolog_path=string" | iolog_path=string |
Fully qualified path to the file or directory in which I/O log is |
Fully qualified path to the file or directory in which I/O log is |
to be stored. This is a hint to the I/O logging plugin which may | to be stored. |
choose to ignore it. If no I/O logging plugin is loaded, this | This is a hint to the I/O logging plugin which may choose to ignore it. |
setting has no effect. | If no I/O logging plugin is loaded, this setting has no effect. |
.IP "iolog_stdin=bool" 4 | .TP 6n |
.IX Item "iolog_stdin=bool" | iolog_stdin=bool |
Set to true if the I/O logging plugins, if any, should log the |
Set to true if the I/O logging plugins, if any, should log the |
standard input if it is not connected to a terminal device. This | standard input if it is not connected to a terminal device. |
is a hint to the I/O logging plugin which may choose to ignore it. | This is a hint to the I/O logging plugin which may choose to ignore it. |
.IP "iolog_stdout=bool" 4 | .TP 6n |
.IX Item "iolog_stdout=bool" | iolog_stdout=bool |
Set to true if the I/O logging plugins, if any, should log the |
Set to true if the I/O logging plugins, if any, should log the |
standard output if it is not connected to a terminal device. This | standard output if it is not connected to a terminal device. |
is a hint to the I/O logging plugin which may choose to ignore it. | This is a hint to the I/O logging plugin which may choose to ignore it. |
.IP "iolog_stderr=bool" 4 | .TP 6n |
.IX Item "iolog_stderr=bool" | iolog_stderr=bool |
Set to true if the I/O logging plugins, if any, should log the |
Set to true if the I/O logging plugins, if any, should log the |
standard error if it is not connected to a terminal device. This | standard error if it is not connected to a terminal device. |
is a hint to the I/O logging plugin which may choose to ignore it. | This is a hint to the I/O logging plugin which may choose to ignore it. |
.IP "iolog_ttyin=bool" 4 | .TP 6n |
.IX Item "iolog_ttyin=bool" | iolog_ttyin=bool |
Set to true if the I/O logging plugins, if any, should log all |
Set to true if the I/O logging plugins, if any, should log all |
terminal input. This only includes input typed by the user and not | terminal input. |
from a pipe or redirected from a file. This is a hint to the I/O | This only includes input typed by the user and not from a pipe or |
logging plugin which may choose to ignore it. | redirected from a file. |
.IP "iolog_ttyout=bool" 4 | This is a hint to the I/O logging plugin which may choose to ignore it. |
.IX Item "iolog_ttyout=bool" | .TP 6n |
| iolog_ttyout=bool |
Set to true if the I/O logging plugins, if any, should log all |
Set to true if the I/O logging plugins, if any, should log all |
terminal output. This only includes output to the screen, not | terminal output. |
output to a pipe or file. This is a hint to the I/O logging plugin | This only includes output to the screen, not output to a pipe or file. |
which may choose to ignore it. | This is a hint to the I/O logging plugin which may choose to ignore it. |
.IP "use_pty=bool" 4 | .TP 6n |
.IX Item "use_pty=bool" | login_class=string |
| BSD login class to use when setting resource limits and nice value |
| (optional). |
| This option is only set on systems that support login classes. |
| .TP 6n |
| nice=int |
| Nice value (priority) to use when executing the command. |
| The nice value, if specified, overrides the priority associated with the |
| \fIlogin_class\fR |
| on BSD systems. |
| .TP 6n |
| noexec=bool |
| If set, prevent the command from executing other programs. |
| .TP 6n |
| preserve_groups=bool |
| If set, |
| \fBsudo\fR |
| will preserve the user's group vector instead of |
| initializing the group vector based on |
| \fRrunas_user\fR. |
| .TP 6n |
| runas_egid=gid |
| Effective group ID to run the command as. |
| If not specified, the value of |
| \fIrunas_gid\fR |
| is used. |
| .TP 6n |
| runas_euid=uid |
| Effective user ID to run the command as. |
| If not specified, the value of |
| \fIrunas_uid\fR |
| is used. |
| .TP 6n |
| runas_gid=gid |
| Group ID to run the command as. |
| .TP 6n |
| runas_groups=list |
| The supplementary group vector to use for the command in the form |
| of a comma-separated list of group IDs. |
| If |
| \fIpreserve_groups\fR |
| is set, this option is ignored. |
| .TP 6n |
| runas_uid=uid |
| User ID to run the command as. |
| .TP 6n |
| selinux_role=string |
| SELinux role to use when executing the command. |
| .TP 6n |
| selinux_type=string |
| SELinux type to use when executing the command. |
| .TP 6n |
| set_utmp=bool |
| Create a utmp (or utmpx) entry when a pseudo-tty is allocated. |
| By default, the new entry will be a copy of the user's existing utmp |
| entry (if any), with the tty, time, type and pid fields updated. |
| .TP 6n |
| sudoedit=bool |
| Set to true when in |
| \fIsudoedit\fR |
| mode. |
| The plugin may enable |
| \fIsudoedit\fR |
| mode even if |
| \fBsudo\fR |
| was not invoked as |
| \fBsudoedit\fR. |
| This allows the plugin to perform command substitution and transparently |
| enable |
| \fIsudoedit\fR |
| when the user attempts to run an editor. |
| .TP 6n |
| timeout=int |
| Command timeout. |
| If non-zero then when the timeout expires the command will be killed. |
| .TP 6n |
| umask=octal |
| The file creation mask to use when executing the command. |
| .TP 6n |
| use_pty=bool |
Allocate a pseudo-tty to run the command in, regardless of whether |
Allocate a pseudo-tty to run the command in, regardless of whether |
or not I/O logging is in use. By default, \fBsudo\fR will only run | or not I/O logging is in use. |
| By default, |
| \fBsudo\fR |
| will only run |
the command in a pty when an I/O log plugin is loaded. |
the command in a pty when an I/O log plugin is loaded. |
.IP "set_utmp=bool" 4 | .TP 6n |
.IX Item "set_utmp=bool" | utmp_user=string |
Create a utmp (or utmpx) entry when a pseudo-tty is allocated. By | |
default, the new entry will be a copy of the user's existing utmp | |
entry (if any), with the tty, time, type and pid fields updated. | |
.IP "utmp_user=string" 4 | |
.IX Item "utmp_user=string" | |
User name to use when constructing a new utmp (or utmpx) entry when |
User name to use when constructing a new utmp (or utmpx) entry when |
\&\fIset_utmp\fR is enabled. This option can be used to set the user | \fIset_utmp\fR |
field in the utmp entry to the user the command runs as rather than | is enabled. |
the invoking user. If not set, \fBsudo\fR will base the new entry on | This option can be used to set the user field in the utmp entry to |
| the user the command runs as rather than the invoking user. |
| If not set, |
| \fBsudo\fR |
| will base the new entry on |
the invoking user's existing entry. |
the invoking user's existing entry. |
.RE | .PP |
.RS 4 | |
.Sp | |
Unsupported values will be ignored. |
Unsupported values will be ignored. |
|
.PP |
.RE |
.RE |
.IP "argv_out" 4 | .PD 0 |
.IX Item "argv_out" | .TP 6n |
The \f(CW\*(C`NULL\*(C'\fR\-terminated argument vector to pass to the \fIexecve()\fR | argv_out |
system call when executing the command. The plugin is responsible | The |
for allocating and populating the vector. | \fRNULL\fR-terminated |
.IP "user_env_out" 4 | argument vector to pass to the |
.IX Item "user_env_out" | execve(2) |
The \f(CW\*(C`NULL\*(C'\fR\-terminated environment vector to use when executing the | system call when executing the command. |
command. The plugin is responsible for allocating and populating | The plugin is responsible for allocating and populating the vector. |
the vector. | .PD |
| .TP 6n |
| user_env_out |
| The |
| \fRNULL\fR-terminated |
| environment vector to use when executing the command. |
| The plugin is responsible for allocating and populating the vector. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| list |
| .RS |
| .nf |
| .RS 0n |
| int (*list)(int verbose, const char *list_user, |
| int argc, char * const argv[]); |
.RE |
.RE |
.IP "list" 4 | .fi |
.IX Item "list" | .sp |
.Vb 2 | List available privileges for the invoking user. |
\& int (*list)(int verbose, const char *list_user, | Returns 1 on success, 0 on failure and \-1 on error. |
\& int argc, char * const argv[]); | On error, the plugin may optionally call the |
.Ve | \fBconversation\fR() |
.Sp | or |
List available privileges for the invoking user. Returns 1 on | \fBplugin_printf\fR() |
success, 0 on failure and \-1 on error. On error, the plugin may | function with |
optionally call the conversation or plugin_printf function with | \fRSUDO_CONF_ERROR_MSG\fR |
\&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to | to present additional error information to |
the user. |
the user. |
.Sp | .sp |
Privileges should be output via the conversation or plugin_printf | Privileges should be output via the |
function using \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR. | \fBconversation\fR() |
.RS 4 | or |
.IP "verbose" 4 | \fBplugin_printf\fR() |
.IX Item "verbose" | function using |
| \fRSUDO_CONV_INFO_MSG\fR, |
| .PD |
| .TP 6n |
| verbose |
Flag indicating whether to list in verbose mode or not. |
Flag indicating whether to list in verbose mode or not. |
.IP "list_user" 4 | .TP 6n |
.IX Item "list_user" | list_user |
The name of a different user to list privileges for if the policy |
The name of a different user to list privileges for if the policy |
allows it. If \f(CW\*(C`NULL\*(C'\fR, the plugin should list the privileges of | allows it. |
the invoking user. | If |
.IP "argc" 4 | \fRNULL\fR, |
.IX Item "argc" | the plugin should list the privileges of the invoking user. |
The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR | .TP 6n |
| argc |
| The number of elements in |
| \fIargv\fR, |
| not counting the final |
| \fRNULL\fR |
pointer. |
pointer. |
.IP "argv" 4 | .TP 6n |
.IX Item "argv" | argv |
If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user | If |
| non-\fRNULL\fR, |
| an argument vector describing a command the user |
wishes to check against the policy in the same form as what would |
wishes to check against the policy in the same form as what would |
be passed to the \fIexecve()\fR system call. If the command is permitted | be passed to the |
by the policy, the fully-qualified path to the command should be | execve(2) |
displayed along with any command line arguments. | system call. |
| If the command is permitted by the policy, the fully-qualified path |
| to the command should be displayed along with any command line arguments. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| validate |
| .RS |
| .nf |
| .RS 0n |
| int (*validate)(void); |
.RE |
.RE |
.IP "validate" 4 | .fi |
.IX Item "validate" | .sp |
.Vb 1 | The |
\& int (*validate)(void); | \fBvalidate\fR() |
.Ve | function is called when |
.Sp | \fBsudo\fR |
The \f(CW\*(C`validate\*(C'\fR function is called when \fBsudo\fR is run with the | is run with the |
\&\f(CW\*(C`\-v\*(C'\fR flag. For policy plugins such as \fIsudoers\fR that cache | \fB\-v\fR |
| flag. |
| For policy plugins such as |
| \fBsudoers\fR |
| that cache |
authentication credentials, this function will validate and cache |
authentication credentials, this function will validate and cache |
the credentials. |
the credentials. |
.Sp | .sp |
The \f(CW\*(C`validate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not | The |
support credential caching. | \fBvalidate\fR() |
.Sp | function should be |
| \fRNULL\fR |
| if the plugin does not support credential caching. |
| .sp |
Returns 1 on success, 0 on failure and \-1 on error. |
Returns 1 on success, 0 on failure and \-1 on error. |
On error, the plugin may optionally call the conversation or plugin_printf | On error, the plugin may optionally call the |
function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional | \fBconversation\fR() |
| or |
| \fBplugin_printf\fR() |
| function with |
| \fRSUDO_CONF_ERROR_MSG\fR |
| to present additional |
error information to the user. |
error information to the user. |
.IP "invalidate" 4 | .PD |
.IX Item "invalidate" | .PP |
.Vb 1 | .RE |
\& void (*invalidate)(int remove); | .PD 0 |
.Ve | .TP 6n |
.Sp | invalidate |
The \f(CW\*(C`invalidate\*(C'\fR function is called when \fBsudo\fR is called with | .RS |
the \f(CW\*(C`\-k\*(C'\fR or \f(CW\*(C`\-K\*(C'\fR flag. For policy plugins such as \fIsudoers\fR that | .nf |
| .RS 0n |
| void (*invalidate)(int remove); |
| .RE |
| .fi |
| .sp |
| The |
| \fBinvalidate\fR() |
| function is called when |
| \fBsudo\fR |
| is called with |
| the |
| \fB\-k\fR |
| or |
| \fB\-K\fR |
| flag. |
| For policy plugins such as |
| \fBsudoers\fR |
| that |
cache authentication credentials, this function will invalidate the |
cache authentication credentials, this function will invalidate the |
credentials. If the \fIremove\fR flag is set, the plugin may remove | credentials. |
| If the |
| \fIremove\fR |
| flag is set, the plugin may remove |
the credentials instead of simply invalidating them. |
the credentials instead of simply invalidating them. |
.Sp | .sp |
The \f(CW\*(C`invalidate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not | The |
support credential caching. | \fBinvalidate\fR() |
.IP "init_session" 4 | function should be |
.IX Item "init_session" | \fRNULL\fR |
.Vb 1 | if the plugin does not support credential caching. |
\& int (*init_session)(struct passwd *pwd, char **user_envp[); | .PD |
.Ve | .PP |
.Sp | .RE |
The \f(CW\*(C`init_session\*(C'\fR function is called before \fBsudo\fR sets up the | .PD 0 |
execution environment for the command. It is run in the parent | .TP 6n |
\&\fBsudo\fR process and before any uid or gid changes. This can be used | init_session |
to perform session setup that is not supported by \fIcommand_info\fR, | .RS |
such as opening the \s-1PAM\s0 session. The \f(CW\*(C`close\*(C'\fR function can be | .nf |
used to tear down the session that was opened by \f(CW\*(C`init_session\*(C'\fR. | .RS 0n |
.Sp | int (*init_session)(struct passwd *pwd, char **user_envp[); |
The \fIpwd\fR argument points to a passwd struct for the user the | .RE |
| .fi |
| .sp |
| The |
| \fBinit_session\fR() |
| function is called before |
| \fBsudo\fR |
| sets up the |
| execution environment for the command. |
| It is run in the parent |
| \fBsudo\fR |
| process and before any uid or gid changes. |
| This can be used to perform session setup that is not supported by |
| \fIcommand_info\fR, |
| such as opening the PAM session. |
| The |
| \fBclose\fR() |
| function can be |
| used to tear down the session that was opened by |
| \fRinit_session\fR. |
| .sp |
| The |
| \fIpwd\fR |
| argument points to a passwd struct for the user the |
command will be run as if the uid the command will run as was found |
command will be run as if the uid the command will run as was found |
in the password database, otherwise it will be \s-1NULL\s0. | in the password database, otherwise it will be |
.Sp | \fRNULL\fR. |
The \fIuser_env\fR argument points to the environment the command will | .sp |
run in, in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R" | The |
strings. This is the same string passed back to the front end via | \fIuser_env\fR |
the Policy Plugin's \fIuser_env_out\fR parameter. If the \f(CW\*(C`init_session\*(C'\fR | argument points to the environment the command will |
| run in, in the form of a |
| \fRNULL\fR-terminated |
| vector of |
| ``name=value'' |
| strings. |
| This is the same string passed back to the front end via |
| the Policy Plugin's |
| \fIuser_env_out\fR |
| parameter. |
| If the |
| \fBinit_session\fR() |
function needs to modify the user environment, it should update the |
function needs to modify the user environment, it should update the |
pointer stored in \fIuser_env\fR. The expected use case is to merge | pointer stored in |
the contents of the \s-1PAM\s0 environment (if any) with the contents of | \fIuser_env\fR. |
\&\fIuser_env\fR. \s-1NOTE:\s0 the \fIuser_env\fR parameter is only available | The expected use case is to merge the contents of the PAM environment |
starting with \s-1API\s0 version 1.2. A plugin \fBmust\fR check the \s-1API\s0 | (if any) with the contents of |
version specified by the \fBsudo\fR front end before using \fIuser_env\fR. | \fIuser_env\fR. |
| NOTE: the |
| \fIuser_env\fR |
| parameter is only available |
| starting with API version 1.2. |
| A plugin |
| \fBmust\fR |
| check the API |
| version specified by the |
| \fBsudo\fR |
| front end before using |
| \fIuser_env\fR. |
Failure to do so may result in a crash. |
Failure to do so may result in a crash. |
.Sp | .sp |
Returns 1 on success, 0 on failure and \-1 on error. |
Returns 1 on success, 0 on failure and \-1 on error. |
On error, the plugin may optionally call the conversation or plugin_printf | On error, the plugin may optionally call the |
function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional | \fBconversation\fR() |
| or |
| \fBplugin_printf\fR() |
| function with |
| \fRSUDO_CONF_ERROR_MSG\fR |
| to present additional |
error information to the user. |
error information to the user. |
.IP "register_hooks" 4 | .PD |
.IX Item "register_hooks" | .PP |
.Vb 2 | .RE |
\& void (*register_hooks)(int version, | .PD 0 |
\& int (*register_hook)(struct sudo_hook *hook)); | .TP 6n |
.Ve | register_hooks |
.Sp | .RS |
The \f(CW\*(C`register_hooks\*(C'\fR function is called by the sudo front end to | .nf |
register any hooks the plugin needs. If the plugin does not support | .RS 0n |
hooks, \f(CW\*(C`register_hooks\*(C'\fR should be set to the \s-1NULL\s0 pointer. | void (*register_hooks)(int version, |
.Sp | int (*register_hook)(struct sudo_hook *hook)); |
The \fIversion\fR argument describes the version of the hooks \s-1API\s0 | .RE |
supported by the \fBsudo\fR front end. | .fi |
.Sp | .sp |
The \f(CW\*(C`register_hook\*(C'\fR function should be used to register any supported | The |
hooks the plugin needs. It returns 0 on success, 1 if the hook | \fBregister_hooks\fR() |
type is not supported and \-1 if the major version in \f(CW\*(C`struct hook\*(C'\fR | function is called by the sudo front end to |
does not match the front end's major hook \s-1API\s0 version. | register any hooks the plugin needs. |
.Sp | If the plugin does not support hooks, |
See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information | \fRregister_hooks\fR |
| should be set to the |
| \fRNULL\fR |
| pointer. |
| .sp |
| The |
| \fIversion\fR |
| argument describes the version of the hooks API |
| supported by the |
| \fBsudo\fR |
| front end. |
| .sp |
| The |
| \fBregister_hook\fR() |
| function should be used to register any supported |
| hooks the plugin needs. |
| It returns 0 on success, 1 if the hook type is not supported and \-1 |
| if the major version in |
| \fRstruct hook\fR |
| does not match the front end's major hook API version. |
| .sp |
| See the |
| \fIHook function API\fR |
| section below for more information |
about hooks. |
about hooks. |
.Sp | .sp |
\&\s-1NOTE:\s0 the \f(CW\*(C`register_hooks\*(C'\fR function is only available starting | NOTE: the |
with \s-1API\s0 version 1.2. If the \fBsudo\fR front end doesn't support \s-1API\s0 | \fBregister_hooks\fR() |
version 1.2 or higher, \f(CW\*(C`register_hooks\*(C'\fR will not be called. | function is only available starting |
.IP "deregister_hooks" 4 | with API version 1.2. |
.IX Item "deregister_hooks" | If the |
.Vb 2 | \fBsudo\fR |
\& void (*deregister_hooks)(int version, | front end doesn't support API |
\& int (*deregister_hook)(struct sudo_hook *hook)); | version 1.2 or higher, |
.Ve | \fRregister_hooks\fR |
.Sp | will not be called. |
The \f(CW\*(C`deregister_hooks\*(C'\fR function is called by the sudo front end | .PD |
to deregister any hooks the plugin has registered. If the plugin | .PP |
does not support hooks, \f(CW\*(C`deregister_hooks\*(C'\fR should be set to the | .RE |
\&\s-1NULL\s0 pointer. | .PD 0 |
.Sp | .TP 6n |
The \fIversion\fR argument describes the version of the hooks \s-1API\s0 | deregister_hooks |
supported by the \fBsudo\fR front end. | .RS |
.Sp | .nf |
The \f(CW\*(C`deregister_hook\*(C'\fR function should be used to deregister any | .RS 0n |
hooks that were put in place by the \f(CW\*(C`register_hook\*(C'\fR function. If | void (*deregister_hooks)(int version, |
the plugin tries to deregister a hook that the front end does not | int (*deregister_hook)(struct sudo_hook *hook)); |
support, \f(CW\*(C`deregister_hook\*(C'\fR will return an error. | .RE |
.Sp | .fi |
See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information | .sp |
| The |
| \fBderegister_hooks\fR() |
| function is called by the sudo front end |
| to deregister any hooks the plugin has registered. |
| If the plugin does not support hooks, |
| \fRderegister_hooks\fR |
| should be set to the |
| \fRNULL\fR |
| pointer. |
| .sp |
| The |
| \fIversion\fR |
| argument describes the version of the hooks API |
| supported by the |
| \fBsudo\fR |
| front end. |
| .sp |
| The |
| \fBderegister_hook\fR() |
| function should be used to deregister any |
| hooks that were put in place by the |
| \fBregister_hook\fR() |
| function. |
| If the plugin tries to deregister a hook that the front end does not support, |
| \fRderegister_hook\fR |
| will return an error. |
| .sp |
| See the |
| \fIHook function API\fR |
| section below for more information |
about hooks. |
about hooks. |
.Sp | .sp |
\&\s-1NOTE:\s0 the \f(CW\*(C`deregister_hooks\*(C'\fR function is only available starting | NOTE: the |
with \s-1API\s0 version 1.2. If the \fBsudo\fR front end doesn't support \s-1API\s0 | \fBderegister_hooks\fR() |
version 1.2 or higher, \f(CW\*(C`deregister_hooks\*(C'\fR will not be called. | function is only available starting |
| with API version 1.2. |
| If the |
| \fBsudo\fR |
| front end doesn't support API |
| version 1.2 or higher, |
| \fRderegister_hooks\fR |
| will not be called. |
| .RE |
| .PD |
.PP |
.PP |
\fIPolicy Plugin Version Macros\fR |
\fIPolicy Plugin Version Macros\fR |
.IX Subsection "Policy Plugin Version Macros" | .nf |
| .sp |
| .RS 0n |
| /* Plugin API version major/minor. */ |
| #define SUDO_API_VERSION_MAJOR 1 |
| #define SUDO_API_VERSION_MINOR 2 |
| #define SUDO_API_MKVERSION(x, y) ((x << 16) | y) |
| #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e |
| SUDO_API_VERSION_MINOR) |
| |
| /* Getters and setters for API version */ |
| #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) |
| #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) |
| #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e |
| *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e |
| } while(0) |
| #define SUDO_VERSION_SET_MINOR(vp, n) do { \e |
| *(vp) = (*(vp) & 0xffff0000) | (n); \e |
| } while(0) |
| .RE |
| .fi |
| .SS "I/O plugin API" |
| .nf |
| .RS 0n |
| struct io_plugin { |
| #define SUDO_IO_PLUGIN 2 |
| unsigned int type; /* always SUDO_IO_PLUGIN */ |
| unsigned int version; /* always SUDO_API_VERSION */ |
| int (*open)(unsigned int version, sudo_conv_t conversation, |
| sudo_printf_t plugin_printf, char * const settings[], |
| char * const user_info[], char * const command_info[], |
| int argc, char * const argv[], char * const user_env[], |
| char * const plugin_options[]); |
| void (*close)(int exit_status, int error); /* wait status or error */ |
| int (*show_version)(int verbose); |
| int (*log_ttyin)(const char *buf, unsigned int len); |
| int (*log_ttyout)(const char *buf, unsigned int len); |
| int (*log_stdin)(const char *buf, unsigned int len); |
| int (*log_stdout)(const char *buf, unsigned int len); |
| int (*log_stderr)(const char *buf, unsigned int len); |
| void (*register_hooks)(int version, |
| int (*register_hook)(struct sudo_hook *hook)); |
| void (*deregister_hooks)(int version, |
| int (*deregister_hook)(struct sudo_hook *hook)); |
| }; |
| .RE |
| .fi |
.PP |
.PP |
.Vb 6 | When an I/O plugin is loaded, |
\& /* Plugin API version major/minor. */ | \fBsudo\fR |
\& #define SUDO_API_VERSION_MAJOR 1 | runs the command in a pseudo-tty. |
\& #define SUDO_API_VERSION_MINOR 2 | |
\& #define SUDO_API_MKVERSION(x, y) ((x << 16) | y) | |
\& #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e | |
\& SUDO_API_VERSION_MINOR) | |
\& | |
\& /* Getters and setters for API version */ | |
\& #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) | |
\& #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) | |
\& #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e | |
\& *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e | |
\& } while(0) | |
\& #define SUDO_VERSION_SET_MINOR(vp, n) do { \e | |
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e | |
\& } while(0) | |
.Ve | |
.SS "I/O Plugin \s-1API\s0" | |
.IX Subsection "I/O Plugin API" | |
.Vb 10 | |
\& struct io_plugin { | |
\& #define SUDO_IO_PLUGIN 2 | |
\& unsigned int type; /* always SUDO_IO_PLUGIN */ | |
\& unsigned int version; /* always SUDO_API_VERSION */ | |
\& int (*open)(unsigned int version, sudo_conv_t conversation | |
\& sudo_printf_t plugin_printf, char * const settings[], | |
\& char * const user_info[], int argc, char * const argv[], | |
\& char * const user_env[], char * const plugin_options[]); | |
\& void (*close)(int exit_status, int error); /* wait status or error */ | |
\& int (*show_version)(int verbose); | |
\& int (*log_ttyin)(const char *buf, unsigned int len); | |
\& int (*log_ttyout)(const char *buf, unsigned int len); | |
\& int (*log_stdin)(const char *buf, unsigned int len); | |
\& int (*log_stdout)(const char *buf, unsigned int len); | |
\& int (*log_stderr)(const char *buf, unsigned int len); | |
\& void (*register_hooks)(int version, | |
\& int (*register_hook)(struct sudo_hook *hook)); | |
\& void (*deregister_hooks)(int version, | |
\& int (*deregister_hook)(struct sudo_hook *hook)); | |
\& }; | |
.Ve | |
.PP | |
When an I/O plugin is loaded, \fBsudo\fR runs the command in a pseudo-tty. | |
This makes it possible to log the input and output from the user's |
This makes it possible to log the input and output from the user's |
session. If any of the standard input, standard output or standard | session. |
error do not correspond to a tty, \fBsudo\fR will open a pipe to capture | If any of the standard input, standard output or standard error do not |
| correspond to a tty, |
| \fBsudo\fR |
| will open a pipe to capture |
the I/O for logging before passing it on. |
the I/O for logging before passing it on. |
.PP |
.PP |
The log_ttyin function receives the raw user input from the terminal |
The log_ttyin function receives the raw user input from the terminal |
device (note that this will include input even when echo is disabled, |
device (note that this will include input even when echo is disabled, |
such as when a password is read). The log_ttyout function receives | such as when a password is read). |
output from the pseudo-tty that is suitable for replaying the user's | The log_ttyout function receives output from the pseudo-tty that is |
session at a later time. The log_stdin, log_stdout and log_stderr | suitable for replaying the user's session at a later time. |
| The |
| \fBlog_stdin\fR(), |
| \fBlog_stdout\fR() |
| and |
| \fBlog_stderr\fR() |
functions are only called if the standard input, standard output |
functions are only called if the standard input, standard output |
or standard error respectively correspond to something other than |
or standard error respectively correspond to something other than |
a tty. |
a tty. |
.PP |
.PP |
Any of the logging functions may be set to the \s-1NULL\s0 | Any of the logging functions may be set to the |
pointer if no logging is to be performed. If the open function | \fRNULL\fR |
returns \f(CW0\fR, no I/O will be sent to the plugin. | pointer if no logging is to be performed. |
| If the open function returns 0, no I/O will be sent to the plugin. |
.PP |
.PP |
The io_plugin struct has the following fields: |
The io_plugin struct has the following fields: |
.IP "type" 4 | .TP 6n |
.IX Item "type" | type |
The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_IO_PLUGIN\s0 | The |
.IP "version" 4 | \fRtype\fR |
.IX Item "version" | field should always be set to |
The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0. | \fRSUDO_IO_PLUGIN\fR. |
.Sp | .TP 6n |
This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was | version |
| The |
| \fRversion\fR |
| field should be set to |
| \fRSUDO_API_VERSION\fR. |
| .sp |
| This allows |
| \fBsudo\fR |
| to determine the API version the plugin was |
built against. |
built against. |
.IP "open" 4 | .TP 6n |
.IX Item "open" | open |
.Vb 4 | .RS |
\& int (*open)(unsigned int version, sudo_conv_t conversation | .nf |
\& sudo_printf_t plugin_printf, char * const settings[], | .RS 0n |
\& char * const user_info[], int argc, char * const argv[], | int (*open)(unsigned int version, sudo_conv_t conversation, |
\& char * const user_env[], char * const plugin_options[]); | sudo_printf_t plugin_printf, char * const settings[], |
.Ve | char * const user_info[], int argc, char * const argv[], |
.Sp | char * const user_env[], char * const plugin_options[]); |
The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR | .RE |
or \fIshow_version\fR functions are called. It is only called if the | .fi |
version is being requested or the \fIcheck_policy\fR function has | .sp |
returned successfully. It returns 1 on success, 0 on failure, \-1 | The |
if a general error occurred, or \-2 if there was a usage error. In | \fBopen\fR() |
the latter case, \fBsudo\fR will print a usage message before it exits. | function is run before the |
If an error occurs, the plugin may optionally call the conversation | \fBlog_input\fR(), |
or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present | \fBlog_output\fR() |
| or |
| \fBshow_version\fR() |
| functions are called. |
| It is only called if the version is being requested or the |
| \fBcheck_policy\fR() |
| function has |
| returned successfully. |
| It returns 1 on success, 0 on failure, \-1 if a general error occurred, |
| or \-2 if there was a usage error. |
| In the latter case, |
| \fBsudo\fR |
| will print a usage message before it exits. |
| If an error occurs, the plugin may optionally call the |
| \fBconversation\fR() |
| or |
| \fBplugin_printf\fR() |
| function with |
| \fRSUDO_CONF_ERROR_MSG\fR |
| to present |
additional error information to the user. |
additional error information to the user. |
.Sp | .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .TP 6n |
.IP "version" 4 | version |
.IX Item "version" | The version passed in by |
The version passed in by \fBsudo\fR allows the plugin to determine the | \fBsudo\fR |
major and minor version number of the plugin \s-1API\s0 supported by | allows the plugin to determine the |
\&\fBsudo\fR. | major and minor version number of the plugin API supported by |
.IP "conversation" 4 | \fBsudo\fR. |
.IX Item "conversation" | .TP 6n |
A pointer to the conversation function that may be used by the | conversation |
\&\fIshow_version\fR function to display version information (see | A pointer to the |
show_version below). The conversation function may also be used | \fBconversation\fR() |
to display additional error message to the user. | function that may be used by the |
The conversation function returns 0 on success and \-1 on failure. | \fBshow_version\fR() |
.IP "plugin_printf" 4 | function to display version information (see |
.IX Item "plugin_printf" | \fBshow_version\fR() |
A pointer to a printf-style function that may be used by the | below). |
\&\fIshow_version\fR function to display version information (see | The |
show_version below). The plugin_printf function may also be used | \fBconversation\fR() |
to display additional error message to the user. | function may also be used to display additional error message to the user. |
The plugin_printf function returns number of characters printed on | The |
success and \-1 on failure. | \fBconversation\fR() |
.IP "settings" 4 | function returns 0 on success and \-1 on failure. |
.IX Item "settings" | .TP 6n |
A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R" | plugin_printf |
strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. These | A pointer to a |
settings correspond to flags the user specified when running \fBsudo\fR. | \fBprintf\fR()-style |
| function that may be used by the |
| \fBshow_version\fR() |
| function to display version information (see |
| show_version below). |
| The |
| \fBplugin_printf\fR() |
| function may also be used to display additional error message to the user. |
| The |
| \fBplugin_printf\fR() |
| function returns number of characters printed on success and \-1 on failure. |
| .TP 6n |
| settings |
| A vector of user-supplied |
| \fBsudo\fR |
| settings in the form of |
| ``name=value'' |
| strings. |
| The vector is terminated by a |
| \fRNULL\fR |
| pointer. |
| These settings correspond to flags the user specified when running |
| \fBsudo\fR. |
As such, they will only be present when the corresponding flag has |
As such, they will only be present when the corresponding flag has |
been specified on the command line. |
been specified on the command line. |
.Sp | .sp |
When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR | When parsing |
equal sign ('=') since the \fIname\fR field will never include one | \fIsettings\fR, |
itself but the \fIvalue\fR might. | the plugin should split on the |
.Sp | \fBfirst\fR |
See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible settings. | equal sign |
.IP "user_info" 4 | (`=') |
.IX Item "user_info" | since the |
| \fIname\fR |
| field will never include one |
| itself but the |
| \fIvalue\fR |
| might. |
| .sp |
| See the |
| \fIPolicy plugin API\fR |
| section for a list of all possible settings. |
| .TP 6n |
| user_info |
A vector of information about the user running the command in the form of |
A vector of information about the user running the command in the form of |
\&\*(L"name=value\*(R" strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. | ``name=value'' |
.Sp | strings. |
When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR | The vector is terminated by a |
equal sign ('=') since the \fIname\fR field will never include one | \fRNULL\fR |
itself but the \fIvalue\fR might. | |
.Sp | |
See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible strings. | |
.IP "argc" 4 | |
.IX Item "argc" | |
The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR | |
pointer. |
pointer. |
.IP "argv" 4 | .sp |
.IX Item "argv" | When parsing |
If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user | \fIuser_info\fR, |
| the plugin should split on the |
| \fBfirst\fR |
| equal sign |
| (`=') |
| since the |
| \fIname\fR |
| field will never include one |
| itself but the |
| \fIvalue\fR |
| might. |
| .sp |
| See the |
| \fIPolicy plugin API\fR |
| section for a list of all possible strings. |
| .TP 6n |
| argc |
| The number of elements in |
| \fIargv\fR, |
| not counting the final |
| \fRNULL\fR |
| pointer. |
| .TP 6n |
| argv |
| If |
| non-\fRNULL\fR, |
| an argument vector describing a command the user |
wishes to run in the same form as what would be passed to the |
wishes to run in the same form as what would be passed to the |
\&\fIexecve()\fR system call. | execve(2) |
.IP "user_env" 4 | system call. |
.IX Item "user_env" | .TP 6n |
The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of | user_env |
\&\*(L"name=value\*(R" strings. | The user's environment in the form of a |
.Sp | \fRNULL\fR-terminated |
When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR | vector of |
equal sign ('=') since the \fIname\fR field will never include one | ``name=value'' |
itself but the \fIvalue\fR might. | strings. |
.IP "plugin_options" 4 | .sp |
.IX Item "plugin_options" | When parsing |
| \fIuser_env\fR, |
| the plugin should split on the |
| \fBfirst\fR |
| equal sign |
| (`=') |
| since the |
| \fIname\fR |
| field will never include one |
| itself but the |
| \fIvalue\fR |
| might. |
| .TP 6n |
| plugin_options |
Any (non-comment) strings immediately after the plugin path are |
Any (non-comment) strings immediately after the plugin path are |
treated as arguments to the plugin. These arguments are split on | treated as arguments to the plugin. |
a white space boundary and are passed to the plugin in the form of | These arguments are split on a white space boundary and are passed to |
a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings. If no arguments were | the plugin in the form of a |
specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer. | \fRNULL\fR-terminated |
.Sp | array of strings. |
\&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with | If no arguments were specified, |
\&\s-1API\s0 version 1.2. A plugin \fBmust\fR check the \s-1API\s0 version specified | \fIplugin_options\fR |
by the \fBsudo\fR front end before using \fIplugin_options\fR. Failure to | will be the |
do so may result in a crash. | \fRNULL\fR |
| pointer. |
| .sp |
| NOTE: the |
| \fIplugin_options\fR |
| parameter is only available starting with |
| API version 1.2. |
| A plugin |
| \fBmust\fR |
| check the API version specified |
| by the |
| \fBsudo\fR |
| front end before using |
| \fIplugin_options\fR. |
| Failure to do so may result in a crash. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| close |
| .br |
| .RS |
| .nf |
| .RS 0n |
| void (*close)(int exit_status, int error); |
.RE |
.RE |
.IP "close" 4 | .fi |
.IX Item "close" | .sp |
.Vb 1 | The |
\& void (*close)(int exit_status, int error); | \fBclose\fR() |
.Ve | function is called when the command being run by |
.Sp | \fBsudo\fR |
The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR | |
finishes. |
finishes. |
.Sp | .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "exit_status" 4 | .TP 6n |
.IX Item "exit_status" | exit_status |
The command's exit status, as returned by the \fIwait\fR\|(2) system call. | The command's exit status, as returned by the |
The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero. | wait(2) |
.IP "error" 4 | system call. |
.IX Item "error" | The value of |
| \fRexit_status\fR |
| is undefined if |
| \fRerror\fR |
| is non-zero. |
| .TP 6n |
| error |
| .br |
If the command could not be executed, this is set to the value of |
If the command could not be executed, this is set to the value of |
\&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call. If the command was | \fRerrno\fR |
successfully executed, the value of \f(CW\*(C`error\*(C'\fR is 0. | set by the |
| execve(2) |
| system call. |
| If the command was successfully executed, the value of |
| \fRerror\fR |
| is 0. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| show_version |
| .RS |
| .nf |
| .RS 0n |
| int (*show_version)(int verbose); |
.RE |
.RE |
.IP "show_version" 4 | .fi |
.IX Item "show_version" | .sp |
.Vb 1 | The |
\& int (*show_version)(int verbose); | \fBshow_version\fR() |
.Ve | function is called by |
.Sp | \fBsudo\fR |
The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies | when the user specifies |
the \f(CW\*(C`\-V\*(C'\fR option. The plugin may display its version information | the |
to the user via the conversation or plugin_printf function using | \fB\-V\fR |
\&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR. If the user requests detailed version | option. |
information, the verbose flag will be set. | The plugin may display its version information to the user via the |
.IP "log_ttyin" 4 | \fBconversation\fR() |
.IX Item "log_ttyin" | or |
.Vb 1 | \fBplugin_printf\fR() |
\& int (*log_ttyin)(const char *buf, unsigned int len); | function using |
.Ve | \fRSUDO_CONV_INFO_MSG\fR. |
.Sp | If the user requests detailed version information, the verbose flag will be set. |
The \fIlog_ttyin\fR function is called whenever data can be read from | .PD |
the user but before it is passed to the running command. This | .PP |
allows the plugin to reject data if it chooses to (for instance | .RE |
if the input contains banned content). Returns \f(CW1\fR if the data | .PD 0 |
should be passed to the command, \f(CW0\fR if the data is rejected | .TP 6n |
(which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred. | log_ttyin |
.Sp | .RS |
| .nf |
| .RS 0n |
| int (*log_ttyin)(const char *buf, unsigned int len); |
| .RE |
| .fi |
| .sp |
| The |
| \fBlog_ttyin\fR() |
| function is called whenever data can be read from |
| the user but before it is passed to the running command. |
| This allows the plugin to reject data if it chooses to (for instance |
| if the input contains banned content). |
| Returns 1 if the data should be passed to the command, 0 if the data |
| is rejected (which will terminate the command) or \-1 if an error occurred. |
| .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "buf" 4 | .TP 6n |
.IX Item "buf" | buf |
The buffer containing user input. |
The buffer containing user input. |
.IP "len" 4 | .TP 6n |
.IX Item "len" | len |
The length of \fIbuf\fR in bytes. | The length of |
| \fIbuf\fR |
| in bytes. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| log_ttyout |
| .RS |
| .nf |
| .RS 0n |
| int (*log_ttyout)(const char *buf, unsigned int len); |
.RE |
.RE |
.IP "log_ttyout" 4 | .fi |
.IX Item "log_ttyout" | .sp |
.Vb 1 | The |
\& int (*log_ttyout)(const char *buf, unsigned int len); | \fBlog_ttyout\fR() |
.Ve | function is called whenever data can be read from |
.Sp | the command but before it is written to the user's terminal. |
The \fIlog_ttyout\fR function is called whenever data can be read from | This allows the plugin to reject data if it chooses to (for instance |
the command but before it is written to the user's terminal. This | if the output contains banned content). |
allows the plugin to reject data if it chooses to (for instance | Returns 1 if the data should be passed to the user, 0 if the data is rejected |
if the output contains banned content). Returns \f(CW1\fR if the data | (which will terminate the command) or \-1 if an error occurred. |
should be passed to the user, \f(CW0\fR if the data is rejected | .sp |
(which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred. | |
.Sp | |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "buf" 4 | .TP 6n |
.IX Item "buf" | buf |
The buffer containing command output. |
The buffer containing command output. |
.IP "len" 4 | .TP 6n |
.IX Item "len" | len |
The length of \fIbuf\fR in bytes. | The length of |
| \fIbuf\fR |
| in bytes. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| log_stdin |
| .RS |
| .nf |
| .RS 0n |
| int (*log_stdin)(const char *buf, unsigned int len); |
.RE |
.RE |
.IP "log_stdin" 4 | .fi |
.IX Item "log_stdin" | .sp |
.Vb 1 | The |
\& int (*log_stdin)(const char *buf, unsigned int len); | \fBlog_stdin\fR() |
.Ve | function is only used if the standard input does |
.Sp | not correspond to a tty device. |
The \fIlog_stdin\fR function is only used if the standard input does | It is called whenever data can be read from the standard input but |
not correspond to a tty device. It is called whenever data can be | before it is passed to the running command. |
read from the standard input but before it is passed to the running | This allows the plugin to reject data if it chooses to |
command. This allows the plugin to reject data if it chooses to | (for instance if the input contains banned content). |
(for instance if the input contains banned content). Returns \f(CW1\fR | Returns 1 if the data should be passed to the command, 0 if the data is |
if the data should be passed to the command, \f(CW0\fR if the data is | rejected (which will terminate the command) or \-1 if an error occurred. |
rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error | .sp |
occurred. | |
.Sp | |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "buf" 4 | .TP 6n |
.IX Item "buf" | buf |
The buffer containing user input. |
The buffer containing user input. |
.IP "len" 4 | .TP 6n |
.IX Item "len" | len |
The length of \fIbuf\fR in bytes. | The length of |
| \fIbuf\fR |
| in bytes. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| log_stdout |
| .RS |
| .nf |
| .RS 0n |
| int (*log_stdout)(const char *buf, unsigned int len); |
.RE |
.RE |
.IP "log_stdout" 4 | .fi |
.IX Item "log_stdout" | .sp |
.Vb 1 | The |
\& int (*log_stdout)(const char *buf, unsigned int len); | \fBlog_stdout\fR() |
.Ve | function is only used if the standard output does not correspond |
.Sp | to a tty device. |
The \fIlog_stdout\fR function is only used if the standard output does | It is called whenever data can be read from the command but before |
not correspond to a tty device. It is called whenever data can be | it is written to the standard output. |
read from the command but before it is written to the standard | This allows the plugin to reject data if it chooses to |
output. This allows the plugin to reject data if it chooses to | (for instance if the output contains banned content). |
(for instance if the output contains banned content). Returns \f(CW1\fR | Returns 1 if the data should be passed to the user, 0 if the data is |
if the data should be passed to the user, \f(CW0\fR if the data is | rejected (which will terminate the command) or \-1 if an error occurred. |
rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error | .sp |
occurred. | |
.Sp | |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "buf" 4 | .TP 6n |
.IX Item "buf" | buf |
The buffer containing command output. |
The buffer containing command output. |
.IP "len" 4 | .TP 6n |
.IX Item "len" | len |
The length of \fIbuf\fR in bytes. | The length of |
| \fIbuf\fR |
| in bytes. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| log_stderr |
| .RS |
| .nf |
| .RS 0n |
| int (*log_stderr)(const char *buf, unsigned int len); |
.RE |
.RE |
.IP "log_stderr" 4 | .fi |
.IX Item "log_stderr" | .sp |
.Vb 1 | The |
\& int (*log_stderr)(const char *buf, unsigned int len); | \fBlog_stderr\fR() |
.Ve | function is only used if the standard error does |
.Sp | not correspond to a tty device. |
The \fIlog_stderr\fR function is only used if the standard error does | It is called whenever data can be read from the command but before it |
not correspond to a tty device. It is called whenever data can be | is written to the standard error. |
read from the command but before it is written to the standard | This allows the plugin to reject data if it chooses to |
error. This allows the plugin to reject data if it chooses to | (for instance if the output contains banned content). |
(for instance if the output contains banned content). Returns \f(CW1\fR | Returns 1 if the data should be passed to the user, 0 if the data is |
if the data should be passed to the user, \f(CW0\fR if the data is | rejected (which will terminate the command) or \-1 if an error occurred. |
rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error | .sp |
occurred. | |
.Sp | |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "buf" 4 | .TP 6n |
.IX Item "buf" | buf |
The buffer containing command output. |
The buffer containing command output. |
.IP "len" 4 | .TP 6n |
.IX Item "len" | len |
The length of \fIbuf\fR in bytes. | The length of |
| \fIbuf\fR |
| in bytes. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
.RE | .TP 6n |
.IP "register_hooks" 4 | register_hooks |
.IX Item "register_hooks" | See the |
See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of | \fIPolicy plugin API\fR |
\&\f(CW\*(C`register_hooks\*(C'\fR. | section for a description of |
.IP "deregister_hooks" 4 | \fRregister_hooks\fR. |
.IX Item "deregister_hooks" | .PD |
See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of | .TP 6n |
\&\f(CW\*(C`deregister_hooks\*(C'\fR. | deregister_hooks |
| See the |
| \fIPolicy plugin API\fR |
| section for a description of |
| \fRderegister_hooks.\fR |
.PP |
.PP |
\fII/O Plugin Version Macros\fR |
\fII/O Plugin Version Macros\fR |
.IX Subsection "I/O Plugin Version Macros" |
|
.PP |
.PP |
Same as for the \*(L"Policy Plugin \s-1API\s0\*(R". | Same as for the |
.SS "Hook Function \s-1API\s0" | \fIPolicy plugin API\fR. |
.IX Subsection "Hook Function API" | .SS "Signal handlers" |
Beginning with plugin \s-1API\s0 version 1.2, it is possible to install | The |
hooks for certain functions called by the \fBsudo\fR front end. | \fBsudo\fR |
| front end installs default signal handlers to trap common signals |
| while the plugin functions are run. |
| The following signals are trapped by default before the command is |
| executed: |
| .TP 4n |
| \fBo\fR |
| \fRSIGALRM\fR |
| .PD 0 |
| .TP 4n |
| \fBo\fR |
| \fRSIGHUP\fR |
| .TP 4n |
| \fBo\fR |
| \fRSIGINT\fR |
| .TP 4n |
| \fBo\fR |
| \fRSIGQUIT\fR |
| .TP 4n |
| \fBo\fR |
| \fRSIGTERM\fR |
| .TP 4n |
| \fBo\fR |
| \fRSIGTSTP\fR |
| .TP 4n |
| \fBo\fR |
| \fRSIGUSR1\fR |
| .TP 4n |
| \fBo\fR |
| \fRSIGUSR2\fR |
| .PD |
.PP |
.PP |
|
If a fatal signal is received before the command is executed, |
|
\fBsudo\fR |
|
will call the plugin's |
|
\fBclose\fR() |
|
function with an exit status of 128 plus the value of the signal |
|
that was received. |
|
This allows for consistent logging of commands killed by a signal |
|
for plugins that log such information in their |
|
\fBclose\fR() |
|
function. |
|
.PP |
|
A plugin may temporarily install its own signal handlers but must |
|
restore the original handler before the plugin function returns. |
|
.SS "Hook function API" |
|
Beginning with plugin API version 1.2, it is possible to install |
|
hooks for certain functions called by the |
|
\fBsudo\fR |
|
front end. |
|
.PP |
Currently, the only supported hooks relate to the handling of |
Currently, the only supported hooks relate to the handling of |
environment variables. Hooks can be used to intercept attempts to | environment variables. |
get, set, or remove environment variables so that these changes can | Hooks can be used to intercept attempts to get, set, or remove |
be reflected in the version of the environment that is used to | environment variables so that these changes can be reflected in |
execute a command. A future version of the \s-1API\s0 will support | the version of the environment that is used to execute a command. |
hooking internal \fBsudo\fR front end functions as well. | A future version of the API will support hooking internal |
| \fBsudo\fR |
| front end functions as well. |
.PP |
.PP |
\fIHook structure\fR |
\fIHook structure\fR |
.IX Subsection "Hook structure" |
|
.PP |
.PP |
Hooks in \fBsudo\fR are described by the following structure: | Hooks in |
| \fBsudo\fR |
| are described by the following structure: |
| .nf |
| .sp |
| .RS 0n |
| typedef int (*sudo_hook_fn_t)(); |
| |
| struct sudo_hook { |
| int hook_version; |
| int hook_type; |
| sudo_hook_fn_t hook_fn; |
| void *closure; |
| }; |
| .RE |
| .fi |
.PP |
.PP |
.Vb 1 | The |
\& typedef int (*sudo_hook_fn_t)(); | \fRsudo_hook\fR |
\& | structure has the following fields: |
\& struct sudo_hook { | .TP 6n |
\& int hook_version; | hook_version |
\& int hook_type; | The |
\& sudo_hook_fn_t hook_fn; | \fRhook_version\fR |
\& void *closure; | field should be set to |
\& }; | \fRSUDO_HOOK_VERSION\fR. |
.Ve | .TP 6n |
.PP | hook_type |
The \f(CW\*(C`sudo_hook\*(C'\fR structure has the following fields: | The |
.IP "hook_version" 4 | \fRhook_type\fR |
.IX Item "hook_version" | field may be one of the following supported hook types: |
The \f(CW\*(C`hook_version\*(C'\fR field should be set to \s-1SUDO_HOOK_VERSION\s0. | .RS |
.IP "hook_type" 4 | .TP 6n |
.IX Item "hook_type" | \fRSUDO_HOOK_SETENV\fR |
The \f(CW\*(C`hook_type\*(C'\fR field may be one of the following supported hook types: | The C library |
.RS 4 | setenv(3) |
.IP "\s-1SUDO_HOOK_SETENV\s0" 4 | function. |
.IX Item "SUDO_HOOK_SETENV" | Any registered hooks will run before the C library implementation. |
The C library \f(CW\*(C`setenv()\*(C'\fR function. Any registered hooks will run | The |
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should | \fRhook_fn\fR |
| field should |
be a function that matches the following typedef: |
be a function that matches the following typedef: |
.Sp | .RS |
.Vb 2 | .nf |
\& typedef int (*sudo_hook_fn_setenv_t)(const char *name, | .sp |
\& const char *value, int overwrite, void *closure); | .RS 0n |
.Ve | typedef int (*sudo_hook_fn_setenv_t)(const char *name, |
.Sp | const char *value, int overwrite, void *closure); |
| .RE |
| .fi |
| .sp |
If the registered hook does not match the typedef the results are |
If the registered hook does not match the typedef the results are |
unspecified. |
unspecified. |
.IP "\s-1SUDO_HOOK_UNSETENV\s0" 4 | .PP |
.IX Item "SUDO_HOOK_UNSETENV" | .RE |
The C library \f(CW\*(C`unsetenv()\*(C'\fR function. Any registered hooks will run | .PD 0 |
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should | .TP 6n |
| \fRSUDO_HOOK_UNSETENV\fR |
| The C library |
| unsetenv(3) |
| function. |
| Any registered hooks will run before the C library implementation. |
| The |
| \fRhook_fn\fR |
| field should |
be a function that matches the following typedef: |
be a function that matches the following typedef: |
.Sp | .RS |
.Vb 2 | .nf |
\& typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, | .sp |
\& void *closure); | .RS 0n |
.Ve | typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, |
.IP "\s-1SUDO_HOOK_GETENV\s0" 4 | void *closure); |
.IX Item "SUDO_HOOK_GETENV" | .RE |
The C library \f(CW\*(C`getenv()\*(C'\fR function. Any registered hooks will run | .fi |
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should | .PD |
| .PP |
| .RE |
| .PD 0 |
| .TP 6n |
| \fRSUDO_HOOK_GETENV\fR |
| The C library |
| getenv(3) |
| function. |
| Any registered hooks will run before the C library implementation. |
| The |
| \fRhook_fn\fR |
| field should |
be a function that matches the following typedef: |
be a function that matches the following typedef: |
.Sp | .RS |
.Vb 2 | .nf |
\& typedef int (*sudo_hook_fn_getenv_t)(const char *name, | .sp |
\& char **value, void *closure); | .RS 0n |
.Ve | typedef int (*sudo_hook_fn_getenv_t)(const char *name, |
.Sp | char **value, void *closure); |
| .RE |
| .fi |
| .sp |
If the registered hook does not match the typedef the results are |
If the registered hook does not match the typedef the results are |
unspecified. |
unspecified. |
.IP "\s-1SUDO_HOOK_PUTENV\s0" 4 | .PD |
.IX Item "SUDO_HOOK_PUTENV" | .PP |
The C library \f(CW\*(C`putenv()\*(C'\fR function. Any registered hooks will run | .RE |
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should | .PD 0 |
| .TP 6n |
| \fRSUDO_HOOK_PUTENV\fR |
| The C library |
| putenv(3) |
| function. |
| Any registered hooks will run before the C library implementation. |
| The |
| \fRhook_fn\fR |
| field should |
be a function that matches the following typedef: |
be a function that matches the following typedef: |
.Sp | .RS |
.Vb 2 | .nf |
\& typedef int (*sudo_hook_fn_putenv_t)(char *string, | .sp |
\& void *closure); | .RS 0n |
.Ve | typedef int (*sudo_hook_fn_putenv_t)(char *string, |
.Sp | void *closure); |
| .RE |
| .fi |
| .sp |
If the registered hook does not match the typedef the results are |
If the registered hook does not match the typedef the results are |
unspecified. |
unspecified. |
.RE |
.RE |
.RS 4 | .PD |
| .PP |
.RE |
.RE |
.IP "hook_fn" 4 | .PD 0 |
.IX Item "hook_fn" | .TP 6n |
.Vb 1 | hook_fn |
\& sudo_hook_fn_t hook_fn; | sudo_hook_fn_t hook_fn; |
.Ve | .sp |
.Sp | The |
The \f(CW\*(C`hook_fn\*(C'\fR field should be set to the plugin's hook implementation. | \fRhook_fn\fR |
The actual function arguments will vary depending on the \f(CW\*(C`hook_type\*(C'\fR | field should be set to the plugin's hook implementation. |
(see \f(CW\*(C`hook_type\*(C'\fR above). In all cases, the \f(CW\*(C`closure\*(C'\fR field of | The actual function arguments will vary depending on the |
\&\f(CW\*(C`struct sudo_hook\*(C'\fR is passed as the last function parameter. This | \fRhook_type\fR |
can be used to pass arbitrary data to the plugin's hook implementation. | (see |
.Sp | \fRhook_type\fR |
| above). |
| In all cases, the |
| \fRclosure\fR |
| field of |
| \fRstruct sudo_hook\fR |
| is passed as the last function parameter. |
| This can be used to pass arbitrary data to the plugin's hook implementation. |
| .sp |
The function return value may be one of the following: |
The function return value may be one of the following: |
.RS 4 | .RS |
.IP "\s-1SUDO_HOOK_RET_ERROR\s0" 4 | .PD |
.IX Item "SUDO_HOOK_RET_ERROR" | .TP 6n |
| \fRSUDO_HOOK_RET_ERROR\fR |
The hook function encountered an error. |
The hook function encountered an error. |
.IP "\s-1SUDO_HOOK_RET_NEXT\s0" 4 | .TP 6n |
.IX Item "SUDO_HOOK_RET_NEXT" | \fRSUDO_HOOK_RET_NEXT\fR |
The hook completed without error, go on to the next hook (including |
The hook completed without error, go on to the next hook (including |
the native implementation if applicable). For example, a \f(CW\*(C`getenv\*(C'\fR | the native implementation if applicable). |
hook might return \f(CW\*(C`SUDO_HOOK_RET_NEXT\*(C'\fR if the specified variable | For example, a |
was not found in the private copy of the environment. | getenv(3) |
.IP "\s-1SUDO_HOOK_RET_STOP\s0" 4 | hook might return |
.IX Item "SUDO_HOOK_RET_STOP" | \fRSUDO_HOOK_RET_NEXT\fR |
The hook completed without error, stop processing hooks for this | if the specified variable was not found in the private copy of the environment. |
invocation. This can be used to replace the native implementation. | .TP 6n |
For example, a \f(CW\*(C`setenv\*(C'\fR hook that operates on a private copy of | \fRSUDO_HOOK_RET_STOP\fR |
the environment but leaves \f(CW\*(C`environ\*(C'\fR unchanged. | The hook completed without error, stop processing hooks for this invocation. |
| This can be used to replace the native implementation. |
| For example, a |
| \fRsetenv\fR |
| hook that operates on a private copy of |
| the environment but leaves |
| \fRenviron\fR |
| unchanged. |
.RE |
.RE |
.RS 4 |
|
.RE |
|
.PP |
.PP |
Note that it is very easy to create an infinite loop when hooking |
Note that it is very easy to create an infinite loop when hooking |
C library functions. For example, a \f(CW\*(C`getenv\*(C'\fR hook that calls the | C library functions. |
\&\f(CW\*(C`snprintf\*(C'\fR function may create a loop if the \f(CW\*(C`snprintf\*(C'\fR implementation | For example, a |
calls \f(CW\*(C`getenv\*(C'\fR to check the locale. To prevent this, you may wish | getenv(3) |
to use a static variable in the hook function to guard against | hook that calls the |
nested calls. E.g. | snprintf(3) |
| function may create a loop if the |
| snprintf(3) |
| implementation calls |
| getenv(3) |
| to check the locale. |
| To prevent this, you may wish to use a static variable in the hook |
| function to guard against nested calls. |
| For example: |
| .nf |
| .sp |
| .RS 0n |
| static int in_progress = 0; /* avoid recursion */ |
| if (in_progress) |
| return SUDO_HOOK_RET_NEXT; |
| in_progress = 1; |
| \&... |
| in_progress = 0; |
| return SUDO_HOOK_RET_STOP; |
| .RE |
| .fi |
.PP |
.PP |
.Vb 7 | \fIHook API Version Macros\fR |
\& static int in_progress = 0; /* avoid recursion */ | .nf |
\& if (in_progress) | .sp |
\& return SUDO_HOOK_RET_NEXT; | .RS 0n |
\& in_progress = 1; | /* Hook API version major/minor */ |
\& ... | #define SUDO_HOOK_VERSION_MAJOR 1 |
\& in_progress = 0; | #define SUDO_HOOK_VERSION_MINOR 0 |
\& return SUDO_HOOK_RET_STOP; | #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y) |
.Ve | #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e |
.PP | SUDO_HOOK_VERSION_MINOR) |
\fIHook \s-1API\s0 Version Macros\fR | |
.IX Subsection "Hook API Version Macros" | /* Getters and setters for hook API version */ |
.PP | #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16) |
.Vb 6 | #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff) |
\& /* Hook API version major/minor */ | #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \e |
\& #define SUDO_HOOK_VERSION_MAJOR 1 | *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e |
\& #define SUDO_HOOK_VERSION_MINOR 0 | } while(0) |
\& #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y) | #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \e |
\& #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e | *(vp) = (*(vp) & 0xffff0000) | (n); \e |
\& SUDO_HOOK_VERSION_MINOR) | } while(0) |
\& | .RE |
\& /* Getters and setters for hook API version */ | .fi |
\& #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16) | .SS "Conversation API" |
\& #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff) | |
\& #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \e | |
\& *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e | |
\& } while(0) | |
\& #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \e | |
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e | |
\& } while(0) | |
.Ve | |
.SS "Conversation \s-1API\s0" | |
.IX Subsection "Conversation API" | |
If the plugin needs to interact with the user, it may do so via the |
If the plugin needs to interact with the user, it may do so via the |
conversation function. A plugin should not attempt to read directly | \fBconversation\fR() |
from the standard input or the user's tty (neither of which are | function. |
guaranteed to exist). The caller must include a trailing newline | A plugin should not attempt to read directly from the standard input |
in \f(CW\*(C`msg\*(C'\fR if one is to be printed. | or the user's tty (neither of which are guaranteed to exist). |
| The caller must include a trailing newline in |
| \fRmsg\fR |
| if one is to be printed. |
.PP |
.PP |
A printf-style function is also available that can be used to display | A |
informational or error messages to the user, which is usually more | \fBprintf\fR()-style |
convenient for simple messages where no use input is required. | function is also available that can be used to display informational |
| or error messages to the user, which is usually more convenient for |
| simple messages where no use input is required. |
| .nf |
| .sp |
| .RS 0n |
| struct sudo_conv_message { |
| #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ |
| #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ |
| #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ |
| #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ |
| #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ |
| #define SUDO_CONV_DEBUG_MSG 0x0006 /* debugging message */ |
| #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ |
| int msg_type; |
| int timeout; |
| const char *msg; |
| }; |
| |
| struct sudo_conv_reply { |
| char *reply; |
| }; |
| |
| typedef int (*sudo_conv_t)(int num_msgs, |
| const struct sudo_conv_message msgs[], |
| struct sudo_conv_reply replies[]); |
| |
| typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); |
| .RE |
| .fi |
.PP |
.PP |
.Vb 12 | Pointers to the |
\& struct sudo_conv_message { | \fBconversation\fR() |
\& #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ | and |
\& #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ | \fBprintf\fR()-style |
\& #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ | functions are passed |
\& #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ | in to the plugin's |
\& #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ | \fBopen\fR() |
\& #define SUDO_CONV_DEBUG_MSG 0x0006 /* debugging message */ | function when the plugin is initialized. |
\& #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ | |
\& int msg_type; | |
\& int timeout; | |
\& const char *msg; | |
\& }; | |
\& | |
\& struct sudo_conv_reply { | |
\& char *reply; | |
\& }; | |
\& | |
\& typedef int (*sudo_conv_t)(int num_msgs, | |
\& const struct sudo_conv_message msgs[], | |
\& struct sudo_conv_reply replies[]); | |
\& | |
\& typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); | |
.Ve | |
.PP |
.PP |
Pointers to the conversation and printf-style functions are passed | To use the |
in to the plugin's \f(CW\*(C`open\*(C'\fR function when the plugin is initialized. | \fBconversation\fR() |
.PP | function, the plugin must pass an array of |
To use the conversation function, the plugin must pass an array of | \fRsudo_conv_message\fR |
\&\f(CW\*(C`sudo_conv_message\*(C'\fR and \f(CW\*(C`sudo_conv_reply\*(C'\fR structures. There must | and |
be a \f(CW\*(C`struct sudo_conv_message\*(C'\fR and \f(CW\*(C`struct sudo_conv_reply\*(C'\fR for | \fRsudo_conv_reply\fR |
each message in the conversation. The plugin is responsible for | structures. |
freeing the reply buffer filled in to the \f(CW\*(C`struct sudo_conv_reply\*(C'\fR, | There must be a |
| \fRstruct sudo_conv_message\fR |
| and |
| \fRstruct sudo_conv_reply\fR |
| for |
| each message in the conversation. |
| The plugin is responsible for freeing the reply buffer filled in to the |
| \fRstruct sudo_conv_reply\fR, |
if any. |
if any. |
.PP |
.PP |
The printf-style function uses the same underlying mechanism as the | The |
conversation function but only supports \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR, | \fBprintf\fR()-style |
\&\f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_DEBUG_MSG\*(C'\fR for the \fImsg_type\fR | function uses the same underlying mechanism as the |
parameter. It can be more convenient than using the conversation | \fBconversation\fR() |
function if no user reply is needed and supports standard \fIprintf()\fR | function but only supports |
| \fRSUDO_CONV_INFO_MSG\fR, |
| \fRSUDO_CONV_ERROR_MSG\fR |
| and |
| \fRSUDO_CONV_DEBUG_MSG\fR |
| for the |
| \fImsg_type\fR |
| parameter. |
| It can be more convenient than using the |
| \fBconversation\fR() |
| function if no user reply is needed and supports standard |
| \fBprintf\fR() |
escape sequences. |
escape sequences. |
.PP |
.PP |
Unlike, \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR, messages | Unlike, |
sent with the <\s-1SUDO_CONV_DEBUG_MSG\s0> \fImsg_type\fR are not directly | \fRSUDO_CONV_INFO_MSG\fR |
user-visible. Instead, they are logged to the file specified in | and |
the \f(CW\*(C`Debug\*(C'\fR statement (if any) in the \fI@sysconfdir@/sudo.conf\fR | Dv SUDO_CONV_ERROR_MSG , |
file. This allows a plugin to log debugging information and is | messages |
intended to be used in conjunction with the \fIdebug_flags\fR setting. | sent with the |
| \fRSUDO_CONV_DEBUG_MSG\fR |
| \fImsg_type\fR |
| are not directly |
| user-visible. |
| Instead, they are logged to the file specified in the |
| \fRDebug\fR |
| statement (if any) in the |
| sudo.conf(@mansectform@). |
| file. |
| This allows a plugin to log debugging information and is intended |
| to be used in conjunction with the |
| \fIdebug_flags\fR |
| setting. |
.PP |
.PP |
See the sample plugin for an example of the conversation function usage. | See the sample plugin for an example of the |
.SS "Sudoers Group Plugin \s-1API\s0" | \fBconversation\fR() |
.IX Subsection "Sudoers Group Plugin API" | function usage. |
The \fIsudoers\fR module supports a plugin interface to allow non-Unix | .SS "Sudoers group plugin API" |
group lookups. This can be used to query a group source other than | The |
the standard Unix group database. A sample group plugin is bundled | \fBsudoers\fR |
with \fBsudo\fR that implements file-based lookups. Third party group | plugin supports its own plugin interface to allow non-Unix |
plugins include a \s-1QAS\s0 \s-1AD\s0 plugin available from Quest Software. | group lookups. |
| This can be used to query a group source other than the standard Unix |
| group database. |
| Two sample group plugins are bundled with |
| \fBsudo\fR, |
| \fIgroup_file\fR |
| and |
| \fIsystem_group\fR, |
| are detailed in |
| sudoers(@mansectform@). |
| Third party group plugins include a QAS AD plugin available from Quest Software. |
.PP |
.PP |
A group plugin must declare and populate a \f(CW\*(C`sudoers_group_plugin\*(C'\fR | A group plugin must declare and populate a |
struct in the global scope. This structure contains pointers to | \fRsudoers_group_plugin\fR |
the functions that implement plugin initialization, cleanup and | struct in the global scope. |
group lookup. | This structure contains pointers to the functions that implement plugin |
| initialization, cleanup and group lookup. |
| .nf |
| .sp |
| .RS 0n |
| struct sudoers_group_plugin { |
| unsigned int version; |
| int (*init)(int version, sudo_printf_t sudo_printf, |
| char *const argv[]); |
| void (*cleanup)(void); |
| int (*query)(const char *user, const char *group, |
| const struct passwd *pwd); |
| }; |
| .RE |
| .fi |
.PP |
.PP |
.Vb 8 | The |
\& struct sudoers_group_plugin { | \fRsudoers_group_plugin\fR |
\& unsigned int version; | struct has the following fields: |
\& int (*init)(int version, sudo_printf_t sudo_printf, | .TP 6n |
\& char *const argv[]); | version |
\& void (*cleanup)(void); | The |
\& int (*query)(const char *user, const char *group, | \fRversion\fR |
\& const struct passwd *pwd); | field should be set to GROUP_API_VERSION. |
\&}; | .sp |
.Ve | This allows |
.PP | \fBsudoers\fR |
The \f(CW\*(C`sudoers_group_plugin\*(C'\fR struct has the following fields: | to determine the API version the group plugin |
.IP "version" 4 | |
.IX Item "version" | |
The \f(CW\*(C`version\*(C'\fR field should be set to \s-1GROUP_API_VERSION\s0. | |
.Sp | |
This allows \fIsudoers\fR to determine the \s-1API\s0 version the group plugin | |
was built against. |
was built against. |
.IP "init" 4 | .TP 6n |
.IX Item "init" | init |
.Vb 2 | .RS |
\& int (*init)(int version, sudo_printf_t plugin_printf, | .nf |
\& char *const argv[]); | .RS 0n |
.Ve | int (*init)(int version, sudo_printf_t plugin_printf, |
.Sp | char *const argv[]); |
The \fIinit\fR function is called after \fIsudoers\fR has been parsed but | .RE |
before any policy checks. It returns 1 on success, 0 on failure | .fi |
(or if the plugin is not configured), and \-1 if a error occurred. | .sp |
If an error occurs, the plugin may call the plugin_printf function | The |
with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information | \fBinit\fR() |
| function is called after |
| \fIsudoers\fR |
| has been parsed but |
| before any policy checks. |
| It returns 1 on success, 0 on failure (or if the plugin is not configured), |
| and \-1 if a error occurred. |
| If an error occurs, the plugin may call the |
| \fBplugin_printf\fR() |
| function with |
| \fRSUDO_CONF_ERROR_MSG\fR |
| to present additional error information |
to the user. |
to the user. |
.Sp | .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .TP 6n |
.IP "version" 4 | version |
.IX Item "version" | The version passed in by |
The version passed in by \fIsudoers\fR allows the plugin to determine the | \fBsudoers\fR |
major and minor version number of the group plugin \s-1API\s0 supported by | allows the plugin to determine the |
\&\fIsudoers\fR. | major and minor version number of the group plugin API supported by |
.IP "plugin_printf" 4 | \fBsudoers\fR. |
.IX Item "plugin_printf" | .TP 6n |
A pointer to a printf-style function that may be used to display | plugin_printf |
informational or error message to the user. | A pointer to a |
| \fBprintf\fR()-style |
| function that may be used to display informational or error message to the user. |
Returns the number of characters printed on success and \-1 on failure. |
Returns the number of characters printed on success and \-1 on failure. |
.IP "argv" 4 | .TP 6n |
.IX Item "argv" | argv |
A NULL-terminated array of arguments generated from the \fIgroup_plugin\fR | A |
option in \fIsudoers\fR. If no arguments were given, \fIargv\fR will be | \fRNULL\fR-terminated |
\&\s-1NULL\s0. | array of arguments generated from the |
| \fIgroup_plugin\fR |
| option in |
| \fIsudoers\fR. |
| If no arguments were given, |
| \fIargv\fR |
| will be |
| \fRNULL\fR. |
| .PP |
.RE |
.RE |
.RS 4 | .PD 0 |
| .TP 6n |
| cleanup |
| .RS |
| .nf |
| .RS 0n |
| void (*cleanup)(); |
.RE |
.RE |
.IP "cleanup" 4 | .fi |
.IX Item "cleanup" | .sp |
.Vb 1 | The |
\& void (*cleanup)(); | \fBcleanup\fR() |
.Ve | function is called when |
.Sp | \fBsudoers\fR |
The \fIcleanup\fR function is called when \fIsudoers\fR has finished its | has finished its |
group checks. The plugin should free any memory it has allocated | group checks. |
and close open file handles. | The plugin should free any memory it has allocated and close open file handles. |
.IP "query" 4 | .PD |
.IX Item "query" | .PP |
.Vb 2 | .RE |
\& int (*query)(const char *user, const char *group, | .PD 0 |
\& const struct passwd *pwd); | .TP 6n |
.Ve | query |
.Sp | .br |
The \fIquery\fR function is used to ask the group plugin whether \fIuser\fR | .RS |
is a member of \fIgroup\fR. | .nf |
.Sp | .RS 0n |
| int (*query)(const char *user, const char *group, |
| const struct passwd *pwd); |
| .RE |
| .fi |
| .sp |
| The |
| \fBquery\fR() |
| function is used to ask the group plugin whether |
| \fIuser\fR |
| is a member of |
| \fIgroup\fR. |
| .sp |
The function arguments are as follows: |
The function arguments are as follows: |
.RS 4 | .PD |
.IP "user" 4 | .TP 6n |
.IX Item "user" | user |
The name of the user being looked up in the external group database. |
The name of the user being looked up in the external group database. |
.IP "group" 4 | .TP 6n |
.IX Item "group" | group |
| .br |
The name of the group being queried. |
The name of the group being queried. |
.IP "pwd" 4 | .TP 6n |
.IX Item "pwd" | pwd |
The password database entry for \fIuser\fR, if any. If \fIuser\fR is not | The password database entry for |
present in the password database, \fIpwd\fR will be \f(CW\*(C`NULL\*(C'\fR. | \fIuser\fR, |
| if any. |
| If |
| \fIuser\fR |
| is not |
| present in the password database, |
| \fIpwd\fR |
| will be |
| \fRNULL\fR. |
.RE |
.RE |
.RS 4 |
|
.RE |
|
.PP |
.PP |
\fIGroup \s-1API\s0 Version Macros\fR | \fIGroup API Version Macros\fR |
.IX Subsection "Group API Version Macros" | .nf |
.PP | .sp |
.Vb 5 | .RS 0n |
\& /* Sudoers group plugin version major/minor */ | /* Sudoers group plugin version major/minor */ |
\& #define GROUP_API_VERSION_MAJOR 1 | #define GROUP_API_VERSION_MAJOR 1 |
\& #define GROUP_API_VERSION_MINOR 0 | #define GROUP_API_VERSION_MINOR 0 |
\& #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e | #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e |
\& GROUP_API_VERSION_MINOR) | GROUP_API_VERSION_MINOR) |
\& | |
\& /* Getters and setters for group version */ | /* Getters and setters for group version */ |
\& #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16) | #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16) |
\& #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff) | #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff) |
\& #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \e | #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \e |
\& *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e | *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e |
\& } while(0) | } while(0) |
\& #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \e | #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \e |
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e | *(vp) = (*(vp) & 0xffff0000) | (n); \e |
\& } while(0) | } while(0) |
.Ve | .RE |
| .fi |
.SH "PLUGIN API CHANGELOG" |
.SH "PLUGIN API CHANGELOG" |
.IX Header "PLUGIN API CHANGELOG" | The following revisions have been made to the Sudo Plugin API. |
The following revisions have been made to the Sudo Plugin \s-1API\s0. | .TP 6n |
.IP "Version 1.0" 4 | Version 1.0 |
.IX Item "Version 1.0" | Initial API version. |
Initial \s-1API\s0 version. | .TP 6n |
.IP "Version 1.1" 4 | Version 1.1 (sudo 1.8.0) |
.IX Item "Version 1.1" | The I/O logging plugin's |
The I/O logging plugin's \f(CW\*(C`open\*(C'\fR function was modified to take the | \fBopen\fR() |
\&\f(CW\*(C`command_info\*(C'\fR list as an argument. | function was modified to take the |
.IP "Version 1.2" 4 | \fRcommand_info\fR |
.IX Item "Version 1.2" | list as an argument. |
The Policy and I/O logging plugins' \f(CW\*(C`open\*(C'\fR functions are now passed | .TP 6n |
a list of plugin options if any are specified in \fI@sysconfdir@/sudo.conf\fR. | Version 1.2 (sudo 1.8.5) |
.Sp | The Policy and I/O logging plugins' |
A simple hooks \s-1API\s0 has been introduced to allow plugins to hook in to the | \fBopen\fR() |
| functions are now passed |
| a list of plugin parameters if any are specified in |
| sudo.conf(@mansectform@). |
| .sp |
| A simple hooks API has been introduced to allow plugins to hook in to the |
system's environment handling functions. |
system's environment handling functions. |
.Sp | .sp |
The \f(CW\*(C`init_session\*(C'\fR Policy plugin function is now passed a pointer | The |
to the user environment which can be updated as needed. This can | \fRinit_session\fR |
be used to merge in environment variables stored in the \s-1PAM\s0 handle | Policy plugin function is now passed a pointer |
before a command is run. | to the user environment which can be updated as needed. |
| This can be used to merge in environment variables stored in the PAM |
| handle before a command is run. |
| .TP 6n |
| Version 1.3 (sudo 1.8.7) |
| Support for the |
| \fIexec_background\fR |
| entry has been added to the |
| \fRcommand_info\fR |
| list. |
| .sp |
| The |
| \fImax_groups\fR |
| and |
| \fIplugin_dir\fR |
| entries were added to the |
| \fRsettings\fR |
| list. |
| .sp |
| The |
| \fBversion\fR() |
| and |
| \fBclose\fR() |
| functions are now optional. |
| Previously, a missing |
| \fBversion\fR() |
| or |
| \fBclose\fR() |
| function would result in a crash. |
| If no policy plugin |
| \fBclose\fR() |
| function is defined, a default |
| \fBclose\fR() |
| function will be provided by the |
| \fBsudo\fR |
| front end that displays a warning if the command could not be |
| executed. |
| .sp |
| The |
| \fBsudo\fR |
| front end now installs default signal handlers to trap common signals |
| while the plugin functions are run. |
.SH "SEE ALSO" |
.SH "SEE ALSO" |
.IX Header "SEE ALSO" | sudo.conf(@mansectform@), |
\&\fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@) | sudoers(@mansectform@), |
| sudo(@mansectsu@) |
.SH "BUGS" |
.SH "BUGS" |
.IX Header "BUGS" | If you feel you have found a bug in |
If you feel you have found a bug in \fBsudo\fR, please submit a bug report | \fBsudo\fR, |
at http://www.sudo.ws/sudo/bugs/ | please submit a bug report at http://www.sudo.ws/sudo/bugs/ |
.SH "SUPPORT" |
.SH "SUPPORT" |
.IX Header "SUPPORT" | Limited free support is available via the sudo-users mailing list, |
Limited free support is available via the sudo-workers mailing list, | see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or |
see http://www.sudo.ws/mailman/listinfo/sudo\-workers to subscribe or | |
search the archives. |
search the archives. |
.SH "DISCLAIMER" |
.SH "DISCLAIMER" |
.IX Header "DISCLAIMER" | \fBsudo\fR |
\&\fBsudo\fR is provided ``\s-1AS\s0 \s-1IS\s0'' and any express or implied warranties, | is provided |
including, but not limited to, the implied warranties of merchantability | ``AS IS'' |
and fitness for a particular purpose are disclaimed. See the \s-1LICENSE\s0 | and any express or implied warranties, including, but not limited |
file distributed with \fBsudo\fR or http://www.sudo.ws/sudo/license.html | to, the implied warranties of merchantability and fitness for a |
for complete details. | particular purpose are disclaimed. |
| See the LICENSE file distributed with |
| \fBsudo\fR |
| or http://www.sudo.ws/sudo/license.html for complete details. |