b39cfc10bdba8a4187e8067d15e8e9162ecac28a
[debian/sudo] / doc / sudo_plugin.mdoc.in
1 .\"
2 .\" Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
3 .\"
4 .\" Permission to use, copy, modify, and distribute this software for any
5 .\" purpose with or without fee is hereby granted, provided that the above
6 .\" copyright notice and this permission notice appear in all copies.
7 .\"
8 .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 .\"
17 .Dd July 16, 2012
18 .Dt SUDO_PLUGIN @mansectform@
19 .Os Sudo @PACKAGE_VERSION@
20 .Sh NAME
21 .Nm sudo_plugin
22 .Nd Sudo Plugin API
23 .Sh DESCRIPTION
24 Starting with version 1.8,
25 .Nm sudo
26 supports a plugin API
27 for policy and session logging.
28 By default, the
29 .Em sudoers
30 policy plugin and an associated I/O logging plugin are used.
31 Via the plugin API,
32 .Nm sudo
33 can be configured to use alternate policy and/or I/O logging plugins
34 provided by third parties.
35 The plugins to be used are specified via the
36 .Pa @sysconfdir@/sudo.conf
37 file.
38 .Pp
39 The API is versioned with a major and minor number.
40 The minor version number is incremented when additions are made.
41 The major number is incremented when incompatible changes are made.
42 A plugin should be check the version passed to it and make sure that the
43 major version matches.
44 .Pp
45 The plugin API is defined by the
46 .Li sudo_plugin.h
47 header file.
48 .Ss The sudo.conf file
49 The
50 .Pa @sysconfdir@/sudo.conf
51 file contains plugin configuration directives.
52 The primary keyword is the
53 .Li Plugin
54 directive, which causes a plugin to be loaded.
55 .Pp
56 A
57 .Li Plugin
58 line consists of the
59 .Li Plugin
60 keyword, followed by the
61 .Em symbol_name
62 and the
63 .Em path
64 to the shared object containing the plugin.
65 The
66 .Em symbol_name
67 is the name of the
68 .Li struct policy_plugin
69 or
70 .Li struct io_plugin
71 in the plugin shared object.
72 The
73 .Em path
74 may be fully qualified or relative.
75 If not fully qualified it is relative to the
76 .Pa @prefix@/libexec
77 directory.
78 Any additional parameters after the
79 .Em path
80 are passed as options to the plugin's
81 .Fn open
82 function.
83 Lines that don't begin with
84 .Li Plugin ,
85 .Li Path ,
86 .Li Debug
87 or
88 .Li Set
89 are silently ignored.
90 .Pp
91 The same shared object may contain multiple plugins, each with a
92 different symbol name.
93 The shared object file must be owned by uid 0 and only writable by its owner.
94 Because of ambiguities that arise from composite policies, only a single
95 policy plugin may be specified.
96 This limitation does not apply to I/O plugins.
97 .Bd -literal
98 #
99 # Default @sysconfdir@/sudo.conf file
100 #
101 # Format:
102 #   Plugin plugin_name plugin_path plugin_options ...
103 #   Path askpass /path/to/askpass
104 #   Path noexec /path/to/sudo_noexec.so
105 #   Debug sudo /var/log/sudo_debug all@warn
106 #   Set disable_coredump true
107 #
108 # The plugin_path is relative to @prefix@/libexec unless
109 #   fully qualified.
110 # The plugin_name corresponds to a global symbol in the plugin
111 #   that contains the plugin interface structure.
112 # The plugin_options are optional.
113 #
114 Plugin sudoers_policy sudoers.so
115 Plugin sudoers_io sudoers.so
116 .Ed
117 .Ss Policy plugin API
118 A policy plugin must declare and populate a
119 .Li policy_plugin
120 struct in the global scope.
121 This structure contains pointers to the functions that implement the
122 .Nm sudo
123 policy checks.
124 The name of the symbol should be specified in
125 .Pa @sysconfdir@/sudo.conf
126 along with a path to the plugin so that
127 .Nm sudo
128 can load it.
129 .Bd -literal
130 struct policy_plugin {
131 #define SUDO_POLICY_PLUGIN     1
132     unsigned int type; /* always SUDO_POLICY_PLUGIN */
133     unsigned int version; /* always SUDO_API_VERSION */
134     int (*open)(unsigned int version, sudo_conv_t conversation,
135                 sudo_printf_t plugin_printf, char * const settings[],
136                 char * const user_info[], char * const user_env[],
137                 char * const plugin_options[]);
138     void (*close)(int exit_status, int error);
139     int (*show_version)(int verbose);
140     int (*check_policy)(int argc, char * const argv[],
141                         char *env_add[], char **command_info[],
142                         char **argv_out[], char **user_env_out[]);
143     int (*list)(int argc, char * const argv[], int verbose,
144                 const char *list_user);
145     int (*validate)(void);
146     void (*invalidate)(int remove);
147     int (*init_session)(struct passwd *pwd, char **user_env[]);
148     void (*register_hooks)(int version,
149        int (*register_hook)(struct sudo_hook *hook));
150     void (*deregister_hooks)(int version,
151        int (*deregister_hook)(struct sudo_hook *hook));
152 };
153 .Ed
154 .Pp
155 The policy_plugin struct has the following fields:
156 .Bl -tag -width 4n
157 .It type
158 The
159 .Li type
160 field should always be set to SUDO_POLICY_PLUGIN.
161 .It version
162 The
163 .Li version
164 field should be set to
165 .Dv SUDO_API_VERSION .
166 .Pp
167 This allows
168 .Nm sudo
169 to determine the API version the plugin was
170 built against.
171 .It open
172 .Bd -literal -compact
173 int (*open)(unsigned int version, sudo_conv_t conversation,
174             sudo_printf_t plugin_printf, char * const settings[],
175             char * const user_info[], char * const user_env[],
176             char * const plugin_options[]);
177 .Ed
178 .Pp
179 Returns 1 on success, 0 on failure, \-1 if a general error occurred,
180 or \-2 if there was a usage error.
181 In the latter case,
182 .Nm sudo
183 will print a usage message before it exits.
184 If an error occurs, the plugin may optionally call the
185 .Fn conversation
186 or
187 .Fn plugin_printf
188 function with
189 .Dv SUDO_CONF_ERROR_MSG
190 to present additional error information to the user.
191 .Pp
192 The function arguments are as follows:
193 .Bl -tag -width 4n
194 .It version
195 The version passed in by
196 .Nm sudo
197 allows the plugin to determine the
198 major and minor version number of the plugin API supported by
199 .Nm sudo .
200 .It conversation
201 A pointer to the
202 .Fn conversation
203 function that can be used by the plugin to interact with the user (see below).
204 Returns 0 on success and \-1 on failure.
205 .It plugin_printf
206 A pointer to a
207 .Fn printf Ns No -style
208 function that may be used to display informational or error messages
209 (see below).
210 Returns the number of characters printed on success and \-1 on failure.
211 .It settings
212 A vector of user-supplied
213 .Nm sudo
214 settings in the form of
215 .Dq name=value
216 strings.
217 The vector is terminated by a
218 .Dv NULL
219 pointer.
220 These settings correspond to flags the user specified when running
221 .Nm sudo .
222 As such, they will only be present when the corresponding flag has
223 been specified on the command line.
224 .Pp
225 When parsing
226 .Em settings ,
227 the plugin should split on the
228 .Sy first
229 equal sign
230 .Pq Ql =
231 since the
232 .Em name
233 field will never include one
234 itself but the
235 .Em value
236 might.
237 .Bl -tag -width 4n
238 .It debug_flags=string
239 A comma-separated list of debug flags that correspond to
240 .Nm sudo Ns No 's
241 .Li Debug
242 entry in
243 .Pa @sysconfdir@/sudo.conf ,
244 if there is one.
245 The flags are passed to the plugin as they appear in
246 .Pa @sysconfdir@/sudo.conf .
247 The syntax used by
248 .Nm sudo
249 and the
250 .Em sudoers
251 plugin is
252 .Em subsystem Ns No @ Ns Em priority
253 but the plugin is free to use a different
254 format so long as it does not include a comma
255 .Pq Ql ,\& .
256 .Pp
257 For reference, the priorities supported by the
258 .Nm sudo
259 front end and
260 .Em sudoers
261 are:
262 .Em crit ,
263 .Em err ,
264 .Em warn ,
265 .Em notice ,
266 .Em diag ,
267 .Em info ,
268 .Em trace
269 and
270 .Em debug .
271 .Pp
272 The following subsystems are defined:
273 .Em main ,
274 .Em memory ,
275 .Em args ,
276 .Em exec ,
277 .Em pty ,
278 .Em utmp ,
279 .Em conv ,
280 .Em pcomm ,
281 .Em util ,
282 .Em list ,
283 .Em netif ,
284 .Em audit ,
285 .Em edit ,
286 .Em selinux ,
287 .Em ldap ,
288 .Em match ,
289 .Em parser ,
290 .Em alias ,
291 .Em defaults ,
292 .Em auth ,
293 .Em env ,
294 .Em logging ,
295 .Em nss ,
296 .Em rbtree ,
297 .Em perms ,
298 .Em plugin .
299 The subsystem
300 .Em all
301 includes every subsystem.
302 .Pp
303 There is not currently a way to specify a set of debug flags specific
304 to the plugin--the flags are shared by
305 .Nm sudo
306 and the plugin.
307 .It debug_level=number
308 This setting has been deprecated in favor of
309 .Em debug_flags .
310 .It runas_user=string
311 The user name or uid to to run the command as, if specified via the
312 .Fl u
313 flag.
314 .It runas_group=string
315 The group name or gid to to run the command as, if specified via
316 the
317 .Fl g
318 flag.
319 .It prompt=string
320 The prompt to use when requesting a password, if specified via
321 the
322 .Fl p
323 flag.
324 .It set_home=bool
325 Set to true if the user specified the
326 .Fl H
327 flag.
328 If true, set the
329 .Li HOME
330 environment variable to the target user's home directory.
331 .It preserve_environment=bool
332 Set to true if the user specified the
333 .Fl E
334 flag, indicating that
335 the user wishes to preserve the environment.
336 .It run_shell=bool
337 Set to true if the user specified the
338 .Fl s
339 flag, indicating that
340 the user wishes to run a shell.
341 .It login_shell=bool
342 Set to true if the user specified the
343 .Fl i
344 flag, indicating that
345 the user wishes to run a login shell.
346 .It implied_shell=bool
347 If the user does not specify a program on the command line,
348 .Nm sudo
349 will pass the plugin the path to the user's shell and set
350 .Em implied_shell
351 to true.
352 This allows
353 .Nm sudo
354 with no arguments
355 to be used similarly to
356 .Xr su 1 .
357 If the plugin does not to support this usage, it may return a value of \-2
358 from the
359 .Fn check_policy
360 function, which will cause
361 .Nm sudo
362 to print a usage message and
363 exit.
364 .It preserve_groups=bool
365 Set to true if the user specified the
366 .Fl P
367 flag, indicating that
368 the user wishes to preserve the group vector instead of setting it
369 based on the runas user.
370 .It ignore_ticket=bool
371 Set to true if the user specified the
372 .Fl k
373 flag along with a
374 command, indicating that the user wishes to ignore any cached
375 authentication credentials.
376 .It noninteractive=bool
377 Set to true if the user specified the
378 .Fl n
379 flag, indicating that
380 .Nm sudo
381 should operate in non-interactive mode.
382 The plugin may reject a command run in non-interactive mode if user
383 interaction is required.
384 .It login_class=string
385 BSD login class to use when setting resource limits and nice value,
386 if specified by the
387 .Fl c
388 flag.
389 .It selinux_role=string
390 SELinux role to use when executing the command, if specified by
391 the
392 .Fl r
393 flag.
394 .It selinux_type=string
395 SELinux type to use when executing the command, if specified by
396 the
397 .Fl t
398 flag.
399 .It bsdauth_type=string
400 Authentication type, if specified by the
401 .Fl a
402 flag, to use on
403 systems where BSD authentication is supported.
404 .It network_addrs=list
405 A space-separated list of IP network addresses and netmasks in the
406 form
407 .Dq addr/netmask ,
408 e.g.\&
409 .Dq 192.168.1.2/255.255.255.0 .
410 The address and netmask pairs may be either IPv4 or IPv6, depending on
411 what the operating system supports.
412 If the address contains a colon
413 .Pq Ql :\& ,
414 it is an IPv6 address, else it is IPv4.
415 .It progname=string
416 The command name that sudo was run as, typically
417 .Dq sudo
418 or
419 .Dq sudoedit .
420 .It sudoedit=bool
421 Set to true when the
422 .Fl e
423 flag is is specified or if invoked as
424 .Nm sudoedit .
425 The plugin shall substitute an editor into
426 .Em argv
427 in the
428 .Fn check_policy
429 function or return \-2 with a usage error
430 if the plugin does not support
431 .Em sudoedit .
432 For more information, see the
433 .Em check_policy
434 section.
435 .It closefrom=number
436 If specified, the user has requested via the
437 .Fl C
438 flag that
439 .Nm sudo
440 close all files descriptors with a value of
441 .Em number
442 or higher.
443 The plugin may optionally pass this, or another value, back in the
444 .Em command_info
445 list.
446 .El
447 .Pp
448 Additional settings may be added in the future so the plugin should
449 silently ignore settings that it does not recognize.
450 .It user_info
451 A vector of information about the user running the command in the form of
452 .Dq name=value
453 strings.
454 The vector is terminated by a
455 .Dv NULL
456 pointer.
457 .Pp
458 When parsing
459 .Em user_info ,
460 the plugin should split on the
461 .Sy first
462 equal sign
463 .Pq Ql =
464 since the
465 .Em name
466 field will never include one
467 itself but the
468 .Em value
469 might.
470 .Bl -tag -width 4n
471 .It pid=int
472 The process ID of the running
473 .Nm sudo
474 process.
475 Only available starting with API version 1.2
476 .It ppid=int
477 The parent process ID of the running
478 .Nm sudo
479 process.
480 Only available starting with API version 1.2
481 .It sid=int
482 The session ID of the running
483 .Nm sudo
484 process or 0 if
485 .Nm sudo
486 is
487 not part of a POSIX job control session.
488 Only available starting with API version 1.2
489 .It pgid=int
490 The ID of the process group that the running
491 .Nm sudo
492 process belongs
493 to.
494 Only available starting with API version 1.2
495 .It tcpgid=int
496 The ID of the forground process group associated with the terminal
497 device associcated with the
498 .Nm sudo
499 process or \-1 if there is no
500 terminal present.
501 Only available starting with API version 1.2
502 .It user=string
503 The name of the user invoking
504 .Nm sudo .
505 .It euid=uid_t
506 The effective user ID of the user invoking
507 .Nm sudo .
508 .It uid=uid_t
509 The real user ID of the user invoking
510 .Nm sudo .
511 .It egid=gid_t
512 The effective group ID of the user invoking
513 .Nm sudo .
514 .It gid=gid_t
515 The real group ID of the user invoking
516 .Nm sudo .
517 .It groups=list
518 The user's supplementary group list formatted as a string of
519 comma-separated group IDs.
520 .It cwd=string
521 The user's current working directory.
522 .It tty=string
523 The path to the user's terminal device.
524 If the user has no terminal device associated with the session,
525 the value will be empty, as in
526 .Dq Li tty= .
527 .It host=string
528 The local machine's hostname as returned by the
529 .Xr gethostname 2
530 system call.
531 .It lines=int
532 The number of lines the user's terminal supports.
533 If there is
534 no terminal device available, a default value of 24 is used.
535 .It cols=int
536 The number of columns the user's terminal supports.
537 If there is no terminal device available, a default value of 80 is used.
538 .El
539 .It user_env
540 The user's environment in the form of a
541 .Dv NULL Ns No -terminated vector of
542 .Dq name=value
543 strings.
544 .Pp
545 When parsing
546 .Em user_env ,
547 the plugin should split on the
548 .Sy first
549 equal sign
550 .Pq Ql =
551 since the
552 .Em name
553 field will never include one
554 itself but the
555 .Em value
556 might.
557 .It plugin_options
558 Any (non-comment) strings immediately after the plugin path are
559 treated as arguments to the plugin.
560 These arguments are split on a white space boundary and are passed to
561 the plugin in the form of a
562 .Dv NULL Ns No -terminated
563 array of strings.
564 If no arguments were
565 specified,
566 .Em plugin_options
567 will be the
568 .Dv NULL
569 pointer.
570 .Pp
571 NOTE: the
572 .Em plugin_options
573 parameter is only available starting with
574 API version 1.2.
575 A plugin
576 .Sy must
577 check the API version specified
578 by the
579 .Nm sudo
580 front end before using
581 .Em plugin_options .
582 Failure to do so may result in a crash.
583 .El
584 .It close
585 .Bd -literal -compact
586 void (*close)(int exit_status, int error);
587 .Ed
588 .Pp
589 The
590 .Fn close
591 function is called when the command being run by
592 .Nm sudo
593 finishes.
594 .Pp
595 The function arguments are as follows:
596 .Bl -tag -width 4n
597 .It exit_status
598 The command's exit status, as returned by the
599 .Xr wait 2
600 system call.
601 The value of
602 .Li exit_status
603 is undefined if
604 .Li error
605 is non-zero.
606 .It error
607 If the command could not be executed, this is set to the value of
608 .Li errno
609 set by the
610 .Xr execve 2
611 system call.
612 The plugin is responsible for displaying error information via the
613 .Fn conversation
614 or
615 .Fn plugin_printf
616 function.
617 If the command was successfully executed, the value of
618 .Li error
619 is 0.
620 .El
621 .It show_version
622 .Bd -literal -compact
623 int (*show_version)(int verbose);
624 .Ed
625 .Pp
626 The
627 .Fn show_version
628 function is called by
629 .Nm sudo
630 when the user specifies
631 the
632 .Fl V
633 option.
634 The plugin may display its version information to the user via the
635 .Fn conversation
636 or
637 .Fn plugin_printf
638 function using
639 .Dv SUDO_CONV_INFO_MSG .
640 If the user requests detailed version information, the verbose flag will be set.
641 .It check_policy
642 .Bd -literal -compact
643 int (*check_policy)(int argc, char * const argv[]
644                     char *env_add[], char **command_info[],
645                     char **argv_out[], char **user_env_out[]);
646 .Ed
647 .Pp
648 The
649 .Fn check_policy
650 function is called by
651 .Nm sudo
652 to determine
653 whether the user is allowed to run the specified commands.
654 .Pp
655 If the
656 .Em sudoedit
657 option was enabled in the
658 .Em settings
659 array
660 passed to the
661 .Fn open
662 function, the user has requested
663 .Em sudoedit
664 mode.
665 .Em sudoedit
666 is a mechanism for editing one or more files
667 where an editor is run with the user's credentials instead of with
668 elevated privileges.
669 .Nm sudo
670 achieves this by creating user-writable
671 temporary copies of the files to be edited and then overwriting the
672 originals with the temporary copies after editing is complete.
673 If the plugin supports
674 .Em sudoedit ,
675 it should choose the editor to be used, potentially from a variable
676 in the user's environment, such as
677 .Li EDITOR ,
678 and include it in
679 .Em argv_out
680 (note that environment
681 variables may include command line flags).
682 The files to be edited should be copied from
683 .Em argv
684 into
685 .Em argv_out ,
686 separated from the
687 editor and its arguments by a
688 .Dq Li --
689 element.
690 The
691 .Dq Li --
692 will
693 be removed by
694 .Nm sudo
695 before the editor is executed.
696 The plugin should also set
697 .Em sudoedit=true
698 in the
699 .Em command_info
700 list.
701 .Pp
702 The
703 .Fn check_policy
704 function returns 1 if the command is allowed,
705 0 if not allowed, \-1 for a general error, or \-2 for a usage error
706 or if
707 .Em sudoedit
708 was specified but is unsupported by the plugin.
709 In the latter case,
710 .Nm sudo
711 will print a usage message before it
712 exits.
713 If an error occurs, the plugin may optionally call the
714 .Fn conversation
715 or
716 .Fn plugin_printf
717 function with
718 .Dv SUDO_CONF_ERROR_MSG
719 to present additional error information to the user.
720 .Pp
721 The function arguments are as follows:
722 .Bl -tag -width 4n
723 .It argc
724 The number of elements in
725 .Em argv ,
726 not counting the final
727 .Dv NULL
728 pointer.
729 .It argv
730 The argument vector describing the command the user wishes to run,
731 in the same form as what would be passed to the
732 .Xr execve 2
733 system call.
734 The vector is terminated by a
735 .Dv NULL
736 pointer.
737 .It env_add
738 Additional environment variables specified by the user on the command
739 line in the form of a
740 .Dv NULL Ns No -terminated
741 vector of
742 .Dq name=value
743 strings.
744 The plugin may reject the command if one or more variables
745 are not allowed to be set, or it may silently ignore such variables.
746 .Pp
747 When parsing
748 .Em env_add ,
749 the plugin should split on the
750 .Sy first
751 equal sign
752 .Pq Ql =
753 since the
754 .Em name
755 field will never include one
756 itself but the
757 .Em value
758 might.
759 .It command_info
760 Information about the command being run in the form of
761 .Dq name=value
762 strings.
763 These values are used by
764 .Nm sudo
765 to set the execution
766 environment when running a command.
767 The plugin is responsible for creating and populating the vector,
768 which must be terminated with a
769 .Dv NULL
770 pointer.
771 The following values are recognized by
772 .Nm sudo :
773 .Bl -tag -width 4n
774 .It command=string
775 Fully qualified path to the command to be executed.
776 .It runas_uid=uid
777 User ID to run the command as.
778 .It runas_euid=uid
779 Effective user ID to run the command as.
780 If not specified, the value of
781 .Em runas_uid
782 is used.
783 .It runas_gid=gid
784 Group ID to run the command as.
785 .It runas_egid=gid
786 Effective group ID to run the command as.
787 If not specified, the value of
788 .Em runas_gid
789 is used.
790 .It runas_groups=list
791 The supplementary group vector to use for the command in the form
792 of a comma-separated list of group IDs.
793 If
794 .Em preserve_groups
795 is set, this option is ignored.
796 .It login_class=string
797 BSD login class to use when setting resource limits and nice value
798 (optional).
799 This option is only set on systems that support login classes.
800 .It preserve_groups=bool
801 If set,
802 .Nm sudo
803 will preserve the user's group vector instead of
804 initializing the group vector based on
805 .Li runas_user .
806 .It cwd=string
807 The current working directory to change to when executing the command.
808 .It noexec=bool
809 If set, prevent the command from executing other programs.
810 .It chroot=string
811 The root directory to use when running the command.
812 .It nice=int
813 Nice value (priority) to use when executing the command.
814 The nice value, if specified, overrides the priority associated with the
815 .Em login_class
816 on BSD systems.
817 .It umask=octal
818 The file creation mask to use when executing the command.
819 .It selinux_role=string
820 SELinux role to use when executing the command.
821 .It selinux_type=string
822 SELinux type to use when executing the command.
823 .It timeout=int
824 Command timeout.
825 If non-zero then when the timeout expires the command will be killed.
826 .It sudoedit=bool
827 Set to true when in
828 .Em sudoedit
829 mode.
830 The plugin may enable
831 .Em sudoedit
832 mode even if
833 .Nm sudo
834 was not invoked as
835 .Nm sudoedit .
836 This allows the plugin to perform command substitution and transparently
837 enable
838 .Em sudoedit
839 when the user attempts to run an editor.
840 .It closefrom=number
841 If specified,
842 .Nm sudo
843 will close all files descriptors with a value
844 of
845 .Em number
846 or higher.
847 .It iolog_compress=bool
848 Set to true if the I/O logging plugins, if any, should compress the
849 log data.
850 This is a hint to the I/O logging plugin which may choose to ignore it.
851 .It iolog_path=string
852 Fully qualified path to the file or directory in which I/O log is
853 to be stored.
854 This is a hint to the I/O logging plugin which may choose to ignore it.
855 If no I/O logging plugin is loaded, this setting has no effect.
856 .It iolog_stdin=bool
857 Set to true if the I/O logging plugins, if any, should log the
858 standard input if it is not connected to a terminal device.
859 This is a hint to the I/O logging plugin which may choose to ignore it.
860 .It iolog_stdout=bool
861 Set to true if the I/O logging plugins, if any, should log the
862 standard output if it is not connected to a terminal device.
863 This is a hint to the I/O logging plugin which may choose to ignore it.
864 .It iolog_stderr=bool
865 Set to true if the I/O logging plugins, if any, should log the
866 standard error if it is not connected to a terminal device.
867 This is a hint to the I/O logging plugin which may choose to ignore it.
868 .It iolog_ttyin=bool
869 Set to true if the I/O logging plugins, if any, should log all
870 terminal input.
871 This only includes input typed by the user and not from a pipe or
872 redirected from a file.
873 This is a hint to the I/O logging plugin which may choose to ignore it.
874 .It iolog_ttyout=bool
875 Set to true if the I/O logging plugins, if any, should log all
876 terminal output.
877 This only includes output to the screen, not output to a pipe or file.
878 This is a hint to the I/O logging plugin which may choose to ignore it.
879 .It use_pty=bool
880 Allocate a pseudo-tty to run the command in, regardless of whether
881 or not I/O logging is in use.
882 By default,
883 .Nm sudo
884 will only run
885 the command in a pty when an I/O log plugin is loaded.
886 .It set_utmp=bool
887 Create a utmp (or utmpx) entry when a pseudo-tty is allocated.
888 By default, the new entry will be a copy of the user's existing utmp
889 entry (if any), with the tty, time, type and pid fields updated.
890 .It utmp_user=string
891 User name to use when constructing a new utmp (or utmpx) entry when
892 .Em set_utmp
893 is enabled.
894 This option can be used to set the user field in the utmp entry to
895 the user the command runs as rather than the invoking user.
896 If not set,
897 .Nm sudo
898 will base the new entry on
899 the invoking user's existing entry.
900 .El
901 .Pp
902 Unsupported values will be ignored.
903 .It argv_out
904 The
905 .Dv NULL Ns No -terminated
906 argument vector to pass to the
907 .Xr execve 2
908 system call when executing the command.
909 The plugin is responsible for allocating and populating the vector.
910 .It user_env_out
911 The
912 .Dv NULL Ns No -terminated
913 environment vector to use when executing the command.
914 The plugin is responsible for allocating and populating the vector.
915 .El
916 .It list
917 .Bd -literal -compact
918 int (*list)(int verbose, const char *list_user,
919             int argc, char * const argv[]);
920 .Ed
921 .Pp
922 List available privileges for the invoking user.
923 Returns 1 on success, 0 on failure and \-1 on error.
924 On error, the plugin may optionally call the
925 .Fn conversation
926 or
927 .Fn plugin_printf
928 function with
929 .Dv SUDO_CONF_ERROR_MSG
930 to present additional error information to
931 the user.
932 .Pp
933 Privileges should be output via the
934 .Fn conversation
935 or
936 .Fn plugin_printf
937 function using
938 .Dv SUDO_CONV_INFO_MSG ,
939 .Bl -tag -width 4n
940 .It verbose
941 Flag indicating whether to list in verbose mode or not.
942 .It list_user
943 The name of a different user to list privileges for if the policy
944 allows it.
945 If
946 .Dv NULL ,
947 the plugin should list the privileges of the invoking user.
948 .It argc
949 The number of elements in
950 .Em argv ,
951 not counting the final
952 .Dv NULL
953 pointer.
954 .It argv
955 If
956 .No non- Ns Dv NULL ,
957 an argument vector describing a command the user
958 wishes to check against the policy in the same form as what would
959 be passed to the
960 .Xr execve 2
961 system call.
962 If the command is permitted by the policy, the fully-qualified path
963 to the command should be displayed along with any command line arguments.
964 .El
965 .It validate
966 .Bd -literal -compact
967 int (*validate)(void);
968 .Ed
969 .Pp
970 The
971 .Fn validate
972 function is called when
973 .Nm sudo
974 is run with the
975 .Fl v
976 flag.
977 For policy plugins such as
978 .Em sudoers
979 that cache
980 authentication credentials, this function will validate and cache
981 the credentials.
982 .Pp
983 The
984 .Fn validate
985 function should be
986 .Dv NULL
987 if the plugin does not support credential caching.
988 .Pp
989 Returns 1 on success, 0 on failure and \-1 on error.
990 On error, the plugin may optionally call the
991 .Fn conversation
992 or
993 .Fn plugin_printf
994 function with
995 .Dv SUDO_CONF_ERROR_MSG
996 to present additional
997 error information to the user.
998 .It invalidate
999 .Bd -literal -compact
1000 void (*invalidate)(int remove);
1001 .Ed
1002 .Pp
1003 The
1004 .Fn invalidate
1005 function is called when
1006 .Nm sudo
1007 is called with
1008 the
1009 .Fl k
1010 or
1011 .Fl K
1012 flag.
1013 For policy plugins such as
1014 .Em sudoers
1015 that
1016 cache authentication credentials, this function will invalidate the
1017 credentials.
1018 If the
1019 .Em remove
1020 flag is set, the plugin may remove
1021 the credentials instead of simply invalidating them.
1022 .Pp
1023 The
1024 .Fn invalidate
1025 function should be
1026 .Dv NULL
1027 if the plugin does not support credential caching.
1028 .It init_session
1029 .Bd -literal -compact
1030 int (*init_session)(struct passwd *pwd, char **user_envp[);
1031 .Ed
1032 .Pp
1033 The
1034 .Fn init_session
1035 function is called before
1036 .Nm sudo
1037 sets up the
1038 execution environment for the command.
1039 It is run in the parent
1040 .Nm sudo
1041 process and before any uid or gid changes.
1042 This can be used to perform session setup that is not supported by
1043 .Em command_info ,
1044 such as opening the PAM session.
1045 The
1046 .Fn close
1047 function can be
1048 used to tear down the session that was opened by
1049 .Li init_session .
1050 .Pp
1051 The
1052 .Em pwd
1053 argument points to a passwd struct for the user the
1054 command will be run as if the uid the command will run as was found
1055 in the password database, otherwise it will be
1056 .Dv NULL .
1057 .Pp
1058 The
1059 .Em user_env
1060 argument points to the environment the command will
1061 run in, in the form of a
1062 .Dv NULL Ns No -terminated
1063 vector of
1064 .Dq name=value
1065 strings.
1066 This is the same string passed back to the front end via
1067 the Policy Plugin's
1068 .Em user_env_out
1069 parameter.
1070 If the
1071 .Fn init_session
1072 function needs to modify the user environment, it should update the
1073 pointer stored in
1074 .Em user_env .
1075 The expected use case is to merge the contents of the PAM environment
1076 (if any) with the contents of
1077 .Em user_env .
1078 NOTE: the
1079 .Em user_env
1080 parameter is only available
1081 starting with API version 1.2.
1082 A plugin
1083 .Sy must
1084 check the API
1085 version specified by the
1086 .Nm sudo
1087 front end before using
1088 .Em user_env .
1089 Failure to do so may result in a crash.
1090 .Pp
1091 Returns 1 on success, 0 on failure and \-1 on error.
1092 On error, the plugin may optionally call the
1093 .Fn conversation
1094 or
1095 .Fn plugin_printf
1096 function with
1097 .Dv SUDO_CONF_ERROR_MSG
1098 to present additional
1099 error information to the user.
1100 .It register_hooks
1101 .Bd -literal -compact
1102 void (*register_hooks)(int version,
1103    int (*register_hook)(struct sudo_hook *hook));
1104 .Ed
1105 .Pp
1106 The
1107 .Fn register_hooks
1108 function is called by the sudo front end to
1109 register any hooks the plugin needs.
1110 If the plugin does not support hooks,
1111 .Li register_hooks
1112 should be set to the
1113 .Dv NULL
1114 pointer.
1115 .Pp
1116 The
1117 .Em version
1118 argument describes the version of the hooks API
1119 supported by the
1120 .Nm sudo
1121 front end.
1122 .Pp
1123 The
1124 .Fn register_hook
1125 function should be used to register any supported
1126 hooks the plugin needs.
1127 It returns 0 on success, 1 if the hook type is not supported and \-1
1128 if the major version in
1129 .Li struct hook
1130 does not match the front end's major hook API version.
1131 .Pp
1132 See the
1133 .Sx Hook function API
1134 section below for more information
1135 about hooks.
1136 .Pp
1137 NOTE: the
1138 .Fn register_hooks
1139 function is only available starting
1140 with API version 1.2.
1141 If the
1142 .Nm sudo
1143 front end doesn't support API
1144 version 1.2 or higher,
1145 .Li register_hooks
1146 will not be called.
1147 .It deregister_hooks
1148 .Bd -literal -compact
1149 void (*deregister_hooks)(int version,
1150    int (*deregister_hook)(struct sudo_hook *hook));
1151 .Ed
1152 .Pp
1153 The
1154 .Fn deregister_hooks
1155 function is called by the sudo front end
1156 to deregister any hooks the plugin has registered.
1157 If the plugin does not support hooks,
1158 .Li deregister_hooks
1159 should be set to the
1160 .Dv NULL
1161 pointer.
1162 .Pp
1163 The
1164 .Em version
1165 argument describes the version of the hooks API
1166 supported by the
1167 .Nm sudo
1168 front end.
1169 .Pp
1170 The
1171 .Fn deregister_hook
1172 function should be used to deregister any
1173 hooks that were put in place by the
1174 .Fn register_hook
1175 function.
1176 If the plugin tries to deregister a hook that the front end does not support,
1177 .Li deregister_hook
1178 will return an error.
1179 .Pp
1180 See the
1181 .Sx Hook function API
1182 section below for more information
1183 about hooks.
1184 .Pp
1185 NOTE: the
1186 .Fn deregister_hooks
1187 function is only available starting
1188 with API version 1.2.
1189 If the
1190 .Nm sudo
1191 front end doesn't support API
1192 version 1.2 or higher,
1193 .Li deregister_hooks
1194 will not be called.
1195 .El
1196 .Pp
1197 .Em Policy Plugin Version Macros
1198 .Bd -literal
1199 /* Plugin API version major/minor. */
1200 #define SUDO_API_VERSION_MAJOR 1
1201 #define SUDO_API_VERSION_MINOR 2
1202 #define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
1203 #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
1204                                             SUDO_API_VERSION_MINOR)
1205
1206 /* Getters and setters for API version */
1207 #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
1208 #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
1209 #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
1210     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
1211 } while(0)
1212 #define SUDO_VERSION_SET_MINOR(vp, n) do { \e
1213     *(vp) = (*(vp) & 0xffff0000) | (n); \e
1214 } while(0)
1215 .Ed
1216 .Ss I/O plugin API
1217 .Bd -literal
1218 struct io_plugin {
1219 #define SUDO_IO_PLUGIN 2
1220     unsigned int type; /* always SUDO_IO_PLUGIN */
1221     unsigned int version; /* always SUDO_API_VERSION */
1222     int (*open)(unsigned int version, sudo_conv_t conversation
1223                 sudo_printf_t plugin_printf, char * const settings[],
1224                 char * const user_info[], int argc, char * const argv[],
1225                 char * const user_env[], char * const plugin_options[]);
1226     void (*close)(int exit_status, int error); /* wait status or error */
1227     int (*show_version)(int verbose);
1228     int (*log_ttyin)(const char *buf, unsigned int len);
1229     int (*log_ttyout)(const char *buf, unsigned int len);
1230     int (*log_stdin)(const char *buf, unsigned int len);
1231     int (*log_stdout)(const char *buf, unsigned int len);
1232     int (*log_stderr)(const char *buf, unsigned int len);
1233     void (*register_hooks)(int version,
1234        int (*register_hook)(struct sudo_hook *hook));
1235     void (*deregister_hooks)(int version,
1236        int (*deregister_hook)(struct sudo_hook *hook));
1237 };
1238 .Ed
1239 .Pp
1240 When an I/O plugin is loaded,
1241 .Nm sudo
1242 runs the command in a pseudo-tty.
1243 This makes it possible to log the input and output from the user's
1244 session.
1245 If any of the standard input, standard output or standard error do not
1246 correspond to a tty,
1247 .Nm sudo
1248 will open a pipe to capture
1249 the I/O for logging before passing it on.
1250 .Pp
1251 The log_ttyin function receives the raw user input from the terminal
1252 device (note that this will include input even when echo is disabled,
1253 such as when a password is read).
1254 The log_ttyout function receives output from the pseudo-tty that is
1255 suitable for replaying the user's session at a later time.
1256 The
1257 .Fn log_stdin ,
1258 .Fn log_stdout
1259 and
1260 .Fn log_stderr
1261 functions are only called if the standard input, standard output
1262 or standard error respectively correspond to something other than
1263 a tty.
1264 .Pp
1265 Any of the logging functions may be set to the
1266 .Dv NULL
1267 pointer if no logging is to be performed.
1268 If the open function returns 0, no I/O will be sent to the plugin.
1269 .Pp
1270 The io_plugin struct has the following fields:
1271 .Bl -tag -width 4n
1272 .It type
1273 The
1274 .Li type
1275 field should always be set to
1276 .Dv SUDO_IO_PLUGIN .
1277 .It version
1278 The
1279 .Li version
1280 field should be set to
1281 .Dv SUDO_API_VERSION .
1282 .Pp
1283 This allows
1284 .Nm sudo
1285 to determine the API version the plugin was
1286 built against.
1287 .It open
1288 .Bd -literal -compact
1289 int (*open)(unsigned int version, sudo_conv_t conversation
1290             sudo_printf_t plugin_printf, char * const settings[],
1291             char * const user_info[], int argc, char * const argv[],
1292             char * const user_env[], char * const plugin_options[]);
1293 .Ed
1294 .Pp
1295 The
1296 .Fn open
1297 function is run before the
1298 .Fn log_input ,
1299 .Fn log_output
1300 or
1301 .Fn show_version
1302 functions are called.
1303 It is only called if the version is being requested or the
1304 .Fn check_policy
1305 function has
1306 returned successfully.
1307 It returns 1 on success, 0 on failure, \-1 if a general error occurred,
1308 or \-2 if there was a usage error.
1309 In the latter case,
1310 .Nm sudo
1311 will print a usage message before it exits.
1312 If an error occurs, the plugin may optionally call the
1313 .Fn conversation
1314 or
1315 .Fn plugin_printf
1316 function with
1317 .Dv SUDO_CONF_ERROR_MSG
1318 to present
1319 additional error information to the user.
1320 .Pp
1321 The function arguments are as follows:
1322 .Bl -tag -width 4n
1323 .It version
1324 The version passed in by
1325 .Nm sudo
1326 allows the plugin to determine the
1327 major and minor version number of the plugin API supported by
1328 .Nm sudo .
1329 .It conversation
1330 A pointer to the
1331 .Fn conversation
1332 function that may be used by the
1333 .Fn show_version
1334 function to display version information (see
1335 .Fn show_version
1336 below).
1337 The
1338 .Fn conversation
1339 function may also be used to display additional error message to the user.
1340 The
1341 .Fn conversation
1342 function returns 0 on success and \-1 on failure.
1343 .It plugin_printf
1344 A pointer to a
1345 .Fn printf Ns No -style
1346 function that may be used by the
1347 .Fn show_version
1348 function to display version information (see
1349 show_version below).
1350 The
1351 .Fn plugin_printf
1352 function may also be used to display additional error message to the user.
1353 The
1354 .Fn plugin_printf
1355 function returns number of characters printed on success and \-1 on failure.
1356 .It settings
1357 A vector of user-supplied
1358 .Nm sudo
1359 settings in the form of
1360 .Dq name=value
1361 strings.
1362 The vector is terminated by a
1363 .Dv NULL
1364 pointer.
1365 These settings correspond to flags the user specified when running
1366 .Nm sudo .
1367 As such, they will only be present when the corresponding flag has
1368 been specified on the command line.
1369 .Pp
1370 When parsing
1371 .Em settings ,
1372 the plugin should split on the
1373 .Sy first
1374 equal sign
1375 .Pq Ql =
1376 since the
1377 .Em name
1378 field will never include one
1379 itself but the
1380 .Em value
1381 might.
1382 .Pp
1383 See the
1384 .Sx Policy plugin API
1385 section for a list of all possible settings.
1386 .It user_info
1387 A vector of information about the user running the command in the form of
1388 .Dq name=value
1389 strings.
1390 The vector is terminated by a
1391 .Dv NULL
1392 pointer.
1393 .Pp
1394 When parsing
1395 .Em user_info ,
1396 the plugin should split on the
1397 .Sy first
1398 equal sign
1399 .Pq Ql =
1400 since the
1401 .Em name
1402 field will never include one
1403 itself but the
1404 .Em value
1405 might.
1406 .Pp
1407 See the
1408 .Sx Policy plugin API
1409 section for a list of all possible strings.
1410 .It argc
1411 The number of elements in
1412 .Em argv ,
1413 not counting the final
1414 .Dv NULL
1415 pointer.
1416 .It argv
1417 If
1418 .No non- Ns Dv NULL ,
1419 an argument vector describing a command the user
1420 wishes to run in the same form as what would be passed to the
1421 .Xr execve 2
1422 system call.
1423 .It user_env
1424 The user's environment in the form of a
1425 .Dv NULL Ns No -terminated
1426 vector of
1427 .Dq name=value
1428 strings.
1429 .Pp
1430 When parsing
1431 .Em user_env ,
1432 the plugin should split on the
1433 .Sy first
1434 equal sign
1435 .Pq Ql =
1436 since the
1437 .Em name
1438 field will never include one
1439 itself but the
1440 .Em value
1441 might.
1442 .It plugin_options
1443 Any (non-comment) strings immediately after the plugin path are
1444 treated as arguments to the plugin.
1445 These arguments are split on a white space boundary and are passed to
1446 the plugin in the form of a
1447 .Dv NULL Ns No -terminated
1448 array of strings.
1449 If no arguments were specified,
1450 .Em plugin_options
1451 will be the
1452 .Dv NULL
1453 pointer.
1454 .Pp
1455 NOTE: the
1456 .Em plugin_options
1457 parameter is only available starting with
1458 API version 1.2.
1459 A plugin
1460 .Sy must
1461 check the API version specified
1462 by the
1463 .Nm sudo
1464 front end before using
1465 .Em plugin_options .
1466 Failure to do so may result in a crash.
1467 .El
1468 .It close
1469 .Bd -literal -compact
1470 void (*close)(int exit_status, int error);
1471 .Ed
1472 .Pp
1473 The
1474 .Fn close
1475 function is called when the command being run by
1476 .Nm sudo
1477 finishes.
1478 .Pp
1479 The function arguments are as follows:
1480 .Bl -tag -width 4n
1481 .It exit_status
1482 The command's exit status, as returned by the
1483 .Xr wait 2
1484 system call.
1485 The value of
1486 .Li exit_status
1487 is undefined if
1488 .Li error
1489 is non-zero.
1490 .It error
1491 If the command could not be executed, this is set to the value of
1492 .Li errno
1493 set by the
1494 .Xr execve 2
1495 system call.
1496 If the command was successfully executed, the value of
1497 .Li error
1498 is 0.
1499 .El
1500 .It show_version
1501 .Bd -literal -compact
1502 int (*show_version)(int verbose);
1503 .Ed
1504 .Pp
1505 The
1506 .Fn show_version
1507 function is called by
1508 .Nm sudo
1509 when the user specifies
1510 the
1511 .Fl V
1512 option.
1513 The plugin may display its version information to the user via the
1514 .Fn conversation
1515 or
1516 .Fn plugin_printf
1517 function using
1518 .Dv SUDO_CONV_INFO_MSG .
1519 If the user requests detailed version information, the verbose flag will be set.
1520 .It log_ttyin
1521 .Bd -literal -compact
1522 int (*log_ttyin)(const char *buf, unsigned int len);
1523 .Ed
1524 .Pp
1525 The
1526 .Fn log_ttyin
1527 function is called whenever data can be read from
1528 the user but before it is passed to the running command.
1529 This allows the plugin to reject data if it chooses to (for instance
1530 if the input contains banned content).
1531 Returns 1 if the data should be passed to the command, 0 if the data
1532 is rejected (which will terminate the command) or \-1 if an error occurred.
1533 .Pp
1534 The function arguments are as follows:
1535 .Bl -tag -width 4n
1536 .It buf
1537 The buffer containing user input.
1538 .It len
1539 The length of
1540 .Em buf
1541 in bytes.
1542 .El
1543 .It log_ttyout
1544 .Bd -literal -compact
1545 int (*log_ttyout)(const char *buf, unsigned int len);
1546 .Ed
1547 .Pp
1548 The
1549 .Fn log_ttyout
1550 function is called whenever data can be read from
1551 the command but before it is written to the user's terminal.
1552 This allows the plugin to reject data if it chooses to (for instance
1553 if the output contains banned content).
1554 Returns 1 if the data should be passed to the user, 0 if the data is rejected
1555 (which will terminate the command) or \-1 if an error occurred.
1556 .Pp
1557 The function arguments are as follows:
1558 .Bl -tag -width 4n
1559 .It buf
1560 The buffer containing command output.
1561 .It len
1562 The length of
1563 .Em buf
1564 in bytes.
1565 .El
1566 .It log_stdin
1567 .Bd -literal -compact
1568 int (*log_stdin)(const char *buf, unsigned int len);
1569 .Ed
1570 .Pp
1571 The
1572 .Fn log_stdin
1573 function is only used if the standard input does
1574 not correspond to a tty device.
1575 It is called whenever data can be read from the standard input but
1576 before it is passed to the running command.
1577 This allows the plugin to reject data if it chooses to
1578 (for instance if the input contains banned content).
1579 Returns 1 if the data should be passed to the command, 0 if the data is
1580 rejected (which will terminate the command) or \-1 if an error occurred.
1581 .Pp
1582 The function arguments are as follows:
1583 .Bl -tag -width 4n
1584 .It buf
1585 The buffer containing user input.
1586 .It len
1587 The length of
1588 .Em buf
1589 in bytes.
1590 .El
1591 .It log_stdout
1592 .Bd -literal -compact
1593 int (*log_stdout)(const char *buf, unsigned int len);
1594 .Ed
1595 .Pp
1596 The
1597 .Fn log_stdout
1598 function is only used if the standard output does not correspond
1599 to a tty device.
1600 It is called whenever data can be read from the command but before
1601 it is written to the standard output.
1602 This allows the plugin to reject data if it chooses to
1603 (for instance if the output contains banned content).
1604 Returns 1 if the data should be passed to the user, 0 if the data is
1605 rejected (which will terminate the command) or \-1 if an error occurred.
1606 .Pp
1607 The function arguments are as follows:
1608 .Bl -tag -width 4n
1609 .It buf
1610 The buffer containing command output.
1611 .It len
1612 The length of
1613 .Em buf
1614 in bytes.
1615 .El
1616 .It log_stderr
1617 .Bd -literal -compact
1618 int (*log_stderr)(const char *buf, unsigned int len);
1619 .Ed
1620 .Pp
1621 The
1622 .Fn log_stderr
1623 function is only used if the standard error does
1624 not correspond to a tty device.
1625 It is called whenever data can be read from the command but before it
1626 is written to the standard error.
1627 This allows the plugin to reject data if it chooses to
1628 (for instance if the output contains banned content).
1629 Returns 1 if the data should be passed to the user, 0 if the data is
1630 rejected (which will terminate the command) or \-1 if an error occurred.
1631 .Pp
1632 The function arguments are as follows:
1633 .Bl -tag -width 4n
1634 .It buf
1635 The buffer containing command output.
1636 .It len
1637 The length of
1638 .Em buf
1639 in bytes.
1640 .El
1641 .It register_hooks
1642 See the
1643 .Sx Policy plugin API
1644 section for a description of
1645 .Li register_hooks .
1646 .It deregister_hooks
1647 See the
1648 .Sx Policy plugin API
1649 section for a description of
1650 .Li deregister_hooks.
1651 .El
1652 .Pp
1653 .Em I/O Plugin Version Macros
1654 .Pp
1655 Same as for the
1656 .Sx Policy plugin API .
1657 .Ss Hook function API
1658 Beginning with plugin API version 1.2, it is possible to install
1659 hooks for certain functions called by the
1660 .Nm sudo
1661 front end.
1662 .Pp
1663 Currently, the only supported hooks relate to the handling of
1664 environment variables.
1665 Hooks can be used to intercept attempts to get, set, or remove
1666 environment variables so that these changes can be reflected in
1667 the version of the environment that is used to execute a command.
1668 A future version of the API will support hooking internal
1669 .Nm sudo
1670 front end functions as well.
1671 .Pp
1672 .Em Hook structure
1673 .Pp
1674 Hooks in
1675 .Nm sudo
1676 are described by the following structure:
1677 .Bd -literal
1678 typedef int (*sudo_hook_fn_t)();
1679
1680 struct sudo_hook {
1681     int hook_version;
1682     int hook_type;
1683     sudo_hook_fn_t hook_fn;
1684     void *closure;
1685 };
1686 .Ed
1687 .Pp
1688 The
1689 .Li sudo_hook
1690 structure has the following fields:
1691 .Bl -tag -width 4n
1692 .It hook_version
1693 The
1694 .Li hook_version
1695 field should be set to
1696 .Dv SUDO_HOOK_VERSION .
1697 .It hook_type
1698 The
1699 .Li hook_type
1700 field may be one of the following supported hook types:
1701 .Bl -tag -width 4n
1702 .It Dv SUDO_HOOK_SETENV
1703 The C library
1704 .Xr setenv 3
1705 function.
1706 Any registered hooks will run before the C library implementation.
1707 The
1708 .Li hook_fn
1709 field should
1710 be a function that matches the following typedef:
1711 .Bd -literal
1712 typedef int (*sudo_hook_fn_setenv_t)(const char *name,
1713    const char *value, int overwrite, void *closure);
1714 .Ed
1715 .Pp
1716 If the registered hook does not match the typedef the results are
1717 unspecified.
1718 .It Dv SUDO_HOOK_UNSETENV
1719 The C library
1720 .Xr unsetenv 3
1721 function.
1722 Any registered hooks will run before the C library implementation.
1723 The
1724 .Li hook_fn
1725 field should
1726 be a function that matches the following typedef:
1727 .Bd -literal
1728 typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
1729    void *closure);
1730 .Ed
1731 .It Dv SUDO_HOOK_GETENV
1732 The C library
1733 .Xr getenv 3
1734 function.
1735 Any registered hooks will run before the C library implementation.
1736 The
1737 .Li hook_fn
1738 field should
1739 be a function that matches the following typedef:
1740 .Bd -literal
1741 typedef int (*sudo_hook_fn_getenv_t)(const char *name,
1742    char **value, void *closure);
1743 .Ed
1744 .Pp
1745 If the registered hook does not match the typedef the results are
1746 unspecified.
1747 .It Dv SUDO_HOOK_PUTENV
1748 The C library
1749 .Xr putenv 3
1750 function.
1751 Any registered hooks will run before the C library implementation.
1752 The
1753 .Li hook_fn
1754 field should
1755 be a function that matches the following typedef:
1756 .Bd -literal
1757 typedef int (*sudo_hook_fn_putenv_t)(char *string,
1758    void *closure);
1759 .Ed
1760 .Pp
1761 If the registered hook does not match the typedef the results are
1762 unspecified.
1763 .El
1764 .It hook_fn
1765 sudo_hook_fn_t hook_fn;
1766 .Pp
1767 The
1768 .Li hook_fn
1769 field should be set to the plugin's hook implementation.
1770 The actual function arguments will vary depending on the
1771 .Li hook_type
1772 (see
1773 .Li hook_type
1774 above).
1775 In all cases, the
1776 .Li closure
1777 field of
1778 .Li struct sudo_hook
1779 is passed as the last function parameter.
1780 This can be used to pass arbitrary data to the plugin's hook implementation.
1781 .Pp
1782 The function return value may be one of the following:
1783 .Bl -tag -width 4n
1784 .It Dv SUDO_HOOK_RET_ERROR
1785 The hook function encountered an error.
1786 .It Dv SUDO_HOOK_RET_NEXT
1787 The hook completed without error, go on to the next hook (including
1788 the native implementation if applicable).
1789 For example, a
1790 .Xr getenv 3
1791 hook might return
1792 .Dv SUDO_HOOK_RET_NEXT
1793 if the specified variable was not found in the private copy of the environment.
1794 .It Dv SUDO_HOOK_RET_STOP
1795 The hook completed without error, stop processing hooks for this invocation.
1796 This can be used to replace the native implementation.
1797 For example, a
1798 .Li setenv
1799 hook that operates on a private copy of
1800 the environment but leaves
1801 .Li environ
1802 unchanged.
1803 .El
1804 .El
1805 .Pp
1806 Note that it is very easy to create an infinite loop when hooking
1807 C library functions.
1808 For example, a
1809 .Xr getenv 3
1810 hook that calls the
1811 .Xr snprintf 3
1812 function may create a loop if the
1813 .Xr snprintf 3
1814 implementation calls
1815 .Xr getenv 3
1816 to check the locale.
1817 To prevent this, you may wish to use a static variable in the hook
1818 function to guard against nested calls.
1819 For example:
1820 .Bd -literal
1821 static int in_progress = 0; /* avoid recursion */
1822 if (in_progress)
1823     return SUDO_HOOK_RET_NEXT;
1824 in_progress = 1;
1825 \&...
1826 in_progress = 0;
1827 return SUDO_HOOK_RET_STOP;
1828 .Ed
1829 .Pp
1830 .Em Hook API Version Macros
1831 .Bd -literal
1832 /* Hook API version major/minor */
1833 #define SUDO_HOOK_VERSION_MAJOR 1
1834 #define SUDO_HOOK_VERSION_MINOR 0
1835 #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y)
1836 #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
1837                                               SUDO_HOOK_VERSION_MINOR)
1838
1839 /* Getters and setters for hook API version */
1840 #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16)
1841 #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff)
1842 #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \e
1843     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
1844 } while(0)
1845 #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \e
1846     *(vp) = (*(vp) & 0xffff0000) | (n); \e
1847 } while(0)
1848 .Ed
1849 .Ss Conversation API
1850 If the plugin needs to interact with the user, it may do so via the
1851 .Fn conversation
1852 function.
1853 A plugin should not attempt to read directly from the standard input
1854 or the user's tty (neither of which are guaranteed to exist).
1855 The caller must include a trailing newline in
1856 .Li msg
1857 if one is to be printed.
1858 .Pp
1859 A
1860 .Fn printf Ns No -style
1861 function is also available that can be used to display informational
1862 or error messages to the user, which is usually more convenient for
1863 simple messages where no use input is required.
1864 .Bd -literal
1865 struct sudo_conv_message {
1866 #define SUDO_CONV_PROMPT_ECHO_OFF  0x0001 /* do not echo user input */
1867 #define SUDO_CONV_PROMPT_ECHO_ON   0x0002 /* echo user input */
1868 #define SUDO_CONV_ERROR_MSG        0x0003 /* error message */
1869 #define SUDO_CONV_INFO_MSG         0x0004 /* informational message */
1870 #define SUDO_CONV_PROMPT_MASK      0x0005 /* mask user input */
1871 #define SUDO_CONV_DEBUG_MSG        0x0006 /* debugging message */
1872 #define SUDO_CONV_PROMPT_ECHO_OK   0x1000 /* flag: allow echo if no tty */
1873     int msg_type;
1874     int timeout;
1875     const char *msg;
1876 };
1877
1878 struct sudo_conv_reply {
1879     char *reply;
1880 };
1881
1882 typedef int (*sudo_conv_t)(int num_msgs,
1883              const struct sudo_conv_message msgs[],
1884              struct sudo_conv_reply replies[]);
1885
1886 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
1887 .Ed
1888 .Pp
1889 Pointers to the
1890 .Fn conversation
1891 and
1892 .Fn printf Ns No -style
1893 functions are passed
1894 in to the plugin's
1895 .Fn open
1896 function when the plugin is initialized.
1897 .Pp
1898 To use the
1899 .Fn conversation
1900 function, the plugin must pass an array of
1901 .Li sudo_conv_message
1902 and
1903 .Li sudo_conv_reply
1904 structures.
1905 There must be a
1906 .Li struct sudo_conv_message
1907 and
1908 .Li struct sudo_conv_reply
1909 for
1910 each message in the conversation.
1911 The plugin is responsible for freeing the reply buffer filled in to the
1912 .Li struct sudo_conv_reply ,
1913 if any.
1914 .Pp
1915 The
1916 .Fn printf Ns No -style
1917 function uses the same underlying mechanism as the
1918 .Fn conversation
1919 function but only supports
1920 .Dv SUDO_CONV_INFO_MSG ,
1921 .Dv SUDO_CONV_ERROR_MSG
1922 and
1923 .Dv SUDO_CONV_DEBUG_MSG
1924 for the
1925 .Em msg_type
1926 parameter.
1927 It can be more convenient than using the
1928 .Fn conversation
1929 function if no user reply is needed and supports standard
1930 .Fn printf
1931 escape sequences.
1932 .Pp
1933 Unlike,
1934 .Dv SUDO_CONV_INFO_MSG
1935 and
1936 Dv SUDO_CONV_ERROR_MSG ,
1937 messages
1938 sent with the
1939 .Dv SUDO_CONV_DEBUG_MSG
1940 .Em msg_type
1941 are not directly
1942 user-visible.
1943 Instead, they are logged to the file specified in the
1944 .Li Debug
1945 statement (if any) in the
1946 .Pa @sysconfdir@/sudo.conf
1947 .Pp
1948 file.
1949 This allows a plugin to log debugging information and is intended
1950 to be used in conjunction with the
1951 .Em debug_flags
1952 setting.
1953 .Pp
1954 See the sample plugin for an example of the
1955 .Fn conversation
1956 function usage.
1957 .Ss Sudoers group plugin API
1958 The
1959 .Em sudoers
1960 module supports a plugin interface to allow non-Unix
1961 group lookups.
1962 This can be used to query a group source other than the standard Unix
1963 group database.
1964 A sample group plugin is bundled with
1965 .Nm sudo
1966 that implements file-based lookups.
1967 Third party group plugins include a QAS AD plugin available from Quest Software.
1968 .Pp
1969 A group plugin must declare and populate a
1970 .Li sudoers_group_plugin
1971 struct in the global scope.
1972 This structure contains pointers to the functions that implement plugin
1973 initialization, cleanup and group lookup.
1974 .Bd -literal
1975 struct sudoers_group_plugin {
1976    unsigned int version;
1977    int (*init)(int version, sudo_printf_t sudo_printf,
1978                char *const argv[]);
1979    void (*cleanup)(void);
1980    int (*query)(const char *user, const char *group,
1981                 const struct passwd *pwd);
1982 };
1983 .Ed
1984 .Pp
1985 The
1986 .Li sudoers_group_plugin
1987 struct has the following fields:
1988 .Bl -tag -width 4n
1989 .It version
1990 The
1991 .Li version
1992 field should be set to GROUP_API_VERSION.
1993 .Pp
1994 This allows
1995 .Em sudoers
1996 to determine the API version the group plugin
1997 was built against.
1998 .It init
1999 .Bd -literal -compact
2000 int (*init)(int version, sudo_printf_t plugin_printf,
2001             char *const argv[]);
2002 .Ed
2003 .Pp
2004 The
2005 .Fn init
2006 function is called after
2007 .Em sudoers
2008 has been parsed but
2009 before any policy checks.
2010 It returns 1 on success, 0 on failure (or if the plugin is not configured),
2011 and \-1 if a error occurred.
2012 If an error occurs, the plugin may call the
2013 .Fn plugin_printf
2014 function with
2015 .Dv SUDO_CONF_ERROR_MSG
2016 to present additional error information
2017 to the user.
2018 .Pp
2019 The function arguments are as follows:
2020 .Bl -tag -width 4n
2021 .It version
2022 The version passed in by
2023 .Em sudoers
2024 allows the plugin to determine the
2025 major and minor version number of the group plugin API supported by
2026 .Em sudoers .
2027 .It plugin_printf
2028 A pointer to a
2029 .Fn printf Ns No -style
2030 function that may be used to display informational or error message to the user.
2031 Returns the number of characters printed on success and \-1 on failure.
2032 .It argv
2033 A
2034 .Dv NULL Ns No -terminated
2035 array of arguments generated from the
2036 .Em group_plugin
2037 option in
2038 .Em sudoers .
2039 If no arguments were given,
2040 .Em argv
2041 will be
2042 .Dv NULL .
2043 .El
2044 .It cleanup
2045 .Bd -literal -compact
2046 void (*cleanup)();
2047 .Ed
2048 .Pp
2049 The
2050 .Fn cleanup
2051 function is called when
2052 .Em sudoers
2053 has finished its
2054 group checks.
2055 The plugin should free any memory it has allocated and close open file handles.
2056 .It query
2057 .Bd -literal -compact
2058 int (*query)(const char *user, const char *group,
2059              const struct passwd *pwd);
2060 .Ed
2061 .Pp
2062 The
2063 .Fn query
2064 function is used to ask the group plugin whether
2065 .Em user
2066 is a member of
2067 .Em group .
2068 .Pp
2069 The function arguments are as follows:
2070 .Bl -tag -width 4n
2071 .It user
2072 The name of the user being looked up in the external group database.
2073 .It group
2074 The name of the group being queried.
2075 .It pwd
2076 The password database entry for
2077 .Em user ,
2078 if any.
2079 If
2080 .Em user
2081 is not
2082 present in the password database,
2083 .Em pwd
2084 will be
2085 .Dv NULL .
2086 .El
2087 .El
2088 .Pp
2089 .Em Group API Version Macros
2090 .Bd -literal
2091 /* Sudoers group plugin version major/minor */
2092 #define GROUP_API_VERSION_MAJOR 1
2093 #define GROUP_API_VERSION_MINOR 0
2094 #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
2095                            GROUP_API_VERSION_MINOR)
2096
2097 /* Getters and setters for group version */
2098 #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
2099 #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
2100 #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \e
2101     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
2102 } while(0)
2103 #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \e
2104     *(vp) = (*(vp) & 0xffff0000) | (n); \e
2105 } while(0)
2106 .Ed
2107 .Sh PLUGIN API CHANGELOG
2108 The following revisions have been made to the Sudo Plugin API.
2109 .Bl -tag -width 4n
2110 .It Version 1.0
2111 Initial API version.
2112 .It Version 1.1
2113 The I/O logging plugin's
2114 .Fn open
2115 function was modified to take the
2116 .Li command_info
2117 list as an argument.
2118 .It Version 1.2
2119 The Policy and I/O logging plugins'
2120 .Fn open
2121 functions are now passed
2122 a list of plugin options if any are specified in
2123 .Pa @sysconfdir@/sudo.conf .
2124 .Pp
2125 A simple hooks API has been introduced to allow plugins to hook in to the
2126 system's environment handling functions.
2127 .Pp
2128 The
2129 .Li init_session
2130 Policy plugin function is now passed a pointer
2131 to the user environment which can be updated as needed.
2132 This can be used to merge in environment variables stored in the PAM
2133 handle before a command is run.
2134 .El
2135 .Sh SEE ALSO
2136 .Xr sudoers @mansectform@ ,
2137 .Xr sudo @mansectsu@
2138 .Sh BUGS
2139 If you feel you have found a bug in
2140 .Nm sudo ,
2141 please submit a bug report at http://www.sudo.ws/sudo/bugs/
2142 .Sh SUPPORT
2143 Limited free support is available via the sudo-users mailing list,
2144 see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
2145 search the archives.
2146 .Sh DISCLAIMER
2147 .Nm sudo
2148 is provided
2149 .Dq AS IS
2150 and any express or implied warranties, including, but not limited
2151 to, the implied warranties of merchantability and fitness for a
2152 particular purpose are disclaimed.
2153 See the LICENSE file distributed with
2154 .Nm sudo
2155 or http://www.sudo.ws/sudo/license.html for complete details.