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