1SUDO_PLUGIN(5) BSD File Formats Manual SUDO_PLUGIN(5)
2
4 sudo_plugin — Sudo Plugin API
5
7 Starting with version 1.8, sudo supports a plugin API for policy and ses‐
8 sion logging. By default, the sudoers policy plugin and an associated
9 I/O logging plugin are used. Via the plugin API, sudo can be configured
10 to use alternate policy and/or I/O logging plugins provided by third par‐
11 ties. The plugins to be used are specified via the /etc/sudo.conf file.
12
13 The API is versioned with a major and minor number. The minor version
14 number is incremented when additions are made. The major number is
15 incremented when incompatible changes are made. A plugin should be check
16 the version passed to it and make sure that the major version matches.
17
18 The plugin API is defined by the sudo_plugin.h header file.
19
20 The sudo.conf file
21 The /etc/sudo.conf file contains plugin configuration directives. The
22 primary keyword is the Plugin directive, which causes a plugin to be
23 loaded.
24
25 A Plugin line consists of the Plugin keyword, followed by the symbol_name
26 and the path to the shared object containing the plugin. The symbol_name
27 is the name of the struct policy_plugin or struct io_plugin in the plugin
28 shared object. The path may be fully qualified or relative. If not
29 fully qualified it is relative to the /usr/libexec directory. Any addi‐
30 tional parameters after the path are passed as options to the plugin's
31 open() function. Lines that don't begin with Plugin, Path, Debug or Set
32 are silently ignored.
33
34 The same shared object may contain multiple plugins, each with a differ‐
35 ent symbol name. The shared object file must be owned by uid 0 and only
36 writable by its owner. Because of ambiguities that arise from composite
37 policies, only a single policy plugin may be specified. This limitation
38 does not apply to I/O plugins.
39
40 #
41 # Default /etc/sudo.conf file
42 #
43 # Format:
44 # Plugin plugin_name plugin_path plugin_options ...
45 # Path askpass /path/to/askpass
46 # Path noexec /path/to/sudo_noexec.so
47 # Debug sudo /var/log/sudo_debug all@warn
48 # Set disable_coredump true
49 #
50 # The plugin_path is relative to /usr/libexec unless
51 # fully qualified.
52 # The plugin_name corresponds to a global symbol in the plugin
53 # that contains the plugin interface structure.
54 # The plugin_options are optional.
55 #
56 Plugin sudoers_policy sudoers.so
57 Plugin sudoers_io sudoers.so
58
59 Policy plugin API
60 A policy plugin must declare and populate a policy_plugin struct in the
61 global scope. This structure contains pointers to the functions that
62 implement the sudo policy checks. The name of the symbol should be spec‐
63 ified in /etc/sudo.conf along with a path to the plugin so that sudo can
64 load it.
65
66 struct policy_plugin {
67 #define SUDO_POLICY_PLUGIN 1
68 unsigned int type; /* always SUDO_POLICY_PLUGIN */
69 unsigned int version; /* always SUDO_API_VERSION */
70 int (*open)(unsigned int version, sudo_conv_t conversation,
71 sudo_printf_t plugin_printf, char * const settings[],
72 char * const user_info[], char * const user_env[],
73 char * const plugin_options[]);
74 void (*close)(int exit_status, int error);
75 int (*show_version)(int verbose);
76 int (*check_policy)(int argc, char * const argv[],
77 char *env_add[], char **command_info[],
78 char **argv_out[], char **user_env_out[]);
79 int (*list)(int argc, char * const argv[], int verbose,
80 const char *list_user);
81 int (*validate)(void);
82 void (*invalidate)(int remove);
83 int (*init_session)(struct passwd *pwd, char **user_env[]);
84 void (*register_hooks)(int version,
85 int (*register_hook)(struct sudo_hook *hook));
86 void (*deregister_hooks)(int version,
87 int (*deregister_hook)(struct sudo_hook *hook));
88 };
89
90 The policy_plugin struct has the following fields:
91
92 type The type field should always be set to SUDO_POLICY_PLUGIN.
93
94 version
95 The version field should be set to SUDO_API_VERSION.
96
97 This allows sudo to determine the API version the plugin was built
98 against.
99
100 open
101 int (*open)(unsigned int version, sudo_conv_t conversation,
102 sudo_printf_t plugin_printf, char * const settings[],
103 char * const user_info[], char * const user_env[],
104 char * const plugin_options[]);
105
106 Returns 1 on success, 0 on failure, -1 if a general error occurred,
107 or -2 if there was a usage error. In the latter case, sudo will
108 print a usage message before it exits. If an error occurs, the
109 plugin may optionally call the conversation() or plugin_printf()
110 function with SUDO_CONF_ERROR_MSG to present additional error
111 information to the user.
112
113 The function arguments are as follows:
114
115 version
116 The version passed in by sudo allows the plugin to determine
117 the major and minor version number of the plugin API sup‐
118 ported by sudo.
119
120 conversation
121 A pointer to the conversation() function that can be used by
122 the plugin to interact with the user (see below). Returns 0
123 on success and -1 on failure.
124
125 plugin_printf
126 A pointer to a printf()-style function that may be used to
127 display informational or error messages (see below). Returns
128 the number of characters printed on success and -1 on fail‐
129 ure.
130
131 settings
132 A vector of user-supplied sudo settings in the form of
133 “name=value” strings. The vector is terminated by a NULL
134 pointer. These settings correspond to flags the user speci‐
135 fied when running sudo. As such, they will only be present
136 when the corresponding flag has been specified on the command
137 line.
138
139 When parsing settings, the plugin should split on the first
140 equal sign (‘=’) since the name field will never include one
141 itself but the value might.
142
143 debug_flags=string
144 A comma-separated list of debug flags that correspond
145 to sudo's Debug entry in /etc/sudo.conf, if there is
146 one. The flags are passed to the plugin as they appear
147 in /etc/sudo.conf. The syntax used by sudo and the
148 sudoers plugin is subsystem@priority but the plugin is
149 free to use a different format so long as it does not
150 include a comma (‘,’).
151
152 For reference, the priorities supported by the sudo
153 front end and sudoers are: crit, err, warn, notice,
154 diag, info, trace and debug.
155
156 The following subsystems are defined: main, memory,
157 args, exec, pty, utmp, conv, pcomm, util, list, netif,
158 audit, edit, selinux, ldap, match, parser, alias,
159 defaults, auth, env, logging, nss, rbtree, perms,
160 plugin. The subsystem all includes every subsystem.
161
162 There is not currently a way to specify a set of debug
163 flags specific to the plugin--the flags are shared by
164 sudo and the plugin.
165
166 debug_level=number
167 This setting has been deprecated in favor of
168 debug_flags.
169
170 runas_user=string
171 The user name or uid to to run the command as, if spec‐
172 ified via the -u flag.
173
174 runas_group=string
175 The group name or gid to to run the command as, if
176 specified via the -g flag.
177
178 prompt=string
179 The prompt to use when requesting a password, if speci‐
180 fied via the -p flag.
181
182 set_home=bool
183 Set to true if the user specified the -H flag. If
184 true, set the HOME environment variable to the target
185 user's home directory.
186
187 preserve_environment=bool
188 Set to true if the user specified the -E flag, indicat‐
189 ing that the user wishes to preserve the environment.
190
191 run_shell=bool
192 Set to true if the user specified the -s flag, indicat‐
193 ing that the user wishes to run a shell.
194
195 login_shell=bool
196 Set to true if the user specified the -i flag, indicat‐
197 ing that the user wishes to run a login shell.
198
199 implied_shell=bool
200 If the user does not specify a program on the command
201 line, sudo will pass the plugin the path to the user's
202 shell and set implied_shell to true. This allows sudo
203 with no arguments to be used similarly to su(1). If
204 the plugin does not to support this usage, it may
205 return a value of -2 from the check_policy() function,
206 which will cause sudo to print a usage message and
207 exit.
208
209 preserve_groups=bool
210 Set to true if the user specified the -P flag, indicat‐
211 ing that the user wishes to preserve the group vector
212 instead of setting it based on the runas user.
213
214 ignore_ticket=bool
215 Set to true if the user specified the -k flag along
216 with a command, indicating that the user wishes to
217 ignore any cached authentication credentials.
218
219 noninteractive=bool
220 Set to true if the user specified the -n flag, indicat‐
221 ing that sudo should operate in non-interactive mode.
222 The plugin may reject a command run in non-interactive
223 mode if user interaction is required.
224
225 login_class=string
226 BSD login class to use when setting resource limits and
227 nice value, if specified by the -c flag.
228
229 selinux_role=string
230 SELinux role to use when executing the command, if
231 specified by the -r flag.
232
233 selinux_type=string
234 SELinux type to use when executing the command, if
235 specified by the -t flag.
236
237 bsdauth_type=string
238 Authentication type, if specified by the -a flag, to
239 use on systems where BSD authentication is supported.
240
241 network_addrs=list
242 A space-separated list of IP network addresses and net‐
243 masks in the form “addr/netmask”, e.g.
244 “192.168.1.2/255.255.255.0”. The address and netmask
245 pairs may be either IPv4 or IPv6, depending on what the
246 operating system supports. If the address contains a
247 colon (‘:’), it is an IPv6 address, else it is IPv4.
248
249 progname=string
250 The command name that sudo was run as, typically “sudo”
251 or “sudoedit”.
252
253 sudoedit=bool
254 Set to true when the -e flag is is specified or if
255 invoked as sudoedit. The plugin shall substitute an
256 editor into argv in the check_policy() function or
257 return -2 with a usage error if the plugin does not
258 support sudoedit. For more information, see the
259 check_policy section.
260
261 closefrom=number
262 If specified, the user has requested via the -C flag
263 that sudo close all files descriptors with a value of
264 number or higher. The plugin may optionally pass this,
265 or another value, back in the command_info list.
266
267 Additional settings may be added in the future so the plugin
268 should silently ignore settings that it does not recognize.
269
270 user_info
271 A vector of information about the user running the command in
272 the form of “name=value” strings. The vector is terminated
273 by a NULL pointer.
274
275 When parsing user_info, the plugin should split on the first
276 equal sign (‘=’) since the name field will never include one
277 itself but the value might.
278
279 pid=int
280 The process ID of the running sudo process. Only
281 available starting with API version 1.2
282
283 ppid=int
284 The parent process ID of the running sudo process.
285 Only available starting with API version 1.2
286
287 sid=int
288 The session ID of the running sudo process or 0 if sudo
289 is not part of a POSIX job control session. Only
290 available starting with API version 1.2
291
292 pgid=int
293 The ID of the process group that the running sudo
294 process belongs to. Only available starting with API
295 version 1.2
296
297 tcpgid=int
298 The ID of the forground process group associated with
299 the terminal device associcated with the sudo process
300 or -1 if there is no terminal present. Only available
301 starting with API version 1.2
302
303 user=string
304 The name of the user invoking sudo.
305
306 euid=uid_t
307 The effective user ID of the user invoking sudo.
308
309 uid=uid_t
310 The real user ID of the user invoking sudo.
311
312 egid=gid_t
313 The effective group ID of the user invoking sudo.
314
315 gid=gid_t
316 The real group ID of the user invoking sudo.
317
318 groups=list
319 The user's supplementary group list formatted as a
320 string of comma-separated group IDs.
321
322 cwd=string
323 The user's current working directory.
324
325 tty=string
326 The path to the user's terminal device. If the user
327 has no terminal device associated with the session, the
328 value will be empty, as in “tty=”.
329
330 host=string
331 The local machine's hostname as returned by the
332 gethostname(2) system call.
333
334 lines=int
335 The number of lines the user's terminal supports. If
336 there is no terminal device available, a default value
337 of 24 is used.
338
339 cols=int
340 The number of columns the user's terminal supports. If
341 there is no terminal device available, a default value
342 of 80 is used.
343
344 user_env
345 The user's environment in the form of a NULL-terminated
346 vector of “name=value” strings.
347
348 When parsing user_env, the plugin should split on the first
349 equal sign (‘=’) since the name field will never include one
350 itself but the value might.
351
352 plugin_options
353 Any (non-comment) strings immediately after the plugin path
354 are treated as arguments to the plugin. These arguments are
355 split on a white space boundary and are passed to the plugin
356 in the form of a NULL-terminated array of strings. If no
357 arguments were specified, plugin_options will be the NULL
358 pointer.
359
360 NOTE: the plugin_options parameter is only available starting
361 with API version 1.2. A plugin must check the API version
362 specified by the sudo front end before using plugin_options.
363 Failure to do so may result in a crash.
364
365 close
366 void (*close)(int exit_status, int error);
367
368 The close() function is called when the command being run by sudo
369 finishes.
370
371 The function arguments are as follows:
372
373 exit_status
374 The command's exit status, as returned by the wait(2) system
375 call. The value of exit_status is undefined if error is non-
376 zero.
377
378 error
379 If the command could not be executed, this is set to the
380 value of errno set by the execve(2) system call. The plugin
381 is responsible for displaying error information via the
382 conversation() or plugin_printf() function. If the command
383 was successfully executed, the value of error is 0.
384
385 show_version
386 int (*show_version)(int verbose);
387
388 The show_version() function is called by sudo when the user speci‐
389 fies the -V option. The plugin may display its version information
390 to the user via the conversation() or plugin_printf() function
391 using SUDO_CONV_INFO_MSG. If the user requests detailed version
392 information, the verbose flag will be set.
393
394 check_policy
395 int (*check_policy)(int argc, char * const argv[]
396 char *env_add[], char **command_info[],
397 char **argv_out[], char **user_env_out[]);
398
399 The check_policy() function is called by sudo to determine whether
400 the user is allowed to run the specified commands.
401
402 If the sudoedit option was enabled in the settings array passed to
403 the open() function, the user has requested sudoedit mode.
404 sudoedit is a mechanism for editing one or more files where an edi‐
405 tor is run with the user's credentials instead of with elevated
406 privileges. sudo achieves this by creating user-writable temporary
407 copies of the files to be edited and then overwriting the originals
408 with the temporary copies after editing is complete. If the plugin
409 supports sudoedit, it should choose the editor to be used, poten‐
410 tially from a variable in the user's environment, such as EDITOR,
411 and include it in argv_out (note that environment variables may
412 include command line flags). The files to be edited should be
413 copied from argv into argv_out, separated from the editor and its
414 arguments by a “--” element. The “--” will be removed by sudo
415 before the editor is executed. The plugin should also set
416 sudoedit=true in the command_info list.
417
418 The check_policy() function returns 1 if the command is allowed, 0
419 if not allowed, -1 for a general error, or -2 for a usage error or
420 if sudoedit was specified but is unsupported by the plugin. In the
421 latter case, sudo will print a usage message before it exits. If
422 an error occurs, the plugin may optionally call the conversation()
423 or plugin_printf() function with SUDO_CONF_ERROR_MSG to present
424 additional error information to the user.
425
426 The function arguments are as follows:
427
428 argc The number of elements in argv, not counting the final NULL
429 pointer.
430
431 argv The argument vector describing the command the user wishes to
432 run, in the same form as what would be passed to the
433 execve(2) system call. The vector is terminated by a NULL
434 pointer.
435
436 env_add
437 Additional environment variables specified by the user on the
438 command line in the form of a NULL-terminated vector of
439 “name=value” strings. The plugin may reject the command if
440 one or more variables are not allowed to be set, or it may
441 silently ignore such variables.
442
443 When parsing env_add, the plugin should split on the first
444 equal sign (‘=’) since the name field will never include one
445 itself but the value might.
446
447 command_info
448 Information about the command being run in the form of
449 “name=value” strings. These values are used by sudo to set
450 the execution environment when running a command. The plugin
451 is responsible for creating and populating the vector, which
452 must be terminated with a NULL pointer. The following values
453 are recognized by sudo:
454
455 command=string
456 Fully qualified path to the command to be executed.
457
458 runas_uid=uid
459 User ID to run the command as.
460
461 runas_euid=uid
462 Effective user ID to run the command as. If not speci‐
463 fied, the value of runas_uid is used.
464
465 runas_gid=gid
466 Group ID to run the command as.
467
468 runas_egid=gid
469 Effective group ID to run the command as. If not spec‐
470 ified, the value of runas_gid is used.
471
472 runas_groups=list
473 The supplementary group vector to use for the command
474 in the form of a comma-separated list of group IDs. If
475 preserve_groups is set, this option is ignored.
476
477 login_class=string
478 BSD login class to use when setting resource limits and
479 nice value (optional). This option is only set on sys‐
480 tems that support login classes.
481
482 preserve_groups=bool
483 If set, sudo will preserve the user's group vector
484 instead of initializing the group vector based on
485 runas_user.
486
487 cwd=string
488 The current working directory to change to when execut‐
489 ing the command.
490
491 noexec=bool
492 If set, prevent the command from executing other pro‐
493 grams.
494
495 chroot=string
496 The root directory to use when running the command.
497
498 nice=int
499 Nice value (priority) to use when executing the com‐
500 mand. The nice value, if specified, overrides the pri‐
501 ority associated with the login_class on BSD systems.
502
503 umask=octal
504 The file creation mask to use when executing the com‐
505 mand.
506
507 selinux_role=string
508 SELinux role to use when executing the command.
509
510 selinux_type=string
511 SELinux type to use when executing the command.
512
513 timeout=int
514 Command timeout. If non-zero then when the timeout
515 expires the command will be killed.
516
517 sudoedit=bool
518 Set to true when in sudoedit mode. The plugin may
519 enable sudoedit mode even if sudo was not invoked as
520 sudoedit. This allows the plugin to perform command
521 substitution and transparently enable sudoedit when the
522 user attempts to run an editor.
523
524 closefrom=number
525 If specified, sudo will close all files descriptors
526 with a value of number or higher.
527
528 iolog_compress=bool
529 Set to true if the I/O logging plugins, if any, should
530 compress the log data. This is a hint to the I/O log‐
531 ging plugin which may choose to ignore it.
532
533 iolog_path=string
534 Fully qualified path to the file or directory in which
535 I/O log is to be stored. This is a hint to the I/O
536 logging plugin which may choose to ignore it. If no
537 I/O logging plugin is loaded, this setting has no
538 effect.
539
540 iolog_stdin=bool
541 Set to true if the I/O logging plugins, if any, should
542 log the standard input if it is not connected to a ter‐
543 minal device. This is a hint to the I/O logging plugin
544 which may choose to ignore it.
545
546 iolog_stdout=bool
547 Set to true if the I/O logging plugins, if any, should
548 log the standard output if it is not connected to a
549 terminal device. This is a hint to the I/O logging
550 plugin which may choose to ignore it.
551
552 iolog_stderr=bool
553 Set to true if the I/O logging plugins, if any, should
554 log the standard error if it is not connected to a ter‐
555 minal device. This is a hint to the I/O logging plugin
556 which may choose to ignore it.
557
558 iolog_ttyin=bool
559 Set to true if the I/O logging plugins, if any, should
560 log all terminal input. This only includes input typed
561 by the user and not from a pipe or redirected from a
562 file. This is a hint to the I/O logging plugin which
563 may choose to ignore it.
564
565 iolog_ttyout=bool
566 Set to true if the I/O logging plugins, if any, should
567 log all terminal output. This only includes output to
568 the screen, not output to a pipe or file. This is a
569 hint to the I/O logging plugin which may choose to
570 ignore it.
571
572 use_pty=bool
573 Allocate a pseudo-tty to run the command in, regardless
574 of whether or not I/O logging is in use. By default,
575 sudo will only run the command in a pty when an I/O log
576 plugin is loaded.
577
578 set_utmp=bool
579 Create a utmp (or utmpx) entry when a pseudo-tty is
580 allocated. By default, the new entry will be a copy of
581 the user's existing utmp entry (if any), with the tty,
582 time, type and pid fields updated.
583
584 utmp_user=string
585 User name to use when constructing a new utmp (or
586 utmpx) entry when set_utmp is enabled. This option can
587 be used to set the user field in the utmp entry to the
588 user the command runs as rather than the invoking user.
589 If not set, sudo will base the new entry on the invok‐
590 ing user's existing entry.
591
592 Unsupported values will be ignored.
593
594 argv_out
595 The NULL-terminated argument vector to pass to the execve(2)
596 system call when executing the command. The plugin is
597 responsible for allocating and populating the vector.
598
599 user_env_out
600 The NULL-terminated environment vector to use when executing
601 the command. The plugin is responsible for allocating and
602 populating the vector.
603
604 list
605 int (*list)(int verbose, const char *list_user,
606 int argc, char * const argv[]);
607
608 List available privileges for the invoking user. Returns 1 on suc‐
609 cess, 0 on failure and -1 on error. On error, the plugin may
610 optionally call the conversation() or plugin_printf() function with
611 SUDO_CONF_ERROR_MSG to present additional error information to the
612 user.
613
614 Privileges should be output via the conversation() or
615 plugin_printf() function using SUDO_CONV_INFO_MSG,
616
617 verbose
618 Flag indicating whether to list in verbose mode or not.
619
620 list_user
621 The name of a different user to list privileges for if the
622 policy allows it. If NULL, the plugin should list the privi‐
623 leges of the invoking user.
624
625 argc The number of elements in argv, not counting the final NULL
626 pointer.
627
628 argv If non-NULL, an argument vector describing a command the user
629 wishes to check against the policy in the same form as what
630 would be passed to the execve(2) system call. If the command
631 is permitted by the policy, the fully-qualified path to the
632 command should be displayed along with any command line argu‐
633 ments.
634
635 validate
636 int (*validate)(void);
637
638 The validate() function is called when sudo is run with the -v
639 flag. For policy plugins such as sudoers that cache authentication
640 credentials, this function will validate and cache the credentials.
641
642 The validate() function should be NULL if the plugin does not sup‐
643 port credential caching.
644
645 Returns 1 on success, 0 on failure and -1 on error. On error, the
646 plugin may optionally call the conversation() or plugin_printf()
647 function with SUDO_CONF_ERROR_MSG to present additional error
648 information to the user.
649
650 invalidate
651 void (*invalidate)(int remove);
652
653 The invalidate() function is called when sudo is called with the -k
654 or -K flag. For policy plugins such as sudoers that cache authen‐
655 tication credentials, this function will invalidate the creden‐
656 tials. If the remove flag is set, the plugin may remove the cre‐
657 dentials instead of simply invalidating them.
658
659 The invalidate() function should be NULL if the plugin does not
660 support credential caching.
661
662 init_session
663 int (*init_session)(struct passwd *pwd, char **user_envp[);
664
665 The init_session() function is called before sudo sets up the exe‐
666 cution environment for the command. It is run in the parent sudo
667 process and before any uid or gid changes. This can be used to
668 perform session setup that is not supported by command_info, such
669 as opening the PAM session. The close() function can be used to
670 tear down the session that was opened by init_session.
671
672 The pwd argument points to a passwd struct for the user the command
673 will be run as if the uid the command will run as was found in the
674 password database, otherwise it will be NULL.
675
676 The user_env argument points to the environment the command will
677 run in, in the form of a NULL-terminated vector of “name=value”
678 strings. This is the same string passed back to the front end via
679 the Policy Plugin's user_env_out parameter. If the init_session()
680 function needs to modify the user environment, it should update the
681 pointer stored in user_env. The expected use case is to merge the
682 contents of the PAM environment (if any) with the contents of
683 user_env. NOTE: the user_env parameter is only available starting
684 with API version 1.2. A plugin must check the API version speci‐
685 fied by the sudo front end before using user_env. Failure to do so
686 may result in a crash.
687
688 Returns 1 on success, 0 on failure and -1 on error. On error, the
689 plugin may optionally call the conversation() or plugin_printf()
690 function with SUDO_CONF_ERROR_MSG to present additional error
691 information to the user.
692
693 register_hooks
694 void (*register_hooks)(int version,
695 int (*register_hook)(struct sudo_hook *hook));
696
697 The register_hooks() function is called by the sudo front end to
698 register any hooks the plugin needs. If the plugin does not sup‐
699 port hooks, register_hooks should be set to the NULL pointer.
700
701 The version argument describes the version of the hooks API sup‐
702 ported by the sudo front end.
703
704 The register_hook() function should be used to register any sup‐
705 ported hooks the plugin needs. It returns 0 on success, 1 if the
706 hook type is not supported and -1 if the major version in struct
707 hook does not match the front end's major hook API version.
708
709 See the Hook function API section below for more information about
710 hooks.
711
712 NOTE: the register_hooks() function is only available starting with
713 API version 1.2. If the sudo front end doesn't support API version
714 1.2 or higher, register_hooks will not be called.
715
716 deregister_hooks
717 void (*deregister_hooks)(int version,
718 int (*deregister_hook)(struct sudo_hook *hook));
719
720 The deregister_hooks() function is called by the sudo front end to
721 deregister any hooks the plugin has registered. If the plugin does
722 not support hooks, deregister_hooks should be set to the NULL
723 pointer.
724
725 The version argument describes the version of the hooks API sup‐
726 ported by the sudo front end.
727
728 The deregister_hook() function should be used to deregister any
729 hooks that were put in place by the register_hook() function. If
730 the plugin tries to deregister a hook that the front end does not
731 support, deregister_hook will return an error.
732
733 See the Hook function API section below for more information about
734 hooks.
735
736 NOTE: the deregister_hooks() function is only available starting
737 with API version 1.2. If the sudo front end doesn't support API
738 version 1.2 or higher, deregister_hooks will not be called.
739
740 Policy Plugin Version Macros
741
742 /* Plugin API version major/minor. */
743 #define SUDO_API_VERSION_MAJOR 1
744 #define SUDO_API_VERSION_MINOR 2
745 #define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
746 #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\
747 SUDO_API_VERSION_MINOR)
748
749 /* Getters and setters for API version */
750 #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
751 #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
752 #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
753 *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
754 } while(0)
755 #define SUDO_VERSION_SET_MINOR(vp, n) do { \
756 *(vp) = (*(vp) & 0xffff0000) | (n); \
757 } while(0)
758
759 I/O plugin API
760 struct io_plugin {
761 #define SUDO_IO_PLUGIN 2
762 unsigned int type; /* always SUDO_IO_PLUGIN */
763 unsigned int version; /* always SUDO_API_VERSION */
764 int (*open)(unsigned int version, sudo_conv_t conversation
765 sudo_printf_t plugin_printf, char * const settings[],
766 char * const user_info[], int argc, char * const argv[],
767 char * const user_env[], char * const plugin_options[]);
768 void (*close)(int exit_status, int error); /* wait status or error */
769 int (*show_version)(int verbose);
770 int (*log_ttyin)(const char *buf, unsigned int len);
771 int (*log_ttyout)(const char *buf, unsigned int len);
772 int (*log_stdin)(const char *buf, unsigned int len);
773 int (*log_stdout)(const char *buf, unsigned int len);
774 int (*log_stderr)(const char *buf, unsigned int len);
775 void (*register_hooks)(int version,
776 int (*register_hook)(struct sudo_hook *hook));
777 void (*deregister_hooks)(int version,
778 int (*deregister_hook)(struct sudo_hook *hook));
779 };
780
781 When an I/O plugin is loaded, sudo runs the command in a pseudo-tty.
782 This makes it possible to log the input and output from the user's ses‐
783 sion. If any of the standard input, standard output or standard error do
784 not correspond to a tty, sudo will open a pipe to capture the I/O for
785 logging before passing it on.
786
787 The log_ttyin function receives the raw user input from the terminal
788 device (note that this will include input even when echo is disabled,
789 such as when a password is read). The log_ttyout function receives out‐
790 put from the pseudo-tty that is suitable for replaying the user's session
791 at a later time. The log_stdin(), log_stdout() and log_stderr() func‐
792 tions are only called if the standard input, standard output or standard
793 error respectively correspond to something other than a tty.
794
795 Any of the logging functions may be set to the NULL pointer if no logging
796 is to be performed. If the open function returns 0, no I/O will be sent
797 to the plugin.
798
799 The io_plugin struct has the following fields:
800
801 type The type field should always be set to SUDO_IO_PLUGIN.
802
803 version
804 The version field should be set to SUDO_API_VERSION.
805
806 This allows sudo to determine the API version the plugin was built
807 against.
808
809 open
810 int (*open)(unsigned int version, sudo_conv_t conversation
811 sudo_printf_t plugin_printf, char * const settings[],
812 char * const user_info[], int argc, char * const argv[],
813 char * const user_env[], char * const plugin_options[]);
814
815 The open() function is run before the log_input(), log_output() or
816 show_version() functions are called. It is only called if the ver‐
817 sion is being requested or the check_policy() function has returned
818 successfully. It returns 1 on success, 0 on failure, -1 if a gen‐
819 eral error occurred, or -2 if there was a usage error. In the lat‐
820 ter case, sudo will print a usage message before it exits. If an
821 error occurs, the plugin may optionally call the conversation() or
822 plugin_printf() function with SUDO_CONF_ERROR_MSG to present addi‐
823 tional error information to the user.
824
825 The function arguments are as follows:
826
827 version
828 The version passed in by sudo allows the plugin to determine
829 the major and minor version number of the plugin API sup‐
830 ported by sudo.
831
832 conversation
833 A pointer to the conversation() function that may be used by
834 the show_version() function to display version information
835 (see show_version() below). The conversation() function may
836 also be used to display additional error message to the user.
837 The conversation() function returns 0 on success and -1 on
838 failure.
839
840 plugin_printf
841 A pointer to a printf()-style function that may be used by
842 the show_version() function to display version information
843 (see show_version below). The plugin_printf() function may
844 also be used to display additional error message to the user.
845 The plugin_printf() function returns number of characters
846 printed on success and -1 on failure.
847
848 settings
849 A vector of user-supplied sudo settings in the form of
850 “name=value” strings. The vector is terminated by a NULL
851 pointer. These settings correspond to flags the user speci‐
852 fied when running sudo. As such, they will only be present
853 when the corresponding flag has been specified on the command
854 line.
855
856 When parsing settings, the plugin should split on the first
857 equal sign (‘=’) since the name field will never include one
858 itself but the value might.
859
860 See the Policy plugin API section for a list of all possible
861 settings.
862
863 user_info
864 A vector of information about the user running the command in
865 the form of “name=value” strings. The vector is terminated
866 by a NULL pointer.
867
868 When parsing user_info, the plugin should split on the first
869 equal sign (‘=’) since the name field will never include one
870 itself but the value might.
871
872 See the Policy plugin API section for a list of all possible
873 strings.
874
875 argc The number of elements in argv, not counting the final NULL
876 pointer.
877
878 argv If non-NULL, an argument vector describing a command the user
879 wishes to run in the same form as what would be passed to the
880 execve(2) system call.
881
882 user_env
883 The user's environment in the form of a NULL-terminated vec‐
884 tor of “name=value” strings.
885
886 When parsing user_env, the plugin should split on the first
887 equal sign (‘=’) since the name field will never include one
888 itself but the value might.
889
890 plugin_options
891 Any (non-comment) strings immediately after the plugin path
892 are treated as arguments to the plugin. These arguments are
893 split on a white space boundary and are passed to the plugin
894 in the form of a NULL-terminated array of strings. If no
895 arguments were specified, plugin_options will be the NULL
896 pointer.
897
898 NOTE: the plugin_options parameter is only available starting
899 with API version 1.2. A plugin must check the API version
900 specified by the sudo front end before using plugin_options.
901 Failure to do so may result in a crash.
902
903 close
904 void (*close)(int exit_status, int error);
905
906 The close() function is called when the command being run by sudo
907 finishes.
908
909 The function arguments are as follows:
910
911 exit_status
912 The command's exit status, as returned by the wait(2) system
913 call. The value of exit_status is undefined if error is non-
914 zero.
915
916 error
917 If the command could not be executed, this is set to the
918 value of errno set by the execve(2) system call. If the com‐
919 mand was successfully executed, the value of error is 0.
920
921 show_version
922 int (*show_version)(int verbose);
923
924 The show_version() function is called by sudo when the user speci‐
925 fies the -V option. The plugin may display its version information
926 to the user via the conversation() or plugin_printf() function
927 using SUDO_CONV_INFO_MSG. If the user requests detailed version
928 information, the verbose flag will be set.
929
930 log_ttyin
931 int (*log_ttyin)(const char *buf, unsigned int len);
932
933 The log_ttyin() function is called whenever data can be read from
934 the user but before it is passed to the running command. This
935 allows the plugin to reject data if it chooses to (for instance if
936 the input contains banned content). Returns 1 if the data should
937 be passed to the command, 0 if the data is rejected (which will
938 terminate the command) or -1 if an error occurred.
939
940 The function arguments are as follows:
941
942 buf The buffer containing user input.
943
944 len The length of buf in bytes.
945
946 log_ttyout
947 int (*log_ttyout)(const char *buf, unsigned int len);
948
949 The log_ttyout() function is called whenever data can be read from
950 the command but before it is written to the user's terminal. This
951 allows the plugin to reject data if it chooses to (for instance if
952 the output contains banned content). Returns 1 if the data should
953 be passed to the user, 0 if the data is rejected (which will termi‐
954 nate the command) or -1 if an error occurred.
955
956 The function arguments are as follows:
957
958 buf The buffer containing command output.
959
960 len The length of buf in bytes.
961
962 log_stdin
963 int (*log_stdin)(const char *buf, unsigned int len);
964
965 The log_stdin() function is only used if the standard input does
966 not correspond to a tty device. It is called whenever data can be
967 read from the standard input but before it is passed to the running
968 command. This allows the plugin to reject data if it chooses to
969 (for instance if the input contains banned content). Returns 1 if
970 the data should be passed to the command, 0 if the data is rejected
971 (which will terminate the command) or -1 if an error occurred.
972
973 The function arguments are as follows:
974
975 buf The buffer containing user input.
976
977 len The length of buf in bytes.
978
979 log_stdout
980 int (*log_stdout)(const char *buf, unsigned int len);
981
982 The log_stdout() function is only used if the standard output does
983 not correspond to a tty device. It is called whenever data can be
984 read from the command but before it is written to the standard out‐
985 put. This allows the plugin to reject data if it chooses to (for
986 instance if the output contains banned content). Returns 1 if the
987 data should be passed to the user, 0 if the data is rejected (which
988 will terminate the command) or -1 if an error occurred.
989
990 The function arguments are as follows:
991
992 buf The buffer containing command output.
993
994 len The length of buf in bytes.
995
996 log_stderr
997 int (*log_stderr)(const char *buf, unsigned int len);
998
999 The log_stderr() function is only used if the standard error does
1000 not correspond to a tty device. It is called whenever data can be
1001 read from the command but before it is written to the standard
1002 error. This allows the plugin to reject data if it chooses to (for
1003 instance if the output contains banned content). Returns 1 if the
1004 data should be passed to the user, 0 if the data is rejected (which
1005 will terminate the command) or -1 if an error occurred.
1006
1007 The function arguments are as follows:
1008
1009 buf The buffer containing command output.
1010
1011 len The length of buf in bytes.
1012
1013 register_hooks
1014 See the Policy plugin API section for a description of
1015 register_hooks.
1016
1017 deregister_hooks
1018 See the Policy plugin API section for a description of
1019 deregister_hooks.
1020
1021 I/O Plugin Version Macros
1022
1023 Same as for the Policy plugin API.
1024
1025 Hook function API
1026 Beginning with plugin API version 1.2, it is possible to install hooks
1027 for certain functions called by the sudo front end.
1028
1029 Currently, the only supported hooks relate to the handling of environment
1030 variables. Hooks can be used to intercept attempts to get, set, or
1031 remove environment variables so that these changes can be reflected in
1032 the version of the environment that is used to execute a command. A
1033 future version of the API will support hooking internal sudo front end
1034 functions as well.
1035
1036 Hook structure
1037
1038 Hooks in sudo are described by the following structure:
1039
1040 typedef int (*sudo_hook_fn_t)();
1041
1042 struct sudo_hook {
1043 int hook_version;
1044 int hook_type;
1045 sudo_hook_fn_t hook_fn;
1046 void *closure;
1047 };
1048
1049 The sudo_hook structure has the following fields:
1050
1051 hook_version
1052 The hook_version field should be set to SUDO_HOOK_VERSION.
1053
1054 hook_type
1055 The hook_type field may be one of the following supported hook
1056 types:
1057
1058 SUDO_HOOK_SETENV
1059 The C library setenv(3) function. Any registered hooks will
1060 run before the C library implementation. The hook_fn field
1061 should be a function that matches the following typedef:
1062
1063 typedef int (*sudo_hook_fn_setenv_t)(const char *name,
1064 const char *value, int overwrite, void *closure);
1065
1066 If the registered hook does not match the typedef the results
1067 are unspecified.
1068
1069 SUDO_HOOK_UNSETENV
1070 The C library unsetenv(3) function. Any registered hooks
1071 will run before the C library implementation. The hook_fn
1072 field should be a function that matches the following type‐
1073 def:
1074
1075 typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
1076 void *closure);
1077
1078 SUDO_HOOK_GETENV
1079 The C library getenv(3) function. Any registered hooks will
1080 run before the C library implementation. The hook_fn field
1081 should be a function that matches the following typedef:
1082
1083 typedef int (*sudo_hook_fn_getenv_t)(const char *name,
1084 char **value, void *closure);
1085
1086 If the registered hook does not match the typedef the results
1087 are unspecified.
1088
1089 SUDO_HOOK_PUTENV
1090 The C library putenv(3) function. Any registered hooks will
1091 run before the C library implementation. The hook_fn field
1092 should be a function that matches the following typedef:
1093
1094 typedef int (*sudo_hook_fn_putenv_t)(char *string,
1095 void *closure);
1096
1097 If the registered hook does not match the typedef the results
1098 are unspecified.
1099
1100 hook_fn
1101 sudo_hook_fn_t hook_fn;
1102
1103 The hook_fn field should be set to the plugin's hook implementa‐
1104 tion. The actual function arguments will vary depending on the
1105 hook_type (see hook_type above). In all cases, the closure field
1106 of struct sudo_hook is passed as the last function parameter. This
1107 can be used to pass arbitrary data to the plugin's hook implementa‐
1108 tion.
1109
1110 The function return value may be one of the following:
1111
1112 SUDO_HOOK_RET_ERROR
1113 The hook function encountered an error.
1114
1115 SUDO_HOOK_RET_NEXT
1116 The hook completed without error, go on to the next hook
1117 (including the native implementation if applicable). For
1118 example, a getenv(3) hook might return SUDO_HOOK_RET_NEXT if
1119 the specified variable was not found in the private copy of
1120 the environment.
1121
1122 SUDO_HOOK_RET_STOP
1123 The hook completed without error, stop processing hooks for
1124 this invocation. This can be used to replace the native
1125 implementation. For example, a setenv hook that operates on
1126 a private copy of the environment but leaves environ
1127 unchanged.
1128
1129 Note that it is very easy to create an infinite loop when hooking C
1130 library functions. For example, a getenv(3) hook that calls the
1131 snprintf(3) function may create a loop if the snprintf(3) implementation
1132 calls getenv(3) to check the locale. To prevent this, you may wish to
1133 use a static variable in the hook function to guard against nested calls.
1134 For example:
1135
1136 static int in_progress = 0; /* avoid recursion */
1137 if (in_progress)
1138 return SUDO_HOOK_RET_NEXT;
1139 in_progress = 1;
1140 ...
1141 in_progress = 0;
1142 return SUDO_HOOK_RET_STOP;
1143
1144 Hook API Version Macros
1145
1146 /* Hook API version major/minor */
1147 #define SUDO_HOOK_VERSION_MAJOR 1
1148 #define SUDO_HOOK_VERSION_MINOR 0
1149 #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y)
1150 #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\
1151 SUDO_HOOK_VERSION_MINOR)
1152
1153 /* Getters and setters for hook API version */
1154 #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16)
1155 #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff)
1156 #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \
1157 *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
1158 } while(0)
1159 #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \
1160 *(vp) = (*(vp) & 0xffff0000) | (n); \
1161 } while(0)
1162
1163 Conversation API
1164 If the plugin needs to interact with the user, it may do so via the
1165 conversation() function. A plugin should not attempt to read directly
1166 from the standard input or the user's tty (neither of which are guaran‐
1167 teed to exist). The caller must include a trailing newline in msg if one
1168 is to be printed.
1169
1170 A printf()-style function is also available that can be used to display
1171 informational or error messages to the user, which is usually more conve‐
1172 nient for simple messages where no use input is required.
1173
1174 struct sudo_conv_message {
1175 #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
1176 #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
1177 #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
1178 #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
1179 #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
1180 #define SUDO_CONV_DEBUG_MSG 0x0006 /* debugging message */
1181 #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
1182 int msg_type;
1183 int timeout;
1184 const char *msg;
1185 };
1186
1187 struct sudo_conv_reply {
1188 char *reply;
1189 };
1190
1191 typedef int (*sudo_conv_t)(int num_msgs,
1192 const struct sudo_conv_message msgs[],
1193 struct sudo_conv_reply replies[]);
1194
1195 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
1196
1197 Pointers to the conversation() and printf()-style functions are passed in
1198 to the plugin's open() function when the plugin is initialized.
1199
1200 To use the conversation() function, the plugin must pass an array of
1201 sudo_conv_message and sudo_conv_reply structures. There must be a struct
1202 sudo_conv_message and struct sudo_conv_reply for each message in the con‐
1203 versation. The plugin is responsible for freeing the reply buffer filled
1204 in to the struct sudo_conv_reply, if any.
1205
1206 The printf()-style function uses the same underlying mechanism as the
1207 conversation() function but only supports SUDO_CONV_INFO_MSG,
1208 SUDO_CONV_ERROR_MSG and SUDO_CONV_DEBUG_MSG for the msg_type parameter.
1209 It can be more convenient than using the conversation() function if no
1210 user reply is needed and supports standard printf() escape sequences.
1211
1212 Unlike, SUDO_CONV_INFO_MSG and Dv SUDO_CONV_ERROR_MSG , messages sent
1213 with the SUDO_CONV_DEBUG_MSG msg_type are not directly user-visible.
1214 Instead, they are logged to the file specified in the Debug statement (if
1215 any) in the /etc/sudo.conf
1216
1217 file. This allows a plugin to log debugging information and is intended
1218 to be used in conjunction with the debug_flags setting.
1219
1220 See the sample plugin for an example of the conversation() function
1221 usage.
1222
1223 Sudoers group plugin API
1224 The sudoers module supports a plugin interface to allow non-Unix group
1225 lookups. This can be used to query a group source other than the stan‐
1226 dard Unix group database. A sample group plugin is bundled with sudo
1227 that implements file-based lookups. Third party group plugins include a
1228 QAS AD plugin available from Quest Software.
1229
1230 A group plugin must declare and populate a sudoers_group_plugin struct in
1231 the global scope. This structure contains pointers to the functions that
1232 implement plugin initialization, cleanup and group lookup.
1233
1234 struct sudoers_group_plugin {
1235 unsigned int version;
1236 int (*init)(int version, sudo_printf_t sudo_printf,
1237 char *const argv[]);
1238 void (*cleanup)(void);
1239 int (*query)(const char *user, const char *group,
1240 const struct passwd *pwd);
1241 };
1242
1243 The sudoers_group_plugin struct has the following fields:
1244
1245 version
1246 The version field should be set to GROUP_API_VERSION.
1247
1248 This allows sudoers to determine the API version the group plugin
1249 was built against.
1250
1251 init
1252 int (*init)(int version, sudo_printf_t plugin_printf,
1253 char *const argv[]);
1254
1255 The init() function is called after sudoers has been parsed but
1256 before any policy checks. It returns 1 on success, 0 on failure
1257 (or if the plugin is not configured), and -1 if a error occurred.
1258 If an error occurs, the plugin may call the plugin_printf() func‐
1259 tion with SUDO_CONF_ERROR_MSG to present additional error informa‐
1260 tion to the user.
1261
1262 The function arguments are as follows:
1263
1264 version
1265 The version passed in by sudoers allows the plugin to deter‐
1266 mine the major and minor version number of the group plugin
1267 API supported by sudoers.
1268
1269 plugin_printf
1270 A pointer to a printf()-style function that may be used to
1271 display informational or error message to the user. Returns
1272 the number of characters printed on success and -1 on fail‐
1273 ure.
1274
1275 argv A NULL-terminated array of arguments generated from the
1276 group_plugin option in sudoers. If no arguments were given,
1277 argv will be NULL.
1278
1279 cleanup
1280 void (*cleanup)();
1281
1282 The cleanup() function is called when sudoers has finished its
1283 group checks. The plugin should free any memory it has allocated
1284 and close open file handles.
1285
1286 query
1287 int (*query)(const char *user, const char *group,
1288 const struct passwd *pwd);
1289
1290 The query() function is used to ask the group plugin whether user
1291 is a member of group.
1292
1293 The function arguments are as follows:
1294
1295 user The name of the user being looked up in the external group
1296 database.
1297
1298 group
1299 The name of the group being queried.
1300
1301 pwd The password database entry for user, if any. If user is not
1302 present in the password database, pwd will be NULL.
1303
1304 Group API Version Macros
1305
1306 /* Sudoers group plugin version major/minor */
1307 #define GROUP_API_VERSION_MAJOR 1
1308 #define GROUP_API_VERSION_MINOR 0
1309 #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \
1310 GROUP_API_VERSION_MINOR)
1311
1312 /* Getters and setters for group version */
1313 #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
1314 #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
1315 #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \
1316 *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
1317 } while(0)
1318 #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \
1319 *(vp) = (*(vp) & 0xffff0000) | (n); \
1320 } while(0)
1321
1323 The following revisions have been made to the Sudo Plugin API.
1324
1325 Version 1.0
1326 Initial API version.
1327
1328 Version 1.1
1329 The I/O logging plugin's open() function was modified to take the
1330 command_info list as an argument.
1331
1332 Version 1.2
1333 The Policy and I/O logging plugins' open() functions are now passed
1334 a list of plugin options if any are specified in /etc/sudo.conf.
1335
1336 A simple hooks API has been introduced to allow plugins to hook in
1337 to the system's environment handling functions.
1338
1339 The init_session Policy plugin function is now passed a pointer to
1340 the user environment which can be updated as needed. This can be
1341 used to merge in environment variables stored in the PAM handle
1342 before a command is run.
1343
1345 sudoers(5), sudo(8)
1346
1348 If you feel you have found a bug in sudo, please submit a bug report at
1349 http://www.sudo.ws/sudo/bugs/
1350
1352 Limited free support is available via the sudo-users mailing list, see
1353 http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search the
1354 archives.
1355
1357 sudo is provided “AS IS” and any express or implied warranties, includ‐
1358 ing, but not limited to, the implied warranties of merchantability and
1359 fitness for a particular purpose are disclaimed. See the LICENSE file
1360 distributed with sudo or http://www.sudo.ws/sudo/license.html for com‐
1361 plete details.
1362
1363Sudo 1.8.6p3 July 16, 2012 Sudo 1.8.6p3