1618 lines
51 KiB
Plaintext
1618 lines
51 KiB
Plaintext
Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
|
|
Permission to use, copy, modify, and distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
sudo_plugin - Sudo Plugin API
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Starting with version 1.8, B<sudo> supports a plugin API
|
|
for policy and session logging. By default, the I<sudoers> policy
|
|
plugin and an associated I/O logging plugin are used. Via the plugin
|
|
API, B<sudo> can be configured to use alternate policy and/or I/O
|
|
logging plugins provided by third parties. The plugins to be used
|
|
are specified via the F<@sysconfdir@/sudo.conf> file.
|
|
|
|
The API is versioned with a major and minor number. The minor
|
|
version number is incremented when additions are made. The major
|
|
number is incremented when incompatible changes are made. A plugin
|
|
should be check the version passed to it and make sure that the
|
|
major version matches.
|
|
|
|
The plugin API is defined by the C<sudo_plugin.h> header file.
|
|
|
|
=head2 The sudo.conf File
|
|
|
|
The F<@sysconfdir@/sudo.conf> file contains plugin configuration directives.
|
|
The primary keyword is the C<Plugin> directive, which causes a plugin
|
|
to be loaded.
|
|
|
|
A C<Plugin> line consists of the C<Plugin> keyword, followed by the
|
|
I<symbol_name> and the I<path> to the shared object containing the
|
|
plugin. The I<symbol_name> is the name of the C<struct policy_plugin>
|
|
or C<struct io_plugin> in the plugin shared object. The I<path>
|
|
may be fully qualified or relative. If not fully qualified it is
|
|
relative to the F<@prefix@/libexec> directory. Any additional
|
|
parameters after the I<path> are passed as options to the plugin's
|
|
I<open> function. Lines that don't begin with C<Plugin>, C<Path>,
|
|
C<Debug> or C<Set> are silently ignored.
|
|
|
|
The same shared object may contain multiple plugins, each with a
|
|
different symbol name. The shared object file must be owned by uid
|
|
0 and only writable by its owner. Because of ambiguities that arise
|
|
from composite policies, only a single policy plugin may be specified.
|
|
This limitation does not apply to I/O plugins.
|
|
|
|
#
|
|
# Default @sysconfdir@/sudo.conf file
|
|
#
|
|
# Format:
|
|
# Plugin plugin_name plugin_path plugin_options ...
|
|
# Path askpass /path/to/askpass
|
|
# Path noexec /path/to/sudo_noexec.so
|
|
# Debug sudo /var/log/sudo_debug all@warn
|
|
# Set disable_coredump true
|
|
#
|
|
# The plugin_path is relative to @prefix@/libexec unless
|
|
# fully qualified.
|
|
# The plugin_name corresponds to a global symbol in the plugin
|
|
# that contains the plugin interface structure.
|
|
# The plugin_options are optional.
|
|
#
|
|
Plugin sudoers_policy sudoers.so
|
|
Plugin sudoers_io sudoers.so
|
|
|
|
=head2 Policy Plugin API
|
|
|
|
A policy plugin must declare and populate a C<policy_plugin> struct
|
|
in the global scope. This structure contains pointers to the functions
|
|
that implement the B<sudo> policy checks. The name of the symbol should
|
|
be specified in F<@sysconfdir@/sudo.conf> along with a path to the plugin
|
|
so that B<sudo> can load it.
|
|
|
|
struct policy_plugin {
|
|
#define SUDO_POLICY_PLUGIN 1
|
|
unsigned int type; /* always SUDO_POLICY_PLUGIN */
|
|
unsigned int version; /* always SUDO_API_VERSION */
|
|
int (*open)(unsigned int version, sudo_conv_t conversation,
|
|
sudo_printf_t plugin_printf, char * const settings[],
|
|
char * const user_info[], char * const user_env[],
|
|
char * const plugin_options[]);
|
|
void (*close)(int exit_status, int error);
|
|
int (*show_version)(int verbose);
|
|
int (*check_policy)(int argc, char * const argv[],
|
|
char *env_add[], char **command_info[],
|
|
char **argv_out[], char **user_env_out[]);
|
|
int (*list)(int argc, char * const argv[], int verbose,
|
|
const char *list_user);
|
|
int (*validate)(void);
|
|
void (*invalidate)(int remove);
|
|
int (*init_session)(struct passwd *pwd, char **user_env[]);
|
|
void (*register_hooks)(int version,
|
|
int (*register_hook)(struct sudo_hook *hook));
|
|
void (*deregister_hooks)(int version,
|
|
int (*deregister_hook)(struct sudo_hook *hook));
|
|
};
|
|
|
|
The policy_plugin struct has the following fields:
|
|
|
|
=over 4
|
|
|
|
=item type
|
|
|
|
The C<type> field should always be set to SUDO_POLICY_PLUGIN.
|
|
|
|
=item version
|
|
|
|
The C<version> field should be set to SUDO_API_VERSION.
|
|
|
|
This allows B<sudo> to determine the API version the plugin was
|
|
built against.
|
|
|
|
=item open
|
|
|
|
int (*open)(unsigned int version, sudo_conv_t conversation,
|
|
sudo_printf_t plugin_printf, char * const settings[],
|
|
char * const user_info[], char * const user_env[],
|
|
char * const plugin_options[]);
|
|
|
|
Returns 1 on success, 0 on failure, -1 if a general error occurred,
|
|
or -2 if there was a usage error. In the latter case, B<sudo> will
|
|
print a usage message before it exits. If an error occurs, the
|
|
plugin may optionally call the conversation or plugin_printf function
|
|
with C<SUDO_CONF_ERROR_MSG> to present additional error information
|
|
to the user.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item version
|
|
|
|
The version passed in by B<sudo> allows the plugin to determine the
|
|
major and minor version number of the plugin API supported by
|
|
B<sudo>.
|
|
|
|
=item conversation
|
|
|
|
A pointer to the conversation function that can be used by the
|
|
plugin to interact with the user (see below).
|
|
Returns 0 on success and -1 on failure.
|
|
|
|
=item plugin_printf
|
|
|
|
A pointer to a printf-style function that may be used to display
|
|
informational or error messages (see below).
|
|
Returns the number of characters printed on success and -1 on failure.
|
|
|
|
=item settings
|
|
|
|
A vector of user-supplied B<sudo> settings in the form of "name=value"
|
|
strings. The vector is terminated by a C<NULL> pointer. These
|
|
settings correspond to flags the user specified when running B<sudo>.
|
|
As such, they will only be present when the corresponding flag has
|
|
been specified on the command line.
|
|
|
|
When parsing I<settings>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
=over 4
|
|
|
|
=item debug_flags=string
|
|
|
|
A comma-separated list of debug flags that correspond to B<sudo>'s
|
|
C<Debug> entry in F<@sysconfdir@/sudo.conf>, if there is one. The
|
|
flags are passed to the plugin as they appear in F<@sysconfdir@/sudo.conf>.
|
|
The syntax used by B<sudo> and the I<sudoers> plugin is
|
|
I<subsystem>@I<priority> but the plugin is free to use a different
|
|
format so long as it does not include a comma (C<,>).
|
|
|
|
For reference, the priorities supported by the B<sudo> front end and
|
|
I<sudoers> are: I<crit>, I<err>, I<warn>, I<notice>, I<diag>,
|
|
I<info>, I<trace> and I<debug>.
|
|
|
|
The following subsystems are defined: I<main>, I<memory>, I<args>,
|
|
I<exec>, I<pty>, I<utmp>, I<conv>, I<pcomm>, I<util>, I<list>,
|
|
I<netif>, I<audit>, I<edit>, I<selinux>, I<ldap>, I<match>, I<parser>,
|
|
I<alias>, I<defaults>, I<auth>, I<env>, I<logging>, I<nss>, I<rbtree>,
|
|
I<perms>, I<plugin>. The subsystem I<all> includes every subsystem.
|
|
|
|
There is not currently a way to specify a set of debug flags specific
|
|
to the plugin--the flags are shared by B<sudo> and the plugin.
|
|
|
|
=item debug_level=number
|
|
|
|
This setting has been deprecated in favor of I<debug_flags>.
|
|
|
|
=item runas_user=string
|
|
|
|
The user name or uid to to run the command as, if specified via the
|
|
B<-u> flag.
|
|
|
|
=item runas_group=string
|
|
|
|
The group name or gid to to run the command as, if specified via
|
|
the B<-g> flag.
|
|
|
|
=item prompt=string
|
|
|
|
The prompt to use when requesting a password, if specified via
|
|
the B<-p> flag.
|
|
|
|
=item set_home=bool
|
|
|
|
Set to true if the user specified the B<-H> flag. If true, set the
|
|
C<HOME> environment variable to the target user's home directory.
|
|
|
|
=item preserve_environment=bool
|
|
|
|
Set to true if the user specified the B<-E> flag, indicating that
|
|
the user wishes to preserve the environment.
|
|
|
|
=item run_shell=bool
|
|
|
|
Set to true if the user specified the B<-s> flag, indicating that
|
|
the user wishes to run a shell.
|
|
|
|
=item login_shell=bool
|
|
|
|
Set to true if the user specified the B<-i> flag, indicating that
|
|
the user wishes to run a login shell.
|
|
|
|
=item implied_shell=bool
|
|
|
|
If the user does not specify a program on the command line, B<sudo>
|
|
will pass the plugin the path to the user's shell and set
|
|
I<implied_shell> to true. This allows B<sudo> with no arguments
|
|
to be used similarly to L<su(1)>. If the plugin does not to support
|
|
this usage, it may return a value of -2 from the C<check_policy>
|
|
function, which will cause B<sudo> to print a usage message and
|
|
exit.
|
|
|
|
=item preserve_groups=bool
|
|
|
|
Set to true if the user specified the B<-P> flag, indicating that
|
|
the user wishes to preserve the group vector instead of setting it
|
|
based on the runas user.
|
|
|
|
=item ignore_ticket=bool
|
|
|
|
Set to true if the user specified the B<-k> flag along with a
|
|
command, indicating that the user wishes to ignore any cached
|
|
authentication credentials.
|
|
|
|
=item noninteractive=bool
|
|
|
|
Set to true if the user specified the B<-n> flag, indicating that
|
|
B<sudo> should operate in non-interactive mode. The plugin may
|
|
reject a command run in non-interactive mode if user interaction
|
|
is required.
|
|
|
|
=item login_class=string
|
|
|
|
BSD login class to use when setting resource limits and nice value,
|
|
if specified by the B<-c> flag.
|
|
|
|
=item selinux_role=string
|
|
|
|
SELinux role to use when executing the command, if specified by
|
|
the B<-r> flag.
|
|
|
|
=item selinux_type=string
|
|
|
|
SELinux type to use when executing the command, if specified by
|
|
the B<-t> flag.
|
|
|
|
=item bsdauth_type=string
|
|
|
|
Authentication type, if specified by the B<-a> flag, to use on
|
|
systems where BSD authentication is supported.
|
|
|
|
=item network_addrs=list
|
|
|
|
A space-separated list of IP network addresses and netmasks in the
|
|
form "addr/netmask", e.g. "192.168.1.2/255.255.255.0". The address
|
|
and netmask pairs may be either IPv4 or IPv6, depending on what the
|
|
operating system supports. If the address contains a colon (':'),
|
|
it is an IPv6 address, else it is IPv4.
|
|
|
|
=item progname=string
|
|
|
|
The command name that sudo was run as, typically "sudo" or "sudoedit".
|
|
|
|
=item sudoedit=bool
|
|
|
|
Set to true when the B<-e> flag is is specified or if invoked as
|
|
B<sudoedit>. The plugin shall substitute an editor into I<argv>
|
|
in the I<check_policy> function or return C<-2> with a usage error
|
|
if the plugin does not support I<sudoedit>. For more information,
|
|
see the I<check_policy> section.
|
|
|
|
=item closefrom=number
|
|
|
|
If specified, the user has requested via the B<-C> flag that B<sudo>
|
|
close all files descriptors with a value of I<number> or higher.
|
|
The plugin may optionally pass this, or another value, back in the
|
|
I<command_info> list.
|
|
|
|
=back
|
|
|
|
Additional settings may be added in the future so the plugin should
|
|
silently ignore settings that it does not recognize.
|
|
|
|
=item user_info
|
|
|
|
A vector of information about the user running the command in the form of
|
|
"name=value" strings. The vector is terminated by a C<NULL> pointer.
|
|
|
|
When parsing I<user_info>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
=over 4
|
|
|
|
=item pid=int
|
|
|
|
The process ID of the running B<sudo> process.
|
|
Only available starting with API version 1.2
|
|
|
|
=item ppid=int
|
|
|
|
The parent process ID of the running B<sudo> process.
|
|
Only available starting with API version 1.2
|
|
|
|
=item sid=int
|
|
|
|
The session ID of the running B<sudo> process or 0 if B<sudo> is
|
|
not part of a POSIX job control session.
|
|
Only available starting with API version 1.2
|
|
|
|
=item pgid=int
|
|
|
|
The ID of the process group that the running B<sudo> process belongs
|
|
to.
|
|
Only available starting with API version 1.2
|
|
|
|
=item tcpgid=int
|
|
|
|
The ID of the forground process group associated with the terminal
|
|
device associcated with the B<sudo> process or -1 if there is no
|
|
terminal present.
|
|
Only available starting with API version 1.2
|
|
|
|
=item user=string
|
|
|
|
The name of the user invoking B<sudo>.
|
|
|
|
=item euid=uid_t
|
|
|
|
The effective user ID of the user invoking B<sudo>.
|
|
|
|
=item uid=uid_t
|
|
|
|
The real user ID of the user invoking B<sudo>.
|
|
|
|
=item egid=gid_t
|
|
|
|
The effective group ID of the user invoking B<sudo>.
|
|
|
|
=item gid=gid_t
|
|
|
|
The real group ID of the user invoking B<sudo>.
|
|
|
|
=item groups=list
|
|
|
|
The user's supplementary group list formatted as a string of
|
|
comma-separated group IDs.
|
|
|
|
=item cwd=string
|
|
|
|
The user's current working directory.
|
|
|
|
=item tty=string
|
|
|
|
The path to the user's terminal device. If the user has no terminal
|
|
device associated with the session, the value will be empty, as in
|
|
C<tty=>.
|
|
|
|
=item host=string
|
|
|
|
The local machine's hostname as returned by the C<gethostname()>
|
|
system call.
|
|
|
|
=item lines=int
|
|
|
|
The number of lines the user's terminal supports. If there is
|
|
no terminal device available, a default value of 24 is used.
|
|
|
|
=item cols=int
|
|
|
|
The number of columns the user's terminal supports. If there is
|
|
no terminal device available, a default value of 80 is used.
|
|
|
|
=back
|
|
|
|
=item user_env
|
|
|
|
The user's environment in the form of a C<NULL>-terminated vector of
|
|
"name=value" strings.
|
|
|
|
When parsing I<user_env>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
=item plugin_options
|
|
|
|
Any (non-comment) strings immediately after the plugin path are
|
|
treated as arguments to the plugin. These arguments are split on
|
|
a white space boundary and are passed to the plugin in the form of
|
|
a C<NULL>-terminated array of strings. If no arguments were
|
|
specified, I<plugin_options> will be the NULL pointer.
|
|
|
|
NOTE: the I<plugin_options> parameter is only available starting with
|
|
API version 1.2. A plugin B<must> check the API version specified
|
|
by the B<sudo> front end before using I<plugin_options>. Failure to
|
|
do so may result in a crash.
|
|
|
|
=back
|
|
|
|
=item close
|
|
|
|
void (*close)(int exit_status, int error);
|
|
|
|
The C<close> function is called when the command being run by B<sudo>
|
|
finishes.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item exit_status
|
|
|
|
The command's exit status, as returned by the wait(2) system call.
|
|
The value of C<exit_status> is undefined if C<error> is non-zero.
|
|
|
|
=item error
|
|
|
|
If the command could not be executed, this is set to the value of
|
|
C<errno> set by the execve(2) system call. The plugin is responsible
|
|
for displaying error information via the conversation or plugin_printf
|
|
function. If the command was successfully executed, the value of
|
|
C<error> is 0.
|
|
|
|
=back
|
|
|
|
=item show_version
|
|
|
|
int (*show_version)(int verbose);
|
|
|
|
The C<show_version> function is called by B<sudo> when the user specifies
|
|
the B<-V> option. The plugin may display its version information
|
|
to the user via the conversation or plugin_printf function using
|
|
C<SUDO_CONV_INFO_MSG>. If the user requests detailed version
|
|
information, the verbose flag will be set.
|
|
|
|
=item check_policy
|
|
|
|
int (*check_policy)(int argc, char * const argv[]
|
|
char *env_add[], char **command_info[],
|
|
char **argv_out[], char **user_env_out[]);
|
|
|
|
The I<check_policy> function is called by B<sudo> to determine
|
|
whether the user is allowed to run the specified commands.
|
|
|
|
If the I<sudoedit> option was enabled in the I<settings> array
|
|
passed to the I<open> function, the user has requested I<sudoedit>
|
|
mode. I<sudoedit> is a mechanism for editing one or more files
|
|
where an editor is run with the user's credentials instead of with
|
|
elevated privileges. B<sudo> achieves this by creating user-writable
|
|
temporary copies of the files to be edited and then overwriting the
|
|
originals with the temporary copies after editing is complete. If
|
|
the plugin supports B<sudoedit>, it should choose the editor to be
|
|
used, potentially from a variable in the user's environment, such
|
|
as C<EDITOR>, and include it in I<argv_out> (note that environment
|
|
variables may include command line flags). The files to be edited
|
|
should be copied from I<argv> into I<argv_out>, separated from the
|
|
editor and its arguments by a C<"--"> element. The C<"--"> will
|
|
be removed by B<sudo> before the editor is executed. The plugin
|
|
should also set I<sudoedit=true> in the I<command_info> list.
|
|
|
|
The I<check_policy> function returns 1 if the command is allowed,
|
|
0 if not allowed, -1 for a general error, or -2 for a usage error
|
|
or if B<sudoedit> was specified but is unsupported by the plugin.
|
|
In the latter case, B<sudo> will print a usage message before it
|
|
exits. If an error occurs, the plugin may optionally call the
|
|
conversation or plugin_printf function with C<SUDO_CONF_ERROR_MSG>
|
|
to present additional error information to the user.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item argc
|
|
|
|
The number of elements in I<argv>, not counting the final C<NULL>
|
|
pointer.
|
|
|
|
=item argv
|
|
|
|
The argument vector describing the command the user wishes to run,
|
|
in the same form as what would be passed to the execve() system
|
|
call. The vector is terminated by a C<NULL> pointer.
|
|
|
|
=item env_add
|
|
|
|
Additional environment variables specified by the user on the command
|
|
line in the form of a C<NULL>-terminated vector of "name=value"
|
|
strings. The plugin may reject the command if one or more variables
|
|
are not allowed to be set, or it may silently ignore such variables.
|
|
|
|
When parsing I<env_add>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
=item command_info
|
|
|
|
Information about the command being run in the form of "name=value"
|
|
strings. These values are used by B<sudo> to set the execution
|
|
environment when running a command. The plugin is responsible for
|
|
creating and populating the vector, which must be terminated with
|
|
a C<NULL> pointer. The following values are recognized by B<sudo>:
|
|
|
|
=over 4
|
|
|
|
=item command=string
|
|
|
|
Fully qualified path to the command to be executed.
|
|
|
|
=item runas_uid=uid
|
|
|
|
User ID to run the command as.
|
|
|
|
=item runas_euid=uid
|
|
|
|
Effective user ID to run the command as.
|
|
If not specified, the value of I<runas_uid> is used.
|
|
|
|
=item runas_gid=gid
|
|
|
|
Group ID to run the command as.
|
|
|
|
=item runas_egid=gid
|
|
|
|
Effective group ID to run the command as.
|
|
If not specified, the value of I<runas_gid> is used.
|
|
|
|
=item runas_groups=list
|
|
|
|
The supplementary group vector to use for the command in the form
|
|
of a comma-separated list of group IDs. If I<preserve_groups>
|
|
is set, this option is ignored.
|
|
|
|
=item login_class=string
|
|
|
|
BSD login class to use when setting resource limits and nice value
|
|
(optional). This option is only set on systems that support login
|
|
classes.
|
|
|
|
=item preserve_groups=bool
|
|
|
|
If set, B<sudo> will preserve the user's group vector instead of
|
|
initializing the group vector based on C<runas_user>.
|
|
|
|
=item cwd=string
|
|
|
|
The current working directory to change to when executing the command.
|
|
|
|
=item noexec=bool
|
|
|
|
If set, prevent the command from executing other programs.
|
|
|
|
=item chroot=string
|
|
|
|
The root directory to use when running the command.
|
|
|
|
=item nice=int
|
|
|
|
Nice value (priority) to use when executing the command. The nice
|
|
value, if specified, overrides the priority associated with the
|
|
I<login_class> on BSD systems.
|
|
|
|
=item umask=octal
|
|
|
|
The file creation mask to use when executing the command.
|
|
|
|
=item selinux_role=string
|
|
|
|
SELinux role to use when executing the command.
|
|
|
|
=item selinux_type=string
|
|
|
|
SELinux type to use when executing the command.
|
|
|
|
=item timeout=int
|
|
|
|
Command timeout. If non-zero then when the timeout expires the
|
|
command will be killed.
|
|
|
|
=item sudoedit=bool
|
|
|
|
Set to true when in I<sudoedit> mode. The plugin may enable
|
|
I<sudoedit> mode even if B<sudo> was not invoked as B<sudoedit>.
|
|
This allows the plugin to perform command substitution and transparently
|
|
enable I<sudoedit> when the user attempts to run an editor.
|
|
|
|
=item closefrom=number
|
|
|
|
If specified, B<sudo> will close all files descriptors with a value
|
|
of I<number> or higher.
|
|
|
|
=item iolog_compress=bool
|
|
|
|
Set to true if the I/O logging plugins, if any, should compress the
|
|
log data. This is a hint to the I/O logging plugin which may choose
|
|
to ignore it.
|
|
|
|
=item iolog_path=string
|
|
|
|
Fully qualified path to the file or directory in which I/O log is
|
|
to be stored. This is a hint to the I/O logging plugin which may
|
|
choose to ignore it. If no I/O logging plugin is loaded, this
|
|
setting has no effect.
|
|
|
|
=item iolog_stdin=bool
|
|
|
|
Set to true if the I/O logging plugins, if any, should log the
|
|
standard input if it is not connected to a terminal device. This
|
|
is a hint to the I/O logging plugin which may choose to ignore it.
|
|
|
|
=item iolog_stdout=bool
|
|
|
|
Set to true if the I/O logging plugins, if any, should log the
|
|
standard output if it is not connected to a terminal device. This
|
|
is a hint to the I/O logging plugin which may choose to ignore it.
|
|
|
|
=item iolog_stderr=bool
|
|
|
|
Set to true if the I/O logging plugins, if any, should log the
|
|
standard error if it is not connected to a terminal device. This
|
|
is a hint to the I/O logging plugin which may choose to ignore it.
|
|
|
|
=item iolog_ttyin=bool
|
|
|
|
Set to true if the I/O logging plugins, if any, should log all
|
|
terminal input. This only includes input typed by the user and not
|
|
from a pipe or redirected from a file. This is a hint to the I/O
|
|
logging plugin which may choose to ignore it.
|
|
|
|
=item iolog_ttyout=bool
|
|
|
|
Set to true if the I/O logging plugins, if any, should log all
|
|
terminal output. This only includes output to the screen, not
|
|
output to a pipe or file. This is a hint to the I/O logging plugin
|
|
which may choose to ignore it.
|
|
|
|
=item use_pty=bool
|
|
|
|
Allocate a pseudo-tty to run the command in, regardless of whether
|
|
or not I/O logging is in use. By default, B<sudo> will only run
|
|
the command in a pty when an I/O log plugin is loaded.
|
|
|
|
=item set_utmp=bool
|
|
|
|
Create a utmp (or utmpx) entry when a pseudo-tty is allocated. By
|
|
default, the new entry will be a copy of the user's existing utmp
|
|
entry (if any), with the tty, time, type and pid fields updated.
|
|
|
|
=item utmp_user=string
|
|
|
|
User name to use when constructing a new utmp (or utmpx) entry when
|
|
I<set_utmp> is enabled. This option can be used to set the user
|
|
field in the utmp entry to the user the command runs as rather than
|
|
the invoking user. If not set, B<sudo> will base the new entry on
|
|
the invoking user's existing entry.
|
|
|
|
=back
|
|
|
|
Unsupported values will be ignored.
|
|
|
|
=item argv_out
|
|
|
|
The C<NULL>-terminated argument vector to pass to the execve()
|
|
system call when executing the command. The plugin is responsible
|
|
for allocating and populating the vector.
|
|
|
|
=item user_env_out
|
|
|
|
The C<NULL>-terminated environment vector to use when executing the
|
|
command. The plugin is responsible for allocating and populating
|
|
the vector.
|
|
|
|
=back
|
|
|
|
=item list
|
|
|
|
int (*list)(int verbose, const char *list_user,
|
|
int argc, char * const argv[]);
|
|
|
|
List available privileges for the invoking user. Returns 1 on
|
|
success, 0 on failure and -1 on error. On error, the plugin may
|
|
optionally call the conversation or plugin_printf function with
|
|
C<SUDO_CONF_ERROR_MSG> to present additional error information to
|
|
the user.
|
|
|
|
Privileges should be output via the conversation or plugin_printf
|
|
function using C<SUDO_CONV_INFO_MSG>.
|
|
|
|
=over 4
|
|
|
|
=item verbose
|
|
|
|
Flag indicating whether to list in verbose mode or not.
|
|
|
|
=item list_user
|
|
|
|
The name of a different user to list privileges for if the policy
|
|
allows it. If C<NULL>, the plugin should list the privileges of
|
|
the invoking user.
|
|
|
|
=item argc
|
|
|
|
The number of elements in I<argv>, not counting the final C<NULL>
|
|
pointer.
|
|
|
|
=item argv
|
|
|
|
If non-C<NULL>, an argument vector describing a command the user
|
|
wishes to check against the policy in the same form as what would
|
|
be passed to the execve() system call. If the command is permitted
|
|
by the policy, the fully-qualified path to the command should be
|
|
displayed along with any command line arguments.
|
|
|
|
=back
|
|
|
|
=item validate
|
|
|
|
int (*validate)(void);
|
|
|
|
The C<validate> function is called when B<sudo> is run with the
|
|
B<-v> flag. For policy plugins such as I<sudoers> that cache
|
|
authentication credentials, this function will validate and cache
|
|
the credentials.
|
|
|
|
The C<validate> function should be C<NULL> if the plugin does not
|
|
support credential caching.
|
|
|
|
Returns 1 on success, 0 on failure and -1 on error.
|
|
On error, the plugin may optionally call the conversation or plugin_printf
|
|
function with C<SUDO_CONF_ERROR_MSG> to present additional
|
|
error information to the user.
|
|
|
|
=item invalidate
|
|
|
|
void (*invalidate)(int remove);
|
|
|
|
The C<invalidate> function is called when B<sudo> is called with
|
|
the B<-k> or B<-K> flag. For policy plugins such as I<sudoers> that
|
|
cache authentication credentials, this function will invalidate the
|
|
credentials. If the I<remove> flag is set, the plugin may remove
|
|
the credentials instead of simply invalidating them.
|
|
|
|
The C<invalidate> function should be C<NULL> if the plugin does not
|
|
support credential caching.
|
|
|
|
=item init_session
|
|
|
|
int (*init_session)(struct passwd *pwd, char **user_envp[);
|
|
|
|
The C<init_session> function is called before B<sudo> sets up the
|
|
execution environment for the command. It is run in the parent
|
|
B<sudo> process and before any uid or gid changes. This can be used
|
|
to perform session setup that is not supported by I<command_info>,
|
|
such as opening the PAM session. The C<close> function can be
|
|
used to tear down the session that was opened by C<init_session>.
|
|
|
|
The I<pwd> argument points to a passwd struct for the user the
|
|
command will be run as if the uid the command will run as was found
|
|
in the password database, otherwise it will be NULL.
|
|
|
|
The I<user_env> argument points to the environment the command will
|
|
run in, in the form of a C<NULL>-terminated vector of "name=value"
|
|
strings. This is the same string passed back to the front end via
|
|
the Policy Plugin's I<user_env_out> parameter. If the C<init_session>
|
|
function needs to modify the user environment, it should update the
|
|
pointer stored in I<user_env>. The expected use case is to merge
|
|
the contents of the PAM environment (if any) with the contents of
|
|
I<user_env>. NOTE: the I<user_env> parameter is only available
|
|
starting with API version 1.2. A plugin B<must> check the API
|
|
version specified by the B<sudo> front end before using I<user_env>.
|
|
Failure to do so may result in a crash.
|
|
|
|
Returns 1 on success, 0 on failure and -1 on error.
|
|
On error, the plugin may optionally call the conversation or plugin_printf
|
|
function with C<SUDO_CONF_ERROR_MSG> to present additional
|
|
error information to the user.
|
|
|
|
=item register_hooks
|
|
|
|
void (*register_hooks)(int version,
|
|
int (*register_hook)(struct sudo_hook *hook));
|
|
|
|
The C<register_hooks> function is called by the sudo front end to
|
|
register any hooks the plugin needs. If the plugin does not support
|
|
hooks, C<register_hooks> should be set to the NULL pointer.
|
|
|
|
The I<version> argument describes the version of the hooks API
|
|
supported by the B<sudo> front end.
|
|
|
|
The C<register_hook> function should be used to register any supported
|
|
hooks the plugin needs. It returns 0 on success, 1 if the hook
|
|
type is not supported and -1 if the major version in C<struct hook>
|
|
does not match the front end's major hook API version.
|
|
|
|
See the L<Hook Function API> section below for more information
|
|
about hooks.
|
|
|
|
NOTE: the C<register_hooks> function is only available starting
|
|
with API version 1.2. If the B<sudo> front end doesn't support API
|
|
version 1.2 or higher, C<register_hooks> will not be called.
|
|
|
|
=item deregister_hooks
|
|
|
|
void (*deregister_hooks)(int version,
|
|
int (*deregister_hook)(struct sudo_hook *hook));
|
|
|
|
The C<deregister_hooks> function is called by the sudo front end
|
|
to deregister any hooks the plugin has registered. If the plugin
|
|
does not support hooks, C<deregister_hooks> should be set to the
|
|
NULL pointer.
|
|
|
|
The I<version> argument describes the version of the hooks API
|
|
supported by the B<sudo> front end.
|
|
|
|
The C<deregister_hook> function should be used to deregister any
|
|
hooks that were put in place by the C<register_hook> function. If
|
|
the plugin tries to deregister a hook that the front end does not
|
|
support, C<deregister_hook> will return an error.
|
|
|
|
See the L<Hook Function API> section below for more information
|
|
about hooks.
|
|
|
|
NOTE: the C<deregister_hooks> function is only available starting
|
|
with API version 1.2. If the B<sudo> front end doesn't support API
|
|
version 1.2 or higher, C<deregister_hooks> will not be called.
|
|
|
|
=back
|
|
|
|
=head3 Policy Plugin Version Macros
|
|
|
|
/* Plugin API version major/minor. */
|
|
#define SUDO_API_VERSION_MAJOR 1
|
|
#define SUDO_API_VERSION_MINOR 2
|
|
#define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
|
|
#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\
|
|
SUDO_API_VERSION_MINOR)
|
|
|
|
/* Getters and setters for API version */
|
|
#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
|
|
#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
|
|
#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
|
|
*(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
|
|
} while(0)
|
|
#define SUDO_VERSION_SET_MINOR(vp, n) do { \
|
|
*(vp) = (*(vp) & 0xffff0000) | (n); \
|
|
} while(0)
|
|
|
|
=head2 I/O Plugin API
|
|
|
|
struct io_plugin {
|
|
#define SUDO_IO_PLUGIN 2
|
|
unsigned int type; /* always SUDO_IO_PLUGIN */
|
|
unsigned int version; /* always SUDO_API_VERSION */
|
|
int (*open)(unsigned int version, sudo_conv_t conversation
|
|
sudo_printf_t plugin_printf, char * const settings[],
|
|
char * const user_info[], int argc, char * const argv[],
|
|
char * const user_env[], char * const plugin_options[]);
|
|
void (*close)(int exit_status, int error); /* wait status or error */
|
|
int (*show_version)(int verbose);
|
|
int (*log_ttyin)(const char *buf, unsigned int len);
|
|
int (*log_ttyout)(const char *buf, unsigned int len);
|
|
int (*log_stdin)(const char *buf, unsigned int len);
|
|
int (*log_stdout)(const char *buf, unsigned int len);
|
|
int (*log_stderr)(const char *buf, unsigned int len);
|
|
void (*register_hooks)(int version,
|
|
int (*register_hook)(struct sudo_hook *hook));
|
|
void (*deregister_hooks)(int version,
|
|
int (*deregister_hook)(struct sudo_hook *hook));
|
|
};
|
|
|
|
When an I/O plugin is loaded, B<sudo> runs the command in a pseudo-tty.
|
|
This makes it possible to log the input and output from the user's
|
|
session. If any of the standard input, standard output or standard
|
|
error do not correspond to a tty, B<sudo> will open a pipe to capture
|
|
the I/O for logging before passing it on.
|
|
|
|
The log_ttyin function receives the raw user input from the terminal
|
|
device (note that this will include input even when echo is disabled,
|
|
such as when a password is read). The log_ttyout function receives
|
|
output from the pseudo-tty that is suitable for replaying the user's
|
|
session at a later time. The log_stdin, log_stdout and log_stderr
|
|
functions are only called if the standard input, standard output
|
|
or standard error respectively correspond to something other than
|
|
a tty.
|
|
|
|
Any of the logging functions may be set to the NULL
|
|
pointer if no logging is to be performed. If the open function
|
|
returns C<0>, no I/O will be sent to the plugin.
|
|
|
|
The io_plugin struct has the following fields:
|
|
|
|
=over 4
|
|
|
|
=item type
|
|
|
|
The C<type> field should always be set to SUDO_IO_PLUGIN
|
|
|
|
=item version
|
|
|
|
The C<version> field should be set to SUDO_API_VERSION.
|
|
|
|
This allows B<sudo> to determine the API version the plugin was
|
|
built against.
|
|
|
|
=item open
|
|
|
|
int (*open)(unsigned int version, sudo_conv_t conversation
|
|
sudo_printf_t plugin_printf, char * const settings[],
|
|
char * const user_info[], int argc, char * const argv[],
|
|
char * const user_env[], char * const plugin_options[]);
|
|
|
|
The I<open> function is run before the I<log_input>, I<log_output>
|
|
or I<show_version> functions are called. It is only called if the
|
|
version is being requested or the I<check_policy> function has
|
|
returned successfully. It returns 1 on success, 0 on failure, -1
|
|
if a general error occurred, or -2 if there was a usage error. In
|
|
the latter case, B<sudo> will print a usage message before it exits.
|
|
If an error occurs, the plugin may optionally call the conversation
|
|
or plugin_printf function with C<SUDO_CONF_ERROR_MSG> to present
|
|
additional error information to the user.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item version
|
|
|
|
The version passed in by B<sudo> allows the plugin to determine the
|
|
major and minor version number of the plugin API supported by
|
|
B<sudo>.
|
|
|
|
=item conversation
|
|
|
|
A pointer to the conversation function that may be used by the
|
|
I<show_version> function to display version information (see
|
|
show_version below). The conversation function may also be used
|
|
to display additional error message to the user.
|
|
The conversation function returns 0 on success and -1 on failure.
|
|
|
|
=item plugin_printf
|
|
|
|
A pointer to a printf-style function that may be used by the
|
|
I<show_version> function to display version information (see
|
|
show_version below). The plugin_printf function may also be used
|
|
to display additional error message to the user.
|
|
The plugin_printf function returns number of characters printed on
|
|
success and -1 on failure.
|
|
|
|
=item settings
|
|
|
|
A vector of user-supplied B<sudo> settings in the form of "name=value"
|
|
strings. The vector is terminated by a C<NULL> pointer. These
|
|
settings correspond to flags the user specified when running B<sudo>.
|
|
As such, they will only be present when the corresponding flag has
|
|
been specified on the command line.
|
|
|
|
When parsing I<settings>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
See the L<Policy Plugin API> section for a list of all possible settings.
|
|
|
|
=item user_info
|
|
|
|
A vector of information about the user running the command in the form of
|
|
"name=value" strings. The vector is terminated by a C<NULL> pointer.
|
|
|
|
When parsing I<user_info>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
See the L<Policy Plugin API> section for a list of all possible strings.
|
|
|
|
=item argc
|
|
|
|
The number of elements in I<argv>, not counting the final C<NULL>
|
|
pointer.
|
|
|
|
=item argv
|
|
|
|
If non-C<NULL>, an argument vector describing a command the user
|
|
wishes to run in the same form as what would be passed to the
|
|
execve() system call.
|
|
|
|
=item user_env
|
|
|
|
The user's environment in the form of a C<NULL>-terminated vector of
|
|
"name=value" strings.
|
|
|
|
When parsing I<user_env>, the plugin should split on the B<first>
|
|
equal sign ('=') since the I<name> field will never include one
|
|
itself but the I<value> might.
|
|
|
|
=item plugin_options
|
|
|
|
Any (non-comment) strings immediately after the plugin path are
|
|
treated as arguments to the plugin. These arguments are split on
|
|
a white space boundary and are passed to the plugin in the form of
|
|
a C<NULL>-terminated array of strings. If no arguments were
|
|
specified, I<plugin_options> will be the NULL pointer.
|
|
|
|
NOTE: the I<plugin_options> parameter is only available starting with
|
|
API version 1.2. A plugin B<must> check the API version specified
|
|
by the B<sudo> front end before using I<plugin_options>. Failure to
|
|
do so may result in a crash.
|
|
|
|
=back
|
|
|
|
=item close
|
|
|
|
void (*close)(int exit_status, int error);
|
|
|
|
The C<close> function is called when the command being run by B<sudo>
|
|
finishes.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item exit_status
|
|
|
|
The command's exit status, as returned by the wait(2) system call.
|
|
The value of C<exit_status> is undefined if C<error> is non-zero.
|
|
|
|
=item error
|
|
|
|
If the command could not be executed, this is set to the value of
|
|
C<errno> set by the execve(2) system call. If the command was
|
|
successfully executed, the value of C<error> is 0.
|
|
|
|
=back
|
|
|
|
=item show_version
|
|
|
|
int (*show_version)(int verbose);
|
|
|
|
The C<show_version> function is called by B<sudo> when the user specifies
|
|
the B<-V> option. The plugin may display its version information
|
|
to the user via the conversation or plugin_printf function using
|
|
C<SUDO_CONV_INFO_MSG>. If the user requests detailed version
|
|
information, the verbose flag will be set.
|
|
|
|
=item log_ttyin
|
|
|
|
int (*log_ttyin)(const char *buf, unsigned int len);
|
|
|
|
The I<log_ttyin> function is called whenever data can be read from
|
|
the user but before it is passed to the running command. This
|
|
allows the plugin to reject data if it chooses to (for instance
|
|
if the input contains banned content). Returns C<1> if the data
|
|
should be passed to the command, C<0> if the data is rejected
|
|
(which will terminate the command) or C<-1> if an error occurred.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item buf
|
|
|
|
The buffer containing user input.
|
|
|
|
=item len
|
|
|
|
The length of I<buf> in bytes.
|
|
|
|
=back
|
|
|
|
=item log_ttyout
|
|
|
|
int (*log_ttyout)(const char *buf, unsigned int len);
|
|
|
|
The I<log_ttyout> function is called whenever data can be read from
|
|
the command but before it is written to the user's terminal. This
|
|
allows the plugin to reject data if it chooses to (for instance
|
|
if the output contains banned content). Returns C<1> if the data
|
|
should be passed to the user, C<0> if the data is rejected
|
|
(which will terminate the command) or C<-1> if an error occurred.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item buf
|
|
|
|
The buffer containing command output.
|
|
|
|
=item len
|
|
|
|
The length of I<buf> in bytes.
|
|
|
|
=back
|
|
|
|
=item log_stdin
|
|
|
|
int (*log_stdin)(const char *buf, unsigned int len);
|
|
|
|
The I<log_stdin> function is only used if the standard input does
|
|
not correspond to a tty device. It is called whenever data can be
|
|
read from the standard input but before it is passed to the running
|
|
command. This allows the plugin to reject data if it chooses to
|
|
(for instance if the input contains banned content). Returns C<1>
|
|
if the data should be passed to the command, C<0> if the data is
|
|
rejected (which will terminate the command) or C<-1> if an error
|
|
occurred.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item buf
|
|
|
|
The buffer containing user input.
|
|
|
|
=item len
|
|
|
|
The length of I<buf> in bytes.
|
|
|
|
=back
|
|
|
|
=item log_stdout
|
|
|
|
int (*log_stdout)(const char *buf, unsigned int len);
|
|
|
|
The I<log_stdout> function is only used if the standard output does
|
|
not correspond to a tty device. It is called whenever data can be
|
|
read from the command but before it is written to the standard
|
|
output. This allows the plugin to reject data if it chooses to
|
|
(for instance if the output contains banned content). Returns C<1>
|
|
if the data should be passed to the user, C<0> if the data is
|
|
rejected (which will terminate the command) or C<-1> if an error
|
|
occurred.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item buf
|
|
|
|
The buffer containing command output.
|
|
|
|
=item len
|
|
|
|
The length of I<buf> in bytes.
|
|
|
|
=back
|
|
|
|
=item log_stderr
|
|
|
|
int (*log_stderr)(const char *buf, unsigned int len);
|
|
|
|
The I<log_stderr> function is only used if the standard error does
|
|
not correspond to a tty device. It is called whenever data can be
|
|
read from the command but before it is written to the standard
|
|
error. This allows the plugin to reject data if it chooses to
|
|
(for instance if the output contains banned content). Returns C<1>
|
|
if the data should be passed to the user, C<0> if the data is
|
|
rejected (which will terminate the command) or C<-1> if an error
|
|
occurred.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item buf
|
|
|
|
The buffer containing command output.
|
|
|
|
=item len
|
|
|
|
The length of I<buf> in bytes.
|
|
|
|
=back
|
|
|
|
=item register_hooks
|
|
|
|
See the L<Policy Plugin API> section for a description of
|
|
C<register_hooks>.
|
|
|
|
=item deregister_hooks
|
|
|
|
See the L<Policy Plugin API> section for a description of
|
|
C<deregister_hooks>.
|
|
|
|
=back
|
|
|
|
=head3 I/O Plugin Version Macros
|
|
|
|
Same as for the L<Policy Plugin API>.
|
|
|
|
=head2 Hook Function API
|
|
|
|
Beginning with plugin API version 1.2, it is possible to install
|
|
hooks for certain functions called by the B<sudo> front end.
|
|
|
|
Currently, the only supported hooks relate to the handling of
|
|
environment variables. Hooks can be used to intercept attempts to
|
|
get, set, or remove environment variables so that these changes can
|
|
be reflected in the version of the environment that is used to
|
|
execute a command. A future version of the API will support
|
|
hooking internal B<sudo> front end functions as well.
|
|
|
|
=head3 Hook structure
|
|
|
|
Hooks in B<sudo> are described by the following structure:
|
|
|
|
typedef int (*sudo_hook_fn_t)();
|
|
|
|
struct sudo_hook {
|
|
int hook_version;
|
|
int hook_type;
|
|
sudo_hook_fn_t hook_fn;
|
|
void *closure;
|
|
};
|
|
|
|
The C<sudo_hook> structure has the following fields:
|
|
|
|
=over 4
|
|
|
|
=item hook_version
|
|
|
|
The C<hook_version> field should be set to SUDO_HOOK_VERSION.
|
|
|
|
=item hook_type
|
|
|
|
The C<hook_type> field may be one of the following supported hook types:
|
|
|
|
=over 4
|
|
|
|
=item SUDO_HOOK_SETENV
|
|
|
|
The C library C<setenv()> function. Any registered hooks will run
|
|
before the C library implementation. The C<hook_fn> field should
|
|
be a function that matches the following typedef:
|
|
|
|
typedef int (*sudo_hook_fn_setenv_t)(const char *name,
|
|
const char *value, int overwrite, void *closure);
|
|
|
|
If the registered hook does not match the typedef the results are
|
|
unspecified.
|
|
|
|
=item SUDO_HOOK_UNSETENV
|
|
|
|
The C library C<unsetenv()> function. Any registered hooks will run
|
|
before the C library implementation. The C<hook_fn> field should
|
|
be a function that matches the following typedef:
|
|
|
|
typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
|
|
void *closure);
|
|
|
|
=item SUDO_HOOK_GETENV
|
|
|
|
The C library C<getenv()> function. Any registered hooks will run
|
|
before the C library implementation. The C<hook_fn> field should
|
|
be a function that matches the following typedef:
|
|
|
|
typedef int (*sudo_hook_fn_getenv_t)(const char *name,
|
|
char **value, void *closure);
|
|
|
|
If the registered hook does not match the typedef the results are
|
|
unspecified.
|
|
|
|
=item SUDO_HOOK_PUTENV
|
|
|
|
The C library C<putenv()> function. Any registered hooks will run
|
|
before the C library implementation. The C<hook_fn> field should
|
|
be a function that matches the following typedef:
|
|
|
|
typedef int (*sudo_hook_fn_putenv_t)(char *string,
|
|
void *closure);
|
|
|
|
If the registered hook does not match the typedef the results are
|
|
unspecified.
|
|
|
|
=back
|
|
|
|
=item hook_fn
|
|
|
|
sudo_hook_fn_t hook_fn;
|
|
|
|
The C<hook_fn> field should be set to the plugin's hook implementation.
|
|
The actual function arguments will vary depending on the C<hook_type>
|
|
(see C<hook_type> above). In all cases, the C<closure> field of
|
|
C<struct sudo_hook> is passed as the last function parameter. This
|
|
can be used to pass arbitrary data to the plugin's hook implementation.
|
|
|
|
The function return value may be one of the following:
|
|
|
|
=over 4
|
|
|
|
=item SUDO_HOOK_RET_ERROR
|
|
|
|
The hook function encountered an error.
|
|
|
|
=item SUDO_HOOK_RET_NEXT
|
|
|
|
The hook completed without error, go on to the next hook (including
|
|
the native implementation if applicable). For example, a C<getenv>
|
|
hook might return C<SUDO_HOOK_RET_NEXT> if the specified variable
|
|
was not found in the private copy of the environment.
|
|
|
|
=item SUDO_HOOK_RET_STOP
|
|
|
|
The hook completed without error, stop processing hooks for this
|
|
invocation. This can be used to replace the native implementation.
|
|
For example, a C<setenv> hook that operates on a private copy of
|
|
the environment but leaves C<environ> unchanged.
|
|
|
|
=back
|
|
|
|
=back
|
|
|
|
Note that it is very easy to create an infinite loop when hooking
|
|
C library functions. For example, a C<getenv> hook that calls the
|
|
C<snprintf> function may create a loop if the C<snprintf> implementation
|
|
calls C<getenv> to check the locale. To prevent this, you may wish
|
|
to use a static variable in the hook function to guard against
|
|
nested calls. E.g.
|
|
|
|
static int in_progress = 0; /* avoid recursion */
|
|
if (in_progress)
|
|
return SUDO_HOOK_RET_NEXT;
|
|
in_progress = 1;
|
|
...
|
|
in_progress = 0;
|
|
return SUDO_HOOK_RET_STOP;
|
|
|
|
=head3 Hook API Version Macros
|
|
|
|
/* Hook API version major/minor */
|
|
#define SUDO_HOOK_VERSION_MAJOR 1
|
|
#define SUDO_HOOK_VERSION_MINOR 0
|
|
#define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y)
|
|
#define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\
|
|
SUDO_HOOK_VERSION_MINOR)
|
|
|
|
/* Getters and setters for hook API version */
|
|
#define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16)
|
|
#define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff)
|
|
#define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \
|
|
*(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
|
|
} while(0)
|
|
#define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \
|
|
*(vp) = (*(vp) & 0xffff0000) | (n); \
|
|
} while(0)
|
|
|
|
=head2 Conversation API
|
|
|
|
If the plugin needs to interact with the user, it may do so via the
|
|
conversation function. A plugin should not attempt to read directly
|
|
from the standard input or the user's tty (neither of which are
|
|
guaranteed to exist). The caller must include a trailing newline
|
|
in C<msg> if one is to be printed.
|
|
|
|
A printf-style function is also available that can be used to display
|
|
informational or error messages to the user, which is usually more
|
|
convenient for simple messages where no use input is required.
|
|
|
|
struct sudo_conv_message {
|
|
#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
|
|
#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
|
|
#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
|
|
#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
|
|
#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
|
|
#define SUDO_CONV_DEBUG_MSG 0x0006 /* debugging message */
|
|
#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
|
|
int msg_type;
|
|
int timeout;
|
|
const char *msg;
|
|
};
|
|
|
|
struct sudo_conv_reply {
|
|
char *reply;
|
|
};
|
|
|
|
typedef int (*sudo_conv_t)(int num_msgs,
|
|
const struct sudo_conv_message msgs[],
|
|
struct sudo_conv_reply replies[]);
|
|
|
|
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
|
|
|
Pointers to the conversation and printf-style functions are passed
|
|
in to the plugin's C<open> function when the plugin is initialized.
|
|
|
|
To use the conversation function, the plugin must pass an array of
|
|
C<sudo_conv_message> and C<sudo_conv_reply> structures. There must
|
|
be a C<struct sudo_conv_message> and C<struct sudo_conv_reply> for
|
|
each message in the conversation. The plugin is responsible for
|
|
freeing the reply buffer filled in to the C<struct sudo_conv_reply>,
|
|
if any.
|
|
|
|
The printf-style function uses the same underlying mechanism as the
|
|
conversation function but only supports C<SUDO_CONV_INFO_MSG>,
|
|
C<SUDO_CONV_ERROR_MSG> and C<SUDO_CONV_DEBUG_MSG> for the I<msg_type>
|
|
parameter. It can be more convenient than using the conversation
|
|
function if no user reply is needed and supports standard printf()
|
|
escape sequences.
|
|
|
|
Unlike, C<SUDO_CONV_INFO_MSG> and C<SUDO_CONV_ERROR_MSG>, messages
|
|
sent with the C<SUDO_CONV_DEBUG_MSG> I<msg_type> are not directly
|
|
user-visible. Instead, they are logged to the file specified in
|
|
the C<Debug> statement (if any) in the F<@sysconfdir@/sudo.conf>
|
|
file. This allows a plugin to log debugging information and is
|
|
intended to be used in conjunction with the I<debug_flags> setting.
|
|
|
|
See the sample plugin for an example of the conversation function usage.
|
|
|
|
=head2 Sudoers Group Plugin API
|
|
|
|
The I<sudoers> module supports a plugin interface to allow non-Unix
|
|
group lookups. This can be used to query a group source other than
|
|
the standard Unix group database. A sample group plugin is bundled
|
|
with B<sudo> that implements file-based lookups. Third party group
|
|
plugins include a QAS AD plugin available from Quest Software.
|
|
|
|
A group plugin must declare and populate a C<sudoers_group_plugin>
|
|
struct in the global scope. This structure contains pointers to
|
|
the functions that implement plugin initialization, cleanup and
|
|
group lookup.
|
|
|
|
struct sudoers_group_plugin {
|
|
unsigned int version;
|
|
int (*init)(int version, sudo_printf_t sudo_printf,
|
|
char *const argv[]);
|
|
void (*cleanup)(void);
|
|
int (*query)(const char *user, const char *group,
|
|
const struct passwd *pwd);
|
|
};
|
|
|
|
The C<sudoers_group_plugin> struct has the following fields:
|
|
|
|
=over 4
|
|
|
|
=item version
|
|
|
|
The C<version> field should be set to GROUP_API_VERSION.
|
|
|
|
This allows I<sudoers> to determine the API version the group plugin
|
|
was built against.
|
|
|
|
=item init
|
|
|
|
int (*init)(int version, sudo_printf_t plugin_printf,
|
|
char *const argv[]);
|
|
|
|
The I<init> function is called after I<sudoers> has been parsed but
|
|
before any policy checks. It returns 1 on success, 0 on failure
|
|
(or if the plugin is not configured), and -1 if a error occurred.
|
|
If an error occurs, the plugin may call the plugin_printf function
|
|
with C<SUDO_CONF_ERROR_MSG> to present additional error information
|
|
to the user.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item version
|
|
|
|
The version passed in by I<sudoers> allows the plugin to determine the
|
|
major and minor version number of the group plugin API supported by
|
|
I<sudoers>.
|
|
|
|
=item plugin_printf
|
|
|
|
A pointer to a printf-style function that may be used to display
|
|
informational or error message to the user.
|
|
Returns the number of characters printed on success and -1 on failure.
|
|
|
|
=item argv
|
|
|
|
A NULL-terminated array of arguments generated from the I<group_plugin>
|
|
option in I<sudoers>. If no arguments were given, I<argv> will be
|
|
NULL.
|
|
|
|
=back
|
|
|
|
=item cleanup
|
|
|
|
void (*cleanup)();
|
|
|
|
The I<cleanup> function is called when I<sudoers> has finished its
|
|
group checks. The plugin should free any memory it has allocated
|
|
and close open file handles.
|
|
|
|
=item query
|
|
|
|
int (*query)(const char *user, const char *group,
|
|
const struct passwd *pwd);
|
|
|
|
The I<query> function is used to ask the group plugin whether I<user>
|
|
is a member of I<group>.
|
|
|
|
The function arguments are as follows:
|
|
|
|
=over 4
|
|
|
|
=item user
|
|
|
|
The name of the user being looked up in the external group database.
|
|
|
|
=item group
|
|
|
|
The name of the group being queried.
|
|
|
|
=item pwd
|
|
|
|
The password database entry for I<user>, if any. If I<user> is not
|
|
present in the password database, I<pwd> will be C<NULL>.
|
|
|
|
=back
|
|
|
|
=back
|
|
|
|
=head3 Group API Version Macros
|
|
|
|
/* Sudoers group plugin version major/minor */
|
|
#define GROUP_API_VERSION_MAJOR 1
|
|
#define GROUP_API_VERSION_MINOR 0
|
|
#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \
|
|
GROUP_API_VERSION_MINOR)
|
|
|
|
/* Getters and setters for group version */
|
|
#define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
|
|
#define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
|
|
#define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \
|
|
*(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
|
|
} while(0)
|
|
#define GROUP_API_VERSION_SET_MINOR(vp, n) do { \
|
|
*(vp) = (*(vp) & 0xffff0000) | (n); \
|
|
} while(0)
|
|
|
|
=head1 PLUGIN API CHANGELOG
|
|
|
|
The following revisions have been made to the Sudo Plugin API.
|
|
|
|
=over 4
|
|
|
|
=item Version 1.0
|
|
|
|
Initial API version.
|
|
|
|
=item Version 1.1
|
|
|
|
The I/O logging plugin's C<open> function was modified to take the
|
|
C<command_info> list as an argument.
|
|
|
|
=item Version 1.2
|
|
|
|
The Policy and I/O logging plugins' C<open> functions are now passed
|
|
a list of plugin options if any are specified in F<@sysconfdir@/sudo.conf>.
|
|
|
|
A simple hooks API has been introduced to allow plugins to hook in to the
|
|
system's environment handling functions.
|
|
|
|
The C<init_session> Policy plugin function is now passed a pointer
|
|
to the user environment which can be updated as needed. This can
|
|
be used to merge in environment variables stored in the PAM handle
|
|
before a command is run.
|
|
|
|
=back
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
L<sudoers(5)>, L<sudo(8)>
|
|
|
|
=head1 BUGS
|
|
|
|
If you feel you have found a bug in B<sudo>, please submit a bug report
|
|
at http://www.sudo.ws/sudo/bugs/
|
|
|
|
=head1 SUPPORT
|
|
|
|
Limited free support is available via the sudo-workers mailing list,
|
|
see http://www.sudo.ws/mailman/listinfo/sudo-workers to subscribe or
|
|
search the archives.
|
|
|
|
=head1 DISCLAIMER
|
|
|
|
B<sudo> is provided ``AS IS'' and any express or implied warranties,
|
|
including, but not limited to, the implied warranties of merchantability
|
|
and fitness for a particular purpose are disclaimed. See the LICENSE
|
|
file distributed with B<sudo> or http://www.sudo.ws/sudo/license.html
|
|
for complete details.
|