{
    "mode": "man",
    "parameter": "sudo_plugin",
    "section": "5",
    "url": "https://www.chedong.com/phpMan.php/man/sudo_plugin/5/json",
    "generated": "2026-11-07T23:23:04Z",
    "sections": {
        "NAME": {
            "content": "sudoplugin — Sudo Plugin API\n",
            "subsections": []
        },
        "DESCRIPTION": {
            "content": "Starting  with version 1.8, sudo supports a plugin API for policy and session logging.  Plug‐\nins may be compiled as dynamic shared objects (the default on systems that support  them)  or\ncompiled statically into the sudo binary itself.  By default, the sudoers plugin provides au‐\ndit,  security  policy and I/O logging capabilities.  Via the plugin API, sudo can be config‐\nured to use alternate plugins provided by third parties.  The plugins to be used  are  speci‐\nfied in the sudo.conf(5) file.\n\nThe  API is versioned with a major and minor number.  The minor version number is incremented\nwhen additions are made.  The major number is incremented when incompatible changes are made.\nA plugin should be check the version passed to it  and  make  sure  that  the  major  version\nmatches.\n\nThe plugin API is defined by the <sudoplugin.h> header file.\n",
            "subsections": [
                {
                    "name": "Policy plugin API",
                    "content": "A  policy  plugin must declare and populate a struct policyplugin in the global scope.  This\nstructure contains pointers to the functions that implement the sudo policy checks.  The name\nof the symbol should be specified in sudo.conf(5) along with a path to  the  plugin  so  that\nsudo can load 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 sudopluginprintf, 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 *user, const char errstr);\nint (*validate)(const char errstr);\nvoid (*invalidate)(int rmcred);\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\nA struct policyplugin 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 against.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudopluginprintf, 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, or -2 if there was\na usage error.  In the latter case, sudo will print a usage message  before  it  exits.\nIf   an   error   occurs,   the  plugin  may  optionally  call  the  conversation()  or\nsudopluginprintf() function 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 the major and minor\nversion number of the plugin API supported by sudo.\n\nconversation\nA pointer to the conversation() function that can be used by the plugin to inter‐\nact with the user (see “Conversation API” for details).  Returns 0 on success and\n-1 on failure.\n\nsudopluginprintf\nA pointer to a printf()-style function that may be used to display  informational\nor  error  messages  (see “Conversation API” for details).  Returns the number of\ncharacters printed on success and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of “name=value” strings.  The\nvector is terminated by a NULL pointer.  These settings correspond to options the\nuser specified when running sudo.  As such, they will only be  present  when  the\ncorresponding option has been specified on the command line.\n\nWhen  parsing  settings,  the  plugin  should split on the first equal sign (‘=’)\nsince the name field will never include one itself 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 use on systems where\nBSD authentication is supported.\n\nclosefrom=number\nIf specified, the user has requested via the -C option that sudo close  all\nfiles descriptors with a value of number or higher.  The plugin may option‐\nally pass this, or another value, back in the commandinfo list.\n\ncmndchroot=string\nThe  root  directory (see chroot(2)) to run the command in, as specified by\nthe user via the -R option.  The plugin may ignore or restrict  the  user's\nability  to specify a new root directory.  Only available starting with API\nversion 1.16.\n\ncmndcwd=string\nThe working directory to run the command in, as specified by the  user  via\nthe  -D  option.   The  plugin may ignore or restrict the user's ability to\nspecify a new working directory.  Only available starting with API  version\n1.16.\n\ndebugflags=string\nA  debug  file  path name followed by a space and a comma-separated list of\ndebug flags that correspond to the plugin's Debug entry in sudo.conf(5), if\nthere is one.  The flags are passed to the plugin exactly as they appear in\nsudo.conf(5).   The  syntax  used  by  sudo  and  the  sudoers  plugin   is\nsubsystem@priority  but  a plugin is free to use a different format so long\nas it does not include a comma (‘,’).  Prior to sudo 1.8.12, there  was  no\nway to specify plugin-specific debugflags so the value was always the same\nas  that  used  by the sudo front-end and did not include a path name, only\nthe flags themselves.  As of version 1.7 of the plugin interface, sudo will\nonly pass debugflags if sudo.conf(5) contains a plugin-specific Debug  en‐\ntry.\n\nignoreticket=bool\nSet to true if the user specified the -k option along with a command, indi‐\ncating  that  the  user  wishes to ignore any cached authentication creden‐\ntials.  impliedshell to true.  This allows sudo with no  arguments  to  be\nused  similarly to su(1).  If the plugin does not to support this usage, it\nmay return a value of -2 from the checkpolicy() function, which will cause\nsudo to print a usage message and exit.\n\nimpliedshell=bool\nIf the user does not specify a program on the command line, sudo will  pass\nthe plugin the path to the user's shell and set impliedshell.\n\ninterceptptrace=bool\nIndicates   whether  or  not  the  system  supports  intercept  mode  using\nptrace(2).  This is currently only true  for  Linux  systems  that  support\nseccomp(2)  filtering  and the “trap” action.  Other systems will use a dy‐\nnamic shared object to implement intercept.  Only available  starting  with\nAPI version 1.19.\n\ninterceptsetid=bool\nIndicates  whether  or not the system supports running set-user-ID and set-\ngroup-ID binaries in intercept mode.  This is currently only true for Linux\nsystems that support seccomp(2) filtering and the “trap” action.   On  sys‐\ntems  that  use a dynamic shared object to implement intercept, the dynamic\nlinker (ld.so or the equivalent) will disable preloading of shared  objects\nwhen executing a set-user-ID or set-group-ID binary.  This will disable in‐\ntercept mode for that program and any other programs that it executes.  The\npolicy plugin may refuse to execute a set-user-ID or set-group-ID binary in\nintercept  mode  to  avoid  this.  Only available starting with API version\n1.19.\n\nloginclass=string\nBSD login class to use when setting resource  limits  and  nice  value,  if\nspecified by the -c option.\n\nloginshell=bool\nSet  to  true if the user specified the -i option, indicating that the user\nwishes to run a login shell.\n\nmaxgroups=int\nThe maximum number of groups a user may  belong  to.   This  will  only  be\npresent if there is a corresponding setting in sudo.conf(5).\n\nnetworkaddrs=list\nA  space-separated  list  of  IP network addresses and netmasks in the form\n“addr/netmask”, e.g., “192.168.1.2/255.255.255.0”.  The address and netmask\npairs may be either IPv4 or IPv6, depending on what  the  operating  system\nsupports.   If  the  address contains a colon (‘:’), it is an IPv6 address,\nelse it is IPv4.\n\nnoninteractive=bool\nSet to true if the user specified  the  -n  option,  indicating  that  sudo\nshould  operate  in  non-interactive mode.  The plugin may reject a command\nrun in non-interactive mode if user interaction is required.\n\nplugindir=string\nThe default plugin directory used by the sudo front-end.  This is  the  de‐\nfault directory set at compile time and may not correspond to the directory\nthe  running  plugin was loaded from.  It may be used by a plugin to locate\nsupport files.\n\npluginpath=string\nThe path name of plugin loaded by the sudo front-end.  The path  name  will\nbe a fully-qualified unless the plugin was statically compiled into sudo.\n\npreserveenvironment=bool\nSet  to  true if the user specified the -E option, indicating that the user\nwishes to preserve the environment.\n\npreservegroups=bool\nSet to true if the user specified the -P option, indicating that  the  user\nwishes  to  preserve  the  group  vector instead of setting it based on the\nrunas user.\n\nprogname=string\nThe command name that sudo was run as, typically “sudo” or “sudoedit”.\n\nprompt=string\nThe prompt to use when requesting a password, if specified via the  -p  op‐\ntion.\n\nremotehost=string\nThe  name of the remote host to run the command on, if specified via the -h\noption.  Support for running the command on a remote host is  meant  to  be\nimplemented  via  a  helper  program that is executed in place of the user-\nspecified command.  The sudo front-end is only capable  of  executing  com‐\nmands on the local host.  Only available starting with API version 1.4.\n\nrunshell=bool\nSet  to  true if the user specified the -s option, indicating that the user\nwishes to run a shell.\n\nrunasgroup=string\nThe group name or group-ID to run the command as, if specified via  the  -g\noption.\n\nrunasuser=string\nThe user name or user-ID to run the command as, if specified via the -u op‐\ntion.\n\nselinuxrole=string\nSELinux  role to use when executing the command, if specified by the -r op‐\ntion.\n\nselinuxtype=string\nSELinux type to use when executing the command, if specified by the -t  op‐\ntion.\n\nsethome=bool\nSet to true if the user specified the -H option.  If true, set the HOME en‐\nvironment variable to the target user's home directory.\n\nsudoedit=bool\nSet to true when the -e option is specified or if invoked as sudoedit.  The\nplugin  shall substitute an editor into argv in the checkpolicy() function\nor return -2 with a usage error if the plugin does  not  support  sudoedit.\nFor more information, see the checkpolicy() section.\n\ntimeout=string\nCommand  timeout  specified by the user via the -T option.  Not all plugins\nsupport command timeouts and the ability of the user to set a  timeout  may\nbe  restricted  by policy.  The format of the timeout string is plugin-spe‐\ncific.\n\nupdateticket=bool\nSet to false if the user specified the -N option, indicating that the  user\nwishes  to  avoid  updating  any  cached  authentication credentials.  Only\navailable starting with API version 1.20.\n\nAdditional settings may be added in the future so the plugin should silently  ig‐\nnore settings that it does not recognize.\n\nuserinfo\nA  vector  of  information  about  the  user  running  the command in the form of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen parsing userinfo, the plugin should split on the  first  equal  sign  (‘=’)\nsince the name field will never include one itself 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 there is no termi‐\nnal device available, a default value of 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  string  of  comma-sepa‐\nrated group-IDs.\n\nhost=string\nThe local machine's hostname as returned by the gethostname(2) system call.\n\nlines=int\nThe  number of lines the user's terminal supports.  If there is no terminal\ndevice available, a default value of 24 is used.\n\npgid=int\nThe ID of the process group that the running sudo process is a  member  of.\nOnly available starting with API version 1.2.\n\npid=int\nThe  process  ID of the running sudo process.  Only available starting with\nAPI version 1.2.\n\nppid=int\nThe parent process ID of the running sudo process.  Only available starting\nwith API version 1.2.\n\nrlimitas=soft,hard\nThe maximum size to which the process's address space may grow (in  bytes),\nif  supported  by the operating system.  The soft and hard limits are sepa‐\nrated by a comma.  A value of “infinity” indicates that there is no  limit.\nOnly available starting with API version 1.16.\n\nrlimitcore=soft,hard\nThe  largest  size core dump file that may be created (in bytes).  The soft\nand hard limits are separated by a comma.  A value of “infinity”  indicates\nthat there is no limit.  Only available starting with API version 1.16.\n\nrlimitcpu=soft,hard\nThe  maximum amount of CPU time that the process may use (in seconds).  The\nsoft and hard limits are separated by a comma.  A value of “infinity” indi‐\ncates that there is no limit.  Only available  starting  with  API  version\n1.16.\n\nrlimitdata=soft,hard\nThe  maximum size of the data segment for the process (in bytes).  The soft\nand hard limits are separated by a comma.  A value of “infinity”  indicates\nthat there is no limit.  Only available starting with API version 1.16.\n\nrlimitfsize=soft,hard\nThe largest size file that the process may create (in bytes).  The soft and\nhard limits are separated by a comma.  A value of “infinity” indicates that\nthere is no limit.  Only available starting with API version 1.16.\n\nrlimitlocks=soft,hard\nThe maximum number of locks that the process may establish, if supported by\nthe  operating  system.  The soft and hard limits are separated by a comma.\nA value of “infinity” indicates that there is  no  limit.   Only  available\nstarting with API version 1.16.\n\nrlimitmemlock=soft,hard\nThe  maximum  size  that the process may lock in memory (in bytes), if sup‐\nported by the operating system.  The soft and hard limits are separated  by\na  comma.   A  value  of “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 open.  The  soft  and\nhard limits are separated by a comma.  A value of “infinity” indicates that\nthere is no limit.  Only available starting with API version 1.16.\n\nrlimitnproc=soft,hard\nThe  maximum number of processes that the user may run simultaneously.  The\nsoft and hard limits are separated by a comma.  A value of “infinity” indi‐\ncates that there is no limit.  Only available  starting  with  API  version\n1.16.\n\nrlimitrss=soft,hard\nThe  maximum  size  to  which  the process's resident set size may grow (in\nbytes).  The soft and hard limits are separated by a  comma.   A  value  of\n“infinity”  indicates that 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  (in  bytes).   The\nsoft and hard limits are separated by a comma.  A value of “infinity” indi‐\ncates  that  there  is  no limit.  Only available starting with API version\n1.16.\n\nsid=int\nThe session ID of the running sudo process or 0 if sudo is not  part  of  a\nPOSIX job control session.  Only available starting with API version 1.2.\n\ntcpgid=int\nThe  ID of the foreground process group associated with the terminal device\nassociated with the sudo process or 0 if  there  is  no  terminal  present.\nOnly available starting with API version 1.2.\n\ntty=string\nThe path to the user's terminal device.  If the user has no terminal device\nassociated with the session, the value 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 starting with API\nversion 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  vector  of  “name=value”\nstrings.\n\nWhen  parsing  userenv,  the  plugin  should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path are passed  as  argu‐\nments to the plugin.  These arguments are split on a white space boundary and are\npassed  to  the  plugin in the form of a NULL-terminated array of strings.  If no\narguments were specified, pluginoptions will be the NULL pointer.\n\nThe pluginoptions parameter is only available starting with API version 1.2.   A\nplugin  must  check  the API version specified by the sudo front-end before using\npluginoptions.  Failure to do so may result in a crash.\n\nerrstr\nIf the open() function returns a value other than 1, the plugin may store a  mes‐\nsage  describing  the  failure  or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 before it exits.  Start‐\ning with API version 1.15, close() is called regardless of whether or not a command was\nactually executed.  This makes it possible for plugins to perform cleanup even  when  a\ncommand was not run.  It is not possible to tell whether a command was run based solely\non  the  arguments passed to the close() function.  To determine if a command was actu‐\nally run, the plugin must keep track of whether or not the checkpolicy() function  re‐\nturned successfully.\n\nThe function arguments are as follows:\n\nexitstatus\nThe  command's exit status, as returned by the wait(2) system call, or zero if no\ncommand was run.  The value of exitstatus is undefined if error is non-zero.\n\nerror\nIf the command could not be executed, this is set to the value of  errno  set  by\nthe execve(2) system call.  The plugin is responsible for displaying error infor‐\nmation  via  the conversation() or sudopluginprintf() 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 loaded, and  neither  the\ntimeout  nor  usepty  options are set in the commandinfo list, the sudo front-end may\nexecute the command directly 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 specifies  the  -V  option.\nThe  plugin  may  display its version information to the user via the conversation() or\nsudopluginprintf() function using SUDOCONVINFOMSG.  If the user requests  detailed\nversion information, the verbose flag will be non-zero.\n\nReturns  1 on success, 0 on failure, -1 if a general error occurred, or -2 if there was\na usage error, although the return value is currently 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 the user is  allowed\nto run the specified commands.\n\nIf the sudoedit option was enabled in the settings array passed to the open() function,\nthe  user has requested sudoedit mode.  sudoedit is a mechanism for editing one or more\nfiles where an editor is run with the user's credentials instead of with elevated priv‐\nileges.  sudo achieves this by creating user-writable temporary copies of the files  to\nbe edited and then overwriting the originals with the temporary copies after editing is\ncomplete.   If  the  plugin  supports  sudoedit,  it  must  set  sudoedit=true  in  the\ncommandinfo list.  The plugin is responsible for choosing the editor to be  used,  po‐\ntentially  from  a  variable  in  the user's environment, such as EDITOR, and should be\nstored in argvout (environment variables may include command line options).  The files\nto be edited should be copied from argv to argvout, separated from the editor and  its\narguments by a ‘--’ element.  The ‘--’ will be removed by sudo before the editor is ex‐\necuted.  The plugin may also set sudoeditnfiles to the number of files to be edited in\nthe  commandinfo  list; this will only be used by the sudo front-end starting with API\nversion 1.21.\n\nThe checkpolicy() function returns 1 if the command is allowed, 0 if not  allowed,  -1\nfor a general error, or -2 for a usage error or if sudoedit was specified but is unsup‐\nported  by  the  plugin.  In the latter case, sudo will print a usage message before it\nexits.  If an error occurs, the  plugin  may  optionally  call  the  conversation()  or\nsudopluginprintf()  function with SUDOCONFERRORMSG to present additional error in‐\nformation to the user.\n\nThe function arguments are as follows:\n\nargc  The number of elements in argv, not counting the final NULL pointer.\n\nargv  The argument vector describing the command the user wishes to run,  in  the  same\nform  as what would be passed to the execve(2) system call.  The vector is termi‐\nnated by a NULL pointer.\n\nenvadd\nAdditional environment variables specified by the user on the command line in the\nform of a NULL-terminated vector of “name=value” strings.  The plugin may  reject\nthe  command  if  one  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 equal sign (‘=’) since\nthe name field will never include one itself but the value might.\n\ncommandinfo\nInformation about the command being run in  the  form  of  “name=value”  strings.\nThese  values  are  used  by sudo to set the execution environment when running a\ncommand.  The plugin is responsible for creating and populating the vector, which\nmust be terminated with a NULL pointer.  The following values are  recognized  by\nsudo:\n\napparmorprofile=string\nAppArmor  profile to transition to when executing the command.  Only avail‐\nable starting with API version 1.19.\n\nchroot=string\nThe root directory to use when running the command.\n\nclosefrom=number\nIf specified, sudo will close all files descriptors with a value of  number\nor higher.\n\ncommand=string\nFully qualified path to the command to be executed.\n\ncwd=string\nThe  current working directory to change to when executing the command.  If\nsudo is unable to change to the new working directory, the command will not\nbe run unless cwdoptional is also set (see below).\n\ncwdoptional=bool\nIf set, sudo will treat an inability to change to the new working directory\nas a non-fatal error.  This setting has no effect unless cwd is also set.\n\nexecbackground=bool\nBy default, sudo runs a command as the foreground process as long  as  sudo\nitself  is  running in the foreground.  When execbackground is enabled and\nthe command is being run in a pseudo-terminal (due to I/O  logging  or  the\nusepty  setting),  the  command  will be run as a background process.  At‐\ntempts to read from the controlling terminal (or to  change  terminal  set‐\ntings)  will  result in the command being suspended with the SIGTTIN signal\n(or SIGTTOU in the case of terminal settings).  If this happens  when  sudo\nis a foreground process, the command will be granted the controlling termi‐\nnal  and resumed in the foreground with no user intervention required.  The\nadvantage of initially running the command in the background is  that  sudo\nneed  not read from the terminal unless the command explicitly requests it.\nOtherwise, any terminal input must be passed to the command, whether it has\nrequired it or not (the kernel buffers terminals so it is not  possible  to\ntell  whether  the command really wants the input).  This is different from\nhistoric sudo behavior or when the command is not being run  in  a  pseudo-\nterminal.\n\nFor  this  to  work seamlessly, the operating system must support the auto‐\nmatic restarting of system calls.  Unfortunately, not all operating systems\ndo this by default, and even those that do may have bugs.  For example, ma‐\ncOS fails to restart the tcgetattr() and tcsetattr() system calls (this  is\na bug in macOS).  Furthermore, because this behavior depends on the command\nstopping  with  the  SIGTTIN  or SIGTTOU signals, programs that catch these\nsignals and suspend themselves with a  different  signal  (usually  SIGTOP)\nwill  not  be automatically foregrounded.  Some versions of the linux su(1)\ncommand behave this  way.   Because  of  this,  a  plugin  should  not  set\nexecbackground  unless  it  is explicitly enabled by the administrator and\nthere should be a way to enabled or disable it on a per-command basis.\n\nThis setting has no effect unless I/O logging is enabled or usepty is  en‐\nabled.\n\nexecfd=number\nIf  specified, sudo will use the fexecve(2) system call to execute the com‐\nmand instead of execve(2).  The specified number must refer to an open file\ndescriptor.\n\nintercept=bool\nIf set, sudo will intercept attempts to execute a  subsequent  command  and\nperform  a  policy check via the policy plugin's checkpolicy() function to\ndetermine whether or not the command is permitted.  This  can  be  used  to\nprevent shell escapes on supported platforms but it has a number of limita‐\ntions.   See  Preventing  shell  escapes  in  sudoers(5) for details.  Only\navailable starting with API version 1.18.\n\ninterceptverify=bool\nIf set, sudo will attempt to verify that a command run  in  intercept  mode\nhas  the  expected path name, command line arguments and environment.  This\nsetting has no effect unless useptrace is also  enabled.   Only  available\nstarting with API version 1.20.\n\niologcompress=bool\nSet  to  true  if  the I/O logging plugins, if any, should compress the log\ndata.  This is a hint to the I/O logging plugin which may choose to  ignore\nit.\n\niologgroup=string\nThe  group that will own newly created I/O log files and directories.  This\nis a hint to the I/O logging plugin which may choose to ignore it.\n\niologmode=octal\nThe file permission mode to use when creating I/O log  files  and  directo‐\nries.   This is a hint to the I/O logging plugin which may choose to ignore\nit.\n\niologuser=string\nThe user that will own newly created I/O log files and  directories.   This\nis a hint to the I/O logging plugin which may choose to ignore it.\n\niologpath=string\nFully  qualified  path  to  the file or directory in which I/O log is to be\nstored.  This is a hint to the I/O logging plugin which may choose  to  ig‐\nnore it.  If no I/O logging plugin is loaded, this setting has no effect.\n\niologstdin=bool\nSet to true if the I/O logging plugins, if any, should log the standard in‐\nput if it is not connected to a terminal device.  This is a hint to the I/O\nlogging plugin which may choose to ignore it.\n\niologstdout=bool\nSet  to  true  if  the I/O logging plugins, if any, should log the standard\noutput if it is not connected to a terminal device.  This is a hint to  the\nI/O logging plugin which may choose to ignore it.\n\niologstderr=bool\nSet to true if the I/O logging plugins, if any, should log the standard er‐\nror if it is not connected to a terminal device.  This is a hint to the I/O\nlogging plugin which may choose to ignore it.\n\niologttyin=bool\nSet to true if the I/O logging plugins, if any, should log all terminal in‐\nput.   This  only  includes  input typed by the user and not from a pipe or\nredirected from a file.  This is a hint to the I/O logging plugin which may\nchoose to ignore it.\n\niologttyout=bool\nSet to true if the I/O logging plugins, if any,  should  log  all  terminal\noutput.   This  only includes output to the screen, not output to a pipe or\nfile.  This is a hint to the I/O logging plugin which may choose to  ignore\nit.\n\nloginclass=string\nBSD  login  class  to  use when setting resource limits and nice value (op‐\ntional).  This option is only set on systems that support login classes.\n\nnice=int\nNice value (priority) to use when executing the command.  The  nice  value,\nif specified, overrides the priority associated with the loginclass on BSD\nsystems.\n\nlogsubcmds=bool\nIf set, sudo will call the audit plugin's accept() function to log when the\ncommand  runs  a  subsequent  command,  if  supported  by  the  system.  If\nintercept is also specified, logsubcmds will be ignored.   See  Preventing\nshell  escapes in sudoers(5) for more information.  Only available starting\nwith API version 1.18.\n\nnoexec=bool\nIf set, prevent the command from executing other programs.\n\npreservefds=list\nA comma-separated list of file descriptors that should  be  preserved,  re‐\ngardless  of  the  value of the closefrom setting.  Only available starting\nwith API version 1.5.\n\npreservegroups=bool\nIf set, sudo will preserve the user's group vector instead of  initializing\nthe group vector based on runasuser.\n\nrlimitas=soft,hard\nThe  maximum size to which the process's address space may grow (in bytes),\nif supported by the operating system.  The soft and hard limits  are  sepa‐\nrated  by  a comma.  If only a single value is specified, both the hard and\nsoft limits are set.  A value of “infinity”  indicates  that  there  is  no\nlimit.   A value of “user” will cause the invoking user's resource limit to\nbe preserved.  A value of “default” will cause the  target  user's  default\nresource limit to be used on systems that allow per-user resource limits to\nbe configured.  Only available starting with API version 1.18.\n\nrlimitcore=soft,hard\nThe  largest  size core dump file that may be created (in bytes).  The soft\nand hard limits are separated by a comma.  If only a single value is speci‐\nfied, both the hard and soft limits are set.  A value of  “infinity”  indi‐\ncates  that  there  is no limit.  A value of “user” will cause the invoking\nuser's resource limit to be preserved.  A value of “default” will cause the\ntarget user's default resource limit to be used on systems that allow  per-\nuser  resource  limits  to be configured.  Only available starting with API\nversion 1.18.\n\nrlimitcpu=soft,hard\nThe maximum amount of CPU time that the process may use (in seconds).   The\nsoft  and  hard limits are separated by a comma.  If only a single value is\nspecified, both the hard and soft limits are set.  A  value  of  “infinity”\nindicates  that there is no limit.  A value of “user” will cause the invok‐\ning user's resource limit to be preserved.  A value of “default” will cause\nthe target user's default resource limit to be used on systems  that  allow\nper-user  resource  limits  to be configured.  Only available starting with\nAPI version 1.18.\n\nrlimitdata=soft,hard\nThe maximum size of the data segment for the process (in bytes).  The  soft\nand hard limits are separated by a comma.  If only a single value is speci‐\nfied,  both  the hard and soft limits are set.  A value of “infinity” indi‐\ncates that there is no limit.  A value of “user” will  cause  the  invoking\nuser's resource limit to be preserved.  A value of “default” will cause the\ntarget  user's default resource limit to be used on systems that allow per-\nuser resource limits to be configured.  Only available  starting  with  API\nversion 1.18.\n\nrlimitfsize=soft,hard\nThe largest size file that the process may create (in bytes).  The soft and\nhard limits are separated by a comma.  If only a single value is specified,\nboth  the  hard  and  soft limits are set.  A value of “infinity” indicates\nthat there is no limit.  A value of “user” will cause the  invoking  user's\nresource limit to be preserved.  A value of “default” will cause the target\nuser's default resource limit to be used on systems that allow per-user re‐\nsource  limits  to be configured.  Only available starting with API version\n1.18.\n\nrlimitlocks=soft,hard\nThe maximum number of locks that the process may establish, if supported by\nthe operating system.  The soft and hard limits are separated by  a  comma.\nIf only a single value is specified, both the hard and soft limits are set.\nA  value of “infinity” indicates that there is no limit.  A value of “user”\nwill cause the invoking user's resource limit to be preserved.  A value  of\n“default” will cause the target user's default resource limit to be used on\nsystems  that allow per-user resource limits to be configured.  Only avail‐\nable starting with API version 1.18.\n\nrlimitmemlock=soft,hard\nThe maximum size that the process may lock in memory (in  bytes),  if  sup‐\nported  by the operating system.  The soft and hard limits are separated by\na comma.  If only a single value is specified, both the hard and soft  lim‐\nits  are  set.   A value of “infinity” indicates that there is no limit.  A\nvalue of “user” will cause the invoking user's resource limit  to  be  pre‐\nserved.  A value of “default” will cause the target user's default resource\nlimit  to be used on systems that allow per-user resource limits to be con‐\nfigured.  Only available starting with API version 1.18.\n\nrlimitnofile=soft,hard\nThe maximum number of files that the process may have open.  The  soft  and\nhard limits are separated by a comma.  If only a single value is specified,\nboth  the  hard  and  soft limits are set.  A value of “infinity” indicates\nthat there is no limit.  A value of “user” will cause the  invoking  user's\nresource limit to be preserved.  A value of “default” will cause the target\nuser's default resource limit to be used on systems that allow per-user re‐\nsource  limits  to be configured.  Only available starting with API version\n1.18.\n\nrlimitnproc=soft,hard\nThe maximum number of processes that the user may run simultaneously.   The\nsoft  and  hard limits are separated by a comma.  If only a single value is\nspecified, both the hard and soft limits are set.  A  value  of  “infinity”\nindicates  that there is no limit.  A value of “user” will cause the invok‐\ning user's resource limit to be preserved.  A value of “default” will cause\nthe target user's default resource limit to be used on systems  that  allow\nper-user  resource  limits  to be configured.  Only available starting with\nAPI version 1.18.\n\nrlimitrss=soft,hard\nThe maximum size to which the process's resident  set  size  may  grow  (in\nbytes).  The soft and hard limits are separated by a comma.  If only a sin‐\ngle  value is specified, both the hard and soft limits are set.  A value of\n“infinity” indicates that there is no limit.  A value of “user” will  cause\nthe  invoking  user's resource limit to be preserved.  A value of “default”\nwill cause the target user's default resource limit to be used  on  systems\nthat  allow  per-user  resource  limits  to  be configured.  Only available\nstarting with API version 1.18.\n\nrlimitstack=soft,hard\nThe maximum size to which the process's stack may  grow  (in  bytes).   The\nsoft  and  hard limits are separated by a comma.  If only a single value is\nspecified, both the hard and soft limits are set.  A  value  of  “infinity”\nindicates  that there is no limit.  A value of “user” will cause the invok‐\ning user's resource limit to be preserved.  A value of “default” will cause\nthe target user's default resource limit to be used on systems  that  allow\nper-user  resource  limits  to be configured.  Only available starting with\nAPI version 1.18.\n\nrunasegid=gid\nEffective group-ID to run the command as.  If not specified, the  value  of\nrunasgid is used.\n\nrunaseuid=uid\nEffective  user-ID  to  run the command as.  If not specified, the value of\nrunasuid 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 different from  the\nrunasuser's  default  group.  This value is provided for auditing purposes\nonly, the sudo front-end uses runasegid and runasgid when  executing  the\ncommand.\n\nrunasgroups=list\nThe  supplementary  group  vector  to  use for the command in the form of a\ncomma-separated list of group-IDs.  If preservegroups is set, this  option\nis 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 should correspond to\nrunaseuid (or runasuid if runaseuid is not set).  This value is provided\nfor  auditing  purposes  only,  the  sudo  front-end  uses  runaseuid  and\nrunasuid 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 is allocated.  By de‐\nfault,  the  new entry will be a copy of the user's existing utmp entry (if\nany), with the tty, time, type, and pid fields updated.\n\nsudoedit=bool\nSet to true when in sudoedit mode.  The plugin  may  enable  sudoedit  mode\neven  if  sudo was not invoked as sudoedit.  This allows the plugin to per‐\nform command substitution and transparently enable sudoedit when  the  user\nattempts to run an editor.\n\nsudoeditcheckdir=bool\nSet  to  false to disable directory writability checks in sudoedit.  By de‐\nfault, sudoedit 1.8.16 and higher will check all  directory  components  of\nthe path to be edited for writability by the invoking user.  Symbolic links\nwill  not  be  followed in writable directories and sudoedit will refuse to\nedit a file located in a writable directory.  These  restrictions  are  not\nenforced when sudoedit is run by root.  The sudoeditcheckdir option can be\nset  to false to disable this check.  Only available starting with API ver‐\nsion 1.8.\n\nsudoeditfollow=bool\nSet to true to allow sudoedit to edit files that are  symbolic  links.   By\ndefault,  sudoedit  1.8.15  and higher will refuse to open a symbolic link.\nThe sudoeditfollow option can be used to restore the  older  behavior  and\nallow  sudoedit  to  open symbolic links.  Only available starting with API\nversion 1.8.\n\nsudoeditnfiles=number\nThe number of files to be edited by the user.  If present, this is will  be\nused by the sudo front-end to determine which elements of the argvout vec‐\ntor  are files to be edited.  The ‘--’ element must immediately precede the\nfirst file to be editied.  If sudoeditnfiles is not  specified,  the  sudo\nfront-end  will use the position of the ‘--’ element to determine where the\nfile list begins.  Only available starting with API version 1.21.\n\ntimeout=int\nCommand timeout.  If non-zero then when the  timeout  expires  the  command\nwill be killed.\n\numask=octal\nThe  file  creation mask to use when executing the command.  This value may\nbe  overridden  by  PAM  or  login.conf  on   some   systems   unless   the\numaskoverride option is also set.\n\numaskoverride=bool\nForce  the value specified by the umask option to override any umask set by\nPAM or login.conf.\n\nuseptrace=bool\nIf set, sudo will use ptrace(2) to implement intercept mode if supported by\nthe system.  This setting has no effect unless intercept is also set.  Only\navailable starting with API version 1.19.\n\nusepty=bool\nAllocate a pseudo-terminal to run the command in, regardless of whether  or\nnot I/O logging is in use.  By default, sudo will only run the command in a\npseudo-terminal when an I/O log plugin is loaded.\n\nutmpuser=string\nUser  name  to  use  when  constructing  a  new  utmp (or utmpx) entry when\nsetutmp is enabled.  This option can be used to set the user field in  the\nutmp  entry  to the user the command runs as rather than the invoking user.\nIf not set, sudo will base the new entry on the  invoking  user's  existing\nentry.\n\nUnsupported values will be ignored.\n\nargvout\nThe NULL-terminated argument vector to pass to the execve(2) system call when ex‐\necuting the command.  The plugin is responsible for allocating and populating the\nvector.\n\nuserenvout\nThe  NULL-terminated  environment  vector to use when executing the command.  The\nplugin is responsible for allocating and populating the vector.\n\nerrstr\nIf the checkpolicy() function returns a value other than 1, the plugin may store\na message describing the failure or error in errstr.   The  sudo  front-end  will\nthen  pass  this  value  to  any  registered audit plugins.  The string stored in\nerrstr must remain valid until the plugin's close() function is called.\n\nThe errstr parameter is only available starting with API version 1.15.  A  plugin\nmust  check  the API version specified by the sudo front-end before using errstr.\nFailure to do so may result in a crash.\n\nlist\nint (*list)(int argc, char * const argv[], int verbose,\nconst char *user, const char errstr);\n\nList available privileges for the invoking user.  Returns 1 on success, 0  on  failure,\nand  -1  on  error.   On  error,  the  plugin may optionally call the conversation() or\nsudopluginprintf() function with SUDOCONFERRORMSG to present additional error  in‐\nformation to the user.\n\nPrivileges should be output via the conversation() or sudopluginprintf() function us‐\ning SUDOCONVINFOMSG.\n\nThe function arguments are as follows:\n\nargc  The number of elements in argv, not counting the final NULL pointer.\n\nargv  If  non-NULL,  an  argument  vector describing a command the user wishes to check\nagainst the policy in the same form as what would be passed to the execve(2) sys‐\ntem call.  If the command is permitted by the policy, the fully-qualified path to\nthe command should be displayed along with any command line arguments.\n\nverbose\nFlag indicating whether to list in verbose mode or not.\n\nuser  The name of a different user to list privileges for if the policy allows it.   If\nNULL, the plugin should list the privileges of the invoking user.\n\nerrstr\nIf  the list() function returns a value other than 1, the plugin may store a mes‐\nsage describing the failure or error in errstr.  The  sudo  front-end  will  then\npass  this  value  to  any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is called.\n\nThe errstr parameter is only available starting with API version 1.15.  A  plugin\nmust  check  the API version specified by the sudo front-end before using errstr.\nFailure to do 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 option.  For policy plu‐\ngins such as sudoers that cache authentication credentials, this function will validate\nand cache the credentials.\n\nThe validate() function should be NULL  if  the  plugin  does  not  support  credential\ncaching.\n\nReturns  1 on success, 0 on failure, and -1 on error.  On error, the plugin may option‐\nally call the conversation() or sudopluginprintf() function with  SUDOCONFERRORMSG\nto present additional error information to the user.\n\nThe function arguments are as follows:\n\nerrstr\nIf  the  validate() function returns a value other than 1, the plugin may store a\nmessage describing the failure or error in errstr.  The sudo front-end will  then\npass  this  value  to  any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is called.\n\nThe errstr parameter is only available starting with API version 1.15.  A  plugin\nmust  check  the API version specified by the sudo front-end before using errstr.\nFailure to do so may result in a crash.\n\ninvalidate\nvoid (*invalidate)(int rmcred);\n\nThe invalidate() function is called when sudo is run with the -k  or  -K  option.   For\npolicy  plugins  such  as  sudoers that cache authentication credentials, this function\nwill invalidate the credentials.  If the rmcred flag is non-zero, the plugin may remove\nthe credentials instead of simply invalidating them.\n\nThe invalidate() function should be NULL if the  plugin  does  not  support  credential\ncaching.\n\ninitsession\nint (*initsession)(struct passwd *pwd, char userenv[],\nconst char errstr);\n\nThe initsession() function is called before sudo sets up the execution environment for\nthe  command.   It  is  run  in  the parent sudo process before any user-ID or group-ID\nchanges.  This can  be  used  to  perform  session  setup  that  is  not  supported  by\ncommandinfo,  such  as  opening  the PAM session.  The close() function can be used to\ntear down the session that was opened by initsession().\n\nReturns 1 on success, 0 on failure, and -1 on error.  On error, the plugin may  option‐\nally  call the conversation() or sudopluginprintf() function with SUDOCONFERRORMSG\nto present additional error information to the user.\n\nThe function arguments are as follows:\n\npwd   If the user-ID the command will run as was found in the  password  database,  pwd\nwill describe that user, otherwise it will be NULL.\n\nuserenvout\nThe  NULL-terminated  environment vector to use when executing the command.  This\nis the same  string  passed  back  to  the  front-end  via  the  Policy  Plugin's\nuserenvout  parameter.  If the initsession() function needs to modify the user\nenvironment, it should update the pointer stored in userenvout.   The  expected\nuse  case  is to merge the contents of the PAM environment (if any) with the con‐\ntents of userenvout.  The userenvout parameter  is  only  available  starting\nwith  API version 1.2.  A plugin must check the API version specified by the sudo\nfront-end before using userenvout.  Failure to do so may result in a crash.\n\nerrstr\nIf the initsession() function returns a value other than 1, the plugin may store\na message describing the failure or error in errstr.   The  sudo  front-end  will\nthen  pass  this  value  to  any  registered audit plugins.  The string stored in\nerrstr must remain valid until the plugin's close() function is called.\n\nThe errstr parameter is only available starting with API version 1.15.  A  plugin\nmust  check  the API version specified by the sudo front-end before using errstr.\nFailure to do so may result in a crash.\n\nregisterhooks\nvoid (*registerhooks)(int version,\nint (*registerhook)(struct sudohook *hook));\n\nThe registerhooks() function is called by the sudo front-end to register any hooks the\nplugin needs.  If the plugin does not support hooks, registerhooks should  be  set  to\nthe NULL pointer.\n\nThe  version  argument  describes  the  version  of the hooks API supported by the sudo\nfront-end.\n\nThe registerhook() function should be used to register any supported hooks the  plugin\nneeds.  It returns 0 on success, 1 if the hook type is not supported, and -1 if the ma‐\njor version in struct sudohook does not match the front-end's major hook API version.\n\nSee the “Hook function API” section below for more information about hooks.\n\nThe  registerhooks() function is only available starting with API version 1.2.  If the\nsudo front-end doesn't support API version 1.2 or higher, registerhooks() will not  be\ncalled.\n\nderegisterhooks\nvoid (*deregisterhooks)(int version,\nint (*deregisterhook)(struct sudohook *hook));\n\nThe deregisterhooks() function is called by the sudo front-end to deregister any hooks\nthe  plugin  has  registered.   If  the plugin does not support hooks, deregisterhooks\nshould be set to the NULL pointer.\n\nThe version argument describes the version of the  hooks  API  supported  by  the  sudo\nfront-end.\n\nThe  deregisterhook() function should be used to deregister any hooks that were put in\nplace by the registerhook() function.  If the plugin tries to deregister a  hook  that\nthe front-end does not support, deregisterhook() will return an error.\n\nSee the “Hook function API” section below for more information about hooks.\n\nThe  deregisterhooks()  function  is only available starting with API version 1.2.  If\nthe sudo front-end doesn't support API version 1.2 or higher,  deregisterhooks()  will\nnot be called.\n\neventalloc\nstruct sudopluginevent * (*eventalloc)(void);\n\nThe  eventalloc()  function  is used to allocate a struct sudopluginevent which pro‐\nvides access to the main sudo event loop.  Unlike the  other  fields,  the  eventalloc\npointer is filled in by the sudo front-end, not by the plugin.\n\nSee the “Event API” section below for more information about events.\n\nThe  eventalloc()  function  is only available starting with API version 1.15.  If the\nsudo front-end doesn't support API version 1.15 or higher, eventalloc will not be set.\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"
                },
                {
                    "name": "I/O plugin API",
                    "content": "struct ioplugin {\n#define SUDOIOPLUGIN 2\nunsigned int type; /* always SUDOIOPLUGIN */\nunsigned int version; /* always SUDOAPIVERSION */\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudopluginprintf, 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.  This makes it pos‐\nsible to log the input and output from the user's session.  If any  of  the  standard  input,\nstandard  output, or standard error do not correspond to a tty, sudo will open a pipe to cap‐\nture the I/O for logging before passing it on.\n\nThe logttyin() function receives the raw user input from the terminal device (this will  in‐\nclude  input  even when echo is disabled, such as when a password is read).  The logttyout()\nfunction receives output from the pseudo-terminal that is suitable for replaying  the  user's\nsession  at a later time.  The logstdin(), logstdout(), and logstderr() functions are only\ncalled if the standard input, standard output, or standard error respectively  correspond  to\nsomething other than a tty.\n\nAny of the logging functions may be set to the NULL pointer if no logging is to be performed.\nIf the open function returns 0, no I/O will be sent to the plugin.\n\nIf  a  logging function returns an error (-1), the running command will be terminated and all\nof the plugin's logging functions will be disabled.  Other I/O logging plugins will still re‐\nceive any remaining input or output that has not yet been processed.\n\nIf an input logging function rejects the data by returning 0, the command will be  terminated\nand the data will not be passed to the command, though it will still be sent to any other I/O\nlogging  plugins.  If an output logging function rejects the data by returning 0, the command\nwill be terminated and the data will not be written to the terminal, though it will still  be\nsent to any other I/O logging plugins.\n\nA struct auditplugin 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 against.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudopluginprintf, 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(),  logstdin(),\nlogstdout(), logstderr(), logsuspend(), changewinsize(),  or  showversion()  func‐\ntions are called.  It is only called if the version is being requested or if the policy\nplugin's checkpolicy() function has returned successfully.  It returns 1 on success, 0\non  failure,  -1 if a general error occurred, or -2 if there was a usage error.  In the\nlatter case, sudo will print a usage message before it exits.  If an error occurs,  the\nplugin  may  optionally  call  the conversation() or sudopluginprintf() function with\nSUDOCONFERRORMSG to present additional 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 the major and  minor\nversion number of the plugin API supported by sudo.\n\nconversation\nA pointer to the conversation() function that may be used by the Fa(showversion)\nfunction   to  display  version  information  (see  showversion()  below).   The\nconversation() function may also be used to display additional error  message  to\nthe user.  The conversation() function returns 0 on success and -1 on failure.\n\nsudopluginprintf\nA  pointer  to  a  printf()-style function that may be used by the showversion()\nfunction  to  display  version  information  (see   showversion   below).    The\nsudopluginprintf()  function  may also be used to display additional error mes‐\nsage to the user.  The sudopluginprintf() 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 “name=value” strings.  The\nvector is terminated by a NULL pointer.  These settings correspond to options the\nuser specified when running sudo.  As such, they will only be  present  when  the\ncorresponding option has been specified on the command line.\n\nWhen  parsing  settings,  the  plugin  should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible settings.\n\nuserinfo\nA vector of information about the  user  running  the  command  in  the  form  of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen  parsing  userinfo,  the  plugin should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\ncommandinfo\nA vector of  information  describing  the  command  being  run  in  the  form  of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen  parsing commandinfo, the plugin should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nargc  The number of elements in argv, not counting the final NULL pointer.  It  can  be\nzero, such as when sudo is called with the -V option.\n\nargv  If  non-NULL,  an  argument vector describing a command the user wishes to run in\nthe same form as what would be passed to the execve(2) system call.\n\nuserenv\nThe user's environment in the form of a NULL-terminated  vector  of  “name=value”\nstrings.\n\nWhen  parsing  userenv,  the  plugin  should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path are treated as  argu‐\nments to the plugin.  These arguments are split on a white space boundary and are\npassed  to  the  plugin in the form of a NULL-terminated array of strings.  If no\narguments were specified, pluginoptions will be the NULL pointer.\n\nThe pluginoptions parameter is only available starting with API version 1.2.   A\nplugin  must  check  the API version specified by the sudo front-end before using\npluginoptions.  Failure to do so may result in a crash.\n\nerrstr\nIf the open() function returns a value other than 1, the plugin may store a  mes‐\nsage  describing  the  failure  or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 before it exits.\n\nThe function arguments are as follows:\n\nexitstatus\nThe  command's exit status, as returned by the wait(2) system call, or zero if no\ncommand was run.  The value of exitstatus is undefined if error is non-zero.\n\nerror\nIf the command could not be executed, this is set to the value of  errno  set  by\nthe  execve(2)  system call.  If the command was successfully executed, the value\nof error is zero.\n\nshowversion\nint (*showversion)(int verbose);\n\nThe showversion() function is called by sudo when the user specifies  the  -V  option.\nThe  plugin  may  display its version information to the user via the conversation() or\nsudopluginprintf() function using SUDOCONVINFOMSG.  If the user requests  detailed\nversion information, the verbose flag will be non-zero.\n\nReturns  1 on success, 0 on failure, -1 if a general error occurred, or -2 if there was\na usage error, although the return value is currently 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 the user  but  before\nit  is  passed  to  the  running  command.  This allows the plugin to reject data if it\nchooses to (for instance if the input contains banned content).  Returns 1 if the  data\nshould  be  passed  to the command, 0 if the data is rejected (which will terminate the\nrunning 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 plugin may store  a\nmessage  describing the failure or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 the command but be‐\nfore it is written to the user's terminal.  This allows the plugin to reject data if it\nchooses to (for instance if the output contains banned content).  Returns 1 if the data\nshould be passed to the user, 0 if the data is rejected (which will terminate the  run‐\nning 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, the plugin may store a\nmessage  describing the failure or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 not correspond to a\ntty device.  It is called whenever data can be read from the standard input but  before\nit  is  passed  to  the  running  command.  This allows the plugin to reject data if it\nchooses to (for instance if the input contains banned content).  Returns 1 if the  data\nshould  be  passed  to the command, 0 if the data is rejected (which will terminate the\nrunning 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 logstdin() function returns a value other than 1, the plugin may store  a\nmessage  describing the failure or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 not correspond to a\ntty device.  It is called whenever data can be read from the command but before  it  is\nwritten to the standard output.  This allows the plugin to reject data if it chooses to\n(for  instance if the output contains banned content).  Returns 1 if the data should be\npassed to the user, 0 if the data is rejected (which will terminate  the  running  com‐\nmand), 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, the plugin may store a\nmessage  describing the failure or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 not correspond to a\ntty device.  It is called whenever data can be read from the command but before  it  is\nwritten  to the standard error.  This allows the plugin to reject data if it chooses to\n(for instance if the output contains banned content).  Returns 1 if the data should  be\npassed  to  the  user, 0 if the data is rejected (which will terminate the running com‐\nmand), 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, the plugin may store a\nmessage describing the failure or error in errstr.  The sudo front-end will  then\npass  this  value  to  any registered audit plugins.  The string stored in errstr\nmust remain valid until the plugin's close() function is called.\n\nThe errstr parameter is only available starting with API version 1.15.  A  plugin\nmust  check  the API version specified by the sudo front-end before using errstr.\nFailure to do so may result in a crash.\n\nregisterhooks\nSee the “Policy plugin API” section for a description of registerhooks().\n\nderegisterhooks\nSee the “Policy plugin API” section for a description of deregisterhooks().\n\nchangewinsize\nint (*changewinsize)(unsigned int lines, unsigned int cols,\nconst char errstr);\n\nThe changewinsize() function is called  whenever  the  window  size  of  the  terminal\nchanges  from the initial values specified in the userinfo list.  Returns -1 if an er‐\nror occurred, in which case no further 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  1,  the  plugin  may\nstore  a  message  describing the failure or error in errstr.  The sudo front-end\nwill then pass this value to any registered audit plugins.  The string stored  in\nerrstr must remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do 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 suspended or resumed.  Log‐\nging this information makes it possible to skip the period of time when the command was\nsuspended during playback 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 SIGCONT if the command was\nresumed.\n\nerrstr\nIf the logsuspend() function returns a value other than 1, the plugin may  store\na  message  describing  the  failure or error in errstr.  The sudo front-end will\nthen pass this value to any registered  audit  plugins.   The  string  stored  in\nerrstr must remain valid until the plugin's close() function is called.\n\nThe  errstr parameter is only available starting with API version 1.15.  A plugin\nmust check the API version specified by the sudo front-end before  using  errstr.\nFailure to do so may result in a crash.\n\neventalloc\nstruct sudopluginevent * (*eventalloc)(void);\n\nThe  eventalloc()  function is used to allocate a struct sudopluginevent which\nprovides access to the main sudo  event  loop.   Unlike  the  other  fields,  the\neventalloc() pointer is filled in by the sudo front-end, not by the plugin.\n\nSee the “Event API” section below for more information about events.\n\nThe  eventalloc() function is only available starting with API version 1.15.  If\nthe sudo front-end doesn't support API version 1.15 or higher, eventalloc() will\nnot be set.\n\nI/O Plugin Version Macros\n\nSame as for the “Policy plugin API”.\n"
                },
                {
                    "name": "Audit plugin API",
                    "content": "/* 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 sudopluginprintf, 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 to run sudo  indepen‐\ndent  of  the  policy  or  any  I/O  plugins.   Multiple  audit  plugins  may be specified in\nsudo.conf(5).\n\nA struct auditplugin 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 against.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudopluginprintf, 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  functions.   This\nmakes  it  possible to audit failures in the other plugins.  It returns 1 on success, 0\non failure, -1 if a general error occurred, or -2 if there was a usage error.   In  the\nlatter  case, sudo will print a usage message before it exits.  If an error occurs, the\nplugin  may  optionally  call  the  conversation()  or  pluginprintf()  function  with\nSUDOCONFERRORMSG to present additional 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 the major and minor\nversion number of the plugin API supported by sudo.\n\nconversation\nA pointer to the conversation() function that may be used by  the  showversion()\nfunction   to  display  version  information  (see  showversion()  below).   The\nconversation() function may also be used to display additional error  message  to\nthe user.  The conversation() function returns 0 on success, and -1 on failure.\n\npluginprintf\nA  pointer  to  a  printf()-style function that may be used by the showversion()\nfunction  to  display  version  information  (see   showversion   below).    The\npluginprintf()  function may also be used to display additional error message to\nthe user.  The pluginprintf() function returns number of characters  printed  on\nsuccess and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of “name=value” strings.  The\nvector is terminated by a NULL pointer.  These settings correspond to options the\nuser  specified  when  running sudo.  As such, they will only be present when the\ncorresponding option has been specified on the command line.\n\nWhen parsing settings, the plugin should split on  the  first  equal  sign  (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible settings.\n\nuserinfo\nA  vector  of  information  about  the  user  running  the command in the form of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen parsing userinfo, the plugin should split on the  first  equal  sign  (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nsubmitoptind\nThe index into submitargv that corresponds to the first entry that is not a com‐\nmand line option.  If submitargv only consists of options, which may be the case\nwith  the  -l or -v options, submitargv[submitoptind] will evaluate to the NULL\npointer.\n\nsubmitargv\nThe argument vector sudo was invoked with, including all  command  line  options.\nThe  submitoptind  argument can be used to determine the end of the command line\noptions.\n\nsubmitenvp\nThe invoking user's environment in  the  form  of  a  NULL-terminated  vector  of\n“name=value” strings.\n\nWhen  parsing  submitenvp, the plugin should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\npluginoptions\nAny (non-comment) strings immediately after the plugin path are treated as  argu‐\nments to the plugin.  These arguments are split on a white space boundary and are\npassed  to  the  plugin in the form of a NULL-terminated array of strings.  If no\narguments were specified, pluginoptions will be the NULL pointer.\n\nerrstr\nIf the open() function returns a value other than 1, the plugin may store a  mes‐\nsage  describing  the  failure  or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain 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 before it exits.\n\nThe function arguments are as follows:\n\nstatustype\nThe    type    of   status   being   passed.    One   of   SUDOPLUGINNOSTATUS,\nSUDOPLUGINWAITSTATUS, SUDOPLUGINEXECERROR or SUDOPLUGINSUDOERROR.\n\nstatus\nDepending on the value of statustype, this value is  either  ignored,  the  com‐\nmand's exit status as returned by the wait(2) system call, the value of errno set\nby  the  execve(2)  system call, or the value of errno resulting from an error in\nthe sudo 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 accepted by a policy or ap‐\nproval plugin.  The function arguments are as follows:\n\npluginname\nThe name of the plugin that accepted the command or “sudo” for  the  sudo  front-\nend.\n\nplugintype\nThe    type   of   plugin   that   accepted   the   command,   currently   either\nSUDOPOLICYPLUGIN, SUDOPOLICYAPPROVAL, or SUDOFRONTEND.  The accept()  func‐\ntion  is called multiple times--once for each policy or approval plugin that suc‐\nceeds and once for the sudo front-end.  When called on behalf of the sudo  front-\nend, commandinfo may include information from an I/O logging plugin as well.\n\nTypically,  an  audit  plugin  is interested in either the accept status from the\nsudo front-end or from the various policy and approval plugins, but not both.  It\nis possible for the policy plugin to accept a command that is later  rejected  by\nan  approval plugin, in which case the audit plugin's accept() and reject() func‐\ntions will both be called.\n\ncommandinfo\nAn optional vector of information describing the command being run in the form of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the first equal sign  (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nrunargv\nA  NULL-terminated  argument  vector describing a command that will be run in the\nsame form as what would be passed to the execve(2) system call.\n\nrunenvp\nThe environment the command will be run with in the  form  of  a  NULL-terminated\nvector of “name=value” strings.\n\nWhen  parsing  runenvp,  the  plugin  should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nerrstr\nIf the accept() function returns a value other than 1, the  plugin  may  store  a\nmessage  describing the failure or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain 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 rejected by a plugin.  The\nfunction 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    either\nSUDOPOLICYPLUGIN, SUDOAPPROVALPLUGIN, or SUDOIOPLUGIN.\n\nUnlike  the  accept()  function, the reject() function is not called on behalf of\nthe sudo front-end.\n\nauditmsg\nAn optional string describing the reason the command was rejected by the  plugin.\nIf the plugin did not provide a reason, auditmsg will be the NULL pointer.\n\ncommandinfo\nAn optional vector of information describing the command being run in the form of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen  parsing commandinfo, the plugin should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nerrstr\nIf the reject() function returns a value other than 1, the  plugin  may  store  a\nmessage  describing the failure or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain 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 returns an error.\nThe function arguments are as follows:\n\npluginname\nThe name of the plugin that generated the error or “sudo” for the sudo front-end.\n\nplugintype\nThe type of plugin that generated the  error,  or  SUDOFRONTEND  for  the  sudo\nfront-end.\n\nauditmsg\nAn  optional string describing the plugin error.  If the plugin did not provide a\ndescription, auditmsg will be the NULL pointer.\n\ncommandinfo\nAn optional vector of information describing the command being run in the form of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen parsing commandinfo, the plugin should split on the first equal sign  (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nerrstr\nIf the error() function returns a value other than 1, the plugin may store a mes‐\nsage  describing  the  failure  or error in errstr.  The sudo front-end will then\npass this value to any registered audit plugins.  The  string  stored  in  errstr\nmust remain 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 specifies the -V option.\nThe plugin may display its version information to the user via  the  conversation()  or\npluginprintf()  function using SUDOCONVINFOMSG.  If the user requests detailed ver‐\nsion information, the verbose flag will be set.\n\nReturns 1 on success, 0 on failure, -1 if a general error occurred, or -2 if there  was\na usage error, although the return value is currently ignored.\n\nregisterhooks\nSee the “Policy plugin API” section for a description of registerhooks().\n\nderegisterhooks\nSee the “Policy plugin API” section for a description of deregisterhooks().\n\neventalloc\nstruct sudopluginevent * (*eventalloc)(void);\n\nThe  eventalloc()  function  is used to allocate a struct sudopluginevent which pro‐\nvides access to the main sudo event loop.  Unlike the  other  fields,  the  eventalloc\npointer is filled in by the sudo front-end, not by the plugin.\n\nSee the “Event API” section below for more information about events.\n\nThe  eventalloc()  function  is only available starting with API version 1.17.  If the\nsudo front-end doesn't support API version 1.17 or higher, eventalloc()  will  not  be\nset.\n"
                },
                {
                    "name": "Approval plugin API",
                    "content": "struct approvalplugin {\n#define SUDOAPPROVALPLUGIN 4\nunsigned int type; /* always SUDOAPPROVALPLUGIN */\nunsigned int version; /* always SUDOAPIVERSION */\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudopluginprintf, 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 has been accepted\nby the policy plugin.  Unlike the other plugin types, it does not remain open until the  com‐\nmand  completes.   The plugin is opened before a call to check() or showversion() and closed\nshortly thereafter (audit plugin functions must be called before the plugin is closed).  Mul‐\ntiple approval plugins may be specified in sudo.conf(5).\n\nA struct approvalplugin 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 against.\n\nopen\nint (*open)(unsigned int version, sudoconvt conversation,\nsudoprintft sudopluginprintf, 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 the  plugin's  check()\nor showversion() functions.  It is only called if the version is being requested or if\nthe policy plugin's checkpolicy() function has returned successfully.  It returns 1 on\nsuccess,  0  on failure, -1 if a general error occurred, or -2 if there was a usage er‐\nror.  In the latter case, sudo will print a usage message before it exits.  If an error\noccurs, the plugin may optionally call the conversation() or  pluginprintf()  function\nwith SUDOCONFERRORMSG to present additional 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 the major and minor\nversion number of the plugin API supported by sudo.\n\nconversation\nA pointer to the conversation() function that can be used by the plugin to inter‐\nact with the user (see “Conversation API” for details).  Returns 0 on success and\n-1 on failure.\n\npluginprintf\nA pointer to a printf()-style function that may be used to display  informational\nor  error  messages  (see “Conversation API” for details).  Returns the number of\ncharacters printed on success and -1 on failure.\n\nsettings\nA vector of user-supplied sudo settings in the form of “name=value” strings.  The\nvector is terminated by a NULL pointer.  These settings correspond to options the\nuser specified when running sudo.  As such, they will only be  present  when  the\ncorresponding option has been specified on the command line.\n\nWhen  parsing  settings,  the  plugin  should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible settings.\n\nuserinfo\nA vector of information about the  user  running  the  command  in  the  form  of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen  parsing  userinfo,  the  plugin should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nsubmitoptind\nThe index into submitargv that corresponds to the first entry that is not a com‐\nmand line option.  If submitargv only consists of options, which may be the case\nwith the -l or -v options, submitargv[submitoptind] will evaluate to  the  NULL\npointer.\n\nsubmitargv\nThe  argument  vector  sudo was invoked with, including all command line options.\nThe submitoptind argument can be used to determine the end of the  command  line\noptions.\n\nsubmitenvp\nThe  invoking  user's  environment  in  the  form  of a NULL-terminated vector of\n“name=value” strings.\n\nWhen parsing submitenvp, the plugin should split on the first equal  sign  (‘=’)\nsince the name field will never include one itself but the value might.\n\npluginoptions\nAny  (non-comment) strings immediately after the plugin path are treated as argu‐\nments to the plugin.  These arguments are split on a white space boundary and are\npassed to the plugin in the form of a NULL-terminated array of  strings.   If  no\narguments were specified, pluginoptions will be the NULL pointer.\n\nerrstr\nIf  the open() function returns a value other than 1, the plugin may store a mes‐\nsage describing the failure or error in errstr.  The  sudo  front-end  will  then\npass  this  value  to  any registered audit plugins.  The string stored in errstr\nmust remain 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()  or  showversion()\nfunctions  have been called.  It takes no arguments.  The close() function is typically\nused to perform plugin-specific cleanup, such as the freeing of  memory  objects  allo‐\ncated  by  the plugin.  If the plugin does not need to perform any cleanup, close() may\nbe 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  checkpolicy()  function\nand before any I/O logging plugins.  If multiple approval plugins are loaded, they must\nall  succeed  for the command 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  the  latter  case,\nsudo  will  print  a usage message before it exits.  If an error occurs, the plugin may\noptionally call the conversation() 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  the  form  of\n“name=value” strings.  The vector is terminated by a NULL pointer.\n\nWhen  parsing commandinfo, the plugin should split on the first equal sign (‘=’)\nsince the name field will never include one itself but the value might.\n\nSee the “Policy plugin API” section for a list of all possible strings.\n\nrunargv\nA NULL-terminated argument vector describing a command that will be  run  in  the\nsame form as what would be passed to the execve(2) system call.\n\nrunenvp\nThe  environment  the  command  will be run with in the form of a NULL-terminated\nvector of “name=value” strings.\n\nWhen parsing runenvp, the plugin should split on  the  first  equal  sign  (‘=’)\nsince the name field will never include one itself but the value might.\n\nerrstr\nIf  the open() function returns a value other than 1, the plugin may store a mes‐\nsage describing the failure or error in errstr.  The  sudo  front-end  will  then\npass  this  value  to  any registered audit plugins.  The string stored in errstr\nmust remain 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 specifies  the  -V  option.\nThe  plugin  may  display its version information to the user via the conversation() or\npluginprintf() function using SUDOCONVINFOMSG.  If the user requests detailed  ver‐\nsion information, the verbose flag will be set.\n\nReturns  1 on success, 0 on failure, -1 if a general error occurred, or -2 if there was\na usage error, although the return value is currently ignored.\n"
                },
                {
                    "name": "Signal handlers",
                    "content": "The sudo front-end installs default signal handlers to trap common signals while  the  plugin\nfunctions  are  run.  The following signals are trapped by default before the command is exe‐\ncuted:\n\n•  SIGALRM\n•  SIGHUP\n•  SIGINT\n•  SIGPIPE\n•  SIGQUIT\n•  SIGTERM\n•  SIGTSTP\n•  SIGUSR1\n•  SIGUSR2\n\nIf a fatal signal is received before the command is executed, sudo  will  call  the  plugin's\nclose()  function  with an exit status of 128 plus the value of the signal that was received.\nThis allows for consistent logging of commands killed by a signal for plugins that  log  such\ninformation in their close() function.  An exception to this is SIGPIPE, which is ignored un‐\ntil the command is executed.\n\nA  plugin  may temporarily install its own signal handlers but must restore the original han‐\ndler before the plugin function returns.\n"
                },
                {
                    "name": "Hook function API",
                    "content": "Beginning with plugin API version 1.2, it is possible to install hooks for certain  functions\ncalled by the sudo front-end.\n\nCurrently,  the  only supported hooks relate to the handling of environment variables.  Hooks\ncan be used to intercept attempts to get, set, or remove environment variables so that  these\nchanges can be reflected in the version of the environment that is used to execute a command.\nA future version of the API will support hooking internal sudo front-end functions as 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\nA struct sudohook 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 types:\n\nSUDOHOOKSETENV\nThe C library setenv(3) function.  Any registered hooks will run before the C li‐\nbrary  implementation.   The  hookfn field should be a function that matches the\nfollowing 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 are unspecified.\n\nSUDOHOOKUNSETENV\nThe C library unsetenv(3) function.  Any registered hooks will run before  the  C\nlibrary  implementation.  The hookfn field should be a function that matches the\nfollowing typedef:\n\ntypedef int (*sudohookfnunsetenvt)(const char *name,\nvoid *closure);\n\nSUDOHOOKGETENV\nThe C library getenv(3) function.  Any registered hooks will run before the C li‐\nbrary implementation.  The hookfn field should be a function  that  matches  the\nfollowing typedef:\n\ntypedef int (*sudohookfngetenvt)(const char *name,\nchar value, void *closure);\n\nIf the registered hook does not match the typedef the results are unspecified.\n\nSUDOHOOKPUTENV\nThe C library putenv(3) function.  Any registered hooks will run before the C li‐\nbrary  implementation.   The  hookfn field should be a function that matches the\nfollowing typedef:\n\ntypedef int (*sudohookfnputenvt)(char *string,\nvoid *closure);\n\nIf the registered hook does not match the typedef the results are unspecified.\n\nhookfn\nsudohookfnt hookfn;\n\nThe hookfn field should be set to the plugin's hook implementation.  The actual  func‐\ntion  arguments  will  vary  depending  on the hooktype (see hooktype above).  In all\ncases, the closure field of struct sudohook is passed as the last function  parameter.\nThis can be used to pass arbitrary data to the plugin's hook implementation.\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 (including the system\nimplementation if applicable).   For  example,  a  getenv(3)  hook  might  return\nSUDOHOOKRETNEXT if the specified variable was not found in the private copy of\nthe environment.\n\nSUDOHOOKRETSTOP\nThe  hook  completed  without  error,  stop processing hooks for this invocation.\nThis can be used to replace the system implementation.   For  example,  a  setenv\nhook  that  operates  on a private copy of the environment but leaves environ un‐\nchanged.\n\nCare must be taken when hooking C library functions, it is very easy to  create  an  infinite\nloop.  For example, a getenv(3) hook that calls the snprintf(3) function may create a loop if\nthe snprintf(3) implementation calls getenv(3) to check the locale.  To prevent this, you may\nwish  to use a static variable in the hook function to guard against nested calls.  For exam‐\nple:\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"
                },
                {
                    "name": "Event API",
                    "content": "When sudo runs a command, it uses an event loop to service signals and I/O.   Events  may  be\ntriggered  based  on time, a file or socket descriptor becoming ready, or due to receipt of a\nsignal.  Starting with API version 1.15, it is possible for a plugin to participate  in  this\nevent loop by calling 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\nA struct sudopluginevent 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 signal number for sig‐\nnal events.  For time-based events, fd must be -1.\n\nevents\nThe following values determine what will trigger the event callback:\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 explicitly deleted\n\nSUDOPLUGINEVSIGNAL\ncallback is run when the specified signal is received\n\nThe SUDOPLUGINEVPERSIST flag may be ORed with any of the event types.   It  is\nalso  possible to OR SUDOPLUGINEVREAD and SUDOPLUGINEVWRITE together to run\nthe callback when a descriptor 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 callback() function is run\nwith the following arguments:\n\nfd    The file or socket descriptor for I/O-based events or the signal number for\nsignal events.\n\nwhat  The event type that triggered that callback.  For events that have multiple\nevent types (for example SUDOPLUGINEVREAD and  SUDOPLUGINEVWRITE)  or\nhave  an associated timeout, what can be used to determine why the callback\nwas run.\n\nclosure\nThe generic pointer that was specified in the set() function.\n\nclosure\nA generic pointer that will be passed to the callback function.\n\nThe set() function returns 1 on success, and -1 if a error occurred.\n\nadd\nint (*add)(struct sudopluginevent *pev, struct timespec *timeout);\n\nThe add() function adds the event pev to sudo's event loop.  The event must have previ‐\nously been initialized via the set() function.  If the timeout argument is not NULL, it\nshould specify a (relative) timeout after which the event will be triggered if the main\nevent criteria has not been met.  This is often used to implement an I/O timeout  where\nthe  event will fire if a descriptor is not ready within a certain time period.  If the\nevent is already present in the event loop, its timeout will be adjusted to  match  the\nnew value, if any.\n\nThe add() function returns 1 on success, and -1 if a error occurred.\n\ndel\nint (*del)(struct sudopluginevent *pev);\n\nThe del() function deletes the event pev from sudo's event loop.  Deleted events can be\nadded back via the add() function.\n\nThe del() function returns 1 on success, and -1 if a error occurred.\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 events is pending.\nThe events argument specifies which events to check for.  See the set() function for  a\nlist of valid event types.  If SUDOPLUGINEVTIMEOUT is specified in events, the event\nhas an associated timeout and the ts pointer is non-NULL, it will be filled in with the\nremaining time.\n\nfd\nint (*fd)(struct sudopluginevent *pev);\n\nThe  fd()  function  returns  the descriptor or signal number associated with the event\npev.\n\nsetbase\nvoid (*setbase)(struct sudopluginevent *pev, void *base);\n\nThe setbase() function sets the underlying event base for pev to the  specified  value.\nThis  can  be used to move an event created via eventalloc() to a new event loop allo‐\ncated by sudo's event subsystem.  If base is NULL, pev's event base is reset to the de‐\nfault value, which corresponds to sudo's main event loop.  Using this function requires\nlinking the plugin with the sudoutil library.  It is unlikely to be  used  outside  of\nthe sudoers plugin.\n\nloopbreak\nvoid (*loopbreak)(struct sudopluginevent *pev);\n\nThe  loopbreak()  function causes sudo's event loop to exit immediately and the running\ncommand to be terminated.\n\nfree\nvoid (*free)(struct sudopluginevent *pev);\n\nThe free() function deletes the event pev from the event loop and frees the memory  as‐\nsociated with it.\n"
                },
                {
                    "name": "Remote command execution",
                    "content": "The  sudo  front-end  does  not support running remote commands.  However, starting with sudo\n1.8.8, the -h option may be used to specify a remote host that is passed to the  policy  plu‐\ngin.   A  plugin  may also accept a runasuser in the form of “user@hostname” which will work\nwith older versions of sudo.  It is anticipated that remote commands will be supported by ex‐\necuting a “helper” program.  The policy plugin should setup the  execution  environment  such\nthat  the  sudo front-end will run the helper which, in turn, will connect to the remote host\nand run the command.\n\nFor example, the policy plugin could utilize ssh to perform remote  command  execution.   The\nhelper  program would be responsible for running ssh with the proper options to use a private\nkey or certificate that the remote host will accept and run a program on the remote host that\nwould setup the execution environment accordingly.\n\nRemote sudoedit functionality must be handled by the policy plugin, not sudo  itself  as  the\nfront-end has no knowledge that a remote command is being executed.  This may be addressed in\na future revision of the plugin API.\n"
                },
                {
                    "name": "Conversation API",
                    "content": "If  the plugin needs to interact with the user, it may do so via the conversation() function.\nA plugin should not attempt to read directly from the standard input or the  user's  terminal\n(neither  of  which  are guaranteed to exist).  The caller must include a trailing newline in\nmsg if one is to be printed.\n\nA printf()-style function is also available that can be used to display informational or  er‐\nror  messages  to the user, which is usually more convenient for simple messages where no use\ninput is required.\n\nConversation function structures\n\nThe conversation function takes as arguments pointers to the following structures:\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  to  the  plugin's\nopen()  function  when the plugin is initialized.  The following type definitions can be used\nin the declaration of the open() function:\n\ntypedef int (*sudoconvt)(int nummsgs,\nconst struct sudoconvmessage msgs[],\nstruct sudoconvreply replies[], struct sudoconvcallback *callback);\n\ntypedef int (*sudoprintft)(int msgtype, const char * restrict fmt, ...);\n\nTo use the conversation() function, the plugin must pass an array of struct sudoconvmessage\nand  struct  sudoconvreply.   There  must  be  a  struct   sudoconvmessage   and   struct\nsudoconvreply for each message in the conversation, that is, both arrays must have the same\nnumber  of  elements.   Each struct sudoconvreply must have its reply member initialized to\nNULL.  The struct sudoconvcallback pointer, if not NULL, should contain  function  pointers\nto  be  called  when  the sudo process is suspended and/or resumed during conversation input.\nThe onsuspend and onresume functions are called with the signal that caused sudo to be sus‐\npended and the closure pointer from the struct sudoconvcallback.   These  functions  should\nreturn  0  on success and -1 on error.  On error, the conversation will end and the conversa‐\ntion function will return a value of -1.  The intended use is to allow the plugin to  release\nresources, such as locks, that should not be held indefinitely while suspended and then reac‐\nquire them when the process is resumed.  The functions are not actually invoked from within a\nsignal 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 used for passwords.\nThe reply will be stored in the replies array, and it will never be NULL.\n\nSUDOCONVPROMPTECHOON\nPrompt the user for input with echo enabled.  The reply will be stored in  the  replies\narray, and it will never be NULL.\n\nSUDOCONVERRORMSG\nDisplay  an  error  message.   The  message is written to the standard error unless the\nSUDOCONVPREFERTTY flag is set, in which case it is written to the user's terminal if\npossible.\n\nSUDOCONVINFOMSG\nDisplay a  message.   The  message  is  written  to  the  standard  output  unless  the\nSUDOCONVPREFERTTY flag is set, in which case it is written to the user's terminal if\npossible.\n\nSUDOCONVPROMPTMASK\nPrompt  the user for input but echo an asterisk character for each character read.  The\nreply will be stored in the replies array, and it will never be NULL.  This can be used\nto provide visual feedback to the user while reading sensitive information that  should\nnot be displayed.\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 message type is\nSUDOCONVPROMPTECHOOFF or SUDOCONVPROMPTMASK.  By default, sudo  will  refuse  to\nread input if the echo cannot be disabled for those message types.\n\nSUDOCONVPREFERTTY\nWhen  displaying  a message via SUDOCONVERRORMSG or SUDOCONVINFOMSG, try to write\nthe message to the user's terminal.  If the terminal is unavailable, the standard error\nor standard  output  will  be  used,  depending  upon  whether  SUDOCONVERRORMSG  or\nSUDOCONVINFOMSG  was used.  The user's terminal is always used when possible for in‐\nput, this flag is only used for output.\n\nThe timeout in seconds until the prompt will wait for no more input.  A zero value implies an\ninfinite timeout.\n\nThe  plugin  is  responsible  for  freeing  the  reply  buffer   located   in   each   struct\nsudoconvreply,  if it is not NULL.  SUDOCONVREPLMAX represents the maximum length of the\nreply buffer (not including the trailing NUL character).  In practical  terms,  this  is  the\nlongest password sudo will support.\n\nThe printf()-style function uses the same underlying mechanism as the conversation() function\nbut  only supports SUDOCONVINFOMSG and SUDOCONVERRORMSG for the msgtype parameter.  It\ncan be more convenient than using the conversation() function if no user reply is needed  and\nsupports standard printf() escape sequences.\n\nSee the sample plugin for an example of the conversation() function usage.\n"
                },
                {
                    "name": "Plugin invocation order",
                    "content": "As of sudo 1.9.0, the plugin open() and close() functions are called in the 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 policy close() func‐\ntion.\n"
                },
                {
                    "name": "Sudoers group plugin API",
                    "content": "The sudoers plugin supports its own plugin interface to allow non-Unix group  lookups.   This\ncan  be used to query a group source other than the standard Unix group database.  Two sample\ngroup  plugins  are  bundled  with  sudo,  groupfile,  and  systemgroup,  are  detailed  in\nsudoers(5).  Third party group plugins include a QAS AD plugin available from Quest Software.\n\nA  group  plugin must declare and populate a struct sudoersgroupplugin in the global scope.\nThis structure contains pointers to  the  functions  that  implement  plugin  initialization,\ncleanup, and group lookup.\n\nstruct sudoersgroupplugin {\nunsigned int version;\nint (*init)(int version, sudoprintft sudopluginprintf,\nchar *const argv[]);\nvoid (*cleanup)(void);\nint (*query)(const char *user, const char *group,\nconst struct passwd *pwd);\n};\n\nA struct sudoersgroupplugin 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 was built against.\n\ninit\nint (*init)(int version, sudoprintft sudopluginprintf,\nchar *const argv[]);\n\nThe  init()  function  is  called  after  sudoers has been parsed but before any policy\nchecks.  It returns 1 on success, 0 on failure (or if the plugin  is  not  configured),\nand   -1  if  a  error  occurred.   If  an  error  occurs,  the  plugin  may  call  the\npluginprintf() function with SUDOCONFERRORMSG to present additional error  informa‐\ntion to the user.\n\nThe function arguments are as follows:\n\nversion\nThe version passed in by sudoers allows the plugin to determine the major and mi‐\nnor version number of the group plugin API supported by sudoers.\n\npluginprintf\nA  pointer to a printf()-style function that may be used to display informational\nor error message to the user.  Returns the number of characters printed  on  suc‐\ncess and -1 on failure.\n\nargv  A  NULL-terminated  array  of arguments generated from the groupplugin option in\nsudoers.  If no arguments were given, argv will be NULL.\n\ncleanup\nvoid (*cleanup)();\n\nThe cleanup() function is called when sudoers has finished its group checks.  The  plu‐\ngin should free any memory it has allocated and 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 is 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 database.\n\ngroup\nThe name of the group being queried.\n\npwd   The  password  database  entry  for  user, if any.  If user is not present in the\npassword 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"
                }
            ]
        },
        "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 commandinfo list  as\nan argument.\n\nVersion 1.2 (sudo 1.8.5)\nThe  Policy  and  I/O logging plugins' open() functions are now passed a list of plugin\nparameters if any are specified in sudo.conf(5).\n\nA simple hooks API has been introduced to allow plugins to hook in to the system's  en‐\nvironment handling functions.\n\nThe  initsession() Policy plugin function is now passed a pointer to the user environ‐\nment which can be updated as needed.  This can be used to merge  in  environment  vari‐\nables stored in the PAM handle before a command is run.\n\nVersion 1.3 (sudo 1.8.7)\nSupport for the execbackground entry has been added to the commandinfo list.\n\nThe maxgroups and plugindir entries were added to the settings list.\n\nThe  version() and close() functions are now optional.  Previously, a missing version()\nor close() function would result in a crash.  If no policy plugin close()  function  is\ndefined,  a  default  close() function will be provided by the sudo front-end that dis‐\nplays a warning if the command could not be executed.\n\nThe sudo front-end now installs default signal handlers to trap  common  signals  while\nthe 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 changed.  Previously,\nthe  sudo  front-end  took  no  action when the logttyin(), logttyout(), logstdin(),\nlogstdout(), or logstderr() function returned an error.\n\nThe behavior when an I/O logging plugin returns 0 has changed.  Previously, output from\nthe command would be displayed to the terminal even if an output logging  function  re‐\nturned 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 may occur multiple\ntimes if there are multiple plugin-specific Debug lines in the sudo.conf(5) file.\n\nVersion 1.8 (sudo 1.8.15)\nThe sudoeditcheckdir and sudoeditfollow entries were added to the commandinfo  list.\nThe default value of sudoeditcheckdir was changed to true in sudo 1.8.16.\n\nThe  sudo conversation() function now takes a pointer to a struct sudoconvcallback as\nits fourth argument.  The sudoconvt definition has been updated to match.  The plugin\nmust specify that it supports plugin API version 1.8 or higher to receive  a  conversa‐\ntion function 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, iologmode, and\niologuser entries were added to the commandinfo list.\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() function was added to struct ioplugin.\n\nVersion 1.13 (sudo 1.8.26)\nThe logsuspend() function was added to struct ioplugin.\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() function was added to struct policyplugin and struct ioplugin.\n\nThe errstr argument was added to the policy and I/O plugin functions which  the  plugin\nfunction  can use to return an error string.  This string may be used by the audit plu‐\ngin to report failure or error conditions set by the other plugins.\n\nThe close() function is now is called regardless of whether or not a command was  actu‐\nally  executed.  This makes it possible for plugins to perform cleanup even when a com‐\nmand 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 entries were added to the settings list.\n\nVersion 1.17 (sudo 1.9.4)\nThe eventalloc() function was added to struct auditplugin and struct approvalplugin.\n\nVersion 1.18 (sudo 1.9.9)\nThe policy may now set resource limit values in the commandinfo list.   The  intercept\nand logsubcmds entries were added to the commandinfo list.\n\nVersion 1.19 (sudo 1.9.11)\nThe  interceptptrace and interceptsetid entries were added to the settings list.  The\napparmorprofile and useptrace entries were added to the commandinfo list.\n\nVersion 1.20 (sudo 1.9.12)\nThe updateticket entry was added to the settings list.  The interceptverify entry was\nadded to the commandinfo list.\n\nVersion 1.21 (sudo 1.9.13)\nThe sudoeditnfiles entry was added to the commandinfo list.\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 code written primar‐\nily by:\n\nTodd C. Miller\n\nSee the CONTRIBUTORS.md file in the  sudo  distribution  (https://www.sudo.ws/about/contribu‐\ntors/) for an exhaustive list of people who have contributed to sudo.\n",
            "subsections": []
        },
        "BUGS": {
            "content": "If   you   believe  you  have  found  a  bug  in  sudo,  you  can  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 the archives.\n",
            "subsections": []
        },
        "DISCLAIMER": {
            "content": "sudo  is  provided  “AS IS” and any express or implied warranties, including, but not limited\nto, the implied warranties of merchantability and fitness for a particular purpose  are  dis‐\nclaimed.  See the LICENSE.md file distributed with sudo or https://www.sudo.ws/about/license/\nfor complete details.\n\nSudo 1.9.15p5                               July 10, 2023                             SUDOPLUGIN(5)",
            "subsections": []
        }
    },
    "summary": "sudoplugin — Sudo Plugin API",
    "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"
        }
    ]
}