Annotation of embedaddon/sudo/doc/sudo_plugin.mdoc.in, revision 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>