Annotation of embedaddon/sudo/doc/sudo_plugin.mdoc.in, revision 1.1.1.1
1.1 misho 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.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>