diff options
Diffstat (limited to '')
-rw-r--r-- | doc/sudo_plugin.man.in | 2986 |
1 files changed, 2986 insertions, 0 deletions
diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in new file mode 100644 index 0000000..c336033 --- /dev/null +++ b/doc/sudo_plugin.man.in @@ -0,0 +1,2986 @@ +.\" Automatically generated from an mdoc input file. Do not edit. +.\" +.\" Copyright (c) 2009-2018 Todd C. Miller <Todd.Miller@sudo.ws> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.TH "SUDO_PLUGIN" "5" "October 24, 2018" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.nh +.if n .ad l +.SH "NAME" +\fBsudo_plugin\fR +\- Sudo Plugin API +.SH "DESCRIPTION" +Starting with version 1.8, +\fBsudo\fR +supports a plugin API +for policy and session logging. +Plugins may be compiled as dynamic shared objects (the default on +systems that support them) or compiled statically into the +\fBsudo\fR +binary itself. +By default, the +\fBsudoers\fR +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 +The API is versioned with a major and minor number. +The minor version number is incremented when additions are made. +The major number is incremented when incompatible changes are made. +A plugin should be check the version passed to it and make sure that the +major version matches. +.PP +The plugin API is defined by the +\fRsudo_plugin.h\fR +header file. +.SS "Policy plugin API" +A policy plugin must declare and populate a +\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 +The policy_plugin struct has the following fields: +.TP 6n +type +The +\fRtype\fR +field should always be set to SUDO_POLICY_PLUGIN. +.TP 6n +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. +.TP 6n +open +.nf +.RS 6n +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[]); +.RE +.fi +.RS 6n +.sp +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. +.sp +The function arguments are as follows: +.TP 6n +version +The version passed in by +\fBsudo\fR +allows the plugin to determine the +major and minor version number of the plugin API supported by +\fBsudo\fR. +.TP 6n +conversation +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. +.TP 6n +plugin_printf +A pointer to a +\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. +.TP 6n +settings +A vector of user-supplied +\fBsudo\fR +settings in the form of +\(lqname=value\(rq +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 +been specified on the command line. +.sp +When parsing +\fIsettings\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +since the +\fIname\fR +field will never include one +itself but the +\fIvalue\fR +might. +.PP +.RS 6n +.PD 0 +.TP 6n +bsdauth_type=string +Authentication type, if specified by the +\fB\-a\fR +flag, to use on +systems where +BSD +authentication is supported. +.PD +.TP 6n +closefrom=number +If specified, the user has requested via the +\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 debug file path name followed by a space and a comma-separated +list of debug flags that correspond to the plugin's +\fRDebug\fR +entry in +sudo.conf(@mansectform@), +if there is one. +The flags are passed to the plugin exactly as they appear in +sudo.conf(@mansectform@). +The syntax used by +\fBsudo\fR +and the +\fBsudoers\fR +plugin is +\fIsubsystem\fR@\fIpriority\fR +but a plugin is free to use a different +format so long as it does not include a comma +(\(oq,\&\(cq). +Prior to +\fBsudo\fR +1.8.12, there was no way to specify plugin-specific +\fIdebug_flags\fR +so the value was always the same as that used by the +\fBsudo\fR +front end and did not include a path name, only the flags themselves. +As of version 1.7 of the plugin interface, +\fBsudo\fR +will only pass +\fIdebug_flags\fR +if +sudo.conf(@mansectform@) +contains a plugin-specific +\fRDebug\fR +entry. +.TP 6n +debug_level=number +This setting has been deprecated in favor of +\fIdebug_flags\fR. +.TP 6n +ignore_ticket=bool +Set to true if the user specified the +\fB\-k\fR +flag along with a +command, indicating that the user wishes to ignore any cached +authentication credentials. +\fIimplied_shell\fR +to true. +This allows +\fBsudo\fR +with no arguments +to be used similarly to +su(1). +If the plugin does not to support this usage, it may return a value of \-2 +from the +\fBcheck_policy\fR() +function, which will cause +\fBsudo\fR +to print a usage message and +exit. +.TP 6n +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 +.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 +\(lqaddr/netmask\(rq, +e.g., +\(lq192.168.1.2/255.255.255.0\(rq. +The address and netmask pairs may be either IPv4 or IPv6, depending on +what the operating system supports. +If the address contains a colon +(\(oq:\&\(cq), +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 +plugin_path=string +The path name of plugin loaded by the +\fBsudo\fR +front end. +The path name will be a fully-qualified unless the plugin was +statically compiled into +\fBsudo\fR. +.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 +based on the runas user. +.TP 6n +progname=string +The command name that sudo was run as, typically +\(lqsudo\(rq +or +\(lqsudoedit\(rq. +.TP 6n +prompt=string +The prompt to use when requesting a password, if specified via +the +\fB\-p\fR +flag. +.TP 6n +remote_host=string +The name of the remote host to run the command on, if specified via +the +\fB\-h\fR +option. +Support for running the command on a remote host is meant to be implemented +via a helper program that is executed in place of the user-specified command. +The +\fBsudo\fR +front end is only capable of executing commands on the local host. +Only available starting with API version 1.4. +.TP 6n +run_shell=bool +Set to true if the user specified the +\fB\-s\fR +flag, indicating that the user wishes to run a shell. +.TP 6n +runas_group=string +The group name or gid to run the command as, if specified via +the +\fB\-g\fR +flag. +.TP 6n +runas_user=string +The user name or uid 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 +the +\fB\-r\fR +flag. +.TP 6n +selinux_type=string +SELinux type to use when executing the command, if specified by +the +\fB\-t\fR +flag. +.TP 6n +set_home=bool +Set to true if the user specified the +\fB\-H\fR +flag. +If true, set the +\fRHOME\fR +environment variable to the target user's home directory. +.TP 6n +sudoedit=bool +Set to true when the +\fB\-e\fR +flag is specified or if invoked as +\fBsudoedit\fR. +The plugin shall substitute an editor into +\fIargv\fR +in the +\fBcheck_policy\fR() +function or return \-2 with a usage error +if the plugin does not support +\fIsudoedit\fR. +For more information, see the +\fIcheck_policy\fR +section. +.TP 6n +timeout=string +User-specified command timeout. +Not all plugins support command timeouts and the ability for the +user to set a timeout may be restricted by policy. +The format of the timeout string is plugin-specific. +.PP +Additional settings may be added in the future so the plugin should +silently ignore settings that it does not recognize. +.RE +.TP 6n +user_info +A vector of information about the user running the command in the form of +\(lqname=value\(rq +strings. +The vector is terminated by a +\fRNULL\fR +pointer. +.sp +When parsing +\fIuser_info\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +since the +\fIname\fR +field will never include one +itself but the +\fIvalue\fR +might. +.PP +.RS 6n +.PD 0 +.TP 6n +cols=int +The number of columns the user's terminal supports. +If there is no terminal device available, a default value of 80 is used. +.PD +.TP 6n +cwd=string +The user's current working directory. +.TP 6n +egid=gid_t +The effective group ID of the user invoking +\fBsudo\fR. +.TP 6n +euid=uid_t +The effective user ID of the user invoking +\fBsudo\fR. +.TP 6n +gid=gid_t +The real group ID of the user invoking +\fBsudo\fR. +.TP 6n +groups=list +The user's supplementary group list formatted as a string of +comma-separated group IDs. +.TP 6n +host=string +The local machine's hostname as returned by the +gethostname(2) +system call. +.TP 6n +lines=int +The number of lines the user's terminal supports. +If there is +no terminal device available, a default value of 24 is used. +.TP 6n +pgid=int +The ID of the process group that the running +\fBsudo\fR +process is a member of. +Only available starting with API version 1.2. +.TP 6n +pid=int +The process ID of the running +\fBsudo\fR +process. +Only available starting with API version 1.2. +.TP 6n +plugin_options +Any (non-comment) strings immediately after the plugin path are +passed 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 +\fRNULL\fR-terminated +array of strings. +If no arguments were +specified, +\fIplugin_options\fR +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 +\(lq\fRtty=\fR\(rq. +.TP 6n +uid=uid_t +The real user ID of the user invoking +\fBsudo\fR. +.TP 6n +umask=octal +The invoking user's file creation mask. +Only available starting with API version 1.10. +.TP 6n +user=string +The name of the user invoking +\fBsudo\fR. +.PD 0 +.PP +.RE +.PD +.TP 6n +user_env +The user's environment in the form of a +\fRNULL\fR-terminated vector of +\(lqname=value\(rq +strings. +.sp +When parsing +\fIuser_env\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +since the +\fIname\fR +field will never include one +itself but the +\fIvalue\fR +might. +.PD 0 +.PP +.RE +.PD +.TP 6n +close +.br +.nf +.RS 6n +void (*close)(int exit_status, int error); +.RE +.fi +.RS 6n +.sp +The +\fBclose\fR() +function is called when the command being run by +\fBsudo\fR +finishes. +.sp +The function arguments are as follows: +.TP 6n +exit_status +The command's exit status, as returned by the +wait(2) +system call. +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 +\fRerrno\fR +set by the +execve(2) +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. +.RE +.TP 6n +show_version +.nf +.RS 6n +int (*show_version)(int verbose); +.RE +.fi +.RS 6n +.sp +The +\fBshow_version\fR() +function is called by +\fBsudo\fR +when the user specifies +the +\fB\-V\fR +option. +The plugin may display its version information to the user via the +\fBconversation\fR() +or +\fBplugin_printf\fR() +function using +\fRSUDO_CONV_INFO_MSG\fR. +If the user requests detailed version information, the verbose flag will be set. +.sp +Returns 1 on success, 0 on failure, \-1 if a general error occurred, +or \-2 if there was a usage error, although the return value is currently +ignored. +.RE +.TP 6n +check_policy +.nf +.RS 6n +int (*check_policy)(int argc, char * const argv[], + char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); +.RE +.fi +.RS 6n +.sp +The +\fBcheck_policy\fR() +function is called by +\fBsudo\fR +to determine +whether the user is allowed to run the specified commands. +.sp +If the +\fIsudoedit\fR +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 +elevated privileges. +\fBsudo\fR +achieves this by creating user-writable +temporary copies of the files to be edited and then overwriting the +originals with the temporary copies after editing is complete. +If the plugin supports +\fIsudoedit\fR, +it should choose the editor to be used, potentially from a variable +in the user's environment, such as +\fREDITOR\fR, +and include it in +\fIargv_out\fR +(note that environment +variables may include command line flags). +The files to be edited should be copied from +\fIargv\fR +into +\fIargv_out\fR, +separated from the +editor and its arguments by a +\(lq\fR--\fR\(rq +element. +The +\(lq\fR--\fR\(rq +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 +or if +\fIsudoedit\fR +was specified but is unsupported by the plugin. +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. +.sp +The function arguments are as follows: +.TP 6n +argc +The number of elements in +\fIargv\fR, +not counting the final +\fRNULL\fR +pointer. +.TP 6n +argv +The argument vector describing the command the user wishes to run, +in the same form as what would be passed to the +execve(2) +system call. +The vector is terminated by a +\fRNULL\fR +pointer. +.TP 6n +env_add +Additional environment variables specified by the user on the command +line in the form of a +\fRNULL\fR-terminated +vector of +\(lqname=value\(rq +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. +.sp +When parsing +\fIenv_add\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +since the +\fIname\fR +field will never include one +itself but the +\fIvalue\fR +might. +.TP 6n +command_info +Information about the command being run in the form of +\(lqname=value\(rq +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: +.PP +.RS 6n +.PD 0 +.TP 6n +chroot=string +The root directory to use when running the command. +.PD +.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. +.TP 6n +cwd=string +The current working directory to change to when executing the command. +.TP 6n +exec_background=bool +By default, +\fBsudo\fR +runs a command as the foreground process as long as +\fBsudo\fR +itself is running in the foreground. +When +\fIexec_background\fR +is enabled and the command is being run in a pty (due to I/O logging +or the +\fIuse_pty\fR +setting), the command will be run as a background process. +Attempts to read from the controlling terminal (or to change terminal +settings) will result in the command being suspended with the +\fRSIGTTIN\fR +signal (or +\fRSIGTTOU\fR +in the case of terminal settings). +If this happens when +\fBsudo\fR +is a foreground process, the command will be granted the controlling terminal +and resumed in the foreground with no user intervention required. +The advantage of initially running the command in the background is that +\fBsudo\fR +need not read from the terminal unless the command explicitly requests it. +Otherwise, any terminal input must be passed to the command, whether it +has required it or not (the kernel buffers terminals so it is not possible +to tell whether the command really wants the input). +This is different from historic +\fIsudo\fR +behavior or when the command is not being run in a pty. +.sp +For this to work seamlessly, the operating system must support the +automatic restarting of system calls. +Unfortunately, not all operating systems do this by default, +and even those that do may have bugs. +For example, macOS fails to restart the +\fBtcgetattr\fR() +and +\fBtcsetattr\fR() +system calls (this is a bug in macOS). +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 +execfd=number +If specified, +\fBsudo\fR +will use the +fexecve(2) +system call to execute the command instead of +execve(2). +The specified +\fInumber\fR +must refer to an open file descriptor. +.TP 6n +iolog_compress=bool +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 to ignore it. +.TP 6n +iolog_group=string +The group that will own newly created I/O log files and directories. +This is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_mode=octal +The file permission mode to use when creating I/O log files and directories. +This is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_user=string +The user that will own newly created I/O log files and directories. +This is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_path=string +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 choose to ignore it. +If no I/O logging plugin is loaded, this setting has no effect. +.TP 6n +iolog_stdin=bool +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 is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_stdout=bool +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 is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_stderr=bool +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 is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_ttyin=bool +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 from a pipe or +redirected from a file. +This is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +iolog_ttyout=bool +Set to true if the I/O logging plugins, if any, should log all +terminal output. +This only includes output to the screen, not output to a pipe or file. +This is a hint to the I/O logging plugin which may choose to ignore it. +.TP 6n +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_fds=list +A comma-separated list of file descriptors that should be +preserved, regardless of the value of the +\fIclosefrom\fR +setting. +Only available starting with API version 1.5. +.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 +sudoedit_checkdir=bool +Set to false to disable directory writability checks in +\fBsudoedit\fR. +By default, +\fBsudoedit\fR +1.8.16 and higher will check all directory components of the path to be +edited for writability by the invoking user. +Symbolic links will not be followed in writable directories and +\fBsudoedit\fR +will refuse to edit a file located in a writable directory. +These restrictions are not enforced when +\fBsudoedit\fR +is run by root. +The +\fIsudoedit_follow\fR +option can be set to false to disable this check. +Only available starting with API version 1.8. +.TP 6n +sudoedit_follow=bool +Set to true to allow +\fBsudoedit\fR +to edit files that are symbolic links. +By default, +\fBsudoedit\fR +1.8.15 and higher will refuse to open a symbolic link. +The +\fIsudoedit_follow\fR +option can be used to restore the older behavior and allow +\fBsudoedit\fR +to open symbolic links. +Only available starting with API version 1.8. +.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 +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. +.TP 6n +utmp_user=string +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 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. +.PP +Unsupported values will be ignored. +.RE +.TP 6n +argv_out +The +\fRNULL\fR-terminated +argument vector to pass to the +execve(2) +system call when executing the command. +The plugin is responsible for allocating and populating the vector. +.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. +.PD 0 +.PP +.RE +.PD +.TP 6n +list +.nf +.RS 6n +int (*list)(int argc, char * const argv[], + int verbose, const char *list_user); +.RE +.fi +.RS 6n +.sp +List available privileges for the invoking user. +Returns 1 on success, 0 on failure and \-1 on error. +On error, 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. +.sp +Privileges should be output via the +\fBconversation\fR() +or +\fBplugin_printf\fR() +function using +\fRSUDO_CONV_INFO_MSG\fR, +.TP 6n +verbose +Flag indicating whether to list in verbose mode or not. +.TP 6n +list_user +The name of a different user to list privileges for if the policy +allows it. +If +\fRNULL\fR, +the plugin should list the privileges of the invoking user. +.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 check against the policy in the same form as what would +be passed to the +execve(2) +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. +.PD 0 +.PP +.RE +.PD +.TP 6n +validate +.nf +.RS 6n +int (*validate)(void); +.RE +.fi +.RS 6n +.sp +The +\fBvalidate\fR() +function is called when +\fBsudo\fR +is run with the +\fB\-v\fR +flag. +For policy plugins such as +\fBsudoers\fR +that cache +authentication credentials, this function will validate and cache +the credentials. +.sp +The +\fBvalidate\fR() +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. +On error, 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. +.RE +.TP 6n +invalidate +.nf +.RS 6n +void (*invalidate)(int remove); +.RE +.fi +.RS 6n +.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 +credentials. +If the +\fIremove\fR +flag is set, the plugin may remove +the credentials instead of simply invalidating them. +.sp +The +\fBinvalidate\fR() +function should be +\fRNULL\fR +if the plugin does not support credential caching. +.RE +.TP 6n +init_session +.nf +.RS 6n +int (*init_session)(struct passwd *pwd, char **user_envp[); +.RE +.fi +.RS 6n +.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 +in the password database, otherwise it will be +\fRNULL\fR. +.sp +The +\fIuser_env\fR +argument points to the environment the command will +run in, in the form of a +\fRNULL\fR-terminated +vector of +\(lqname=value\(rq +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 +pointer stored in +\fIuser_env\fR. +The expected use case is to merge the contents of the PAM environment +(if any) with the contents of +\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. +.sp +Returns 1 on success, 0 on failure and \-1 on error. +On error, 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. +.RE +.TP 6n +register_hooks +.nf +.RS 6n +void (*register_hooks)(int version, + int (*register_hook)(struct sudo_hook *hook)); +.RE +.fi +.RS 6n +.sp +The +\fBregister_hooks\fR() +function is called by the sudo front end to +register any hooks the plugin needs. +If the plugin does not support hooks, +\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. +.sp +NOTE: the +\fBregister_hooks\fR() +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, +\fRregister_hooks\fR +will not be called. +.RE +.TP 6n +deregister_hooks +.nf +.RS 6n +void (*deregister_hooks)(int version, + int (*deregister_hook)(struct sudo_hook *hook)); +.RE +.fi +.RS 6n +.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. +.sp +NOTE: the +\fBderegister_hooks\fR() +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 +.PP +\fIPolicy Plugin Version Macros\fR +.nf +.sp +.RS 0n +/* Plugin API version major/minor. */ +#define SUDO_API_VERSION_MAJOR 1 +#define SUDO_API_VERSION_MINOR 13 +#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_API_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)); + int (*change_winsize)(unsigned int lines, unsigned int cols); + int (*log_suspend)(int signo); +}; +.RE +.fi +.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 +session. +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. +.PP +The log_ttyin function receives the raw user input from the terminal +device (note that this will include input even when echo is disabled, +such as when a password is read). +The log_ttyout function receives output from the pseudo-tty that is +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 +or standard error respectively correspond to something other than +a tty. +.PP +Any of the logging functions may be set to the +\fRNULL\fR +pointer if no logging is to be performed. +If the open function returns 0, no I/O will be sent to the plugin. +.PP +If a logging function returns an error +(\-1), +the running command will be terminated and all of the plugin's logging +functions will be disabled. +Other I/O logging plugins will still receive any remaining +input or output that has not yet been processed. +.PP +If an input logging function rejects the data by returning 0, the +command will be terminated and the data will not be passed to the +command, though it will still be sent to any other I/O logging plugins. +If an output logging function rejects the data by returning 0, the +command will be terminated and the data will not be written to the +terminal, though it will still be sent to any other I/O logging plugins. +.PP +The io_plugin struct has the following fields: +.TP 6n +type +The +\fRtype\fR +field should always be set to +\fRSUDO_IO_PLUGIN\fR. +.TP 6n +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. +.TP 6n +open +.nf +.RS 6n +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[]); +.RE +.fi +.RS 6n +.sp +The +\fBopen\fR() +function is run before the +\fBlog_ttyin\fR(), +\fBlog_ttyout\fR(), +\fBlog_stdin\fR(), +\fBlog_stdout\fR(), +\fBlog_stderr\fR(), +\fBlog_suspend\fR(), +\fBchange_winsize\fR(), +or +\fBshow_version\fR() +functions are called. +It is only called if the version is being requested or if the +policy plugin's +\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. +.sp +The function arguments are as follows: +.TP 6n +version +The version passed in by +\fBsudo\fR +allows the plugin to determine the +major and minor version number of the plugin API supported by +\fBsudo\fR. +.TP 6n +conversation +A pointer to the +\fBconversation\fR() +function that may be used by the +\fBshow_version\fR() +function to display version information (see +\fBshow_version\fR() +below). +The +\fBconversation\fR() +function may also be used to display additional error message to the user. +The +\fBconversation\fR() +function returns 0 on success and \-1 on failure. +.TP 6n +plugin_printf +A pointer to a +\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 +\(lqname=value\(rq +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 +been specified on the command line. +.sp +When parsing +\fIsettings\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +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 +\(lqname=value\(rq +strings. +The vector is terminated by a +\fRNULL\fR +pointer. +.sp +When parsing +\fIuser_info\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +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. +It can be zero, when +\fBsudo\fR +is called with +\fB\-V\fR. +.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 +execve(2) +system call. +.TP 6n +user_env +The user's environment in the form of a +\fRNULL\fR-terminated +vector of +\(lqname=value\(rq +strings. +.sp +When parsing +\fIuser_env\fR, +the plugin should split on the +\fBfirst\fR +equal sign +(\(oq=\(cq) +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 +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 +\fRNULL\fR-terminated +array of strings. +If no arguments were specified, +\fIplugin_options\fR +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. +.PD 0 +.PP +.RE +.PD +.TP 6n +close +.br +.nf +.RS 6n +void (*close)(int exit_status, int error); +.RE +.fi +.RS 6n +.sp +The +\fBclose\fR() +function is called when the command being run by +\fBsudo\fR +finishes. +.sp +The function arguments are as follows: +.TP 6n +exit_status +The command's exit status, as returned by the +wait(2) +system call. +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 +\fRerrno\fR +set by the +execve(2) +system call. +If the command was successfully executed, the value of +\fRerror\fR +is 0. +.PD 0 +.PP +.RE +.PD +.TP 6n +show_version +.nf +.RS 6n +int (*show_version)(int verbose); +.RE +.fi +.RS 6n +.sp +The +\fBshow_version\fR() +function is called by +\fBsudo\fR +when the user specifies +the +\fB\-V\fR +option. +The plugin may display its version information to the user via the +\fBconversation\fR() +or +\fBplugin_printf\fR() +function using +\fRSUDO_CONV_INFO_MSG\fR. +If the user requests detailed version information, the verbose flag will be set. +.sp +Returns 1 on success, 0 on failure, \-1 if a general error occurred, +or \-2 if there was a usage error, although the return value is currently +ignored. +.RE +.TP 6n +log_ttyin +.nf +.RS 6n +int (*log_ttyin)(const char *buf, unsigned int len); +.RE +.fi +.RS 6n +.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 running command) or \-1 if an +error occurred. +.sp +The function arguments are as follows: +.TP 6n +buf +The buffer containing user input. +.TP 6n +len +The length of +\fIbuf\fR +in bytes. +.PD 0 +.PP +.RE +.PD +.TP 6n +log_ttyout +.nf +.RS 6n +int (*log_ttyout)(const char *buf, unsigned int len); +.RE +.fi +.RS 6n +.sp +The +\fBlog_ttyout\fR() +function is called whenever data can be read from +the command but before it is written to the user's terminal. +This allows the plugin to reject data if it chooses to (for instance +if the output contains banned content). +Returns 1 if the data should be passed to the user, 0 if the data is rejected +(which will terminate the running command) or \-1 if an error occurred. +.sp +The function arguments are as follows: +.TP 6n +buf +The buffer containing command output. +.TP 6n +len +The length of +\fIbuf\fR +in bytes. +.PD 0 +.PP +.RE +.PD +.TP 6n +log_stdin +.nf +.RS 6n +int (*log_stdin)(const char *buf, unsigned int len); +.RE +.fi +.RS 6n +.sp +The +\fBlog_stdin\fR() +function is only used if the standard input does +not correspond to a tty device. +It is called whenever data can be read from the standard input 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 running command) or \-1 if an error occurred. +.sp +The function arguments are as follows: +.TP 6n +buf +The buffer containing user input. +.TP 6n +len +The length of +\fIbuf\fR +in bytes. +.PD 0 +.PP +.RE +.PD +.TP 6n +log_stdout +.nf +.RS 6n +int (*log_stdout)(const char *buf, unsigned int len); +.RE +.fi +.RS 6n +.sp +The +\fBlog_stdout\fR() +function is only used if the standard output does not correspond +to a tty device. +It is called whenever data can be read from the command but before +it is written to the standard output. +This allows the plugin to reject data if it chooses to +(for instance if the output contains banned content). +Returns 1 if the data should be passed to the user, 0 if the data is +rejected (which will terminate the running command) or \-1 if an error occurred. +.sp +The function arguments are as follows: +.TP 6n +buf +The buffer containing command output. +.TP 6n +len +The length of +\fIbuf\fR +in bytes. +.PD 0 +.PP +.RE +.PD +.TP 6n +log_stderr +.nf +.RS 6n +int (*log_stderr)(const char *buf, unsigned int len); +.RE +.fi +.RS 6n +.sp +The +\fBlog_stderr\fR() +function is only used if the standard error does +not correspond to a tty device. +It is called whenever data can be read from the command but before it +is written to the standard error. +This allows the plugin to reject data if it chooses to +(for instance if the output contains banned content). +Returns 1 if the data should be passed to the user, 0 if the data is +rejected (which will terminate the running command) or \-1 if an error occurred. +.sp +The function arguments are as follows: +.TP 6n +buf +The buffer containing command output. +.TP 6n +len +The length of +\fIbuf\fR +in bytes. +.PD 0 +.PP +.RE +.PD +.TP 6n +register_hooks +See the +\fIPolicy plugin API\fR +section for a description of +\fRregister_hooks\fR. +.TP 6n +deregister_hooks +See the +\fIPolicy plugin API\fR +section for a description of +\fRderegister_hooks\fR. +.TP 6n +change_winsize +.nf +.RS 6n +int (*change_winsize)(unsigned int lines, unsigned int cols); +.RE +.fi +.RS 6n +.sp +The +\fBchange_winsize\fR() +function is called whenever the window size of the terminal changes from +the initial values specified in the +\fRuser_info\fR +list. +Returns \-1 if an error occurred, in which case no further calls to +\fBchange_winsize\fR() +will be made, +.RE +.TP 6n +log_suspend +.nf +.RS 6n +int (*log_suspend)(int signo); +.RE +.fi +.RS 6n +.sp +The +\fBlog_suspend\fR() +function is called whenever a command is suspended or resumed. +The +\fIsigno\fR +argument is either the signal that caused the command to be suspended or +\fRSIGCONT\fR +if the command was resumed. +Logging this information makes it possible to skip the period of time when +the command was suspended during playback of a session. +Returns \-1 if an error occurred, in which case no further calls to +\fBlog_suspend\fR() +will be made, +.RE +.PP +\fII/O Plugin Version Macros\fR +.PP +Same as for the +\fIPolicy plugin API\fR. +.SS "Signal handlers" +The +\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 3n +\fB\(bu\fR +\fRSIGALRM\fR +.PD 0 +.TP 3n +\fB\(bu\fR +\fRSIGHUP\fR +.TP 3n +\fB\(bu\fR +\fRSIGINT\fR +.TP 3n +\fB\(bu\fR +\fRSIGPIPE\fR +.TP 3n +\fB\(bu\fR +\fRSIGQUIT\fR +.TP 3n +\fB\(bu\fR +\fRSIGTERM\fR +.TP 3n +\fB\(bu\fR +\fRSIGTSTP\fR +.TP 3n +\fB\(bu\fR +\fRSIGUSR1\fR +.TP 3n +\fB\(bu\fR +\fRSIGUSR2\fR +.PD +.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. +An exception to this is +\fRSIGPIPE\fR, +which is ignored until the command is executed. +.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 +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 API will support hooking internal +\fBsudo\fR +front end functions as well. +.PP +\fIHook structure\fR +.PP +Hooks in +\fBsudo\fR +are described by the following structure: +.nf +.sp +.RS 0n +typedef int (*sudo_hook_fn_t)(); + +struct sudo_hook { + unsigned int hook_version; + unsigned int hook_type; + sudo_hook_fn_t hook_fn; + void *closure; +}; +.RE +.fi +.PP +The +\fRsudo_hook\fR +structure has the following fields: +.TP 6n +hook_version +The +\fRhook_version\fR +field should be set to +\fRSUDO_HOOK_VERSION\fR. +.TP 6n +hook_type +The +\fRhook_type\fR +field may be one of the following supported hook types: +.PP +.RS 6n +.PD 0 +.TP 6n +\fRSUDO_HOOK_SETENV\fR +The C library +setenv(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: +.nf +.sp +.RS 6n +typedef int (*sudo_hook_fn_setenv_t)(const char *name, + const char *value, int overwrite, void *closure); +.RE +.fi +.RS 6n +.sp +If the registered hook does not match the typedef the results are +unspecified. +.RE +.PD +.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: +.nf +.sp +.RS 6n +typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, + void *closure); +.RE +.fi +.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: +.nf +.sp +.RS 6n +typedef int (*sudo_hook_fn_getenv_t)(const char *name, + char **value, void *closure); +.RE +.fi +.RS 6n +.sp +If the registered hook does not match the typedef the results are +unspecified. +.RE +.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: +.nf +.sp +.RS 6n +typedef int (*sudo_hook_fn_putenv_t)(char *string, + void *closure); +.RE +.fi +.RS 6n +.sp +If the registered hook does not match the typedef the results are +unspecified. +.RE +.PD 0 +.PP +.RE +.PD +.TP 6n +hook_fn +sudo_hook_fn_t hook_fn; +.sp +The +\fRhook_fn\fR +field should be set to the plugin's hook implementation. +The actual function arguments will vary depending on the +\fRhook_type\fR +(see +\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: +.PP +.RS 6n +.PD 0 +.TP 6n +\fRSUDO_HOOK_RET_ERROR\fR +The hook function encountered an error. +.PD +.TP 6n +\fRSUDO_HOOK_RET_NEXT\fR +The hook completed without error, go on to the next hook (including +the native implementation if applicable). +For example, a +getenv(3) +hook might return +\fRSUDO_HOOK_RET_NEXT\fR +if the specified variable was not found in the private copy of the environment. +.TP 6n +\fRSUDO_HOOK_RET_STOP\fR +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. +.PD 0 +.PP +.RE +.PD +.PP +Note that it is very easy to create an infinite loop when hooking +C library functions. +For example, a +getenv(3) +hook that calls the +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 +\fIHook API Version Macros\fR +.nf +.sp +.RS 0n +/* Hook API version major/minor */ +#define SUDO_HOOK_VERSION_MAJOR 1 +#define SUDO_HOOK_VERSION_MINOR 0 +#define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e + SUDO_HOOK_VERSION_MINOR) +.RE +.fi +.PP +For getters and setters see the +\fIPolicy plugin API\fR. +.SS "Remote command execution" +The +\fBsudo\fR +front end does not have native support for running remote commands. +However, starting with +\fBsudo\fR +1.8.8, the +\fB\-h\fR +option may be used to specify a remote host that is passed +to the policy plugin. +A plugin may also accept a +\fIrunas_user\fR +in the form of +\(lquser@hostname\(rq +which will work with older versions of +\fBsudo\fR. +It is anticipated that remote commands will be supported by executing a +\(lqhelper\(rq +program. +The policy plugin should setup the execution environment such that the +\fBsudo\fR +front end will run the helper which, in turn, will connect to the +remote host and run the command. +.PP +For example, the policy plugin could utilize +\fBssh\fR +to perform remote command execution. +The helper program would be responsible for running +\fBssh\fR +with the proper options to use a private key or certificate +that the remote host will accept and run a program +on the remote host that would setup the execution environment +accordingly. +.PP +Note that remote +\fBsudoedit\fR +functionality must be handled by the policy plugin, not +\fBsudo\fR +itself as the front end has no knowledge that a remote command is +being executed. +This may be addressed in a future revision of the plugin API. +.SS "Conversation API" +If the plugin needs to interact with the user, it may do so via the +\fBconversation\fR() +function. +A plugin should not attempt to read directly from the standard input +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 +A +\fBprintf\fR()-style +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. +.PP +\fIConversation function structures\fR +.PP +The conversation function takes as arguments pointers to the following +structures: +.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_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ +#define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */ + int msg_type; + int timeout; + const char *msg; +}; + +#define SUDO_CONV_REPL_MAX 255 + +struct sudo_conv_reply { + char *reply; +}; + +typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure); +struct sudo_conv_callback { + unsigned int version; + void *closure; + sudo_conv_callback_fn_t on_suspend; + sudo_conv_callback_fn_t on_resume; +}; +.RE +.fi +.PP +Pointers to the +\fBconversation\fR() +and +\fBprintf\fR()-style +functions are passed +in to the plugin's +\fBopen\fR() +function when the plugin is initialized. +The following type definitions can be used in the declaration of the +\fBopen\fR() +function: +.nf +.sp +.RS 0n +typedef int (*sudo_conv_t)(int num_msgs, + const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[], + struct sudo_conv_callback *callback); + +typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); +.RE +.fi +.PP +To use the +\fBconversation\fR() +function, the plugin must pass an array of +\fRsudo_conv_message\fR +and +\fRsudo_conv_reply\fR +structures. +There must be a +\fRstruct sudo_conv_message\fR +and +\fRstruct sudo_conv_reply\fR +for +each message in the conversation, that is, both arrays must have the same +number of elements. +Each +\fRstruct sudo_conv_reply\fR +must have its +\fIreply\fR +member initialized to +\fRNULL\fR. +The +\fRstruct sudo_conv_callback\fR +pointer, if not +\fRNULL\fR, +should contain function pointers to be called when the +\fBsudo\fR +process is suspended and/or resumed during conversation input. +The +\fIon_suspend\fR +and +\fIon_resume\fR +functions are called with the signal that caused +\fBsudo\fR +to be suspended and the +\fIclosure\fR +pointer from the +\fRstruct sudo_conv_callback\fR. +These functions should return 0 on success and \-1 on error. +On error, the conversation will end and the conversation function +will return a value of \-1. +The intended use is to allow the plugin to release resources, such as locks, +that should not be held indefinitely while suspended and then reacquire them +when the process is resumed. +Note that the functions are not actually invoked from within a signal handler. +.PP +The +\fImsg_type\fR +must be set to one of the following values: +.TP 6n +SUDO_CONV_PROMPT_ECHO_OFF +Prompt the user for input with echo disabled; +this is generally used for passwords. +The reply will be stored in the +\fIreplies\fR +array, and it will never be +\fRNULL\fR. +.TP 6n +SUDO_CONV_PROMPT_ECHO_ON +Prompt the user for input with echo enabled. +The reply will be stored in the +\fIreplies\fR +array, and it will never be +\fRNULL\fR. +.TP 6n +SUDO_CONV_ERROR_MSG +Display an error message. +The message is written to the standard error unless the +\fRSUDO_CONV_PREFER_TTY\fR +flag is set, in which case it is written to the user's terminal if possible. +.TP 6n +SUDO_CONV_INFO_MSG +Display a message. +The message is written to the standard output unless the +\fRSUDO_CONV_PREFER_TTY\fR +flag is set, in which case it is written to the user's terminal if possible. +.TP 6n +SUDO_CONV_PROMPT_MASK +Prompt the user for input but echo an asterisk character for each +character read. +The reply will be stored in the +\fIreplies\fR +array, and it will never be +\fRNULL\fR. +This can be used to provide visual feedback to the user while reading +sensitive information that should not be displayed. +.PP +In addition to the above values, the following flag bits may also be set: +.TP 6n +SUDO_CONV_PROMPT_ECHO_OK +Allow input to be read when echo cannot be disabled +when the message type is +\fRSUDO_CONV_PROMPT_ECHO_OFF\fR +or +\fRSUDO_CONV_PROMPT_MASK\fR. +By default, +\fBsudo\fR +will refuse to read input if the echo cannot be disabled for those +message types. +.TP 6n +SUDO_CONV_PREFER_TTY +When displaying a message via +\fRSUDO_CONV_ERROR_MSG\fR +or +\fRSUDO_CONV_INFO_MSG\fR, +try to write the message to the user's terminal. +If the terminal is unavailable, the standard error or standard output +will be used, depending upon whether +The user's terminal is always used when possible for input, +this flag is only used for output. +\fRSUDO_CONV_ERROR_MSG\fR +or +\fRSUDO_CONV_INFO_MSG\fR +was used. +.PP +The +\fItimeout\fR +in seconds until the prompt will wait for no more input. +A zero value implies an infinite timeout. +.PP +The plugin is responsible for freeing the reply buffer located in each +\fRstruct sudo_conv_reply\fR, +if it is not +\fRNULL\fR. +\fRSUDO_CONV_REPL_MAX\fR +represents the maximum length of the reply buffer (not including +the trailing NUL character). +In practical terms, this is the longest password +\fBsudo\fR +will support. +It is also useful as a maximum value for the +\fBmemset_s\fR() +function when clearing passwords filled in by the conversation function. +.PP +The +\fBprintf\fR()-style +function uses the same underlying mechanism as the +\fBconversation\fR() +function but only supports +\fRSUDO_CONV_INFO_MSG\fR +and +\fRSUDO_CONV_ERROR_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. +.PP +See the sample plugin for an example of the +\fBconversation\fR() +function usage. +.SS "Sudoers group plugin API" +The +\fBsudoers\fR +plugin supports its own plugin interface to allow non-Unix +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 +A group plugin must declare and populate a +\fRsudoers_group_plugin\fR +struct in the global scope. +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 +The +\fRsudoers_group_plugin\fR +struct has the following fields: +.TP 6n +version +The +\fRversion\fR +field should be set to GROUP_API_VERSION. +.sp +This allows +\fBsudoers\fR +to determine the API version the group plugin +was built against. +.TP 6n +init +.nf +.RS 6n +int (*init)(int version, sudo_printf_t plugin_printf, + char *const argv[]); +.RE +.fi +.RS 6n +.sp +The +\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. +.sp +The function arguments are as follows: +.TP 6n +version +The version passed in by +\fBsudoers\fR +allows the plugin to determine the +major and minor version number of the group plugin API supported by +\fBsudoers\fR. +.TP 6n +plugin_printf +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. +.TP 6n +argv +A +\fRNULL\fR-terminated +array of arguments generated from the +\fIgroup_plugin\fR +option in +\fIsudoers\fR. +If no arguments were given, +\fIargv\fR +will be +\fRNULL\fR. +.PD 0 +.PP +.RE +.PD +.TP 6n +cleanup +.nf +.RS 6n +void (*cleanup)(); +.RE +.fi +.RS 6n +.sp +The +\fBcleanup\fR() +function is called when +\fBsudoers\fR +has finished its +group checks. +The plugin should free any memory it has allocated and close open file handles. +.RE +.TP 6n +query +.br +.nf +.RS 6n +int (*query)(const char *user, const char *group, + const struct passwd *pwd); +.RE +.fi +.RS 6n +.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: +.TP 6n +user +The name of the user being looked up in the external group database. +.TP 6n +group +.br +The name of the group being queried. +.TP 6n +pwd +The password database entry for +\fIuser\fR, +if any. +If +\fIuser\fR +is not +present in the password database, +\fIpwd\fR +will be +\fRNULL\fR. +.PD 0 +.PP +.RE +.PD +.PP +\fIGroup API Version Macros\fR +.nf +.sp +.RS 0n +/* Sudoers group plugin version major/minor */ +#define GROUP_API_VERSION_MAJOR 1 +#define GROUP_API_VERSION_MINOR 0 +#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e + GROUP_API_VERSION_MINOR) +.RE +.fi +For getters and setters see the +\fIPolicy plugin API\fR. +.SH "PLUGIN API CHANGELOG" +The following revisions have been made to the Sudo Plugin API. +.TP 6n +Version 1.0 +Initial API version. +.TP 6n +Version 1.1 (sudo 1.8.0) +The I/O logging plugin's +\fBopen\fR() +function was modified to take the +\fRcommand_info\fR +list as an argument. +.TP 6n +Version 1.2 (sudo 1.8.5) +The Policy and I/O logging plugins' +\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. +.sp +The +\fRinit_session\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 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. +.TP 6n +Version 1.4 (sudo 1.8.8) +The +\fIremote_host\fR +entry was added to the +\fRsettings\fR +list. +.TP 6n +Version 1.5 (sudo 1.8.9) +The +\fIpreserve_fds\fR +entry was added to the +\fRcommand_info\fR +list. +.TP 6n +Version 1.6 (sudo 1.8.11) +The behavior when an I/O logging plugin returns an error +(\-1) +has changed. +Previously, the +\fBsudo\fR +front end took no action when the +\fBlog_ttyin\fR(), +\fBlog_ttyout\fR(), +\fBlog_stdin\fR(), +\fBlog_stdout\fR(), +or +\fBlog_stderr\fR() +function returned an error. +.sp +The behavior when an I/O logging plugin returns 0 has changed. +Previously, output from the command would be displayed to the +terminal even if an output logging function returned 0. +.TP 6n +Version 1.7 (sudo 1.8.12) +The +\fIplugin_path\fR +entry was added to the +\fRsettings\fR +list. +.sp +The +\fIdebug_flags\fR +entry now starts with a debug file path name and may occur multiple +times if there are multiple plugin-specific Debug lines in the +sudo.conf(@mansectform@) file. +.TP 6n +Version 1.8 (sudo 1.8.15) +The +\fIsudoedit_checkdir\fR +and +\fIsudoedit_follow\fR +entries were added to the +\fRcommand_info\fR +list. +The default value of +\fIsudoedit_checkdir\fR +was changed to true in sudo 1.8.16. +.sp +The sudo +\fIconversation\fR +function now takes a pointer to a +\fRstruct sudo_conv_callback\fR +as its fourth argument. +The +\fRsudo_conv_t\fR +definition has been updated to match. +The plugin must specify that it supports plugin API version 1.8 or higher +to receive a conversation function pointer that supports this argument. +.TP 6n +Version 1.9 (sudo 1.8.16) +The +\fIexecfd\fR +entry was added to the +\fRcommand_info\fR +list. +.TP 6n +Version 1.10 (sudo 1.8.19) +The +\fIumask\fR +entry was added to the +\fRuser_info\fR +list. +The +\fIiolog_group\fR, +\fIiolog_mode\fR, +and +\fIiolog_user\fR +entries were added to the +\fRcommand_info\fR +list. +.TP 6n +Version 1.11 (sudo 1.8.20) +The +\fItimeout\fR +entry was added to the +\fRsettings\fR +list. +.TP 6n +Version 1.12 (sudo 1.8.21) +The +\fRchange_winsize\fR +field was added to the io_plugin struct. +.TP 6n +Version 1.13 (sudo 1.8.26) +The +\fRlog_suspend\fR +field was added to the io_plugin struct. +.SH "SEE ALSO" +sudo.conf(@mansectform@), +sudoers(@mansectform@), +sudo(@mansectsu@) +.SH "AUTHORS" +Many people have worked on +\fBsudo\fR +over the years; this version consists of code written primarily by: +.sp +.RS 6n +Todd C. Miller +.RE +.PP +See the CONTRIBUTORS file in the +\fBsudo\fR +distribution (https://www.sudo.ws/contributors.html) for an +exhaustive list of people who have contributed to +\fBsudo\fR. +.SH "BUGS" +If you feel you have found a bug in +\fBsudo\fR, +please submit a bug report at https://bugzilla.sudo.ws/ +.SH "SUPPORT" +Limited free support is available via the sudo-users mailing list, +see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or +search the archives. +.SH "DISCLAIMER" +\fBsudo\fR +is provided +\(lqAS IS\(rq +and any express or implied warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a +particular purpose are disclaimed. +See the LICENSE file distributed with +\fBsudo\fR +or https://www.sudo.ws/license.html for complete details. |