SUDO_PLUGIN(5) File Formats Manual SUDO_PLUGIN(5) (NAME) sudo_plugin - sudo (DESCRIPTION) . sudo (API) (policy) (session logging) . (dynamic shared objects - ) (statically) sudo . sudoers (audit) / (I/O) . API sudo . sudo.conf(5) . API (major) (minor) . . . . API . API (Policy plugin API) struct policy_plugin (global scope) . sudo . (symbol) sudo.conf(5) sudo . struct policy_plugin { #define SUDO_POLICY_PLUGIN 1 unsigned int type; /* always SUDO_POLICY_PLUGIN */ unsigned int version; /* always SUDO_API_VERSION */ int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], char * const user_env[], char * const plugin_options[], const char **errstr); void (*close)(int exit_status, int error); int (*show_version)(int verbose); int (*check_policy)(int argc, char * const argv[], char *env_add[], char **command_info[], char **argv_out[], char **user_env_out[], const char **errstr); int (*list)(int argc, char * const argv[], int verbose, const char *user, const char **errstr); int (*validate)(const char **errstr); void (*invalidate)(int rmcred); int (*init_session)(struct passwd *pwd, char **user_env[], const char **errstr); void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); struct sudo_plugin_event * (*event_alloc)(void); }; struct policy_plugin : type type SUDO_POLICY_PLUGIN . version version SUDO_API_VERSION . sudo API . open int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], char * const user_env[], char * const plugin_options[], const char **errstr); - (usage error) - . sudo . conversation() sudo_plugin_printf() SUDO_CONF_ERROR_MSG . : version sudo API sudo . conversation conversation() ( Conversation API ). - . sudo_plugin_printf printf() ( Conversation API ). - . settings sudo "name=value" . NULL . sudo . . settings (`=') name value . sudo : bsdauth_type=string -a - BSD . closefrom=number -C sudo (file descriptors) number . command_info . cmnd_chroot=string ( chroot(2) ) -R . . . API . cmnd_cwd=string -D . . . API . debug_flags=string Debug sudo.conf(5) ( ). sudo.conf(5) . sudo sudoers subsystem@priority (`,') . sudo 1.8.12 debug_flags sudo . . sudo debug_flags sudo.conf(5) Debug . ignore_ticket=bool -k true (cached) . implied_shell true. sudo su(1) . - check_policy() sudo . implied_shell=bool sudo implied_shell . intercept_ptrace=bool (intercept mode) ptrace(2) . seccomp(2) "trap" . . . API . intercept_setid=bool set-user-ID set- group-ID . seccomp(2) "trap" . (ld.so ) set- user-ID set-group-ID . . set-user-ID set-group-ID . . API . login_class=string BSD nice -c. login_shell=bool -i true (login shell) . max_groups=int . sudo.conf(5) . network_addrs=list IP "addr/netmask " "192.168.1.2/255.255.255.0". IPv4 IPv6 . (`:') IPv6 IPv4 . noninteractive=bool -n true sudo . . plugin_dir=string sudo . . . plugin_path=string sudo . (fully-qualified) sudo . preserve_environment=bool -E true . preserve_groups=bool -P true (runas user) . progname=string sudo "sudo" "sudoedit". prompt=string -p. remote_host=string -h. . sudo . . API . run_shell=bool -s true . runas_group=string (group-ID) -g. runas_user=string (user-ID) -u. selinux_role=string SELinux -r. selinux_type=string SELinux -t. set_home=bool -H true . true HOME . sudoedit=bool -e sudoedit true . argv check_policy() sudoedit - . check_policy() . timeout=string (timeout) -T . . . update_ticket=bool -N false . . API . . user_info "name=value" . NULL . user_info (`=') name value . sudo : cols=int . . cwd=string . egid=gid_t (effective group-ID) sudo . euid=uid_t (effective user-ID) sudo . gid=gid_t (real group-ID) sudo . groups=list . host=string (hostname) gethostname(2) . lines=int . . pgid=int sudo . . API . pid=int (PID) sudo. . API . ppid=int (PPID) sudo. . API . rlimit_as=soft,hard ( ) . (soft) (hard) . "infinity" . . API . rlimit_core=soft,hard core dump ( ). . "infinity" . . API . rlimit_cpu=soft,hard (CPU time) ( ). . "infinity" . . API . rlimit_data=soft,hard (data segment) ( ). . "infinity" . . API . rlimit_fsize=soft,hard ( ). . "infinity" . . API . rlimit_locks=soft,hard . . "infinity" . . API . rlimit_memlock=soft,hard ( ) . . "infinity" . . API . rlimit_nofile=soft,hard . . "infinity" . . API . rlimit_nproc=soft,hard . . "infinity" . . API . rlimit_rss=soft,hard (resident set size) ( ). . "infinity" . . API . rlimit_stack=soft,hard (stack) ( ). . "infinity" . . API . sid=int (session ID) sudo sudo (job control) POSIX . . API . tcpgid=int sudo . . API . tty=string . . ttydev=dev_t long long. . . API . uid=uid_t (real user-ID) sudo . umask=octal . . API . user=string sudo . user_env NULL "name=value" . user_env (`=') name value . plugin_options ( ) . NULL . plugin_options NULL . plugin_options . API . plugin_options API sudo . . errstr open() errstr . sudo . errstr close() . errstr . API . errstr API sudo . . close void (*close)(int exit_status, int error); close() sudo . . API close() . . close() . check_policy() . : exit_status wait(2) . error exit_status . error errno execve(2) . conversation() sudo_plugin_printf() . error . close() / (I/O logging) timeout use_pty command_info sudo . show_version int (*show_version)(int verbose); show_version() sudo -V . conversation() sudo_plugin_printf() SUDO_CONV_INFO_MSG . verbose . - - . check_policy int (*check_policy)(int argc, char * const argv[], char *env_add[], char **command_info[], char **argv_out[], char **user_env_out[], const char **errstr); check_policy() sudo . sudoedit settings open() sudoedit . sudoedit . sudo . sudoedit sudoedit=true command_info . EDITOR argv_out ( ). argv argv_out `--' . `--' sudo . sudoedit_nfiles command_info . API sudo . check_policy() - sudoedit - . sudo . conversation() sudo_plugin_printf() SUDO_CONF_ERROR_MSG . : argc argv NULL. argv execve(2) . NULL . env_add NULL "name=value". . env_add (`=') name value . command_info "name=value". sudo . NULL . sudo : apparmor_profile=string AppArmor . 1.19 API . chroot=string . closefrom=number sudo number . command=string . cwd=string . sudo cwd_optional ( ). cwd_optional=bool sudo . cwd . exec_background=bool sudo . exec_background ( I/O use_pty ) . ( ) SIGTTIN ( SIGTTOU ) . sudo . sudo . ( ). sudo . . . macOS tcgetattr() tcsetattr() ( macOS ). SIGTTIN SIGTTOU ( SIGTOP) . su(1) . exec_background . I/O use_pty . execfd=number sudo fexecve(2) execve(2) . number . intercept=bool sudo check_policy() . . Preventing shell escapes sudoers(5) . 1.18 API . intercept_verify=bool sudo . use_ptrace . 1.20 API . iolog_compress=bool I/O ( ) true . (hint) I/O . iolog_group=string I/O . I/O . iolog_mode=octal I/O. I/O . iolog_user=string I/O . I/O . iolog_path=string I/O . I/O . I/O . iolog_stdin=bool I/O ( ) true . I/O . iolog_stdout=bool I/O ( ) true . I/O . iolog_stderr=bool I/O ( ) true . I/O . iolog_ttyin=bool I/O ( ) true . (pipe) . I/O . iolog_ttyout=bool I/O ( ) true . . I/O . login_class=string BSD nice (). . nice=int nice () . nice login_class BSD . log_subcmds=bool sudo accept() . intercept log_subcmds . Preventing shell escapes sudoers(5) . 1.18 API . noexec=bool . preserve_fds=list closefrom . 1.5 API . preserve_groups=bool sudo runas_user . rlimit_as=soft,hard ( ) . (soft) (hard) . . "infinity" . "user" . "default" . 1.18 API . rlimit_core=soft,hard (core dump) ( ). . . "infinity" . "user" . "default" . 1.18 API . rlimit_cpu=soft,hard ( ). . . "infinity" . "user" . "default" . 1.18 API . rlimit_data=soft,hard ( ). . . "infinity" . "user" . "default" . 1.18 API . rlimit_fsize=soft,hard ( ). . . "infinity" . "user" . "default" . 1.18 API . rlimit_locks=soft,hard . . . "infinity" . "user" . "default" . 1.18 API . rlimit_memlock=soft,hard ( ) . . . "infinity" . "user" . "default" . 1.18 API . rlimit_nofile=soft,hard . . . "infinity" . "user" . "default" . 1.18 API . rlimit_nproc=soft,hard . . . "infinity" . "user" . "default" . 1.18 API . rlimit_rss=soft,hard (resident set size) ( ). . . "infinity" . "user" . "default" . 1.18 API . rlimit_stack=soft,hard ( ). . . "infinity" . "user" . "default" . 1.18 API . runas_egid=gid (effective group-ID) . runas_gid . runas_euid=uid (effective user-ID) . runas_uid . runas_gid=gid (group-ID) . runas_group=string runas_user . sudo runas_egid runas_gid . runas_groups=list (supplementary group vector) . preserve_groups . runas_uid=uid (user-ID) . runas_user=string runas_euid ( runas_euid runas_uid ) . sudo runas_euid runas_uid . selinux_role=string SELinux . selinux_type=string SELinux . set_utmp=bool utmp ( utmpx) . utmp ( ) tty time type pid. sudoedit=bool true sudoedit . sudoedit sudo sudoedit . sudoedit . sudoedit_checkdir=bool sudoedit false . sudoedit 1.8.16 . sudoedit . sudoedit root . sudoedit_checkdir false . 1.8 API . sudoedit_follow=bool true sudoedit . sudoedit 1.8.15 . sudoedit_follow sudoedit . 1.8 API . sudoedit_nfiles=number . sudo argv_out . `--' . sudoedit_nfiles sudo `--' . 1.21 API . timeout=int . ( ). umask=octal . PAM login.conf umask_override . umask_override=bool umask umask PAM login.conf . use_ptrace=bool sudo ptrace(2) . intercept . 1.19 API . use_pty=bool I/O . sudo I/O . utmp_user=string utmp ( utmpx) set_utmp . utmp . sudo . . argv_out NULL execve(2) . . user_env_out NULL . . errstr check_policy() 1 errstr . sudo . errstr close() . errstr 1.15 API . API sudo errstr . . list int (*list)(int argc, char * const argv[], int verbose, const char *user, const char **errstr); . 1 0 -1 . conversation() sudo_plugin_printf() SUDO_CONF_ERROR_MSG . conversation() sudo_plugin_printf() SUDO_CONV_INFO_MSG . : argc argv NULL. argv NULL execve(2) . . verbose (verbose) . user . NULL . errstr list() 1 errstr . sudo . errstr close() . errstr 1.15 API . API sudo errstr . . validate int (*validate)(const char **errstr); validate() sudo -v . sudoers . validate() NULL . 1 0 -1 . conversation() sudo_plugin_printf() SUDO_CONF_ERROR_MSG . : errstr validate() 1 errstr . sudo . errstr close() . errstr 1.15 API . API sudo errstr . . invalidate void (*invalidate)(int rmcred); invalidate() sudo -k -K . sudoers . rmcred . invalidate() NULL . init_session int (*init_session)(struct passwd *pwd, char **user_env[], const char **errstr); init_session() sudo . sudo . command_info PAM. close() init_session() . 1 0 -1 . conversation() sudo_plugin_printf() SUDO_CONF_ERROR_MSG . : pwd pwd NULL . user_env_out NULL . user_env_out . init_session() user_env_out . PAM ( ) user_env_out . user_env_out 1.2 API . API sudo user_env_out . . errstr init_session() 1 errstr . sudo . errstr close() . errstr 1.15 API . API sudo errstr . . register_hooks void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); register_hooks() sudo . register_hooks NULL . version API sudo . register_hook() . 0 1 struct sudo_hook API -1 . Hook function API . register_hooks() 1.2 API . sudo 1.2 API register_hooks() . deregister_hooks void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); deregister_hooks() sudo . deregister_hooks NULL . version API sudo . deregister_hook() register_hook() . deregister_hook() . Hook function API . deregister_hooks() 1.2 API . sudo 1.2 API deregister_hooks() . event_alloc struct sudo_plugin_event * (*event_alloc)(void); event_alloc() struct sudo_plugin_event sudo . event_alloc sudo . Event API . event_alloc() 1.15 API . sudo 1.15 API event_alloc . (Policy Plugin Version Macros) /* Plugin API version major/minor. */ #define SUDO_API_VERSION_MAJOR 1 #define SUDO_API_VERSION_MINOR 13 #define SUDO_API_MKVERSION(x, y) ((x << 16) | y) #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\ SUDO_API_VERSION_MINOR) /* Getters and setters for API version */ #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ } while(0) #define SUDO_API_VERSION_SET_MINOR(vp, n) do { \ *(vp) = (*(vp) & 0xffff0000) | (n); \ } while(0) / (I/O plugin API) struct io_plugin { #define SUDO_IO_PLUGIN 2 unsigned int type; /* always SUDO_IO_PLUGIN */ unsigned int version; /* always SUDO_API_VERSION */ int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], char * const command_info[], int argc, char * const argv[], char * const user_env[], char * const plugin_options[], const char **errstr); void (*close)(int exit_status, int error); /* wait status or error */ int (*show_version)(int verbose); int (*log_ttyin)(const char *buf, unsigned int len, const char **errstr); int (*log_ttyout)(const char *buf, unsigned int len, const char **errstr); int (*log_stdin)(const char *buf, unsigned int len, const char **errstr); int (*log_stdout)(const char *buf, unsigned int len, const char **errstr); int (*log_stderr)(const char *buf, unsigned int len, const char **errstr); void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); int (*change_winsize)(unsigned int lines, unsigned int cols, const char **errstr); int (*log_suspend)(int signo, const char **errstr); struct sudo_plugin_event * (*event_alloc)(void); }; / sudo . . tty sudo (pipe) / . log_ttyin() ( (echo ) ). log_ttyout() . log_stdin() log_stdout() log_stderr() tty . NULL . open 0 / . (-1) . / . 0 / . 0 / . struct audit_plugin : type type SUDO_IO_PLUGIN . version version SUDO_API_VERSION . sudo API . open int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], char * const command_info[], int argc, char * const argv[], char * const user_env[], char * const plugin_options[]); open() log_ttyin() log_ttyout() log_stdin() log_stdout() log_stderr() log_suspend() change_winsize() show_version() . check_policy() . 1 0 -1 -2 . sudo . conversation() sudo_plugin_printf() SUDO_CONF_ERROR_MSG . : version sudo API sudo . conversation conversation() Fa(show_version) ( show_version() ). conversation() . conversation() 0 -1 . sudo_plugin_printf printf()-style show_version() ( show_version ). sudo_plugin_printf() . sudo_plugin_printf() -1 . settings sudo "name=value". NULL . sudo . . settings (`=') name value . Policy plugin API . user_info "name=value". NULL . user_info (`=') name value . Policy plugin API . command_info "name=value". NULL . command_info (`=') name value . Policy plugin API . argc argv NULL. sudo -V . argv NULL (non-NULL) execve(2) . user_env NULL "name=value". user_env (`=') name value . plugin_options ( ) . NULL . plugin_options NULL . plugin_options 1.2 API . plugin_options API sudo . . errstr open() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . close void (*close)(int exit_status, int error); close() sudo . : exit_status wait(2) . error exit_status . error errno execve(2) . error . show_version int (*show_version)(int verbose); show_version() sudo -V . conversation() sudo_plugin_printf() SUDO_CONV_INFO_MSG . verbose . 1 0 -1 -2 . log_ttyin int (*log_ttyin)(const char *buf, unsigned int len, const char **errstr); log_ttyin() . ( ). 1 0 ( ) -1 . : buf . len buf . errstr log_ttyin() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . log_ttyout int (*log_ttyout)(const char *buf, unsigned int len, const char **errstr); log_ttyout() . ( ). 1 0 ( ) -1 . : buf . len buf . errstr log_ttyout() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . log_stdin int (*log_stdin)(const char *buf, unsigned int len, const char **errstr); log_stdin() tty . . ( ). 1 0 ( ) -1 . : buf . len buf . errstr log_stdin() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . log_stdout int (*log_stdout)(const char *buf, unsigned int len, const char **errstr); log_stdout() tty . . ( ). 1 0 ( ) -1 . : buf . len buf . errstr log_stdout() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . log_stderr int (*log_stderr)(const char *buf, unsigned int len, const char **errstr); log_stderr() tty . . ( ). 1 0 ( ) -1 . : buf . len buf . errstr log_stderr() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . register_hooks register_hooks() Policy plugin API . deregister_hooks deregister_hooks() Policy plugin API . change_winsize int (*change_winsize)(unsigned int lines, unsigned int cols, const char **errstr); change_winsize() user_info . -1 change_winsize() : lines () . cols . errstr change_winsize() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . log_suspend int (*log_suspend)(int signo, const char **errstr); log_suspend() . . -1 log_suspend() : signo SIGCONT . errstr log_suspend() 1 errstr . sudo . errstr close() . errstr 1.15 API . errstr API sudo . . event_alloc struct sudo_plugin_event * (*event_alloc)(void); event_alloc() struct sudo_plugin_event sudo . event_alloc() sudo . Event API . event_alloc() 1.15 API . sudo 1.15 API event_alloc() . / (I/O Plugin Version Macros) Policy plugin API. (Audit plugin API) /* Audit plugin close function status types. */ #define SUDO_PLUGIN_NO_STATUS 0 #define SUDO_PLUGIN_WAIT_STATUS 1 #define SUDO_PLUGIN_EXEC_ERROR 2 #define SUDO_PLUGIN_SUDO_ERROR 3 #define SUDO_AUDIT_PLUGIN 3 struct audit_plugin { unsigned int type; /* always SUDO_AUDIT_PLUGIN */ unsigned int version; /* always SUDO_API_VERSION */ int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], int submit_optind, char * const submit_argv[], char * const submit_envp[], char * const plugin_options[], const char **errstr); void (*close)(int status_type, int status); int (*accept)(const char *plugin_name, unsigned int plugin_type, char * const command_info[], char * const run_argv[], char * const run_envp[], const char **errstr); int (*reject)(const char *plugin_name, unsigned int plugin_type, const char *audit_msg, char * const command_info[], const char **errstr); int (*error)(const char *plugin_name, unsigned int plugin_type, const char *audit_msg, char * const command_info[], const char **errstr); int (*show_version)(int verbose); void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); struct sudo_plugin_event * (*event_alloc)(void); } sudo I/O . sudo.conf(5) . struct audit_plugin : type type SUDO_AUDIT_PLUGIN . version version SUDO_API_VERSION . sudo API . open int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], int submit_optind, char * const submit_argv[], char * const submit_envp[], char * const plugin_options[], const char **errstr); open() API sudo . . 1 0 -1 -2 . sudo . conversation() plugin_printf() SUDO_CONF_ERROR_MSG . : version sudo API sudo . conversation conversation() show_version() ( show_version() ). conversation() . conversation() 0 -1 . plugin_printf printf() show_version() ( show_version() ). plugin_printf() . plugin_printf() -1 . settings sudo "name=value". NULL . sudo . . settings (`=') name value . Policy plugin API . user_info "name=value". NULL . user_info (`=') name value . Policy plugin API . submit_optind submit_argv . submit_argv -l -v submit_argv[submit_optind] NULL . submit_argv sudo . submit_optind . submit_envp "name=value" NULL . submit_envp (`=') name value . plugin_options ( ) . NULL . plugin_options NULL . errstr open() 1 errstr . sudo . errstr close() . close void (*close)(int status_type, int status); close() sudo . : status_type . SUDO_PLUGIN_NO_STATUS SUDO_PLUGIN_WAIT_STATUS SUDO_PLUGIN_EXEC_ERROR SUDO_PLUGIN_SUDO_ERROR. status status_type wait(2) errno execve(2) errno sudo . accept int (*accept)(const char *plugin_name, unsigned int plugin_type, char * const command_info[], char * const run_argv[], char * const run_envp[], const char **errstr); accept() . : plugin_name "sudo" sudo. plugin_type SUDO_POLICY_PLUGIN SUDO_POLICY_APPROVAL SUDO_FRONT_END . accept() - sudo. sudo command_info I/O . sudo . accept() reject() . command_info "name=value". NULL . command_info (`=') name value . Policy plugin API . run_argv NULL execve(2) . run_envp "name=value" NULL . run_envp (`=') name value . errstr accept() 1 errstr . sudo . errstr close() . reject int (*reject)(const char *plugin_name, unsigned int plugin_type, const char *audit_msg, char * const command_info[], const char **errstr); reject() . : plugin_name . plugin_type SUDO_POLICY_PLUGIN SUDO_APPROVAL_PLUGIN SUDO_IO_PLUGIN . accept() reject() sudo . audit_msg . audit_msg NULL . command_info "name=value". NULL . command_info (`=') name value . Policy plugin API . errstr reject() 1 errstr . sudo . errstr close() . error int (*error)(const char *plugin_name, unsigned int plugin_type, const char *audit_msg, char * const command_info[], const char **errstr); error() sudo . : plugin_name "sudo" sudo. plugin_type SUDO_FRONT_END sudo. audit_msg . audit_msg NULL . command_info "name=value". NULL . command_info (`=') name value . Policy plugin API . errstr error() 1 errstr . sudo . errstr close() . show_version int (*show_version)(int verbose); show_version() sudo -V . conversation() plugin_printf() SUDO_CONV_INFO_MSG . verbose . 1 0 -1 -2 . register_hooks register_hooks() Policy plugin API . deregister_hooks deregister_hooks() Policy plugin API . event_alloc struct sudo_plugin_event * (*event_alloc)(void); event_alloc() struct sudo_plugin_event sudo . event_alloc sudo . Event API . event_alloc() API 1.17 . sudo API 1.17 event_alloc() . (Approval plugin API) struct approval_plugin { #define SUDO_APPROVAL_PLUGIN 4 unsigned int type; /* always SUDO_APPROVAL_PLUGIN */ unsigned int version; /* always SUDO_API_VERSION */ int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], int submit_optind, char * const submit_argv[], char * const submit_envp[], char * const plugin_options[], const char **errstr); void (*close)(void); int (*check)(char * const command_info[], char * const run_argv[], char * const run_envp[], const char **errstr); int (*show_version)(int verbose); }; . . check() show_version() ( ). sudo.conf(5) . struct approval_plugin : type type SUDO_APPROVAL_PLUGIN . version version SUDO_API_VERSION . sudo API . open int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_plugin_printf, char * const settings[], char * const user_info[], int submit_optind, char * const submit_argv[], char * const submit_envp[], char * const plugin_options[], const char **errstr); open() check() show_version() . check_policy() . 1 0 -1 -2 . sudo . conversation() plugin_printf() SUDO_CONF_ERROR_MSG . : version sudo (major) (minor) API sudo . conversation conversation() ( Conversation API ). 0 -1 . plugin_printf printf() ( Conversation API ). -1 . settings sudo "name=value". NULL . sudo . . settings (`=') name value . Policy plugin API . user_info "name=value". NULL . user_info (`=') name value . Policy plugin API . submit_optind submit_argv . submit_argv -l -v submit_argv[submit_optind] NULL . submit_argv sudo . submit_optind . submit_envp NULL "name=value". submit_envp (`=') name value . plugin_options ( ) . (whitespace) NULL . plugin_options NULL . errstr open() 1 errstr . (front-end) sudo . errstr close() . close void (*close)(void); close() check() show_version() . . close() . close() NULL . check int (*check)(char * const command_info[], char * const run_argv[], char * const run_envp[], const char **errstr); check() check_policy() I/O . . 1 0 -1 -2 . sudo . conversation() plugin_printf() SUDO_CONF_ERROR_MSG . : command_info "name=value". NULL . command_info (`=') name value . Policy plugin API . run_argv NULL execve(2) . run_envp NULL "name=value". run_envp (`=') name value . errstr open() 1 errstr . sudo . errstr close() . show_version int (*show_version)(int verbose); show_version() sudo -V . conversation() plugin_printf() SUDO_CONV_INFO_MSG . verbose . 1 0 -1 -2 . (Signal handlers) (front-end) sudo . : o SIGALRM o SIGHUP o SIGINT o SIGPIPE o SIGQUIT o SIGTERM o SIGTSTP o SIGUSR1 o SIGUSR2 (fatal signal) sudo close() 128 . close() . SIGPIPE . . (Hook function API) 1.2 API () sudo . . . API sudo . (Hook structure) sudo : typedef int (*sudo_hook_fn_t)(); struct sudo_hook { unsigned int hook_version; unsigned int hook_type; sudo_hook_fn_t hook_fn; void *closure; }; struct sudo_hook : hook_version hook_version SUDO_HOOK_VERSION . hook_type hook_type : SUDO_HOOK_SETENV setenv(3) C. C . hook_fn typedef : typedef int (*sudo_hook_fn_setenv_t)(const char *name, const char *value, int overwrite, void *closure); typedef . SUDO_HOOK_UNSETENV unsetenv(3) C. C . hook_fn typedef : typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, void *closure); SUDO_HOOK_GETENV getenv(3) C. C . hook_fn typedef : typedef int (*sudo_hook_fn_getenv_t)(const char *name, char **value, void *closure); typedef . SUDO_HOOK_PUTENV putenv(3) C. C . hook_fn typedef : typedef int (*sudo_hook_fn_putenv_t)(char *string, void *closure); typedef . hook_fn sudo_hook_fn_t hook_fn; hook_fn . hook_type ( hook_type ). closure struct sudo_hook . . : SUDO_HOOK_RET_ERROR . SUDO_HOOK_RET_NEXT ( ). getenv(3) SUDO_HOOK_RET_NEXT . SUDO_HOOK_RET_STOP . . setenv environ . (hooking) C . getenv(3) snprintf(3) snprintf(3) (locale) getenv(3) . (static) . : static int in_progress = 0; /* avoid recursion */ if (in_progress) return SUDO_HOOK_RET_NEXT; in_progress = 1; ... in_progress = 0; return SUDO_HOOK_RET_STOP; (Hook API Version Macros) /* Hook API version major/minor */ #define SUDO_HOOK_VERSION_MAJOR 1 #define SUDO_HOOK_VERSION_MINOR 0 #define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\ SUDO_HOOK_VERSION_MINOR) (getters and setters) Policy plugin API . (Event API) sudo (event loop) I/O . . . (API) event_alloc() . (Event structure) : typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure); struct sudo_plugin_event { int (*set)(struct sudo_plugin_event *pev, int fd, int events, sudo_plugin_ev_callback_t callback, void *closure); int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout); int (*del)(struct sudo_plugin_event *pev); int (*pending)(struct sudo_plugin_event *pev, int events, struct timespec *ts); int (*fd)(struct sudo_plugin_event *pev); void (*setbase)(struct sudo_plugin_event *pev, void *base); void (*loopbreak)(struct sudo_plugin_event *pev); void (*free)(struct sudo_plugin_event *pev); }; struct sudo_plugin_event : set int (*set)(struct sudo_plugin_event *pev, int fd, int events, sudo_plugin_ev_callback_t callback, void *closure); set() : struct sudo_plugin_event *pev struct sudo_plugin_event. fd I/O . fd -1 . events (callback) : SUDO_PLUGIN_EV_TIMEOUT (timeout) SUDO_PLUGIN_EV_READ SUDO_PLUGIN_EV_WRITE SUDO_PLUGIN_EV_PERSIST SUDO_PLUGIN_EV_SIGNAL SUDO_PLUGIN_EV_PERSIST OR . SUDO_PLUGIN_EV_READ SUDO_PLUGIN_EV_WRITE OR . . sudo_plugin_ev_callback_t callback typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure); . callback() : fd I/O . what . ( SUDO_PLUGIN_EV_READ SUDO_PLUGIN_EV_WRITE) what . closure set() . closure . set() 1 -1 . add int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout); add() pev sudo . set() . timeout NULL () . I/O . timeout ( ) . add() 1 -1 . del int (*del)(struct sudo_plugin_event *pev); del() pev sudo . add() . del() 1 -1 . pending int (*pending)(struct sudo_plugin_event *pev, int events, struct timespec *ts); pending() (pending) . events . set() . SUDO_PLUGIN_EV_TIMEOUT events ts NULL . fd int (*fd)(struct sudo_plugin_event *pev); fd() pev . setbase void (*setbase)(struct sudo_plugin_event *pev, void *base); setbase() base pev . event_alloc() sudo . base NULL pev sudo . (link) sudo_util . sudoers . loopbreak void (*loopbreak)(struct sudo_plugin_event *pev); loopbreak() sudo . free void (*free)(struct sudo_plugin_event *pev); free() pev . (Remote command execution) sudo . .. sudo -h . runas_user "user@hostname" sudo . ( "helper" ) . sudo . ssh . ssh . sudoedit sudo . . (Conversation API) conversation() . ( ). msg . printf() . (Conversation function structures) : struct sudo_conv_message { #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ #define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */ int msg_type; int timeout; const char *msg; }; #define SUDO_CONV_REPL_MAX 1023 struct sudo_conv_reply { char *reply; }; typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure); struct sudo_conv_callback { unsigned int version; void *closure; sudo_conv_callback_fn_t on_suspend; sudo_conv_callback_fn_t on_resume; }; conversation() printf() open() . open() : typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[], struct sudo_conv_callback *callback); typedef int (*sudo_printf_t)(int msg_type, const char * restrict fmt, ...); conversation() struct sudo_conv_message struct sudo_conv_reply . struct sudo_conv_message struct sudo_conv_reply . struct sudo_conv_reply reply NULL . struct sudo_conv_callback NULL (suspend) (resume) sudo . on_suspend on_resume sudo closure struct sudo_conv_callback . 0 -1 . -1 . . (signal handler) . msg_type : SUDO_CONV_PROMPT_ECHO_OFF (echo) . replies NULL . SUDO_CONV_PROMPT_ECHO_ON (echo) . replies NULL . SUDO_CONV_ERROR_MSG . (standard error) SUDO_CONV_PREFER_TTY . SUDO_CONV_INFO_MSG . (standard output) SUDO_CONV_PREFER_TTY . SUDO_CONV_PROMPT_MASK . replies NULL . . : SUDO_CONV_PROMPT_ECHO_OK echo SUDO_CONV_PROMPT_ECHO_OFF SUDO_CONV_PROMPT_MASK . echo sudo . SUDO_CONV_PREFER_TTY SUDO_CONV_ERROR_MSG SUDO_CONV_INFO_MSG . SUDO_CONV_ERROR_MSG SUDO_CONV_INFO_MSG . . timeout . . struct sudo_conv_reply NULL . SUDO_CONV_REPL_MAX ( NUL ). sudo . printf() conversation() SUDO_CONV_INFO_MSG SUDO_CONV_ERROR_MSG msg_type . conversation() printf() . conversation() . (Plugin invocation order) .. sudo open() close() : 1. audit open 2. policy open 3. approval open 4. approval close 5. I/O log open 6. (command runs) 7. (command exits) 8. I/O log close 9. policy close 10. audit close 11. sudo .. sudo close() I/O close() . sudoers (Sudoers group plugin API) sudoers . . sudo group_file system_group sudoers(5) . QAS AD Quest Software . struct sudoers_group_plugin (global scope) . . struct sudoers_group_plugin { unsigned int version; int (*init)(int version, sudo_printf_t sudo_plugin_printf, char *const argv[]); void (*cleanup)(void); int (*query)(const char *user, const char *group, const struct passwd *pwd); }; struct sudoers_group_plugin : version version GROUP_API_VERSION . sudoers API . init int (*init)(int version, sudo_printf_t sudo_plugin_printf, char *const argv[]); init() sudoers . 1 ( ) 0 -1 . plugin_printf() SUDO_CONF_ERROR_MSG . : version sudoers sudoers . plugin_printf printf() . -1 . argv NULL group_plugin sudoers . argv NULL . cleanup void (*cleanup)(); cleanup() sudoers . . query int (*query)(const char *user, const char *group, const struct passwd *pwd); query() user group . : user . group . pwd user ( ). user pwd NULL . (Group API Version Macros) /* Sudoers group plugin version major/minor */ #define GROUP_API_VERSION_MAJOR 1 #define GROUP_API_VERSION_MINOR 0 #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \ GROUP_API_VERSION_MINOR) (getters and setters) Policy plugin API. (PLUGIN API CHANGELOG) (API) . Version 1.0 API. Version 1.1 (sudo 1.8.0) open() / (I/O logging) command_info . Version 1.2 (sudo 1.8.5) open() (Policy) / (I/O logging) sudo.conf(5) . (hooks API) . init_session() . PAM . Version 1.3 (sudo 1.8.7) exec_background command_info . max_groups plugin_dir settings . version() close() . version() close() () . close() close() sudo . sudo (signal handlers) . Version 1.4 (sudo 1.8.8) remote_host settings . Version 1.5 (sudo 1.8.9) preserve_fds command_info . Version 1.6 (sudo 1.8.11) / (-1) . sudo log_ttyin() log_ttyout() log_stdin() log_stdout() log_stderr() . / 0 . 0 . Version 1.7 (sudo 1.8.12) plugin_path settings . debug_flags Debug sudo.conf(5) . Version 1.8 (sudo 1.8.15) sudoedit_checkdir sudoedit_follow command_info . sudoedit_checkdir sudo 1.8.16 true . conversation() sudo struct sudo_conv_callback . sudo_conv_t . 1.8 API . Version 1.9 (sudo 1.8.16) execfd command_info . Version 1.10 (sudo 1.8.19) umask user_info . iolog_group iolog_mode iolog_user command_info . Version 1.11 (sudo 1.8.20) timeout settings . Version 1.12 (sudo 1.8.21) change_winsize() struct io_plugin . Version 1.13 (sudo 1.8.26) log_suspend() struct io_plugin . Version 1.14 (sudo 1.8.29) umask_override command_info . Version 1.15 (sudo 1.9.0) cwd_optional command_info . event_alloc() struct policy_plugin struct io_plugin . errstr / . (audit plugin) . close() . . SUDO_CONV_REPL_MAX . (audit) (approval) . Version 1.16 (sudo 1.9.3) user_info . cmnd_chroot cmnd_cwd settings . Version 1.17 (sudo 1.9.4) event_alloc() struct audit_plugin struct approval_plugin . Version 1.18 (sudo 1.9.9) command_info . intercept log_subcmds command_info . Version 1.19 (sudo 1.9.11) intercept_ptrace intercept_setid settings . apparmor_profile use_ptrace command_info . Version 1.20 (sudo 1.9.12) update_ticket settings . intercept_verify command_info . Version 1.21 (sudo 1.9.13) sudoedit_nfiles command_info . Version 1.22 (sudo 1.9.16) ttydev user_info . (SEE ALSO) sudo.conf(5), sudoers(5), sudo(8) (AUTHORS) sudo : Todd C. Miller sudo CONTRIBUTORS.md sudo (https://www.sudo.ws/about/contributors) . (BUGS) sudo_plugin https://bugzilla.sudo.ws issue https://github.com/sudo- project/sudo/issues . sudo- workers https://www.sudo.ws/mailman/listinfo/sudo-workers () () . issue . . PGP https://www.sudo.ws/dist/PGPKEYS . (SUPPORT) sudo-users https://www.sudo.ws/mailman/listinfo/sudo-users . (DISCLAIMER) sudo "AS IS" . LICENSE.md sudo https://www.sudo.ws/about/license . Sudo 1.9.17p2 August 14, 2024 Sudo 1.9.17p2