version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.2, 2012/05/29 12:26:49
|
Line 1
|
Line 1
|
.\" Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com> | .\" Copyright (c) 2009-2012 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 |
Line 139
|
Line 139
|
.\" ======================================================================== |
.\" ======================================================================== |
.\" |
.\" |
.IX Title "SUDO_PLUGIN @mansectsu@" |
.IX Title "SUDO_PLUGIN @mansectsu@" |
.TH SUDO_PLUGIN @mansectsu@ "September 16, 2011" "1.8.3" "MAINTENANCE COMMANDS" | .TH SUDO_PLUGIN @mansectsu@ "April 23, 2012" "1.8.5" "MAINTENANCE COMMANDS" |
.\" For nroff, turn off justification. Always turn off hyphenation; it makes |
.\" For nroff, turn off justification. Always turn off hyphenation; it makes |
.\" way too many mistakes in technical documents. |
.\" way too many mistakes in technical documents. |
.if n .ad l |
.if n .ad l |
Line 174 plugin. The \fIsymbol_name\fR is the name of the \f(C
|
Line 174 plugin. The \fIsymbol_name\fR is the name of the \f(C
|
or \f(CW\*(C`struct io_plugin\*(C'\fR in the plugin shared object. The \fIpath\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 |
may be fully qualified or relative. If not fully qualified it is |
relative to the \fI@prefix@/libexec\fR directory. Any additional |
relative to the \fI@prefix@/libexec\fR directory. Any additional |
parameters after the \fIpath\fR are ignored. Lines that don't begin | parameters after the \fIpath\fR are passed as options to the plugin's |
with \f(CW\*(C`Plugin\*(C'\fR or \f(CW\*(C`Path\*(C'\fR are silently ignored. | \&\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 |
.PP |
The same shared object may contain multiple plugins, each with a |
The same shared object may contain multiple plugins, each with a |
different symbol name. The shared object file must be owned by uid |
different symbol name. The shared object file must be owned by uid |
Line 188 This limitation does not apply to I/O plugins.
|
Line 189 This limitation does not apply to I/O plugins.
|
\& # Default @sysconfdir@/sudo.conf file |
\& # Default @sysconfdir@/sudo.conf file |
\& # |
\& # |
\& # Format: |
\& # Format: |
\& # Plugin plugin_name plugin_path | \& # Plugin plugin_name plugin_path plugin_options ... |
\& # Path askpass /path/to/askpass |
\& # 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 |
\& # The plugin_path is relative to @prefix@/libexec unless |
\& # fully qualified. |
\& # fully qualified. |
\& # The plugin_name corresponds to a global symbol in the plugin |
\& # The plugin_name corresponds to a global symbol in the plugin |
\& # that contains the plugin interface structure. |
\& # that contains the plugin interface structure. |
|
\& # The plugin_options are optional. |
\& # |
\& # |
\& Plugin sudoers_policy sudoers.so |
\& Plugin sudoers_policy sudoers.so |
\& Plugin sudoers_io sudoers.so |
\& Plugin sudoers_io sudoers.so |
Line 214 so that \fBsudo\fR can load it.
|
Line 219 so that \fBsudo\fR can load it.
|
\& unsigned int version; /* always SUDO_API_VERSION */ |
\& unsigned int version; /* always SUDO_API_VERSION */ |
\& int (*open)(unsigned int version, sudo_conv_t conversation, |
\& int (*open)(unsigned int version, sudo_conv_t conversation, |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& char * const user_info[], char * const user_env[]); | \& char * const user_info[], char * const user_env[], |
| \& char * const plugin_options[]); |
\& void (*close)(int exit_status, int error); |
\& void (*close)(int exit_status, int error); |
\& int (*show_version)(int verbose); |
\& int (*show_version)(int verbose); |
\& int (*check_policy)(int argc, char * const argv[], |
\& int (*check_policy)(int argc, char * const argv[], |
Line 224 so that \fBsudo\fR can load it.
|
Line 230 so that \fBsudo\fR can load it.
|
\& const char *list_user); |
\& const char *list_user); |
\& int (*validate)(void); |
\& int (*validate)(void); |
\& void (*invalidate)(int remove); |
\& void (*invalidate)(int remove); |
\& int (*init_session)(struct passwd *pwd); | \& 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 |
.Ve |
.PP |
.PP |
Line 240 This allows \fBsudo\fR to determine the \s-1API\s0 ver
|
Line 250 This allows \fBsudo\fR to determine the \s-1API\s0 ver
|
built against. |
built against. |
.IP "open" 4 |
.IP "open" 4 |
.IX Item "open" |
.IX Item "open" |
.Vb 3 | .Vb 4 |
\& int (*open)(unsigned int version, sudo_conv_t conversation, |
\& int (*open)(unsigned int version, sudo_conv_t conversation, |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& char * const user_info[], char * const user_env[]); | \& char * const user_info[], char * const user_env[], |
| \& char * const plugin_options[]); |
.Ve |
.Ve |
.Sp |
.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, |
Line 282 When parsing \fIsettings\fR, the plugin should split o
|
Line 293 When parsing \fIsettings\fR, the plugin should split o
|
equal sign ('=') since the \fIname\fR field will never include one |
equal sign ('=') since the \fIname\fR field will never include one |
itself but the \fIvalue\fR might. |
itself but the \fIvalue\fR might. |
.RS 4 |
.RS 4 |
|
.IP "debug_flags=string" 4 |
|
.IX Item "debug_flags=string" |
|
A comma-separated list of debug flags that correspond to \fBsudo\fR's |
|
\&\f(CW\*(C`Debug\*(C'\fR entry in \fI@sysconfdir@/sudo.conf\fR, if there is one. The |
|
flags are passed to the plugin as they appear in \fI@sysconfdir@/sudo.conf\fR. |
|
The syntax used by \fBsudo\fR and the \fIsudoers\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 command \f(CW\*(C`,\*(C'\fR. |
|
.Sp |
|
For reference, the priorities supported by the \fBsudo\fR front end and |
|
\&\fIsudoers\fR are: \fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, |
|
\&\fIinfo\fR, \fItrace\fR and \fIdebug\fR. |
|
.Sp |
|
The following subsystems are defined: \fImain\fR, \fImemory\fR, \fIargs\fR, |
|
\&\fIexec\fR, \fIpty\fR, \fIutmp\fR, \fIconv\fR, \fIpcomm\fR, \fIutil\fR, \fIlist\fR, |
|
\&\fInetif\fR, \fIaudit\fR, \fIedit\fR, \fIselinux\fR, \fIldap\fR, \fImatch\fR, \fIparser\fR, |
|
\&\fIalias\fR, \fIdefaults\fR, \fIauth\fR, \fIenv\fR, \fIlogging\fR, \fInss\fR, \fIrbtree\fR, |
|
\&\fIperms\fR, \fIplugin\fR. The subsystem \fIall\fR includes every subsystem. |
|
.Sp |
|
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. |
.IP "debug_level=number" 4 |
.IP "debug_level=number" 4 |
.IX Item "debug_level=number" |
.IX Item "debug_level=number" |
A numeric debug level, from 1\-9, if specified via the \f(CW\*(C`\-D\*(C'\fR flag. | This setting has been deprecated in favor of \fIdebug_flags\fR. |
.IP "runas_user=string" 4 |
.IP "runas_user=string" 4 |
.IX Item "runas_user=string" |
.IX Item "runas_user=string" |
The user name or uid to to run the command as, if specified via the |
The user name or uid to to run the command as, if specified via the |
Line 392 When parsing \fIuser_info\fR, the plugin should split
|
Line 424 When parsing \fIuser_info\fR, the plugin should split
|
equal sign ('=') since the \fIname\fR field will never include one |
equal sign ('=') since the \fIname\fR field will never include one |
itself but the \fIvalue\fR might. |
itself but the \fIvalue\fR might. |
.RS 4 |
.RS 4 |
|
.IP "pid=int" 4 |
|
.IX Item "pid=int" |
|
The process \s-1ID\s0 of the running \fBsudo\fR process. |
|
Only available starting with \s-1API\s0 version 1.2 |
|
.IP "ppid=int" 4 |
|
.IX Item "ppid=int" |
|
The parent process \s-1ID\s0 of the running \fBsudo\fR process. |
|
Only available starting with \s-1API\s0 version 1.2 |
|
.IP "sid=int" 4 |
|
.IX Item "sid=int" |
|
The session \s-1ID\s0 of the running \fBsudo\fR process or 0 if \fBsudo\fR is |
|
not part of a \s-1POSIX\s0 job control session. |
|
Only available starting with \s-1API\s0 version 1.2 |
|
.IP "pgid=int" 4 |
|
.IX Item "pgid=int" |
|
The \s-1ID\s0 of the process group that the running \fBsudo\fR process belongs |
|
to. |
|
Only available starting with \s-1API\s0 version 1.2 |
|
.IP "tcpgid=int" 4 |
|
.IX Item "tcpgid=int" |
|
The \s-1ID\s0 of the forground process group associated with the terminal |
|
device associcated with the \fBsudo\fR process or \-1 if there is no |
|
terminal present. |
|
Only available starting with \s-1API\s0 version 1.2 |
.IP "user=string" 4 |
.IP "user=string" 4 |
.IX Item "user=string" |
.IX Item "user=string" |
The name of the user invoking \fBsudo\fR. |
The name of the user invoking \fBsudo\fR. |
|
.IP "euid=uid_t" 4 |
|
.IX Item "euid=uid_t" |
|
The effective user \s-1ID\s0 of the user invoking \fBsudo\fR. |
.IP "uid=uid_t" 4 |
.IP "uid=uid_t" 4 |
.IX Item "uid=uid_t" |
.IX Item "uid=uid_t" |
The real user \s-1ID\s0 of the user invoking \fBsudo\fR. |
The real user \s-1ID\s0 of the user invoking \fBsudo\fR. |
|
.IP "egid=gid_t" 4 |
|
.IX Item "egid=gid_t" |
|
The effective group \s-1ID\s0 of the user invoking \fBsudo\fR. |
.IP "gid=gid_t" 4 |
.IP "gid=gid_t" 4 |
.IX Item "gid=gid_t" |
.IX Item "gid=gid_t" |
The real group \s-1ID\s0 of the user invoking \fBsudo\fR. |
The real group \s-1ID\s0 of the user invoking \fBsudo\fR. |
Line 436 The user's environment in the form of a \f(CW\*(C`NULL
|
Line 498 The user's environment in the form of a \f(CW\*(C`NULL
|
When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR |
When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR |
equal sign ('=') since the \fIname\fR field will never include one |
equal sign ('=') since the \fIname\fR field will never include one |
itself but the \fIvalue\fR might. |
itself but the \fIvalue\fR might. |
|
.IP "plugin_options" 4 |
|
.IX Item "plugin_options" |
|
Any (non-comment) strings immediately after the plugin path are |
|
treated as arguments to the plugin. These arguments are split on |
|
a white space boundary and are passed to the plugin in the form of |
|
a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings. If no arguments were |
|
specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer. |
|
.Sp |
|
\&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with |
|
\&\s-1API\s0 version 1.2. A plugin \fBmust\fR check the \s-1API\s0 version specified |
|
by the \fBsudo\fR front end before using \fIplugin_options\fR. Failure to |
|
do so may result in a crash. |
.RE |
.RE |
.RS 4 |
.RS 4 |
.RE |
.RE |
Line 753 support credential caching.
|
Line 827 support credential caching.
|
.IP "init_session" 4 |
.IP "init_session" 4 |
.IX Item "init_session" |
.IX Item "init_session" |
.Vb 1 |
.Vb 1 |
\& int (*init_session)(struct passwd *pwd); | \& int (*init_session)(struct passwd *pwd, char **user_envp[); |
.Ve |
.Ve |
.Sp |
.Sp |
The \f(CW\*(C`init_session\*(C'\fR function is called when \fBsudo\fR sets up the | The \f(CW\*(C`init_session\*(C'\fR function is called before \fBsudo\fR sets up the |
execution environment for the command, immediately before the | execution environment for the command. It is run in the parent |
contents of the \fIcommand_info\fR list are applied (before the uid | \&\fBsudo\fR process and before any uid or gid changes. This can be used |
changes). This can be used to do session setup that is not supported | to perform session setup that is not supported by \fIcommand_info\fR, |
by \fIcommand_info\fR, such as opening the \s-1PAM\s0 session. | such as opening the \s-1PAM\s0 session. The \f(CW\*(C`close\*(C'\fR function can be |
| used to tear down the session that was opened by \f(CW\*(C`init_session\*(C'\fR. |
.Sp |
.Sp |
The \fIpwd\fR argument points to a passwd struct for the user the |
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 \s-1NULL\s0. |
.Sp |
.Sp |
|
The \fIuser_env\fR argument points to the environment the command will |
|
run in, in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R" |
|
strings. This is the same string passed back to the front end via |
|
the Policy Plugin's \fIuser_env_out\fR parameter. If the \f(CW\*(C`init_session\*(C'\fR |
|
function needs to modify the user environment, it should update the |
|
pointer stored in \fIuser_env\fR. The expected use case is to merge |
|
the contents of the \s-1PAM\s0 environment (if any) with the contents of |
|
\&\fIuser_env\fR. \s-1NOTE:\s0 the \fIuser_env\fR parameter is only available |
|
starting with \s-1API\s0 version 1.2. A plugin \fBmust\fR check the \s-1API\s0 |
|
version specified by the \fBsudo\fR front end before using \fIuser_env\fR. |
|
Failure to do so may result in a crash. |
|
.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 conversation or plugin_printf |
function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional |
function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional |
error information to the user. |
error information to the user. |
|
.IP "register_hooks" 4 |
|
.IX Item "register_hooks" |
|
.Vb 2 |
|
\& void (*register_hooks)(int version, |
|
\& int (*register_hook)(struct sudo_hook *hook)); |
|
.Ve |
|
.Sp |
|
The \f(CW\*(C`register_hooks\*(C'\fR function is called by the sudo front end to |
|
register any hooks the plugin needs. If the plugin does not support |
|
hooks, \f(CW\*(C`register_hooks\*(C'\fR should be set to the \s-1NULL\s0 pointer. |
|
.Sp |
|
The \fIversion\fR argument describes the version of the hooks \s-1API\s0 |
|
supported by the \fBsudo\fR front end. |
|
.Sp |
|
The \f(CW\*(C`register_hook\*(C'\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 \f(CW\*(C`struct hook\*(C'\fR |
|
does not match the front end's major hook \s-1API\s0 version. |
|
.Sp |
|
See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information |
|
about hooks. |
|
.Sp |
|
\&\s-1NOTE:\s0 the \f(CW\*(C`register_hooks\*(C'\fR function is only available starting |
|
with \s-1API\s0 version 1.2. If the \fBsudo\fR front end doesn't support \s-1API\s0 |
|
version 1.2 or higher, \f(CW\*(C`register_hooks\*(C'\fR will not be called. |
|
.IP "deregister_hooks" 4 |
|
.IX Item "deregister_hooks" |
|
.Vb 2 |
|
\& void (*deregister_hooks)(int version, |
|
\& int (*deregister_hook)(struct sudo_hook *hook)); |
|
.Ve |
|
.Sp |
|
The \f(CW\*(C`deregister_hooks\*(C'\fR function is called by the sudo front end |
|
to deregister any hooks the plugin has registered. If the plugin |
|
does not support hooks, \f(CW\*(C`deregister_hooks\*(C'\fR should be set to the |
|
\&\s-1NULL\s0 pointer. |
|
.Sp |
|
The \fIversion\fR argument describes the version of the hooks \s-1API\s0 |
|
supported by the \fBsudo\fR front end. |
|
.Sp |
|
The \f(CW\*(C`deregister_hook\*(C'\fR function should be used to deregister any |
|
hooks that were put in place by the \f(CW\*(C`register_hook\*(C'\fR function. If |
|
the plugin tries to deregister a hook that the front end does not |
|
support, \f(CW\*(C`deregister_hook\*(C'\fR will return an error. |
|
.Sp |
|
See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information |
|
about hooks. |
|
.Sp |
|
\&\s-1NOTE:\s0 the \f(CW\*(C`deregister_hooks\*(C'\fR function is only available starting |
|
with \s-1API\s0 version 1.2. If the \fBsudo\fR front end doesn't support \s-1API\s0 |
|
version 1.2 or higher, \f(CW\*(C`deregister_hooks\*(C'\fR will not be called. |
.PP |
.PP |
\fIVersion macros\fR | \fIPolicy Plugin Version Macros\fR |
.IX Subsection "Version macros" | .IX Subsection "Policy Plugin Version Macros" |
.PP |
.PP |
.Vb 8 | .Vb 6 |
| \& /* 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_MAJOR(v) ((v) >> 16) |
\& #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) |
\& #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) |
\& #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e |
\& #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e |
Line 783 error information to the user.
|
Line 929 error information to the user.
|
\& #define SUDO_VERSION_SET_MINOR(vp, n) do { \e |
\& #define SUDO_VERSION_SET_MINOR(vp, n) do { \e |
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e |
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e |
\& } while(0) |
\& } while(0) |
\& |
|
\& #define SUDO_API_VERSION_MAJOR 1 |
|
\& #define SUDO_API_VERSION_MINOR 0 |
|
\& #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \e |
|
\& SUDO_API_VERSION_MINOR) |
|
.Ve |
.Ve |
.SS "I/O Plugin \s-1API\s0" |
.SS "I/O Plugin \s-1API\s0" |
.IX Subsection "I/O Plugin API" |
.IX Subsection "I/O Plugin API" |
Line 799 error information to the user.
|
Line 940 error information to the user.
|
\& int (*open)(unsigned int version, sudo_conv_t conversation |
\& int (*open)(unsigned int version, sudo_conv_t conversation |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& char * const user_info[], int argc, char * const argv[], |
\& char * const user_info[], int argc, char * const argv[], |
\& char * const user_env[]); | \& char * const user_env[], char * const plugin_options[]); |
\& void (*close)(int exit_status, int error); /* wait status or error */ |
\& void (*close)(int exit_status, int error); /* wait status or error */ |
\& int (*show_version)(int verbose); |
\& int (*show_version)(int verbose); |
\& int (*log_ttyin)(const char *buf, unsigned int len); |
\& int (*log_ttyin)(const char *buf, unsigned int len); |
Line 807 error information to the user.
|
Line 948 error information to the user.
|
\& int (*log_stdin)(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_stdout)(const char *buf, unsigned int len); |
\& int (*log_stderr)(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 |
.Ve |
.PP |
.PP |
Line 845 built against.
|
Line 990 built against.
|
\& int (*open)(unsigned int version, sudo_conv_t conversation |
\& int (*open)(unsigned int version, sudo_conv_t conversation |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& sudo_printf_t plugin_printf, char * const settings[], |
\& char * const user_info[], int argc, char * const argv[], |
\& char * const user_info[], int argc, char * const argv[], |
\& char * const user_env[]); | \& char * const user_env[], char * const plugin_options[]); |
.Ve |
.Ve |
.Sp |
.Sp |
The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR |
The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR |
Line 920 The user's environment in the form of a \f(CW\*(C`NULL
|
Line 1065 The user's environment in the form of a \f(CW\*(C`NULL
|
When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR |
When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR |
equal sign ('=') since the \fIname\fR field will never include one |
equal sign ('=') since the \fIname\fR field will never include one |
itself but the \fIvalue\fR might. |
itself but the \fIvalue\fR might. |
|
.IP "plugin_options" 4 |
|
.IX Item "plugin_options" |
|
Any (non-comment) strings immediately after the plugin path are |
|
treated as arguments to the plugin. These arguments are split on |
|
a white space boundary and are passed to the plugin in the form of |
|
a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings. If no arguments were |
|
specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer. |
|
.Sp |
|
\&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with |
|
\&\s-1API\s0 version 1.2. A plugin \fBmust\fR check the \s-1API\s0 version specified |
|
by the \fBsudo\fR front end before using \fIplugin_options\fR. Failure to |
|
do so may result in a crash. |
.RE |
.RE |
.RS 4 |
.RS 4 |
.RE |
.RE |
Line 1083 The length of \fIbuf\fR in bytes.
|
Line 1240 The length of \fIbuf\fR in bytes.
|
.RE |
.RE |
.RS 4 |
.RS 4 |
.RE |
.RE |
|
.IP "register_hooks" 4 |
|
.IX Item "register_hooks" |
|
See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of |
|
\&\f(CW\*(C`register_hooks\*(C'\fR. |
|
.IP "deregister_hooks" 4 |
|
.IX Item "deregister_hooks" |
|
See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of |
|
\&\f(CW\*(C`deregister_hooks\*(C'\fR. |
.PP |
.PP |
\fIVersion macros\fR | \fII/O Plugin Version Macros\fR |
.IX Subsection "Version macros" | .IX Subsection "I/O Plugin Version Macros" |
.PP |
.PP |
Same as for the \*(L"Policy Plugin \s-1API\s0\*(R". |
Same as for the \*(L"Policy Plugin \s-1API\s0\*(R". |
|
.SS "Hook Function \s-1API\s0" |
|
.IX Subsection "Hook Function API" |
|
Beginning with plugin \s-1API\s0 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 |
|
environment variables. Hooks can be used to intercept attempts to |
|
get, set, or remove environment variables so that these changes can |
|
be reflected in the version of the environment that is used to |
|
execute a command. A future version of the \s-1API\s0 will support |
|
hooking internal \fBsudo\fR front end functions as well. |
|
.PP |
|
\fIHook structure\fR |
|
.IX Subsection "Hook structure" |
|
.PP |
|
Hooks in \fBsudo\fR are described by the following structure: |
|
.PP |
|
.Vb 1 |
|
\& typedef int (*sudo_hook_fn_t)(); |
|
\& |
|
\& struct sudo_hook { |
|
\& int hook_version; |
|
\& int hook_type; |
|
\& sudo_hook_fn_t hook_fn; |
|
\& void *closure; |
|
\& }; |
|
.Ve |
|
.PP |
|
The \f(CW\*(C`sudo_hook\*(C'\fR structure has the following fields: |
|
.IP "hook_version" 4 |
|
.IX Item "hook_version" |
|
The \f(CW\*(C`hook_version\*(C'\fR field should be set to \s-1SUDO_HOOK_VERSION\s0. |
|
.IP "hook_type" 4 |
|
.IX Item "hook_type" |
|
The \f(CW\*(C`hook_type\*(C'\fR field may be one of the following supported hook types: |
|
.RS 4 |
|
.IP "\s-1SUDO_HOOK_SETENV\s0" 4 |
|
.IX Item "SUDO_HOOK_SETENV" |
|
The C library \f(CW\*(C`setenv()\*(C'\fR function. Any registered hooks will run |
|
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should |
|
be a function that matches the following typedef: |
|
.Sp |
|
.Vb 2 |
|
\& typedef int (*sudo_hook_fn_setenv_t)(const char *name, |
|
\& const char *value, int overwrite, void *closure); |
|
.Ve |
|
.Sp |
|
If the registered hook does not match the typedef the results are |
|
unspecified. |
|
.IP "\s-1SUDO_HOOK_UNSETENV\s0" 4 |
|
.IX Item "SUDO_HOOK_UNSETENV" |
|
The C library \f(CW\*(C`unsetenv()\*(C'\fR function. Any registered hooks will run |
|
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should |
|
be a function that matches the following typedef: |
|
.Sp |
|
.Vb 2 |
|
\& typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, |
|
\& void *closure); |
|
.Ve |
|
.IP "\s-1SUDO_HOOK_GETENV\s0" 4 |
|
.IX Item "SUDO_HOOK_GETENV" |
|
The C library \f(CW\*(C`getenv()\*(C'\fR function. Any registered hooks will run |
|
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should |
|
be a function that matches the following typedef: |
|
.Sp |
|
.Vb 2 |
|
\& typedef int (*sudo_hook_fn_getenv_t)(const char *name, |
|
\& char **value, void *closure); |
|
.Ve |
|
.Sp |
|
If the registered hook does not match the typedef the results are |
|
unspecified. |
|
.IP "\s-1SUDO_HOOK_PUTENV\s0" 4 |
|
.IX Item "SUDO_HOOK_PUTENV" |
|
The C library \f(CW\*(C`putenv()\*(C'\fR function. Any registered hooks will run |
|
before the C library implementation. The \f(CW\*(C`hook_fn\*(C'\fR field should |
|
be a function that matches the following typedef: |
|
.Sp |
|
.Vb 2 |
|
\& typedef int (*sudo_hook_fn_putenv_t)(char *string, |
|
\& void *closure); |
|
.Ve |
|
.Sp |
|
If the registered hook does not match the typedef the results are |
|
unspecified. |
|
.RE |
|
.RS 4 |
|
.RE |
|
.IP "hook_fn" 4 |
|
.IX Item "hook_fn" |
|
.Vb 1 |
|
\& sudo_hook_fn_t hook_fn; |
|
.Ve |
|
.Sp |
|
The \f(CW\*(C`hook_fn\*(C'\fR field should be set to the plugin's hook implementation. |
|
The actual function arguments will vary depending on the \f(CW\*(C`hook_type\*(C'\fR |
|
(see \f(CW\*(C`hook_type\*(C'\fR above). In all cases, the \f(CW\*(C`closure\*(C'\fR field of |
|
\&\f(CW\*(C`struct sudo_hook\*(C'\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: |
|
.RS 4 |
|
.IP "\s-1SUDO_HOOK_RET_ERROR\s0" 4 |
|
.IX Item "SUDO_HOOK_RET_ERROR" |
|
The hook function encountered an error. |
|
.IP "\s-1SUDO_HOOK_RET_NEXT\s0" 4 |
|
.IX Item "SUDO_HOOK_RET_NEXT" |
|
The hook completed without error, go on to the next hook (including |
|
the native implementation if applicable). For example, a \f(CW\*(C`getenv\*(C'\fR |
|
hook might return \f(CW\*(C`SUDO_HOOK_RET_NEXT\*(C'\fR if the specified variable |
|
was not found in the private copy of the environment. |
|
.IP "\s-1SUDO_HOOK_RET_STOP\s0" 4 |
|
.IX Item "SUDO_HOOK_RET_STOP" |
|
The hook completed without error, stop processing hooks for this |
|
invocation. This can be used to replace the native implementation. |
|
For example, a \f(CW\*(C`setenv\*(C'\fR hook that operates on a private copy of |
|
the environment but leaves \f(CW\*(C`environ\*(C'\fR unchanged. |
|
.RE |
|
.RS 4 |
|
.RE |
|
.PP |
|
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 |
|
\&\f(CW\*(C`snprintf\*(C'\fR function may create a loop if the \f(CW\*(C`snprintf\*(C'\fR implementation |
|
calls \f(CW\*(C`getenv\*(C'\fR to check the locale. To prevent this, you may wish |
|
to use a static variable in the hook function to guard against |
|
nested calls. E.g. |
|
.PP |
|
.Vb 7 |
|
\& 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; |
|
.Ve |
|
.PP |
|
\fIHook \s-1API\s0 Version Macros\fR |
|
.IX Subsection "Hook API Version Macros" |
|
.PP |
|
.Vb 6 |
|
\& /* Hook API version major/minor */ |
|
\& #define SUDO_HOOK_VERSION_MAJOR 1 |
|
\& #define SUDO_HOOK_VERSION_MINOR 0 |
|
\& #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y) |
|
\& #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e |
|
\& SUDO_HOOK_VERSION_MINOR) |
|
\& |
|
\& /* Getters and setters for hook API version */ |
|
\& #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16) |
|
\& #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff) |
|
\& #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \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" |
.SS "Conversation \s-1API\s0" |
.IX Subsection "Conversation API" |
.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 |
Line 1100 A printf-style function is also available that can be
|
Line 1424 A printf-style function is also available that can be
|
informational or error messages to the user, which is usually more |
informational or error messages to the user, which is usually more |
convenient for simple messages where no use input is required. |
convenient for simple messages where no use input is required. |
.PP |
.PP |
.Vb 11 | .Vb 12 |
\& struct sudo_conv_message { |
\& struct sudo_conv_message { |
\& #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ |
\& #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_PROMPT_ECHO_ON 0x0002 /* echo user input */ |
\& #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ |
\& #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ |
\& #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ |
\& #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ |
\& #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ |
\& #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 */ |
\& #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ |
\& int msg_type; |
\& int msg_type; |
\& int timeout; |
\& int timeout; |
Line 1135 freeing the reply buffer filled in to the \f(CW\*(C`st
|
Line 1460 freeing the reply buffer filled in to the \f(CW\*(C`st
|
if any. |
if any. |
.PP |
.PP |
The printf-style function uses the same underlying mechanism as the |
The printf-style function uses the same underlying mechanism as the |
conversation function but only supports \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR and | conversation function but only supports \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR, |
\&\f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR for the \fImsg_type\fR parameter. It can be | \&\f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_DEBUG_MSG\*(C'\fR for the \fImsg_type\fR |
more convenient than using the conversation function if no user | parameter. It can be more convenient than using the conversation |
reply is needed and supports standard \fIprintf()\fR escape sequences. | function if no user reply is needed and supports standard \fIprintf()\fR |
| 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 |
|
sent with the <\s-1SUDO_CONV_DEBUG_MSG\s0> \fImsg_type\fR are not directly |
|
user-visible. Instead, they are logged to the file specified in |
|
the \f(CW\*(C`Debug\*(C'\fR statement (if any) in the \fI@sysconfdir@/sudo.conf\fR |
|
file. This allows a plugin to log debugging information and is |
|
intended to be used in conjunction with the \fIdebug_flags\fR setting. |
|
.PP |
See the sample plugin for an example of the conversation function usage. |
See the sample plugin for an example of the conversation function usage. |
.SS "Sudoers Group Plugin \s-1API\s0" |
.SS "Sudoers Group Plugin \s-1API\s0" |
.IX Subsection "Sudoers Group Plugin API" |
.IX Subsection "Sudoers Group Plugin API" |
Line 1241 present in the password database, \fIpwd\fR will be \f
|
Line 1574 present in the password database, \fIpwd\fR will be \f
|
.RS 4 |
.RS 4 |
.RE |
.RE |
.PP |
.PP |
\fIVersion Macros\fR | \fIGroup \s-1API\s0 Version Macros\fR |
.IX Subsection "Version Macros" | .IX Subsection "Group API Version Macros" |
.PP |
.PP |
.Vb 5 |
.Vb 5 |
\& /* Sudoers group plugin version major/minor */ |
\& /* Sudoers group plugin version major/minor */ |
Line 1261 present in the password database, \fIpwd\fR will be \f
|
Line 1594 present in the password database, \fIpwd\fR will be \f
|
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e |
\& *(vp) = (*(vp) & 0xffff0000) | (n); \e |
\& } while(0) |
\& } while(0) |
.Ve |
.Ve |
|
.SH "PLUGIN API CHANGELOG" |
|
.IX Header "PLUGIN API CHANGELOG" |
|
The following revisions have been made to the Sudo Plugin \s-1API\s0. |
|
.IP "Version 1.0" 4 |
|
.IX Item "Version 1.0" |
|
Initial \s-1API\s0 version. |
|
.IP "Version 1.1" 4 |
|
.IX Item "Version 1.1" |
|
The I/O logging plugin's \f(CW\*(C`open\*(C'\fR function was modified to take the |
|
\&\f(CW\*(C`command_info\*(C'\fR list as an argument. |
|
.IP "Version 1.2" 4 |
|
.IX Item "Version 1.2" |
|
The Policy and I/O logging plugins' \f(CW\*(C`open\*(C'\fR functions are now passed |
|
a list of plugin options if any are specified in \fI@sysconfdir@/sudo.conf\fR. |
|
.Sp |
|
A simple hooks \s-1API\s0 has been introduced to allow plugins to hook in to the |
|
system's environment handling functions. |
|
.Sp |
|
The \f(CW\*(C`init_session\*(C'\fR Policy plugin function is now passed a pointer |
|
to the user environment which can be updated as needed. This can |
|
be used to merge in environment variables stored in the \s-1PAM\s0 handle |
|
before a command is run. |
.SH "SEE ALSO" |
.SH "SEE ALSO" |
.IX Header "SEE ALSO" |
.IX Header "SEE ALSO" |
\&\fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@) |
\&\fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@) |