{
    "content": [
        {
            "type": "text",
            "text": "# SUDO_PLUGIN (info)\n\n## NAME\n\nsudoplugin -- Sudo Plugin API\n\n## DESCRIPTION\n\nStarting with version 1.8, sudo supports a plugin API for policy and ses-\nsion logging.  Plugins may be compiled as dynamic shared objects (the de-\nfault on systems that support them) or compiled statically into the sudo\nbinary itself.  By default, the sudoers plugin provides audit, security\npolicy and I/O logging capabilities.  Via the plugin API, sudo can be\nconfigured to use alternate plugins provided by third parties.  The plug-\nins to be used are specified in the sudo.conf(5) file.\n\n## Sections\n\n- **NAME**\n- **DESCRIPTION**\n- **PLUGIN API CHANGELOG**\n- **SEE ALSO**\n- **AUTHORS**\n- **BUGS**\n- **SUPPORT**\n- **DISCLAIMER**\n- **Sudo 1.9.9                     January 20, 2022                     Sudo 1.9.9**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "SUDO_PLUGIN",
        "section": "",
        "mode": "info",
        "summary": "sudoplugin -- Sudo Plugin API",
        "synopsis": null,
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [
            {
                "name": "sudo.conf",
                "section": "5",
                "url": "https://www.chedong.com/phpMan.php/man/sudo.conf/5/json"
            },
            {
                "name": "sudoers",
                "section": "5",
                "url": "https://www.chedong.com/phpMan.php/man/sudoers/5/json"
            },
            {
                "name": "sudo",
                "section": "8",
                "url": "https://www.chedong.com/phpMan.php/man/sudo/8/json"
            }
        ],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 2786,
                "subsections": []
            },
            {
                "name": "PLUGIN API CHANGELOG",
                "lines": 124,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "AUTHORS",
                "lines": 9,
                "subsections": []
            },
            {
                "name": "BUGS",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "SUPPORT",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "DISCLAIMER",
                "lines": 6,
                "subsections": []
            },
            {
                "name": "Sudo 1.9.9                     January 20, 2022                     Sudo 1.9.9",
                "lines": 1,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "sudoplugin -- Sudo Plugin API\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "Starting with version 1.8, sudo supports a plugin API for policy and ses-\nsion logging.  Plugins may be compiled as dynamic shared objects (the de-\nfault on systems that support them) or compiled statically into the sudo\nbinary itself.  By default, the sudoers plugin provides audit, security\npolicy and I/O logging capabilities.  Via the plugin API, sudo can be\nconfigured to use alternate plugins provided by third parties.  The plug-\nins to be used are specified in the sudo.conf(5) file.\n\nThe API is versioned with a major and minor number.  The minor version\nnumber is incremented when additions are made.  The major number is in-\ncremented when incompatible changes are made.  A plugin should be check\nthe version passed to it and make sure that the major version matches.\n\nThe plugin API is defined by the sudoplugin.h header file.\n\nPolicy plugin API\nA policy plugin must declare and populate a policyplugin struct in the\nglobal scope.  This structure contains pointers to the functions that im-\nplement the sudo policy checks.  The name of the symbol should be speci-\nfied in sudo.conf(5) along with a path to the plugin so that sudo can\nload it.\n\nstruct policyplugin {\n#define SUDOPOLICYPLUGIN     1\nunsigned int type; /* always SUDOPOLICYPLUGIN */\nunsigned int version; /* always SUDOAPIVERSION */\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft pluginprintf, char * const settings[],\nchar * const userinfo[], char * const userenv[],\nchar * const pluginoptions[], const char errstr);\nvoid (*close)(int exitstatus, int error);\nint (*showversion)(int verbose);\nint (*checkpolicy)(int argc, char * const argv[],\nchar *envadd[], char commandinfo[],\nchar argvout[], char userenvout[], const char errstr);\nint (*list)(int argc, char * const argv[], int verbose,\nconst char *listuser, const char errstr);\nint (*validate)(const char errstr);\nvoid (*invalidate)(int remove);\nint (*initsession)(struct passwd *pwd, char userenv[],\nconst char errstr);\nvoid (*registerhooks)(int version,\nint (*registerhook)(struct sudohook *hook));\nvoid (*deregisterhooks)(int version,\nint (*deregisterhook)(struct sudohook *hook));\nstruct sudopluginevent * (*eventalloc)(void);\n};\n\nThe policyplugin struct has the following fields:\n\ntype  The type field should always be set to SUDOPOLICYPLUGIN.\n\nversion\nThe version field should be set to SUDOAPIVERSION.\n\nThis allows sudo to determine the API version the plugin was built\nagainst.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft pluginprintf, char * const settings[],\nchar * const userinfo[], char * const userenv[],\nchar * const pluginoptions[], const char errstr);\n\nReturns 1 on success, 0 on failure, -1 if a general error occurred,\nor -2 if there was a usage error.  In the latter case, sudo will\nprint a usage message before it exits.  If an error occurs, the\nplugin may optionally call the conversation() or pluginprintf()\nfunction with SUDOCONFERRORMSG to present additional error in-\nformation to the user.\n\nThe function arguments are as follows:\n\nversion\nThe version passed in by sudo allows the plugin to determine\nthe major and minor version number of the plugin API sup-\nported by sudo.\n\nconversation\nA pointer to the conversation() function that can be used by\nthe plugin to interact with the user (see Conversation API\nfor details).  Returns 0 on success and -1 on failure.\n\npluginprintf\nA pointer to a printf()-style function that may be used to\ndisplay informational or error messages (see Conversation API\nfor details).  Returns the number of characters printed on\nsuccess and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of\n\"name=value\" strings.  The vector is terminated by a NULL\npointer.  These settings correspond to options the user spec-\nified when running sudo.  As such, they will only be present\nwhen the corresponding option has been specified on the com-\nmand line.\n\nWhen parsing settings, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nThe following values may be set by sudo:\n\nbsdauthtype=string\nAuthentication type, if specified by the -a option, to\nuse on systems where BSD authentication is supported.\n\nclosefrom=number\nIf specified, the user has requested via the -C option\nthat sudo close all files descriptors with a value of\nnumber or higher.  The plugin may optionally pass this,\nor another value, back in the commandinfo list.\n\ncmndchroot=string\nThe root directory (see chroot(2)) to run the command\nin, as specified by the user via the -R option.  The\nplugin may ignore or restrict the user's ability to\nspecify a new root directory.  Only available starting\nwith API version 1.16.\n\ncmndcwd=string\nThe working directory to run the command in, as speci-\nfied by the user via the -D option.  The plugin may ig-\nnore or restrict the user's ability to specify a new\nworking directory.  Only available starting with API\nversion 1.16.\n\ndebugflags=string\nA debug file path name followed by a space and a comma-\nseparated list of debug flags that correspond to the\nplugin's Debug entry in sudo.conf(5), if there is one.\nThe flags are passed to the plugin exactly as they ap-\npear in sudo.conf(5).  The syntax used by sudo and the\nsudoers plugin is subsystem@priority but a plugin is\nfree to use a different format so long as it does not\ninclude a comma (',').  Prior to sudo 1.8.12, there was\nno way to specify plugin-specific debugflags so the\nvalue was always the same as that used by the sudo\nfront-end and did not include a path name, only the\nflags themselves.  As of version 1.7 of the plugin in-\nterface, sudo will only pass debugflags if\nsudo.conf(5) contains a plugin-specific Debug entry.\n\nignoreticket=bool\nSet to true if the user specified the -k option along\nwith a command, indicating that the user wishes to ig-\nnore any cached authentication credentials.\nimpliedshell to true.  This allows sudo with no argu-\nments to be used similarly to su(1).  If the plugin\ndoes not to support this usage, it may return a value\nof -2 from the checkpolicy() function, which will\ncause sudo to print a usage message and exit.\n\nimpliedshell=bool\nIf the user does not specify a program on the command\nline, sudo will pass the plugin the path to the user's\nshell and set\n\nloginclass=string\nBSD login class to use when setting resource limits and\nnice value, if specified by the -c option.\n\nloginshell=bool\nSet to true if the user specified the -i option, indi-\ncating that the user wishes to run a login shell.\n\nmaxgroups=int\nThe maximum number of groups a user may belong to.\nThis will only be present if there is a corresponding\nsetting in sudo.conf(5).\n\nnetworkaddrs=list\nA space-separated list of IP network addresses and net-\nmasks in the form \"addr/netmask\", e.g.,\n\"192.168.1.2/255.255.255.0\".  The address and netmask\npairs may be either IPv4 or IPv6, depending on what the\noperating system supports.  If the address contains a\ncolon (':'), it is an IPv6 address, else it is IPv4.\n\nnoninteractive=bool\nSet to true if the user specified the -n option, indi-\ncating that sudo should operate in non-interactive\nmode.  The plugin may reject a command run in non-in-\nteractive mode if user interaction is required.\n\nplugindir=string\nThe default plugin directory used by the sudo front-\nend.  This is the default directory set at compile time\nand may not correspond to the directory the running\nplugin was loaded from.  It may be used by a plugin to\nlocate support files.\n\npluginpath=string\nThe path name of plugin loaded by the sudo front-end.\nThe path name will be a fully-qualified unless the\nplugin was statically compiled into sudo.\n\npreserveenvironment=bool\nSet to true if the user specified the -E option, indi-\ncating that the user wishes to preserve the environ-\nment.\n\npreservegroups=bool\nSet to true if the user specified the -P option, indi-\ncating that the user wishes to preserve the group vec-\ntor instead of setting it based on the runas user.\n\nprogname=string\nThe command name that sudo was run as, typically \"sudo\"\nor \"sudoedit\".\n\nprompt=string\nThe prompt to use when requesting a password, if speci-\nfied via the -p option.\n\nremotehost=string\nThe name of the remote host to run the command on, if\nspecified via the -h option.  Support for running the\ncommand on a remote host is meant to be implemented via\na helper program that is executed in place of the user-\nspecified command.  The sudo front-end is only capable\nof executing commands on the local host.  Only avail-\nable starting with API version 1.4.\n\nrunshell=bool\nSet to true if the user specified the -s option, indi-\ncating that the user wishes to run a shell.\n\nrunasgroup=string\nThe group name or group-ID to run the command as, if\nspecified via the -g option.\n\nrunasuser=string\nThe user name or user-ID to run the command as, if\nspecified via the -u option.\n\nselinuxrole=string\nSELinux role to use when executing the command, if\nspecified by the -r option.\n\nselinuxtype=string\nSELinux type to use when executing the command, if\nspecified by the -t option.\n\nsethome=bool\nSet to true if the user specified the -H option.  If\ntrue, set the HOME environment variable to the target\nuser's home directory.\n\nsudoedit=bool\nSet to true when the -e option is specified or if in-\nvoked as sudoedit.  The plugin shall substitute an edi-\ntor into argv in the checkpolicy() function or return\n-2 with a usage error if the plugin does not support\nsudoedit.  For more information, see the checkpolicy\nsection.\n\ntimeout=string\nCommand timeout specified by the user via the -T op-\ntion.  Not all plugins support command timeouts and the\nability of the user to set a timeout may be restricted\nby policy.  The format of the timeout string is plugin-\nspecific.\n\nAdditional settings may be added in the future so the plugin\nshould silently ignore settings that it does not recognize.\n\nuserinfo\nA vector of information about the user running the command in\nthe form of \"name=value\" strings.  The vector is terminated\nby a NULL pointer.\n\nWhen parsing userinfo, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nThe following values may be set by sudo:\n\ncols=int\nThe number of columns the user's terminal supports.  If\nthere is no terminal device available, a default value\nof 80 is used.\n\ncwd=string\nThe user's current working directory.\n\negid=gidt\nThe effective group-ID of the user invoking sudo.\n\neuid=uidt\nThe effective user-ID of the user invoking sudo.\n\ngid=gidt\nThe real group-ID of the user invoking sudo.\n\ngroups=list\nThe user's supplementary group list formatted as a\nstring of comma-separated group-IDs.\n\nhost=string\nThe local machine's hostname as returned by the\ngethostname(2) system call.\n\nlines=int\nThe number of lines the user's terminal supports.  If\nthere is no terminal device available, a default value\nof 24 is used.\n\npgid=int\nThe ID of the process group that the running sudo\nprocess is a member of.  Only available starting with\nAPI version 1.2.\n\npid=int\nThe process ID of the running sudo process.  Only\navailable starting with API version 1.2.\n\nppid=int\nThe parent process ID of the running sudo process.\nOnly available starting with API version 1.2.\n\nrlimitas=soft,hard\nThe maximum size to which the process's address space\nmay grow (in bytes), if supported by the operating sys-\ntem.  The soft and hard limits are separated by a\ncomma.  A value of \"infinity\" indicates that there is\nno limit.  Only available starting with API version\n1.16.\n\nrlimitcore=soft,hard\nThe largest size core dump file that may be created (in\nbytes).  The soft and hard limits are separated by a\ncomma.  A value of \"infinity\" indicates that there is\nno limit.  Only available starting with API version\n1.16.\n\nrlimitcpu=soft,hard\nThe maximum amount of CPU time that the process may use\n(in seconds).  The soft and hard limits are separated\nby a comma.  A value of \"infinity\" indicates that there\nis no limit.  Only available starting with API version\n1.16.\n\nrlimitdata=soft,hard\nThe maximum size of the data segment for the process\n(in bytes).  The soft and hard limits are separated by\na comma.  A value of \"infinity\" indicates that there is\nno limit.  Only available starting with API version\n1.16.\n\nrlimitfsize=soft,hard\nThe largest size file that the process may create (in\nbytes).  The soft and hard limits are separated by a\ncomma.  A value of \"infinity\" indicates that there is\nno limit.  Only available starting with API version\n1.16.\n\nrlimitlocks=soft,hard\nThe maximum number of locks that the process may estab-\nlish, if supported by the operating system.  The soft\nand hard limits are separated by a comma.  A value of\n\"infinity\" indicates that there is no limit.  Only\navailable starting with API version 1.16.\n\nrlimitmemlock=soft,hard\nThe maximum size that the process may lock in memory\n(in bytes), if supported by the operating system.  The\nsoft and hard limits are separated by a comma.  A value\nof \"infinity\" indicates that there is no limit.  Only\navailable starting with API version 1.16.\n\nrlimitnofile=soft,hard\nThe maximum number of files that the process may have\nopen.  The soft and hard limits are separated by a\ncomma.  A value of \"infinity\" indicates that there is\nno limit.  Only available starting with API version\n1.16.\n\nrlimitnproc=soft,hard\nThe maximum number of processes that the user may run\nsimultaneously.  The soft and hard limits are separated\nby a comma.  A value of \"infinity\" indicates that there\nis no limit.  Only available starting with API version\n1.16.\n\nrlimitrss=soft,hard\nThe maximum size to which the process's resident set\nsize may grow (in bytes).  The soft and hard limits are\nseparated by a comma.  A value of \"infinity\" indicates\nthat there is no limit.  Only available starting with\nAPI version 1.16.\n\nrlimitstack=soft,hard\nThe maximum size to which the process's stack may grow\n(in bytes).  The soft and hard limits are separated by\na comma.  A value of \"infinity\" indicates that there is\nno limit.  Only available starting with API version\n1.16.\n\nsid=int\nThe session ID of the running sudo process or 0 if sudo\nis not part of a POSIX job control session.  Only\navailable starting with API version 1.2.\n\ntcpgid=int\nThe ID of the foreground process group associated with\nthe terminal device associated with the sudo process or\n0 if there is no terminal present.  Only available\nstarting with API version 1.2.\n\ntty=string\nThe path to the user's terminal device.  If the user\nhas no terminal device associated with the session, the\nvalue will be empty, as in \"tty=\".\n\nuid=uidt\nThe real user-ID of the user invoking sudo.\n\numask=octal\nThe invoking user's file creation mask.  Only available\nstarting with API version 1.10.\n\nuser=string\nThe name of the user invoking sudo.\n\nuserenv\nThe user's environment in the form of a NULL-terminated\nvector of \"name=value\" strings.\n\nWhen parsing userenv, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path\nare passed as arguments to the plugin.  These arguments are\nsplit on a white space boundary and are passed to the plugin\nin the form of a NULL-terminated array of strings.  If no ar-\nguments were specified, pluginoptions will be the NULL\npointer.\n\nNOTE: the pluginoptions parameter is only available starting\nwith API version 1.2.  A plugin must check the API version\nspecified by the sudo front-end before using pluginoptions.\nFailure to do so may result in a crash.\n\nerrstr\nIf the open() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nclose\nvoid (*close)(int exitstatus, int error);\n\nThe close() function is called when sudo is finished, shortly be-\nfore it exits.  Starting with API version 1.15, close() is called\nregardless of whether or not a command was actually executed.  This\nmakes it possible for plugins to perform cleanup even when a com-\nmand was not run.  It is not possible to tell whether a command was\nrun based solely on the arguments passed to the close() function.\nTo determine if a command was actually run, the plugin must keep\ntrack of whether or not the checkpolicy() function returned suc-\ncessfully.\n\nThe function arguments are as follows:\n\nexitstatus\nThe command's exit status, as returned by the wait(2) system\ncall, or zero if no command was run.  The value of\nexitstatus is undefined if error is non-zero.\n\nerror\nIf the command could not be executed, this is set to the\nvalue of errno set by the execve(2) system call.  The plugin\nis responsible for displaying error information via the\nconversation() or pluginprintf() function.  If the command\nwas successfully executed, the value of error is zero.\n\nIf no close() function is defined, no I/O logging plugins are\nloaded, and neither the timeout not usepty options are set in the\ncommandinfo list, the sudo front-end may execute the command di-\nrectly instead of running it as a child process.\n\nshowversion\nint (*showversion)(int verbose);\n\nThe showversion() function is called by sudo when the user speci-\nfies the -V option.  The plugin may display its version information\nto the user via the conversation() or pluginprintf() function us-\ning SUDOCONVINFOMSG.  If the user requests detailed version in-\nformation, the verbose flag will be set.\n\nReturns 1 on success, 0 on failure, -1 if a general error occurred,\nor -2 if there was a usage error, although the return value is cur-\nrently ignored.\n\ncheckpolicy\nint (*checkpolicy)(int argc, char * const argv[], char *envadd[],\nchar commandinfo[], char argvout[], char userenvout[],\nconst char errstr);\n\nThe checkpolicy() function is called by sudo to determine whether\nthe user is allowed to run the specified commands.\n\nIf the sudoedit option was enabled in the settings array passed to\nthe open() function, the user has requested sudoedit mode.\nsudoedit is a mechanism for editing one or more files where an edi-\ntor is run with the user's credentials instead of with elevated\nprivileges.  sudo achieves this by creating user-writable temporary\ncopies of the files to be edited and then overwriting the originals\nwith the temporary copies after editing is complete.  If the plugin\nsupports sudoedit, it should choose the editor to be used, poten-\ntially from a variable in the user's environment, such as EDITOR,\nand include it in argvout (note that environment variables may in-\nclude command line options).  The files to be edited should be\ncopied from argv into argvout, separated from the editor and its\narguments by a \"--\" element.  The \"--\" will be removed by sudo be-\nfore the editor is executed.  The plugin should also set\nsudoedit=true in the commandinfo list.\n\nThe checkpolicy() function returns 1 if the command is allowed, 0\nif not allowed, -1 for a general error, or -2 for a usage error or\nif sudoedit was specified but is unsupported by the plugin.  In the\nlatter case, sudo will print a usage message before it exits.  If\nan error occurs, the plugin may optionally call the conversation()\nor pluginprintf() function with SUDOCONFERRORMSG to present ad-\nditional error information to the user.\n\nThe function arguments are as follows:\n\nargc  The number of elements in argv, not counting the final NULL\npointer.\n\nargv  The argument vector describing the command the user wishes to\nrun, in the same form as what would be passed to the\nexecve(2) system call.  The vector is terminated by a NULL\npointer.\n\nenvadd\nAdditional environment variables specified by the user on the\ncommand line in the form of a NULL-terminated vector of\n\"name=value\" strings.  The plugin may reject the command if\none or more variables are not allowed to be set, or it may\nsilently ignore such variables.\n\nWhen parsing envadd, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\ncommandinfo\nInformation about the command being run in the form of\n\"name=value\" strings.  These values are used by sudo to set\nthe execution environment when running a command.  The plugin\nis responsible for creating and populating the vector, which\nmust be terminated with a NULL pointer.  The following values\nare recognized by sudo:\n\nchroot=string\nThe root directory to use when running the command.\n\nclosefrom=number\nIf specified, sudo will close all files descriptors\nwith a value of number or higher.\n\ncommand=string\nFully qualified path to the command to be executed.\n\ncwd=string\nThe current working directory to change to when execut-\ning the command.  If sudo is unable to change to the\nnew working directory, the command will not be run un-\nless cwdoptional is also set (see below).\n\ncwdoptional=bool\nIf enabled, sudo will treat an inability to change to\nthe new working directory as a non-fatal error.  This\nsetting has no effect unless cwd is also set.\n\nexecbackground=bool\nBy default, sudo runs a command as the foreground\nprocess as long as sudo itself is running in the fore-\nground.  When execbackground is enabled and the com-\nmand is being run in a pseudo-terminal (due to I/O log-\nging or the usepty setting), the command will be run\nas a background process.  Attempts to read from the\ncontrolling terminal (or to change terminal settings)\nwill result in the command being suspended with the\nSIGTTIN signal (or SIGTTOU in the case of terminal set-\ntings).  If this happens when sudo is a foreground\nprocess, the command will be granted the controlling\nterminal and resumed in the foreground with no user in-\ntervention required.  The advantage of initially run-\nning the command in the background is that sudo need\nnot read from the terminal unless the command explic-\nitly requests it.  Otherwise, any terminal input must\nbe passed to the command, whether it has required it or\nnot (the kernel buffers terminals so it is not possible\nto tell whether the command really wants the input).\nThis is different from historic sudo behavior or when\nthe command is not being run in a pseudo-terminal.\n\nFor this to work seamlessly, the operating system must\nsupport the automatic restarting of system calls.  Un-\nfortunately, not all operating systems do this by de-\nfault, and even those that do may have bugs.  For exam-\nple, macOS fails to restart the tcgetattr() and\ntcsetattr() system calls (this is a bug in macOS).\nFurthermore, because this behavior depends on the com-\nmand stopping with the SIGTTIN or SIGTTOU signals, pro-\ngrams that catch these signals and suspend themselves\nwith a different signal (usually SIGTOP) will not be\nautomatically foregrounded.  Some versions of the linux\nsu(1) command behave this way.  Because of this, a\nplugin should not set execbackground unless it is ex-\nplicitly enabled by the administrator and there should\nbe a way to enabled or disable it on a per-command ba-\nsis.\n\nThis setting has no effect unless I/O logging is en-\nabled or usepty is enabled.\n\nexecfd=number\nIf specified, sudo will use the fexecve(2) system call\nto execute the command instead of execve(2).  The spec-\nified number must refer to an open file descriptor.\n\niologcompress=bool\nSet to true if the I/O logging plugins, if any, should\ncompress the log data.  This is a hint to the I/O log-\nging plugin which may choose to ignore it.\n\niologgroup=string\nThe group that will own newly created I/O log files and\ndirectories.  This is a hint to the I/O logging plugin\nwhich may choose to ignore it.\n\niologmode=octal\nThe file permission mode to use when creating I/O log\nfiles and directories.  This is a hint to the I/O log-\nging plugin which may choose to ignore it.\n\niologuser=string\nThe user that will own newly created I/O log files and\ndirectories.  This is a hint to the I/O logging plugin\nwhich may choose to ignore it.\n\niologpath=string\nFully qualified path to the file or directory in which\nI/O log is to be stored.  This is a hint to the I/O\nlogging plugin which may choose to ignore it.  If no\nI/O logging plugin is loaded, this setting has no ef-\nfect.\n\niologstdin=bool\nSet to true if the I/O logging plugins, if any, should\nlog the standard input if it is not connected to a ter-\nminal device.  This is a hint to the I/O logging plugin\nwhich may choose to ignore it.\n\niologstdout=bool\nSet to true if the I/O logging plugins, if any, should\nlog the standard output if it is not connected to a\nterminal device.  This is a hint to the I/O logging\nplugin which may choose to ignore it.\n\niologstderr=bool\nSet to true if the I/O logging plugins, if any, should\nlog the standard error if it is not connected to a ter-\nminal device.  This is a hint to the I/O logging plugin\nwhich may choose to ignore it.\n\niologttyin=bool\nSet to true if the I/O logging plugins, if any, should\nlog all terminal input.  This only includes input typed\nby the user and not from a pipe or redirected from a\nfile.  This is a hint to the I/O logging plugin which\nmay choose to ignore it.\n\niologttyout=bool\nSet to true if the I/O logging plugins, if any, should\nlog all terminal output.  This only includes output to\nthe screen, not output to a pipe or file.  This is a\nhint to the I/O logging plugin which may choose to ig-\nnore it.\n\nloginclass=string\nBSD login class to use when setting resource limits and\nnice value (optional).  This option is only set on sys-\ntems that support login classes.\n\nnice=int\nNice value (priority) to use when executing the com-\nmand.  The nice value, if specified, overrides the pri-\nority associated with the loginclass on BSD systems.\n\nnoexec=bool\nIf set, prevent the command from executing other pro-\ngrams.\n\npreservefds=list\nA comma-separated list of file descriptors that should\nbe preserved, regardless of the value of the closefrom\nsetting.  Only available starting with API version 1.5.\n\npreservegroups=bool\nIf set, sudo will preserve the user's group vector in-\nstead of initializing the group vector based on\nrunasuser.\n\nrlimitas=soft,hard\nThe maximum size to which the process's address space\nmay grow (in bytes), if supported by the operating sys-\ntem.  The soft and hard limits are separated by a\ncomma.  If only a single value is specified, both the\nhard and soft limits are set.  A value of \"infinity\"\nindicates that there is no limit.  A value of \"user\"\nwill cause the invoking user's resource limit to be\npreserved.  A value of \"default\" will cause the target\nuser's default resource limit to be used on systems\nthat allow per-user resource limits to be configured.\nOnly available starting with API version 1.17.\n\nrlimitcore=soft,hard\nThe largest size core dump file that may be created (in\nbytes).  The soft and hard limits are separated by a\ncomma.  If only a single value is specified, both the\nhard and soft limits are set.  A value of \"infinity\"\nindicates that there is no limit.  A value of \"user\"\nwill cause the invoking user's resource limit to be\npreserved.  A value of \"default\" will cause the target\nuser's default resource limit to be used on systems\nthat allow per-user resource limits to be configured.\nOnly available starting with API version 1.17.\n\nrlimitcpu=soft,hard\nThe maximum amount of CPU time that the process may use\n(in seconds).  The soft and hard limits are separated\nby a comma.  If only a single value is specified, both\nthe hard and soft limits are set.  A value of\n\"infinity\" indicates that there is no limit.  A value\nof \"user\" will cause the invoking user's resource limit\nto be preserved.  A value of \"default\" will cause the\ntarget user's default resource limit to be used on sys-\ntems that allow per-user resource limits to be config-\nured.  Only available starting with API version 1.17.\n\nrlimitdata=soft,hard\nThe maximum size of the data segment for the process\n(in bytes).  The soft and hard limits are separated by\na comma.  If only a single value is specified, both the\nhard and soft limits are set.  A value of \"infinity\"\nindicates that there is no limit.  A value of \"user\"\nwill cause the invoking user's resource limit to be\npreserved.  A value of \"default\" will cause the target\nuser's default resource limit to be used on systems\nthat allow per-user resource limits to be configured.\nOnly available starting with API version 1.17.\n\nrlimitfsize=soft,hard\nThe largest size file that the process may create (in\nbytes).  The soft and hard limits are separated by a\ncomma.  If only a single value is specified, both the\nhard and soft limits are set.  A value of \"infinity\"\nindicates that there is no limit.  A value of \"user\"\nwill cause the invoking user's resource limit to be\npreserved.  A value of \"default\" will cause the target\nuser's default resource limit to be used on systems\nthat allow per-user resource limits to be configured.\nOnly available starting with API version 1.17.\n\nrlimitlocks=soft,hard\nThe maximum number of locks that the process may estab-\nlish, if supported by the operating system.  The soft\nand hard limits are separated by a comma.  If only a\nsingle value is specified, both the hard and soft lim-\nits are set.  A value of \"infinity\" indicates that\nthere is no limit.  A value of \"user\" will cause the\ninvoking user's resource limit to be preserved.  A\nvalue of \"default\" will cause the target user's default\nresource limit to be used on systems that allow per-\nuser resource limits to be configured.  Only available\nstarting with API version 1.17.\n\nrlimitmemlock=soft,hard\nThe maximum size that the process may lock in memory\n(in bytes), if supported by the operating system.  The\nsoft and hard limits are separated by a comma.  If only\na single value is specified, both the hard and soft\nlimits are set.  A value of \"infinity\" indicates that\nthere is no limit.  A value of \"user\" will cause the\ninvoking user's resource limit to be preserved.  A\nvalue of \"default\" will cause the target user's default\nresource limit to be used on systems that allow per-\nuser resource limits to be configured.  Only available\nstarting with API version 1.17.\n\nrlimitnofile=soft,hard\nThe maximum number of files that the process may have\nopen.  The soft and hard limits are separated by a\ncomma.  If only a single value is specified, both the\nhard and soft limits are set.  A value of \"infinity\"\nindicates that there is no limit.  A value of \"user\"\nwill cause the invoking user's resource limit to be\npreserved.  A value of \"default\" will cause the target\nuser's default resource limit to be used on systems\nthat allow per-user resource limits to be configured.\nOnly available starting with API version 1.17.\n\nrlimitnproc=soft,hard\nThe maximum number of processes that the user may run\nsimultaneously.  The soft and hard limits are separated\nby a comma.  If only a single value is specified, both\nthe hard and soft limits are set.  A value of\n\"infinity\" indicates that there is no limit.  A value\nof \"user\" will cause the invoking user's resource limit\nto be preserved.  A value of \"default\" will cause the\ntarget user's default resource limit to be used on sys-\ntems that allow per-user resource limits to be config-\nured.  Only available starting with API version 1.17.\n\nrlimitrss=soft,hard\nThe maximum size to which the process's resident set\nsize may grow (in bytes).  The soft and hard limits are\nseparated by a comma.  If only a single value is speci-\nfied, both the hard and soft limits are set.  A value\nof \"infinity\" indicates that there is no limit.  A\nvalue of \"user\" will cause the invoking user's resource\nlimit to be preserved.  A value of \"default\" will cause\nthe target user's default resource limit to be used on\nsystems that allow per-user resource limits to be con-\nfigured.  Only available starting with API version\n1.17.\n\nrlimitstack=soft,hard\nThe maximum size to which the process's stack may grow\n(in bytes).  The soft and hard limits are separated by\na comma.  If only a single value is specified, both the\nhard and soft limits are set.  A value of \"infinity\"\nindicates that there is no limit.  A value of \"user\"\nwill cause the invoking user's resource limit to be\npreserved.  A value of \"default\" will cause the target\nuser's default resource limit to be used on systems\nthat allow per-user resource limits to be configured.\nOnly available starting with API version 1.17.\n\nrunasegid=gid\nEffective group-ID to run the command as.  If not spec-\nified, the value of runasgid is used.\n\nrunaseuid=uid\nEffective user-ID to run the command as.  If not speci-\nfied, the value of runasuid is used.\n\nrunasgid=gid\nGroup-ID to run the command as.\n\nrunasgroup=string\nThe name of the group the command will run as, if it is\ndifferent from the runasuser's default group.  This\nvalue is provided for auditing purposes only, the sudo\nfront-end uses runasegid and runasgid when executing\nthe command.\n\nrunasgroups=list\nThe supplementary group vector to use for the command\nin the form of a comma-separated list of group-IDs.  If\npreservegroups is set, this option is ignored.\n\nrunasuid=uid\nUser-ID to run the command as.\n\nrunasuser=string\nThe name of the user the command will run as, which\nshould correspond to runaseuid (or runasuid if\nrunaseuid is not set).  This value is provided for au-\nditing purposes only, the sudo front-end uses\nrunaseuid and runasuid when executing the command.\n\nselinuxrole=string\nSELinux role to use when executing the command.\n\nselinuxtype=string\nSELinux type to use when executing the command.\n\nsetutmp=bool\nCreate a utmp (or utmpx) entry when a pseudo-terminal\nis allocated.  By default, the new entry will be a copy\nof the user's existing utmp entry (if any), with the\ntty, time, type, and pid fields updated.\n\nsudoedit=bool\nSet to true when in sudoedit mode.  The plugin may en-\nable sudoedit mode even if sudo was not invoked as\nsudoedit.  This allows the plugin to perform command\nsubstitution and transparently enable sudoedit when the\nuser attempts to run an editor.\n\nsudoeditcheckdir=bool\nSet to false to disable directory writability checks in\nsudoedit.  By default, sudoedit 1.8.16 and higher will\ncheck all directory components of the path to be edited\nfor writability by the invoking user.  Symbolic links\nwill not be followed in writable directories and\nsudoedit will refuse to edit a file located in a\nwritable directory.  These restrictions are not en-\nforced when sudoedit is run by root.  The\nsudoeditfollow option can be set to false to disable\nthis check.  Only available starting with API version\n1.8.\n\nsudoeditfollow=bool\nSet to true to allow sudoedit to edit files that are\nsymbolic links.  By default, sudoedit 1.8.15 and higher\nwill refuse to open a symbolic link.  The\nsudoeditfollow option can be used to restore the older\nbehavior and allow sudoedit to open symbolic links.\nOnly available starting with API version 1.8.\n\ntimeout=int\nCommand timeout.  If non-zero then when the timeout ex-\npires the command will be killed.\n\numask=octal\nThe file creation mask to use when executing the com-\nmand.  This value may be overridden by PAM or lo-\ngin.conf on some systems unless the umaskoverride op-\ntion is also set.\n\numaskoverride=bool\nForce the value specified by the umask option to over-\nride any umask set by PAM or login.conf.\n\nusepty=bool\nAllocate a pseudo-terminal to run the command in, re-\ngardless of whether or not I/O logging is in use.  By\ndefault, sudo will only run the command in a pseudo-\nterminal when an I/O log plugin is loaded.\n\nutmpuser=string\nUser name to use when constructing a new utmp (or\nutmpx) entry when setutmp is enabled.  This option can\nbe used to set the user field in the utmp entry to the\nuser the command runs as rather than the invoking user.\nIf not set, sudo will base the new entry on the invok-\ning user's existing entry.\n\nUnsupported values will be ignored.\n\nargvout\nThe NULL-terminated argument vector to pass to the execve(2)\nsystem call when executing the command.  The plugin is re-\nsponsible for allocating and populating the vector.\n\nuserenvout\nThe NULL-terminated environment vector to use when executing\nthe command.  The plugin is responsible for allocating and\npopulating the vector.\n\nerrstr\nIf the checkpolicy() function returns a value other than 1,\nthe plugin may store a message describing the failure or er-\nror in errstr.  The sudo front-end will then pass this value\nto any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is\ncalled.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nlist\nint (*list)(int argc, char * const argv[], int verbose,\nconst char *listuser, const char errstr);\n\nList available privileges for the invoking user.  Returns 1 on suc-\ncess, 0 on failure, and -1 on error.  On error, the plugin may op-\ntionally call the conversation() or pluginprintf() function with\nSUDOCONFERRORMSG to present additional error information to the\nuser.\n\nPrivileges should be output via the conversation() or\npluginprintf() function using SUDOCONVINFOMSG.\n\nThe function arguments are as follows:\n\nargc  The number of elements in argv, not counting the final NULL\npointer.\n\nargv  If non-NULL, an argument vector describing a command the user\nwishes to check against the policy in the same form as what\nwould be passed to the execve(2) system call.  If the command\nis permitted by the policy, the fully-qualified path to the\ncommand should be displayed along with any command line argu-\nments.\n\nverbose\nFlag indicating whether to list in verbose mode or not.\n\nlistuser\nThe name of a different user to list privileges for if the\npolicy allows it.  If NULL, the plugin should list the privi-\nleges of the invoking user.\n\nerrstr\nIf the list() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nvalidate\nint (*validate)(const char errstr);\n\nThe validate() function is called when sudo is run with the -v op-\ntion.  For policy plugins such as sudoers that cache authentication\ncredentials, this function will validate and cache the credentials.\n\nThe validate() function should be NULL if the plugin does not sup-\nport credential caching.\n\nReturns 1 on success, 0 on failure, and -1 on error.  On error, the\nplugin may optionally call the conversation() or pluginprintf()\nfunction with SUDOCONFERRORMSG to present additional error in-\nformation to the user.\n\nThe function arguments are as follows:\n\nerrstr\nIf the validate() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\ninvalidate\nvoid (*invalidate)(int remove);\n\nThe invalidate() function is called when sudo is run with the -k or\n-K option.  For policy plugins such as sudoers that cache authenti-\ncation credentials, this function will invalidate the credentials.\nIf the remove flag is set, the plugin may remove the credentials\ninstead of simply invalidating them.\n\nThe invalidate() function should be NULL if the plugin does not\nsupport credential caching.\n\ninitsession\nint (*initsession)(struct passwd *pwd, char userenvout[]);\n\nThe initsession() function is called before sudo sets up the exe-\ncution environment for the command.  It is run in the parent sudo\nprocess and before any user-ID or group-ID changes.  This can be\nused to perform session setup that is not supported by\ncommandinfo, such as opening the PAM session.  The close() func-\ntion can be used to tear down the session that was opened by\ninitsession.\n\nThe pwd argument points to a passwd struct for the user the command\nwill be run as if the user-ID the command will run as was found in\nthe password database, otherwise it will be NULL.\n\nThe userenvout argument points to the environment the command\nwill run in, in the form of a NULL-terminated vector of\n\"name=value\" strings.  This is the same string passed back to the\nfront-end via the Policy Plugin's userenvout parameter.  If the\ninitsession() function needs to modify the user environment, it\nshould update the pointer stored in userenvout.  The expected use\ncase is to merge the contents of the PAM environment (if any) with\nthe contents of userenvout.  NOTE: the userenvout parameter is\nonly available starting with API version 1.2.  A plugin must check\nthe API version specified by the sudo front-end before using\nuserenvout.  Failure to do so may result in a crash.\n\nReturns 1 on success, 0 on failure, and -1 on error.  On error, the\nplugin may optionally call the conversation() or pluginprintf()\nfunction with SUDOCONFERRORMSG to present additional error in-\nformation to the user.\n\nregisterhooks\nvoid (*registerhooks)(int version,\nint (*registerhook)(struct sudohook *hook));\n\nThe registerhooks() function is called by the sudo front-end to\nregister any hooks the plugin needs.  If the plugin does not sup-\nport hooks, registerhooks should be set to the NULL pointer.\n\nThe version argument describes the version of the hooks API sup-\nported by the sudo front-end.\n\nThe registerhook() function should be used to register any sup-\nported hooks the plugin needs.  It returns 0 on success, 1 if the\nhook type is not supported, and -1 if the major version in struct\nhook does not match the front-end's major hook API version.\n\nSee the Hook function API section below for more information about\nhooks.\n\nNOTE: the registerhooks() function is only available starting with\nAPI version 1.2.  If the sudo front-end doesn't support API version\n1.2 or higher, registerhooks will not be called.\n\nderegisterhooks\nvoid (*deregisterhooks)(int version,\nint (*deregisterhook)(struct sudohook *hook));\n\nThe deregisterhooks() function is called by the sudo front-end to\nderegister any hooks the plugin has registered.  If the plugin does\nnot support hooks, deregisterhooks should be set to the NULL\npointer.\n\nThe version argument describes the version of the hooks API sup-\nported by the sudo front-end.\n\nThe deregisterhook() function should be used to deregister any\nhooks that were put in place by the registerhook() function.  If\nthe plugin tries to deregister a hook that the front-end does not\nsupport, deregisterhook will return an error.\n\nSee the Hook function API section below for more information about\nhooks.\n\nNOTE: the deregisterhooks() function is only available starting\nwith API version 1.2.  If the sudo front-end doesn't support API\nversion 1.2 or higher, deregisterhooks will not be called.\n\neventalloc\nstruct sudopluginevent * (*eventalloc)(void);\n\nThe eventalloc() function is used to allocate a struct\nsudopluginevent which provides access to the main sudo event\nloop.  Unlike the other fields, the eventalloc() pointer is filled\nin by the sudo front-end, not by the plugin.\n\nSee the Event API section below for more information about events.\n\nNOTE: the eventalloc() function is only available starting with\nAPI version 1.15.  If the sudo front-end doesn't support API ver-\nsion 1.15 or higher, eventalloc() will not be set.\n\nerrstr\nIf the initsession() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any regis-\ntered audit plugins.  The string stored in errstr must remain valid\nuntil the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with API ver-\nsion 1.15.  A plugin must check the API version specified by the\nsudo front-end before using errstr.  Failure to do so may result in\na crash.\n\nPolicy Plugin Version Macros\n\n/* Plugin API version major/minor. */\n#define SUDOAPIVERSIONMAJOR 1\n#define SUDOAPIVERSIONMINOR 13\n#define SUDOAPIMKVERSION(x, y) ((x << 16) | y)\n#define SUDOAPIVERSION SUDOAPIMKVERSION(SUDOAPIVERSIONMAJOR,\\\nSUDOAPIVERSIONMINOR)\n\n/* Getters and setters for API version */\n#define SUDOAPIVERSIONGETMAJOR(v) ((v) >> 16)\n#define SUDOAPIVERSIONGETMINOR(v) ((v) & 0xffff)\n#define SUDOAPIVERSIONSETMAJOR(vp, n) do { \\\n*(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \\\n} while(0)\n#define SUDOAPIVERSIONSETMINOR(vp, n) do { \\\n*(vp) = (*(vp) & 0xffff0000) | (n); \\\n} while(0)\n\nI/O plugin API\nstruct ioplugin {\n#define SUDOIOPLUGIN 2\nunsigned int type; /* always SUDOIOPLUGIN */\nunsigned int version; /* always SUDOAPIVERSION */\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft pluginprintf, char * const settings[],\nchar * const userinfo[], char * const commandinfo[],\nint argc, char * const argv[], char * const userenv[],\nchar * const pluginoptions[], const char errstr);\nvoid (*close)(int exitstatus, int error); /* wait status or error */\nint (*showversion)(int verbose);\nint (*logttyin)(const char *buf, unsigned int len,\nconst char errstr);\nint (*logttyout)(const char *buf, unsigned int len,\nconst char errstr);\nint (*logstdin)(const char *buf, unsigned int len,\nconst char errstr);\nint (*logstdout)(const char *buf, unsigned int len,\nconst char errstr);\nint (*logstderr)(const char *buf, unsigned int len,\nconst char errstr);\nvoid (*registerhooks)(int version,\nint (*registerhook)(struct sudohook *hook));\nvoid (*deregisterhooks)(int version,\nint (*deregisterhook)(struct sudohook *hook));\nint (*changewinsize)(unsigned int lines, unsigned int cols,\nconst char errstr);\nint (*logsuspend)(int signo, const char errstr);\nstruct sudopluginevent * (*eventalloc)(void);\n};\n\nWhen an I/O plugin is loaded, sudo runs the command in a pseudo-terminal.\nThis makes it possible to log the input and output from the user's ses-\nsion.  If any of the standard input, standard output, or standard error\ndo not correspond to a tty, sudo will open a pipe to capture the I/O for\nlogging before passing it on.\n\nThe logttyin function receives the raw user input from the terminal de-\nvice (note that this will include input even when echo is disabled, such\nas when a password is read).  The logttyout function receives output\nfrom the pseudo-terminal that is suitable for replaying the user's ses-\nsion at a later time.  The logstdin(), logstdout(), and logstderr()\nfunctions are only called if the standard input, standard output, or\nstandard error respectively correspond to something other than a tty.\n\nAny of the logging functions may be set to the NULL pointer if no logging\nis to be performed.  If the open function returns 0, no I/O will be sent\nto the plugin.\n\nIf a logging function returns an error (-1), the running command will be\nterminated and all of the plugin's logging functions will be disabled.\nOther I/O logging plugins will still receive any remaining input or out-\nput that has not yet been processed.\n\nIf an input logging function rejects the data by returning 0, the command\nwill be terminated and the data will not be passed to the command, though\nit will still be sent to any other I/O logging plugins.  If an output\nlogging function rejects the data by returning 0, the command will be\nterminated and the data will not be written to the terminal, though it\nwill still be sent to any other I/O logging plugins.\n\nThe auditplugin struct has the following fields:\n\ntype  The type field should always be set to SUDOIOPLUGIN.\n\nversion\nThe version field should be set to SUDOAPIVERSION.\n\nThis allows sudo to determine the API version the plugin was built\nagainst.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft pluginprintf, char * const settings[],\nchar * const userinfo[], char * const commandinfo[],\nint argc, char * const argv[], char * const userenv[],\nchar * const pluginoptions[]);\n\nThe open() function is run before the logttyin(), logttyout(),\nlogstdin(), logstdout(), logstderr(), logsuspend(),\nchangewinsize(), or showversion() functions are called.  It is\nonly called if the version is being requested or if the policy\nplugin's checkpolicy() function has returned successfully.  It re-\nturns 1 on success, 0 on failure, -1 if a general error occurred,\nor -2 if there was a usage error.  In the latter case, sudo will\nprint a usage message before it exits.  If an error occurs, the\nplugin may optionally call the conversation() or pluginprintf()\nfunction with SUDOCONFERRORMSG to present additional error in-\nformation to the user.\n\nThe function arguments are as follows:\n\nversion\nThe version passed in by sudo allows the plugin to determine\nthe major and minor version number of the plugin API sup-\nported by sudo.\n\nconversation\nA pointer to the conversation() function that may be used by\nthe showversion() function to display version information\n(see showversion() below).  The conversation() function may\nalso be used to display additional error message to the user.\nThe conversation() function returns 0 on success and -1 on\nfailure.\n\npluginprintf\nA pointer to a printf()-style function that may be used by\nthe showversion() function to display version information\n(see showversion below).  The pluginprintf() function may\nalso be used to display additional error message to the user.\nThe pluginprintf() function returns number of characters\nprinted on success and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of\n\"name=value\" strings.  The vector is terminated by a NULL\npointer.  These settings correspond to options the user spec-\nified when running sudo.  As such, they will only be present\nwhen the corresponding option has been specified on the com-\nmand line.\n\nWhen parsing settings, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nsettings.\n\nuserinfo\nA vector of information about the user running the command in\nthe form of \"name=value\" strings.  The vector is terminated\nby a NULL pointer.\n\nWhen parsing userinfo, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\ncommandinfo\nA vector of information describing the command being run in\nthe form of \"name=value\" strings.  The vector is terminated\nby a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nargc  The number of elements in argv, not counting the final NULL\npointer.  It can be zero, when sudo is called with -V.\n\nargv  If non-NULL, an argument vector describing a command the user\nwishes to run in the same form as what would be passed to the\nexecve(2) system call.\n\nuserenv\nThe user's environment in the form of a NULL-terminated vec-\ntor of \"name=value\" strings.\n\nWhen parsing userenv, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path\nare treated as arguments to the plugin.  These arguments are\nsplit on a white space boundary and are passed to the plugin\nin the form of a NULL-terminated array of strings.  If no ar-\nguments were specified, pluginoptions will be the NULL\npointer.\n\nNOTE: the pluginoptions parameter is only available starting\nwith API version 1.2.  A plugin must check the API version\nspecified by the sudo front-end before using pluginoptions.\nFailure to do so may result in a crash.\n\nerrstr\nIf the open() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nclose\nvoid (*close)(int exitstatus, int error);\n\nThe close() function is called when sudo is finished, shortly be-\nfore it exits.\n\nThe function arguments are as follows:\n\nexitstatus\nThe command's exit status, as returned by the wait(2) system\ncall, or zero if no command was run.  The value of\nexitstatus is undefined if error is non-zero.\n\nerror\nIf the command could not be executed, this is set to the\nvalue of errno set by the execve(2) system call.  If the com-\nmand was successfully executed, the value of error is zero.\n\nshowversion\nint (*showversion)(int verbose);\n\nThe showversion() function is called by sudo when the user speci-\nfies the -V option.  The plugin may display its version information\nto the user via the conversation() or pluginprintf() function us-\ning SUDOCONVINFOMSG.\n\nReturns 1 on success, 0 on failure, -1 if a general error occurred,\nor -2 if there was a usage error, although the return value is cur-\nrently ignored.\n\nlogttyin\nint (*logttyin)(const char *buf, unsigned int len,\nconst char errstr);\n\nThe logttyin() function is called whenever data can be read from\nthe user but before it is passed to the running command.  This al-\nlows the plugin to reject data if it chooses to (for instance if\nthe input contains banned content).  Returns 1 if the data should\nbe passed to the command, 0 if the data is rejected (which will\nterminate the running command), or -1 if an error occurred.\n\nThe function arguments are as follows:\n\nbuf   The buffer containing user input.\n\nlen   The length of buf in bytes.\n\nerrstr\nIf the logttyin() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nlogttyout\nint (*logttyout)(const char *buf, unsigned int len,\nconst char errstr);\n\nThe logttyout() function is called whenever data can be read from\nthe command but before it is written to the user's terminal.  This\nallows the plugin to reject data if it chooses to (for instance if\nthe output contains banned content).  Returns 1 if the data should\nbe passed to the user, 0 if the data is rejected (which will termi-\nnate the running command), or -1 if an error occurred.\n\nThe function arguments are as follows:\n\nbuf   The buffer containing command output.\n\nlen   The length of buf in bytes.\n\nerrstr\nIf the logttyout() function returns a value other than 1,\nthe plugin may store a message describing the failure or er-\nror in errstr.  The sudo front-end will then pass this value\nto any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is\ncalled.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nlogstdin\nint (*logstdin)(const char *buf, unsigned int len,\nconst char errstr);\n\nThe logstdin() function is only used if the standard input does\nnot correspond to a tty device.  It is called whenever data can be\nread from the standard input but before it is passed to the running\ncommand.  This allows the plugin to reject data if it chooses to\n(for instance if the input contains banned content).  Returns 1 if\nthe data should be passed to the command, 0 if the data is rejected\n(which will terminate the running command), or -1 if an error oc-\ncurred.\n\nThe function arguments are as follows:\n\nbuf   The buffer containing user input.\n\nlen   The length of buf in bytes.\n\nerrstr\nIf the logstdin() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nlogstdout\nint (*logstdout)(const char *buf, unsigned int len,\nconst char errstr);\n\nThe logstdout() function is only used if the standard output does\nnot correspond to a tty device.  It is called whenever data can be\nread from the command but before it is written to the standard out-\nput.  This allows the plugin to reject data if it chooses to (for\ninstance if the output contains banned content).  Returns 1 if the\ndata should be passed to the user, 0 if the data is rejected (which\nwill terminate the running command), or -1 if an error occurred.\n\nThe function arguments are as follows:\n\nbuf   The buffer containing command output.\n\nlen   The length of buf in bytes.\n\nerrstr\nIf the logstdout() function returns a value other than 1,\nthe plugin may store a message describing the failure or er-\nror in errstr.  The sudo front-end will then pass this value\nto any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is\ncalled.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nlogstderr\nint (*logstderr)(const char *buf, unsigned int len,\nconst char errstr);\n\nThe logstderr() function is only used if the standard error does\nnot correspond to a tty device.  It is called whenever data can be\nread from the command but before it is written to the standard er-\nror.  This allows the plugin to reject data if it chooses to (for\ninstance if the output contains banned content).  Returns 1 if the\ndata should be passed to the user, 0 if the data is rejected (which\nwill terminate the running command), or -1 if an error occurred.\n\nThe function arguments are as follows:\n\nbuf   The buffer containing command output.\n\nlen   The length of buf in bytes.\n\nerrstr\nIf the logstderr() function returns a value other than 1,\nthe plugin may store a message describing the failure or er-\nror in errstr.  The sudo front-end will then pass this value\nto any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is\ncalled.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nregisterhooks\nSee the Policy plugin API section for a description of\nregisterhooks.\n\nderegisterhooks\nSee the Policy plugin API section for a description of\nderegisterhooks.\n\nchangewinsize\nint (*changewinsize)(unsigned int lines, unsigned int cols,\nconst char errstr);\n\nThe changewinsize() function is called whenever the window size of\nthe terminal changes from the initial values specified in the\nuserinfo list.  Returns -1 if an error occurred, in which case no\nfurther calls to changewinsize() will be made,\n\nThe function arguments are as follows:\n\nlines\nThe number of lines (rows) in the re-sized terminal.\n\ncols  The number of columns in the re-sized terminal.\n\nerrstr\nIf the changewinsize() function returns a value other than\n1, the plugin may store a message describing the failure or\nerror in errstr.  The sudo front-end will then pass this\nvalue to any registered audit plugins.  The string stored in\nerrstr must remain valid until the plugin's close() function\nis called.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\nlogsuspend\nint (*logsuspend)(int signo, const char errstr);\n\nThe logsuspend() function is called whenever a command is sus-\npended or resumed.  Logging this information makes it possible to\nskip the period of time when the command was suspended during play-\nback of a session.  Returns -1 if an error occurred, in which case\nno further calls to logsuspend() will be made,\n\nThe function arguments are as follows:\n\nsigno\nThe signal that caused the command to be suspended, or\nSIGCONT if the command was resumed.\n\nerrstr\nIf the logsuspend() function returns a value other than 1,\nthe plugin may store a message describing the failure or er-\nror in errstr.  The sudo front-end will then pass this value\nto any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is\ncalled.\n\nNOTE: the errstr parameter is only available starting with\nAPI version 1.15.  A plugin must check the API version speci-\nfied by the sudo front-end before using errstr.  Failure to\ndo so may result in a crash.\n\neventalloc\nstruct sudopluginevent * (*eventalloc)(void);\n\nThe eventalloc() function is used to allocate a struct\nsudopluginevent which provides access to the main sudo\nevent loop.  Unlike the other fields, the eventalloc()\npointer is filled in by the sudo front-end, not by the\nplugin.\n\nSee the Event API section below for more information about\nevents.\n\nNOTE: the eventalloc() function is only available starting\nwith API version 1.15.  If the sudo front-end doesn't support\nAPI version 1.15 or higher, eventalloc() will not be set.\n\nI/O Plugin Version Macros\n\nSame as for the Policy plugin API.\n\nAudit plugin API\n/* Audit plugin close function status types. */\n#define SUDOPLUGINNOSTATUS           0\n#define SUDOPLUGINWAITSTATUS         1\n#define SUDOPLUGINEXECERROR          2\n#define SUDOPLUGINSUDOERROR          3\n\n#define SUDOAUDITPLUGIN 3\nstruct auditplugin {\nunsigned int type; /* always SUDOAUDITPLUGIN */\nunsigned int version; /* always SUDOAPIVERSION */\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudoprintf, char * const settings[],\nchar * const userinfo[], int submitoptind,\nchar * const submitargv[], char * const submitenvp[],\nchar * const pluginoptions[], const char errstr);\nvoid (*close)(int statustype, int status);\nint (*accept)(const char *pluginname,\nunsigned int plugintype, char * const commandinfo[],\nchar * const runargv[], char * const runenvp[],\nconst char errstr);\nint (*reject)(const char *pluginname, unsigned int plugintype,\nconst char *auditmsg, char * const commandinfo[],\nconst char errstr);\nint (*error)(const char *pluginname, unsigned int plugintype,\nconst char *auditmsg, char * const commandinfo[],\nconst char errstr);\nint (*showversion)(int verbose);\nvoid (*registerhooks)(int version,\nint (*registerhook)(struct sudohook *hook));\nvoid (*deregisterhooks)(int version,\nint (*deregisterhook)(struct sudohook *hook));\nstruct sudopluginevent * (*eventalloc)(void);\n}\n\nAn audit plugin can be used to log successful and unsuccessful attempts\nto run sudo independent of the policy or any I/O plugins.  Multiple audit\nplugins may be specified in sudo.conf(5).\n\nThe auditplugin struct has the following fields:\n\ntype  The type field should always be set to SUDOAUDITPLUGIN.\n\nversion\nThe version field should be set to SUDOAPIVERSION.\n\nThis allows sudo to determine the API version the plugin was built\nagainst.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudoprintf, char * const settings[],\nchar * const userinfo[], int submitoptind,\nchar * const submitargv[], char * const submitenvp[],\nchar * const pluginoptions[], const char errstr);\n\nThe audit open() function is run before any other sudo plugin API\nfunctions.  This makes it possible to audit failures in the other\nplugins.  It returns 1 on success, 0 on failure, -1 if a general\nerror occurred, or -2 if there was a usage error.  In the latter\ncase, sudo will print a usage message before it exits.  If an error\noccurs, the plugin may optionally call the conversation() or\npluginprintf() function with SUDOCONFERRORMSG to present addi-\ntional error information to the user.\n\nThe function arguments are as follows:\n\nversion\nThe version passed in by sudo allows the plugin to determine\nthe major and minor version number of the plugin API sup-\nported by sudo.\n\nconversation\nA pointer to the conversation() function that may be used by\nthe showversion() function to display version information\n(see showversion() below).  The conversation() function may\nalso be used to display additional error message to the user.\nThe conversation() function returns 0 on success, and -1 on\nfailure.\n\npluginprintf\nA pointer to a printf()-style function that may be used by\nthe showversion() function to display version information\n(see showversion below).  The pluginprintf() function may\nalso be used to display additional error message to the user.\nThe pluginprintf() function returns number of characters\nprinted on success and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of\n\"name=value\" strings.  The vector is terminated by a NULL\npointer.  These settings correspond to options the user spec-\nified when running sudo.  As such, they will only be present\nwhen the corresponding option has been specified on the com-\nmand line.\n\nWhen parsing settings, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nsettings.\n\nuserinfo\nA vector of information about the user running the command in\nthe form of \"name=value\" strings.  The vector is terminated\nby a NULL pointer.\n\nWhen parsing userinfo, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nsubmitoptind\nThe index into submitargv that corresponds to the first en-\ntry that is not a command line option.  If submitargv only\nconsists of options, which may be the case with the -l or -v\noptions, submitargv[submitoptind] will evaluate to the NULL\npointer.\n\nsubmitargv\nThe argument vector sudo was invoked with, including all com-\nmand line options.  The submitoptind argument can be used to\ndetermine the end of the command line options.\n\nsubmitenvp\nThe invoking user's environment in the form of a\nNULL-terminated vector of \"name=value\" strings.\n\nWhen parsing submitenvp, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path\nare treated as arguments to the plugin.  These arguments are\nsplit on a white space boundary and are passed to the plugin\nin the form of a NULL-terminated array of strings.  If no ar-\nguments were specified, pluginoptions will be the NULL\npointer.\n\nerrstr\nIf the open() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nclose\nvoid (*close)(int statustype, int status);\n\nThe close() function is called when sudo is finished, shortly be-\nfore it exits.\n\nThe function arguments are as follows:\n\nstatustype\nThe type of status being passed.  One of\nSUDOPLUGINNOSTATUS, SUDOPLUGINWAITSTATUS,\nSUDOPLUGINEXECERROR or SUDOPLUGINSUDOERROR.\n\nstatus\nDepending on the value of statustype, this value is either\nignored, the command's exit status as returned by the wait(2)\nsystem call, the value of errno set by the execve(2) system\ncall, or the value of errno resulting from an error in the\nsudo front-end.\n\naccept\nint (*accept)(const char *pluginname, unsigned int plugintype,\nchar * const commandinfo[], char * const runargv[],\nchar * const runenvp[], const char errstr);\n\nThe accept() function is called when a command or action is ac-\ncepted by a policy or approval plugin.  The function arguments are\nas follows:\n\npluginname\nThe name of the plugin that accepted the command or \"sudo\"\nfor the sudo front-end.\n\nplugintype\nThe type of plugin that accepted the command, currently ei-\nther SUDOPOLICYPLUGIN, SUDOPOLICYAPPROVAL, or\nSUDOFRONTEND.  The accept() function is called multiple\ntimes--once for each policy or approval plugin that succeeds\nand once for the sudo front-end.  When called on behalf of\nthe sudo front-end, commandinfo may include information from\nan I/O logging plugin as well.\n\nTypically, an audit plugin is interested in either the accept\nstatus from the sudo front-end or from the various policy and\napproval plugins, but not both.  It is possible for the pol-\nicy plugin to accept a command that is later rejected by an\napproval plugin, in which case the audit plugin's accept()\nand reject() functions will both be called.\n\ncommandinfo\nAn optional vector of information describing the command be-\ning run in the form of \"name=value\" strings.  The vector is\nterminated by a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nrunargv\nA NULL-terminated argument vector describing a command that\nwill be run in the same form as what would be passed to the\nexecve(2) system call.\n\nrunenvp\nThe environment the command will be run with in the form of a\nNULL-terminated vector of \"name=value\" strings.\n\nWhen parsing runenvp, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nerrstr\nIf the accept() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nreject\nint (*reject)(const char *pluginname, unsigned int plugintype,\nconst char *auditmsg, char * const commandinfo[],\nconst char errstr);\n\nThe reject() function is called when a command or action is re-\njected by a plugin.  The function arguments are as follows:\n\npluginname\nThe name of the plugin that rejected the command.\n\nplugintype\nThe type of plugin that rejected the command, currently ei-\nther SUDOPOLICYPLUGIN, SUDOAPPROVALPLUGIN, or\nSUDOIOPLUGIN.\n\nUnlike the accept() function, the reject() function is not\ncalled on behalf of the sudo front-end.\n\nauditmsg\nAn optional string describing the reason the command was re-\njected by the plugin.  If the plugin did not provide a rea-\nson, auditmsg will be the NULL pointer.\n\ncommandinfo\nAn optional vector of information describing the command be-\ning run in the form of \"name=value\" strings.  The vector is\nterminated by a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nerrstr\nIf the reject() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nerror\nint (*error)(const char *pluginname, unsigned int plugintype,\nconst char *auditmsg, char * const commandinfo[],\nconst char errstr);\n\nThe error() function is called when a plugin or the sudo front-end\nreturns an error.  The function arguments are as follows:\n\npluginname\nThe name of the plugin that generated the error or \"sudo\" for\nthe sudo front-end.\n\nplugintype\nThe type of plugin that generated the error, or\nSUDOFRONTEND for the sudo front-end.\n\nauditmsg\nAn optional string describing the plugin error.  If the\nplugin did not provide a description, auditmsg will be the\nNULL pointer.\n\ncommandinfo\nAn optional vector of information describing the command be-\ning run in the form of \"name=value\" strings.  The vector is\nterminated by a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nerrstr\nIf the error() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nshowversion\nint (*showversion)(int verbose);\n\nThe showversion() function is called by sudo when the user speci-\nfies the -V option.  The plugin may display its version information\nto the user via the conversation() or pluginprintf() function us-\ning SUDOCONVINFOMSG.  If the user requests detailed version in-\nformation, the verbose flag will be set.\n\nReturns 1 on success, 0 on failure, -1 if a general error occurred,\nor -2 if there was a usage error, although the return value is cur-\nrently ignored.\n\nregisterhooks\nSee the Policy plugin API section for a description of\nregisterhooks.\n\nderegisterhooks\nSee the Policy plugin API section for a description of\nderegisterhooks.\n\neventalloc\nstruct sudopluginevent * (*eventalloc)(void);\n\nThe eventalloc() function is used to allocate a struct\nsudopluginevent which provides access to the main sudo event\nloop.  Unlike the other fields, the eventalloc() pointer is filled\nin by the sudo front-end, not by the plugin.\n\nSee the Event API section below for more information about events.\n\nNOTE: the eventalloc() function is only available starting with\nAPI version 1.17.  If the sudo front-end doesn't support API ver-\nsion 1.17 or higher, eventalloc() will not be set.\n\nApproval plugin API\nstruct approvalplugin {\n#define SUDOAPPROVALPLUGIN 4\nunsigned int type; /* always SUDOAPPROVALPLUGIN */\nunsigned int version; /* always SUDOAPIVERSION */\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudoprintf, char * const settings[],\nchar * const userinfo[], int submitoptind,\nchar * const submitargv[], char * const submitenvp[],\nchar * const pluginoptions[], const char errstr);\nvoid (*close)(void);\nint (*check)(char * const commandinfo[], char * const runargv[],\nchar * const runenvp[], const char errstr);\nint (*showversion)(int verbose);\n};\n\nAn approval plugin can be used to apply extra constraints after a command\nhas been accepted by the policy plugin.  Unlike the other plugin types,\nit does not remain open until the command completes.  The plugin is\nopened before a call to check() or showversion() and closed shortly\nthereafter (audit plugin functions must be called before the plugin is\nclosed).  Multiple approval plugins may be specified in sudo.conf(5).\n\nThe approvalplugin struct has the following fields:\n\ntype  The type field should always be set to SUDOAPPROVALPLUGIN.\n\nversion\nThe version field should be set to SUDOAPIVERSION.\n\nThis allows sudo to determine the API version the plugin was built\nagainst.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudoprintf, char * const settings[],\nchar * const userinfo[], int submitoptind,\nchar * const submitargv[], char * const submitenvp[],\nchar * const pluginoptions[], const char errstr);\n\nThe approval open() function is run immediately before a call to\nthe plugin's check() or showversion() functions.  It is only\ncalled if the version is being requested or if the policy plugin's\ncheckpolicy() function has returned successfully.  It returns 1 on\nsuccess, 0 on failure, -1 if a general error occurred, or -2 if\nthere was a usage error.  In the latter case, sudo will print a us-\nage message before it exits.  If an error occurs, the plugin may\noptionally call the conversation() or pluginprintf() function with\nSUDOCONFERRORMSG to present additional error information to the\nuser.\n\nThe function arguments are as follows:\n\nversion\nThe version passed in by sudo allows the plugin to determine\nthe major and minor version number of the plugin API sup-\nported by sudo.\n\nconversation\nA pointer to the conversation() function that can be used by\nthe plugin to interact with the user (see Conversation API\nfor details).  Returns 0 on success and -1 on failure.\n\npluginprintf\nA pointer to a printf()-style function that may be used to\ndisplay informational or error messages (see Conversation API\nfor details).  Returns the number of characters printed on\nsuccess and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of\n\"name=value\" strings.  The vector is terminated by a NULL\npointer.  These settings correspond to options the user spec-\nified when running sudo.  As such, they will only be present\nwhen the corresponding option has been specified on the com-\nmand line.\n\nWhen parsing settings, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nsettings.\n\nuserinfo\nA vector of information about the user running the command in\nthe form of \"name=value\" strings.  The vector is terminated\nby a NULL pointer.\n\nWhen parsing userinfo, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nsubmitoptind\nThe index into submitargv that corresponds to the first en-\ntry that is not a command line option.  If submitargv only\nconsists of options, which may be the case with the -l or -v\noptions, submitargv[submitoptind] will evaluate to the NULL\npointer.\n\nsubmitargv\nThe argument vector sudo was invoked with, including all com-\nmand line options.  The submitoptind argument can be used to\ndetermine the end of the command line options.\n\nsubmitenvp\nThe invoking user's environment in the form of a\nNULL-terminated vector of \"name=value\" strings.\n\nWhen parsing submitenvp, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path\nare treated as arguments to the plugin.  These arguments are\nsplit on a white space boundary and are passed to the plugin\nin the form of a NULL-terminated array of strings.  If no ar-\nguments were specified, pluginoptions will be the NULL\npointer.\n\nerrstr\nIf the open() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nclose\nvoid (*close)(void);\n\nThe close() function is called after the approval plugin's check()\nor showversion() functions have been called.  It takes no argu-\nments.  The close() function is typically used to perform plugin-\nspecific cleanup, such as the freeing of memory objects allocated\nby the plugin.  If the plugin does not need to perform any cleanup,\nclose() may be set to the NULL pointer.\n\ncheck\nint (*check)(char * const commandinfo[], char * const runargv[],\nchar * const runenvp[], const char errstr);\n\nThe approval check() function is run after the policy plugin\ncheckpolicy() function and before any I/O logging plugins.  If\nmultiple approval plugins are loaded, they must all succeed for the\ncommand to be allowed.  It returns 1 on success, 0 on failure, -1\nif a general error occurred, or -2 if there was a usage error.  In\nthe latter case, sudo will print a usage message before it exits.\nIf an error occurs, the plugin may optionally call the\nconversation() or pluginprintf() function with SUDOCONFERRORMSG\nto present additional error information to the user.\n\nThe function arguments are as follows:\n\ncommandinfo\nA vector of information describing the command being run in\nthe form of \"name=value\" strings.  The vector is terminated\nby a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the\nfirst equal sign ('=') since the name field will never in-\nclude one itself but the value might.\n\nSee the Policy plugin API section for a list of all possible\nstrings.\n\nrunargv\nA NULL-terminated argument vector describing a command that\nwill be run in the same form as what would be passed to the\nexecve(2) system call.\n\nrunenvp\nThe environment the command will be run with in the form of a\nNULL-terminated vector of \"name=value\" strings.\n\nWhen parsing runenvp, the plugin should split on the first\nequal sign ('=') since the name field will never include one\nitself but the value might.\n\nerrstr\nIf the open() function returns a value other than 1, the\nplugin may store a message describing the failure or error in\nerrstr.  The sudo front-end will then pass this value to any\nregistered audit plugins.  The string stored in errstr must\nremain valid until the plugin's close() function is called.\n\nshowversion\nint (*showversion)(int verbose);\n\nThe showversion() function is called by sudo when the user speci-\nfies the -V option.  The plugin may display its version information\nto the user via the conversation() or pluginprintf() function us-\ning SUDOCONVINFOMSG.  If the user requests detailed version in-\nformation, the verbose flag will be set.\n\nReturns 1 on success, 0 on failure, -1 if a general error occurred,\nor -2 if there was a usage error, although the return value is cur-\nrently ignored.\n\nSignal handlers\nThe sudo front-end installs default signal handlers to trap common sig-\nnals while the plugin functions are run.  The following signals are\ntrapped by default before the command is executed:\n\no  SIGALRM\no  SIGHUP\no  SIGINT\no  SIGPIPE\no  SIGQUIT\no  SIGTERM\no  SIGTSTP\no  SIGUSR1\no  SIGUSR2\n\nIf a fatal signal is received before the command is executed, sudo will\ncall the plugin's close() function with an exit status of 128 plus the\nvalue of the signal that was received.  This allows for consistent log-\nging of commands killed by a signal for plugins that log such information\nin their close() function.  An exception to this is SIGPIPE, which is ig-\nnored until the command is executed.\n\nA plugin may temporarily install its own signal handlers but must restore\nthe original handler before the plugin function returns.\n\nHook function API\nBeginning with plugin API version 1.2, it is possible to install hooks\nfor certain functions called by the sudo front-end.\n\nCurrently, the only supported hooks relate to the handling of environment\nvariables.  Hooks can be used to intercept attempts to get, set, or re-\nmove environment variables so that these changes can be reflected in the\nversion of the environment that is used to execute a command.  A future\nversion of the API will support hooking internal sudo front-end functions\nas well.\n\nHook structure\n\nHooks in sudo are described by the following structure:\n\ntypedef int (*sudohookfnt)();\n\nstruct sudohook {\nunsigned int hookversion;\nunsigned int hooktype;\nsudohookfnt hookfn;\nvoid *closure;\n};\n\nThe sudohook structure has the following fields:\n\nhookversion\nThe hookversion field should be set to SUDOHOOKVERSION.\n\nhooktype\nThe hooktype field may be one of the following supported hook\ntypes:\n\nSUDOHOOKSETENV\nThe C library setenv(3) function.  Any registered hooks will\nrun before the C library implementation.  The hookfn field\nshould be a function that matches the following typedef:\n\ntypedef int (*sudohookfnsetenvt)(const char *name,\nconst char *value, int overwrite, void *closure);\n\nIf the registered hook does not match the typedef the results\nare unspecified.\n\nSUDOHOOKUNSETENV\nThe C library unsetenv(3) function.  Any registered hooks\nwill run before the C library implementation.  The hookfn\nfield should be a function that matches the following type-\ndef:\n\ntypedef int (*sudohookfnunsetenvt)(const char *name,\nvoid *closure);\n\nSUDOHOOKGETENV\nThe C library getenv(3) function.  Any registered hooks will\nrun before the C library implementation.  The hookfn field\nshould be a function that matches the following typedef:\n\ntypedef int (*sudohookfngetenvt)(const char *name,\nchar value, void *closure);\n\nIf the registered hook does not match the typedef the results\nare unspecified.\n\nSUDOHOOKPUTENV\nThe C library putenv(3) function.  Any registered hooks will\nrun before the C library implementation.  The hookfn field\nshould be a function that matches the following typedef:\n\ntypedef int (*sudohookfnputenvt)(char *string,\nvoid *closure);\n\nIf the registered hook does not match the typedef the results\nare unspecified.\n\nhookfn\nsudohookfnt hookfn;\n\nThe hookfn field should be set to the plugin's hook implementa-\ntion.  The actual function arguments will vary depending on the\nhooktype (see hooktype above).  In all cases, the closure field\nof struct sudohook is passed as the last function parameter.  This\ncan be used to pass arbitrary data to the plugin's hook implementa-\ntion.\n\nThe function return value may be one of the following:\n\nSUDOHOOKRETERROR\nThe hook function encountered an error.\n\nSUDOHOOKRETNEXT\nThe hook completed without error, go on to the next hook (in-\ncluding the system implementation if applicable).  For exam-\nple, a getenv(3) hook might return SUDOHOOKRETNEXT if the\nspecified variable was not found in the private copy of the\nenvironment.\n\nSUDOHOOKRETSTOP\nThe hook completed without error, stop processing hooks for\nthis invocation.  This can be used to replace the system im-\nplementation.  For example, a setenv hook that operates on a\nprivate copy of the environment but leaves environ unchanged.\n\nNote that it is very easy to create an infinite loop when hooking C li-\nbrary functions.  For example, a getenv(3) hook that calls the\nsnprintf(3) function may create a loop if the snprintf(3) implementation\ncalls getenv(3) to check the locale.  To prevent this, you may wish to\nuse a static variable in the hook function to guard against nested calls.\nFor example:\n\nstatic int inprogress = 0; /* avoid recursion */\nif (inprogress)\nreturn SUDOHOOKRETNEXT;\ninprogress = 1;\n...\ninprogress = 0;\nreturn SUDOHOOKRETSTOP;\n\nHook API Version Macros\n\n/* Hook API version major/minor */\n#define SUDOHOOKVERSIONMAJOR 1\n#define SUDOHOOKVERSIONMINOR 0\n#define SUDOHOOKVERSION SUDOAPIMKVERSION(SUDOHOOKVERSIONMAJOR,\\\nSUDOHOOKVERSIONMINOR)\n\nFor getters and setters see the Policy plugin API.\n\nEvent API\nWhen sudo runs a command, it uses an event loop to service signals and\nI/O.  Events may be triggered based on time, a file or socket descriptor\nbecoming ready, or due to receipt of a signal.  Starting with API version\n1.15, it is possible for a plugin to participate in this event loop by\ncalling the eventalloc() function.\n\nEvent structure\n\nEvents are described by the following structure:\n\ntypedef void (*sudopluginevcallbackt)(int fd, int what, void *closure);\n\nstruct sudopluginevent {\nint (*set)(struct sudopluginevent *pev, int fd, int events,\nsudopluginevcallbackt callback, void *closure);\nint (*add)(struct sudopluginevent *pev, struct timespec *timeout);\nint (*del)(struct sudopluginevent *pev);\nint (*pending)(struct sudopluginevent *pev, int events,\nstruct timespec *ts);\nint (*fd)(struct sudopluginevent *pev);\nvoid (*setbase)(struct sudopluginevent *pev, void *base);\nvoid (*loopbreak)(struct sudopluginevent *pev);\nvoid (*free)(struct sudopluginevent *pev);\n};\n\nThe sudopluginevent struct contains the following function pointers:\n\nset()\nint (*set)(struct sudopluginevent *pev, int fd, int events,\nsudopluginevcallbackt callback, void *closure);\n\nThe set() function takes the following arguments:\n\nstruct sudopluginevent *pev\nA pointer to the struct sudopluginevent itself.\n\nfd    The file or socket descriptor for I/O-based events or the\nsignal number for signal events.  For time-based events, fd\nmust be -1.\n\nevents\nThe following values determine what will trigger the event\ncallback:\n\nSUDOPLUGINEVTIMEOUT\ncallback is run after the specified timeout expires\n\nSUDOPLUGINEVREAD\ncallback is run when the file descriptor is readable\n\nSUDOPLUGINEVWRITE\ncallback is run when the file descriptor is writable\n\nSUDOPLUGINEVPERSIST\nevent is persistent and remains enabled until explic-\nitly deleted\n\nSUDOPLUGINEVSIGNAL\ncallback is run when the specified signal is received\n\nThe SUDOPLUGINEVPERSIST flag may be ORed with any of the\nevent types.  It is also possible to OR SUDOPLUGINEVREAD\nand SUDOPLUGINEVWRITE together to run the callback when a\ndescriptor is ready to be either read from or written to.\nAll other event values are mutually exclusive.\n\nsudopluginevcallbackt callback\ntypedef void (*sudopluginevcallbackt)(int fd, int what,\nvoid *closure);\n\nThe function to call when an event is triggered.  The\ncallback() function is run with the following arguments:\n\nfd    The file or socket descriptor for I/O-based events or\nthe signal number for signal events.\n\nwhat  The event type that triggered that callback.  For\nevents that have multiple event types (for example\nSUDOPLUGINEVREAD and SUDOPLUGINEVWRITE) or have\nan associated timeout, what can be used to determine\nwhy the callback was run.\n\nclosure\nThe generic pointer that was specified in the set()\nfunction.\n\nclosure\nA generic pointer that will be passed to the callback func-\ntion.\n\nThe set() function returns 1 on success, and -1 if a error oc-\ncurred.\n\nadd()\nint (*add)(struct sudopluginevent *pev, struct timespec *timeout);\n\nThe add() function adds the event pev to sudo's event loop.  The\nevent must have previously been initialized via the set() function.\nIf the timeout argument is not NULL, it should specify a (relative)\ntimeout after which the event will be triggered if the main event\ncriteria has not been met.  This is often used to implement an I/O\ntimeout where the event will fire if a descriptor is not ready\nwithin a certain time period.  If the event is already present in\nthe event loop, its timeout will be adjusted to match the new\nvalue, if any.\n\nThe add() function returns 1 on success, and -1 if a error oc-\ncurred.\n\ndel()\nint (*del)(struct sudopluginevent *pev);\n\nThe del() function deletes the event pev from sudo's event loop.\nDeleted events can be added back via the add() function.\n\nThe del() function returns 1 on success, and -1 if a error oc-\ncurred.\n\npending()\nint (*pending)(struct sudopluginevent *pev, int events,\nstruct timespec *ts);\n\nThe pending() function can be used to determine whether one or more\nevents is pending.  The events argument specifies which events to\ncheck for.  See the set() function for a list of valid event types.\nIf SUDOPLUGINEVTIMEOUT is specified in events, the event has an\nassociated timeout and the ts pointer is non-NULL, it will be\nfilled in with the remaining time.\n\nfd()\nint (*fd)(struct sudopluginevent *pev);\n\nThe fd() function returns the descriptor or signal number associ-\nated with the event pev.\n\nsetbase()\nvoid (*setbase)(struct sudopluginevent *pev, void *base);\n\nThe setbase() function sets the underlying event base for pev to\nthe specified value.  This can be used to move an event created via\neventalloc() to a new event loop allocated by sudo's event subsys-\ntem.  If base is NULL, pev's event base is reset to the default\nvalue, which corresponds to sudo's main event loop.  Using this\nfunction requires linking the plugin with the sudoutil library.\nIt is unlikely to be used outside of the sudoers plugin.\n\nloopbreak()\nvoid (*loopbreak)(struct sudopluginevent *pev);\n\nThe loopbreak() function causes sudo's event loop to exit immedi-\nately and the running command to be terminated.\n\nfree()\nvoid (*free)(struct sudopluginevent *pev);\n\nThe free() function deletes the event pev from the event loop and\nfrees the memory associated with it.\n\nRemote command execution\nThe sudo front-end does not support running remote commands.  However,\nstarting with sudo 1.8.8, the -h option may be used to specify a remote\nhost that is passed to the policy plugin.  A plugin may also accept a\nrunasuser in the form of \"user@hostname\" which will work with older ver-\nsions of sudo.  It is anticipated that remote commands will be supported\nby executing a \"helper\" program.  The policy plugin should setup the exe-\ncution environment such that the sudo front-end will run the helper\nwhich, in turn, will connect to the remote host and run the command.\n\nFor example, the policy plugin could utilize ssh to perform remote com-\nmand execution.  The helper program would be responsible for running ssh\nwith the proper options to use a private key or certificate that the re-\nmote host will accept and run a program on the remote host that would\nsetup the execution environment accordingly.\n\nNote that remote sudoedit functionality must be handled by the policy\nplugin, not sudo itself as the front-end has no knowledge that a remote\ncommand is being executed.  This may be addressed in a future revision of\nthe plugin API.\n\nConversation API\nIf the plugin needs to interact with the user, it may do so via the\nconversation() function.  A plugin should not attempt to read directly\nfrom the standard input or the user's tty (neither of which are guaran-\nteed to exist).  The caller must include a trailing newline in msg if one\nis to be printed.\n\nA printf()-style function is also available that can be used to display\ninformational or error messages to the user, which is usually more conve-\nnient for simple messages where no use input is required.\n\nConversation function structures\n\nThe conversation function takes as arguments pointers to the following\nstructures:\n\nstruct sudoconvmessage {\n#define SUDOCONVPROMPTECHOOFF  0x0001 /* do not echo user input */\n#define SUDOCONVPROMPTECHOON   0x0002 /* echo user input */\n#define SUDOCONVERRORMSG        0x0003 /* error message */\n#define SUDOCONVINFOMSG         0x0004 /* informational message */\n#define SUDOCONVPROMPTMASK      0x0005 /* mask user input */\n#define SUDOCONVPROMPTECHOOK   0x1000 /* flag: allow echo if no tty */\n#define SUDOCONVPREFERTTY       0x2000 /* flag: use tty if possible */\nint msgtype;\nint timeout;\nconst char *msg;\n};\n\n#define SUDOCONVREPLMAX      1023\n\nstruct sudoconvreply {\nchar *reply;\n};\n\ntypedef int (*sudoconvcallbackfnt)(int signo, void *closure);\nstruct sudoconvcallback {\nunsigned int version;\nvoid *closure;\nsudoconvcallbackfnt onsuspend;\nsudoconvcallbackfnt onresume;\n};\n\nPointers to the conversation() and printf()-style functions are passed in\nto the plugin's open() function when the plugin is initialized.  The fol-\nlowing type definitions can be used in the declaration of the open()\nfunction:\n\ntypedef int (*sudoconvt)(int nummsgs,\nconst struct sudoconvmessage msgs[],\nstruct sudoconvreply replies[], struct sudoconvcallback *callback);\n\ntypedef int (*sudoprintft)(int msgtype, const char *fmt, ...);\n\nTo use the conversation() function, the plugin must pass an array of\nsudoconvmessage and sudoconvreply structures.  There must be a struct\nsudoconvmessage and struct sudoconvreply for each message in the con-\nversation, that is, both arrays must have the same number of elements.\nEach struct sudoconvreply must have its reply member initialized to\nNULL.  The struct sudoconvcallback pointer, if not NULL, should contain\nfunction pointers to be called when the sudo process is suspended and/or\nresumed during conversation input.  The onsuspend and onresume func-\ntions are called with the signal that caused sudo to be suspended and the\nclosure pointer from the struct sudoconvcallback.  These functions\nshould return 0 on success and -1 on error.  On error, the conversation\nwill end and the conversation function will return a value of -1.  The\nintended use is to allow the plugin to release resources, such as locks,\nthat should not be held indefinitely while suspended and then reacquire\nthem when the process is resumed.  Note that the functions are not actu-\nally invoked from within a signal handler.\n\nThe msgtype must be set to one of the following values:\n\nSUDOCONVPROMPTECHOOFF\nPrompt the user for input with echo disabled; this is generally\nused for passwords.  The reply will be stored in the replies array,\nand it will never be NULL.\n\nSUDOCONVPROMPTECHOON\nPrompt the user for input with echo enabled.  The reply will be\nstored in the replies array, and it will never be NULL.\n\nSUDOCONVERRORMSG\nDisplay an error message.  The message is written to the standard\nerror unless the SUDOCONVPREFERTTY flag is set, in which case it\nis written to the user's terminal if possible.\n\nSUDOCONVINFOMSG\nDisplay a message.  The message is written to the standard output\nunless the SUDOCONVPREFERTTY flag is set, in which case it is\nwritten to the user's terminal if possible.\n\nSUDOCONVPROMPTMASK\nPrompt the user for input but echo an asterisk character for each\ncharacter read.  The reply will be stored in the replies array, and\nit will never be NULL.  This can be used to provide visual feedback\nto the user while reading sensitive information that should not be\ndisplayed.\n\nIn addition to the above values, the following flag bits may also be set:\n\nSUDOCONVPROMPTECHOOK\nAllow input to be read when echo cannot be disabled when the mes-\nsage type is SUDOCONVPROMPTECHOOFF or SUDOCONVPROMPTMASK.\nBy default, sudo will refuse to read input if the echo cannot be\ndisabled for those message types.\n\nSUDOCONVPREFERTTY\nWhen displaying a message via SUDOCONVERRORMSG or\nSUDOCONVINFOMSG, try to write the message to the user's termi-\nnal.  If the terminal is unavailable, the standard error or stan-\ndard output will be used, depending upon whether\nSUDOCONVERRORMSG or SUDOCONVINFOMSG was used.  The user's\nterminal is always used when possible for input, this flag is only\nused for output.\n\nThe timeout in seconds until the prompt will wait for no more input.  A\nzero value implies an infinite timeout.\n\nThe plugin is responsible for freeing the reply buffer located in each\nstruct sudoconvreply, if it is not NULL.  SUDOCONVREPLMAX represents\nthe maximum length of the reply buffer (not including the trailing NUL\ncharacter).  In practical terms, this is the longest password sudo will\nsupport.\n\nThe printf()-style function uses the same underlying mechanism as the\nconversation() function but only supports SUDOCONVINFOMSG and\nSUDOCONVERRORMSG for the msgtype parameter.  It can be more conve-\nnient than using the conversation() function if no user reply is needed\nand supports standard printf() escape sequences.\n\nSee the sample plugin for an example of the conversation() function us-\nage.\n\nPlugin invocation order\nAs of sudo 1.9.0, the plugin open() and close() functions are called in\nthe following order:\n\n1.   audit open\n\n2.   policy open\n\n3.   approval open\n\n4.   approval close\n\n5.   I/O log open\n\n6.   command runs\n\n7.   command exits\n\n8.   I/O log close\n\n9.   policy close\n\n10.  audit close\n\n11.  sudo exits\n\nPrior to sudo 1.9.0, the I/O log close() function was called after the\npolicy close() function.\n\nSudoers group plugin API\nThe sudoers plugin supports its own plugin interface to allow non-Unix\ngroup lookups.  This can be used to query a group source other than the\nstandard Unix group database.  Two sample group plugins are bundled with\nsudo, groupfile, and systemgroup, are detailed in sudoers(5).  Third\nparty group plugins include a QAS AD plugin available from Quest Soft-\nware.\n\nA group plugin must declare and populate a sudoersgroupplugin struct in\nthe global scope.  This structure contains pointers to the functions that\nimplement plugin initialization, cleanup, and group lookup.\n\nstruct sudoersgroupplugin {\nunsigned int version;\nint (*init)(int version, sudoprintft sudoprintf,\nchar *const argv[]);\nvoid (*cleanup)(void);\nint (*query)(const char *user, const char *group,\nconst struct passwd *pwd);\n};\n\nThe sudoersgroupplugin struct has the following fields:\n\nversion\nThe version field should be set to GROUPAPIVERSION.\n\nThis allows sudoers to determine the API version the group plugin\nwas built against.\n\ninit\nint (*init)(int version, sudoprintft pluginprintf,\nchar *const argv[]);\n\nThe init() function is called after sudoers has been parsed but be-\nfore any policy checks.  It returns 1 on success, 0 on failure (or\nif the plugin is not configured), and -1 if a error occurred.  If\nan error occurs, the plugin may call the pluginprintf() function\nwith SUDOCONFERRORMSG to present additional error information to\nthe user.\n\nThe function arguments are as follows:\n\nversion\nThe version passed in by sudoers allows the plugin to deter-\nmine the major and minor version number of the group plugin\nAPI supported by sudoers.\n\npluginprintf\nA pointer to a printf()-style function that may be used to\ndisplay informational or error message to the user.  Returns\nthe number of characters printed on success and -1 on fail-\nure.\n\nargv  A NULL-terminated array of arguments generated from the\ngroupplugin option in sudoers.  If no arguments were given,\nargv will be NULL.\n\ncleanup\nvoid (*cleanup)();\n\nThe cleanup() function is called when sudoers has finished its\ngroup checks.  The plugin should free any memory it has allocated\nand close open file handles.\n\nquery\nint (*query)(const char *user, const char *group,\nconst struct passwd *pwd);\n\nThe query() function is used to ask the group plugin whether user\nis a member of group.\n\nThe function arguments are as follows:\n\nuser  The name of the user being looked up in the external group\ndatabase.\n\ngroup\nThe name of the group being queried.\n\npwd   The password database entry for user, if any.  If user is not\npresent in the password database, pwd will be NULL.\n\nGroup API Version Macros\n\n/* Sudoers group plugin version major/minor */\n#define GROUPAPIVERSIONMAJOR 1\n#define GROUPAPIVERSIONMINOR 0\n#define GROUPAPIVERSION ((GROUPAPIVERSIONMAJOR << 16) | \\\nGROUPAPIVERSIONMINOR)\nFor getters and setters see the Policy plugin API.\n",
                "subsections": []
            },
            "PLUGIN API CHANGELOG": {
                "content": "The following revisions have been made to the Sudo Plugin API.\n\nVersion 1.0\nInitial API version.\n\nVersion 1.1 (sudo 1.8.0)\nThe I/O logging plugin's open() function was modified to take the\ncommandinfo list as an argument.\n\nVersion 1.2 (sudo 1.8.5)\nThe Policy and I/O logging plugins' open() functions are now passed\na list of plugin parameters if any are specified in sudo.conf(5).\n\nA simple hooks API has been introduced to allow plugins to hook in\nto the system's environment handling functions.\n\nThe initsession Policy plugin function is now passed a pointer to\nthe user environment which can be updated as needed.  This can be\nused to merge in environment variables stored in the PAM handle be-\nfore a command is run.\n\nVersion 1.3 (sudo 1.8.7)\nSupport for the execbackground entry has been added to the\ncommandinfo list.\n\nThe maxgroups and plugindir entries were added to the settings\nlist.\n\nThe version() and close() functions are now optional.  Previously,\na missing version() or close() function would result in a crash.\nIf no policy plugin close() function is defined, a default close()\nfunction will be provided by the sudo front-end that displays a\nwarning if the command could not be executed.\n\nThe sudo front-end now installs default signal handlers to trap\ncommon signals while the plugin functions are run.\n\nVersion 1.4 (sudo 1.8.8)\nThe remotehost entry was added to the settings list.\n\nVersion 1.5 (sudo 1.8.9)\nThe preservefds entry was added to the commandinfo list.\n\nVersion 1.6 (sudo 1.8.11)\nThe behavior when an I/O logging plugin returns an error (-1) has\nchanged.  Previously, the sudo front-end took no action when the\nlogttyin(), logttyout(), logstdin(), logstdout(), or\nlogstderr() function returned an error.\n\nThe behavior when an I/O logging plugin returns 0 has changed.\nPreviously, output from the command would be displayed to the ter-\nminal even if an output logging function returned 0.\n\nVersion 1.7 (sudo 1.8.12)\nThe pluginpath entry was added to the settings list.\n\nThe debugflags entry now starts with a debug file path name and\nmay occur multiple times if there are multiple plugin-specific De-\nbug lines in the sudo.conf(5) file.\n\nVersion 1.8 (sudo 1.8.15)\nThe sudoeditcheckdir and sudoeditfollow entries were added to the\ncommandinfo list.  The default value of sudoeditcheckdir was\nchanged to true in sudo 1.8.16.\n\nThe sudo conversation function now takes a pointer to a struct\nsudoconvcallback as its fourth argument.  The sudoconvt defini-\ntion has been updated to match.  The plugin must specify that it\nsupports plugin API version 1.8 or higher to receive a conversation\nfunction pointer that supports this argument.\n\nVersion 1.9 (sudo 1.8.16)\nThe execfd entry was added to the commandinfo list.\n\nVersion 1.10 (sudo 1.8.19)\nThe umask entry was added to the userinfo list.  The iologgroup,\niologmode, and iologuser entries were added to the commandinfo\nlist.\n\nVersion 1.11 (sudo 1.8.20)\nThe timeout entry was added to the settings list.\n\nVersion 1.12 (sudo 1.8.21)\nThe changewinsize field was added to the ioplugin struct.\n\nVersion 1.13 (sudo 1.8.26)\nThe logsuspend field was added to the ioplugin struct.\n\nVersion 1.14 (sudo 1.8.29)\nThe umaskoverride entry was added to the commandinfo list.\n\nVersion 1.15 (sudo 1.9.0)\nThe cwdoptional entry was added to the commandinfo list.\n\nThe eventalloc field was added to the policyplugin and ioplugin\nstructs.\n\nThe errstr argument was added to the policy and I/O plugin func-\ntions which the plugin function can use to return an error string.\nThis string may be used by the audit plugin to report failure or\nerror conditions set by the other plugins.\n\nThe close() function is now is called regardless of whether or not\na command was actually executed.  This makes it possible for plug-\nins to perform cleanup even when a command was not run.\n\nSUDOCONVREPLMAX has increased from 255 to 1023 bytes.\n\nSupport for audit and approval plugins was added.\n\nVersion 1.16 (sudo 1.9.3)\nInitial resource limit values were added to the userinfo list.\n\nThe cmndchroot and cmndcwd enties were added to the settings\nlist.\n\nVersion 1.17 (sudo 1.9.4)\nThe eventalloc field was added to the auditplugin and ap-\nprovalplugin structs.\n\nVersion 1.18 (sudo 1.9.9)\nThe policy may now set resource limit values in the commandinfo\nlist.\n",
                "subsections": []
            },
            "SEE ALSO": {
                "content": "sudo.conf(5), sudoers(5), sudo(8)\n",
                "subsections": []
            },
            "AUTHORS": {
                "content": "Many people have worked on sudo over the years; this version consists of\ncode written primarily by:\n\nTodd C. Miller\n\nSee the CONTRIBUTORS file in the sudo distribution\n(https://www.sudo.ws/contributors.html) for an exhaustive list of people\nwho have contributed to sudo.\n",
                "subsections": []
            },
            "BUGS": {
                "content": "If you feel you have found a bug in sudo, please submit a bug report at\nhttps://bugzilla.sudo.ws/\n",
                "subsections": []
            },
            "SUPPORT": {
                "content": "Limited free support is available via the sudo-users mailing list, see\nhttps://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search\nthe archives.\n",
                "subsections": []
            },
            "DISCLAIMER": {
                "content": "sudo is provided \"AS IS\" and any express or implied warranties, includ-\ning, but not limited to, the implied warranties of merchantability and\nfitness for a particular purpose are disclaimed.  See the LICENSE file\ndistributed with sudo or https://www.sudo.ws/license.html for complete\ndetails.\n",
                "subsections": []
            },
            "Sudo 1.9.9                     January 20, 2022                     Sudo 1.9.9": {
                "content": "",
                "subsections": []
            }
        }
    }
}