Define a new plugin type that receives accept and reject messages.
This can be used to implement logging-only plugins. The plugin functions now take an errstr argument that can be used to return an error string to be logged on failure or error.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
.\"
|
||||
.\" SPDX-License-Identifier: ISC
|
||||
.\"
|
||||
.\" Copyright (c) 2009-2019 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
.\" Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd December 5, 2019
|
||||
.Dd Januarry 28, 2020
|
||||
.Dt SUDO_PLUGIN @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -70,17 +70,19 @@ struct policy_plugin {
|
||||
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[]);
|
||||
char * const plugin_options[], const char **errstr);
|
||||
void (*close)(int exit_status, int error);
|
||||
int (*show_version)(int verbose);
|
||||
int (*show_version)(int verbose, const char **errstr);
|
||||
int (*check_policy)(int argc, char * const argv[],
|
||||
char *env_add[], char **command_info[],
|
||||
char **argv_out[], char **user_env_out[]);
|
||||
char **argv_out[], char **user_env_out[],
|
||||
const char **errstr);
|
||||
int (*list)(int argc, char * const argv[], int verbose,
|
||||
const char *list_user);
|
||||
int (*validate)(void);
|
||||
const char *list_user, const char **errstr);
|
||||
int (*validate)(const char **errstr);
|
||||
void (*invalidate)(int remove);
|
||||
int (*init_session)(struct passwd *pwd, char **user_env[]);
|
||||
int (*init_session)(struct passwd *pwd, char **user_env[],
|
||||
const char **errstr);
|
||||
void (*register_hooks)(int version,
|
||||
int (*register_hook)(struct sudo_hook *hook));
|
||||
void (*deregister_hooks)(int version,
|
||||
@@ -110,7 +112,7 @@ built against.
|
||||
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[]);
|
||||
char * const plugin_options[], const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
Returns 1 on success, 0 on failure, \-1 if a general error occurred,
|
||||
@@ -441,32 +443,6 @@ The process ID of the running
|
||||
.Nm sudo
|
||||
process.
|
||||
Only available starting with API version 1.2.
|
||||
.It plugin_options
|
||||
Any (non-comment) strings immediately after the plugin path are
|
||||
passed 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
|
||||
.Dv NULL Ns -terminated
|
||||
array of strings.
|
||||
If no arguments were
|
||||
specified,
|
||||
.Em plugin_options
|
||||
will be the
|
||||
.Dv NULL
|
||||
pointer.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em plugin_options
|
||||
parameter is only available starting with
|
||||
API version 1.2.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified
|
||||
by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em plugin_options .
|
||||
Failure to do so may result in a crash.
|
||||
.It ppid=int
|
||||
The parent process ID of the running
|
||||
.Nm sudo
|
||||
@@ -518,6 +494,53 @@ field will never include one
|
||||
itself but the
|
||||
.Em value
|
||||
might.
|
||||
.It plugin_options
|
||||
Any (non-comment) strings immediately after the plugin path are
|
||||
passed 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
|
||||
.Dv NULL Ns -terminated
|
||||
array of strings.
|
||||
If no arguments were
|
||||
specified,
|
||||
.Em plugin_options
|
||||
will be the
|
||||
.Dv NULL
|
||||
pointer.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em plugin_options
|
||||
parameter is only available starting with
|
||||
API version 1.2.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified
|
||||
by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em plugin_options .
|
||||
Failure to do so may result in a crash.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn open
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It close
|
||||
.Bd -literal -compact
|
||||
@@ -585,7 +608,7 @@ front end may execute the command directly instead of running
|
||||
it as a child process.
|
||||
.It show_version
|
||||
.Bd -literal -compact
|
||||
int (*show_version)(int verbose);
|
||||
int (*show_version)(int verbose, const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -602,16 +625,45 @@ or
|
||||
.Fn plugin_printf
|
||||
function using
|
||||
.Dv SUDO_CONV_INFO_MSG .
|
||||
If the user requests detailed version information, the verbose flag will be set.
|
||||
.Pp
|
||||
Returns 1 on success, 0 on failure, \-1 if a general error occurred,
|
||||
or \-2 if there was a usage error, although the return value is currently
|
||||
ignored.
|
||||
.Pp
|
||||
The function arguments are as follows:
|
||||
.Bl -tag -width 4n
|
||||
.It verbose
|
||||
If the user requests detailed version information, the
|
||||
.Em verbose
|
||||
flag will be set to 1.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn show_version
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It check_policy
|
||||
.Bd -literal -compact
|
||||
int (*check_policy)(int argc, char * const argv[],
|
||||
char *env_add[], char **command_info[],
|
||||
char **argv_out[], char **user_env_out[]);
|
||||
char **argv_out[], char **user_env_out[],
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1006,11 +1058,32 @@ The
|
||||
.Dv NULL Ns -terminated
|
||||
environment vector to use when executing the command.
|
||||
The plugin is responsible for allocating and populating the vector.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn check_policy
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It list
|
||||
.Bd -literal -compact
|
||||
int (*list)(int argc, char * const argv[],
|
||||
int verbose, const char *list_user);
|
||||
int verbose, const char *list_user, const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
List available privileges for the invoking user.
|
||||
@@ -1057,10 +1130,31 @@ allows it.
|
||||
If
|
||||
.Dv NULL ,
|
||||
the plugin should list the privileges of the invoking user.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn list
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It validate
|
||||
.Bd -literal -compact
|
||||
int (*validate)(void);
|
||||
int (*validate)(const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1091,6 +1185,31 @@ function with
|
||||
.Dv SUDO_CONF_ERROR_MSG
|
||||
to present additional
|
||||
error information to the user.
|
||||
.Pp
|
||||
The function arguments are as follows:
|
||||
.Bl -tag -width 4n
|
||||
.It errstr
|
||||
If the
|
||||
.Fn validate
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It invalidate
|
||||
.Bd -literal -compact
|
||||
void (*invalidate)(int remove);
|
||||
@@ -1100,8 +1219,7 @@ The
|
||||
.Fn invalidate
|
||||
function is called when
|
||||
.Nm sudo
|
||||
is called with
|
||||
the
|
||||
is run with the
|
||||
.Fl k
|
||||
or
|
||||
.Fl K
|
||||
@@ -1321,6 +1439,27 @@ front end doesn't support API
|
||||
version 1.15 or higher,
|
||||
.Fn event_alloc
|
||||
will not be set.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn init_session
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.Pp
|
||||
.Em Policy Plugin Version Macros
|
||||
@@ -1352,20 +1491,26 @@ struct io_plugin {
|
||||
sudo_printf_t plugin_printf, char * const settings[],
|
||||
char * const user_info[], char * const command_info[],
|
||||
int argc, char * const argv[], char * const user_env[],
|
||||
char * const plugin_options[]);
|
||||
char * const plugin_options[], const char **errstr);
|
||||
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);
|
||||
int (*show_version)(int verbose, const char **errstr);
|
||||
int (*log_ttyin)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
int (*log_ttyout)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
int (*log_stdin)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
int (*log_stdout)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
int (*log_stderr)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
void (*register_hooks)(int version,
|
||||
int (*register_hook)(struct sudo_hook *hook));
|
||||
void (*deregister_hooks)(int version,
|
||||
int (*deregister_hook)(struct sudo_hook *hook));
|
||||
int (*change_winsize)(unsigned int lines, unsigned int cols);
|
||||
int (*log_suspend)(int signo);
|
||||
int (*change_winsize)(unsigned int lines, unsigned int cols,
|
||||
const char **errstr);
|
||||
int (*log_suspend)(int signo, const char **errstr);
|
||||
struct sudo_plugin_event * (*event_alloc)(void);
|
||||
};
|
||||
.Ed
|
||||
@@ -1621,6 +1766,27 @@ by the
|
||||
front end before using
|
||||
.Em plugin_options .
|
||||
Failure to do so may result in a crash.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn open
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It close
|
||||
.Bd -literal -compact
|
||||
@@ -1678,14 +1844,43 @@ or
|
||||
.Fn plugin_printf
|
||||
function using
|
||||
.Dv SUDO_CONV_INFO_MSG .
|
||||
If the user requests detailed version information, the verbose flag will be set.
|
||||
.Pp
|
||||
Returns 1 on success, 0 on failure, \-1 if a general error occurred,
|
||||
or \-2 if there was a usage error, although the return value is currently
|
||||
ignored.
|
||||
.Pp
|
||||
The function arguments are as follows:
|
||||
.Bl -tag -width 4n
|
||||
.It verbose
|
||||
If the user requests detailed version information, the
|
||||
.Em verbose
|
||||
flag will be set to 1.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn show_version
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It log_ttyin
|
||||
.Bd -literal -compact
|
||||
int (*log_ttyin)(const char *buf, unsigned int len);
|
||||
int (*log_ttyin)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1706,10 +1901,32 @@ The buffer containing user input.
|
||||
The length of
|
||||
.Em buf
|
||||
in bytes.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn log_ttyin
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It log_ttyout
|
||||
.Bd -literal -compact
|
||||
int (*log_ttyout)(const char *buf, unsigned int len);
|
||||
int (*log_ttyout)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1729,10 +1946,32 @@ The buffer containing command output.
|
||||
The length of
|
||||
.Em buf
|
||||
in bytes.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn log_ttyout
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It log_stdin
|
||||
.Bd -literal -compact
|
||||
int (*log_stdin)(const char *buf, unsigned int len);
|
||||
int (*log_stdin)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1754,10 +1993,32 @@ The buffer containing user input.
|
||||
The length of
|
||||
.Em buf
|
||||
in bytes.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn log_stdin
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It log_stdout
|
||||
.Bd -literal -compact
|
||||
int (*log_stdout)(const char *buf, unsigned int len);
|
||||
int (*log_stdout)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1779,10 +2040,32 @@ The buffer containing command output.
|
||||
The length of
|
||||
.Em buf
|
||||
in bytes.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn log_stdout
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It log_stderr
|
||||
.Bd -literal -compact
|
||||
int (*log_stderr)(const char *buf, unsigned int len);
|
||||
int (*log_stderr)(const char *buf, unsigned int len,
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1804,6 +2087,27 @@ The buffer containing command output.
|
||||
The length of
|
||||
.Em buf
|
||||
in bytes.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn log_stderr
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It register_hooks
|
||||
See the
|
||||
@@ -1817,7 +2121,8 @@ section for a description of
|
||||
.Li deregister_hooks .
|
||||
.It change_winsize
|
||||
.Bd -literal -compact
|
||||
int (*change_winsize)(unsigned int lines, unsigned int cols);
|
||||
int (*change_winsize)(unsigned int lines, unsigned int cols,
|
||||
const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
@@ -1829,24 +2134,76 @@ list.
|
||||
Returns \-1 if an error occurred, in which case no further calls to
|
||||
.Fn change_winsize
|
||||
will be made,
|
||||
.Pp
|
||||
The function arguments are as follows:
|
||||
.Bl -tag -width 4n
|
||||
.It lines
|
||||
The number of lines (rows) in the resized terminal.
|
||||
.It cols
|
||||
The number of columns in the resized terminal.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn change_winsize
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.El
|
||||
.It log_suspend
|
||||
.Bd -literal -compact
|
||||
int (*log_suspend)(int signo);
|
||||
int (*log_suspend)(int signo, const char **errstr);
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Fn log_suspend
|
||||
function is called whenever a command is suspended or resumed.
|
||||
The
|
||||
.Fa signo
|
||||
argument is either the signal that caused the command to be suspended or
|
||||
.Dv SIGCONT
|
||||
if the command was resumed.
|
||||
Logging this information makes it possible to skip the period of time when
|
||||
the command was suspended during playback of a session.
|
||||
Returns \-1 if an error occurred, in which case no further calls to
|
||||
.Fn log_suspend
|
||||
will be made,
|
||||
.Pp
|
||||
The function arguments are as follows:
|
||||
.Bl -tag -width 4n
|
||||
.It signo
|
||||
The signal that caused the command to be suspended, or
|
||||
.Dv SIGCONT
|
||||
if the command was resumed.
|
||||
.It errstr
|
||||
If the
|
||||
.Fn log_suspend
|
||||
function returns a value other than 1, the plugin may
|
||||
store a message describing the failure or error in
|
||||
.Em errstr .
|
||||
The
|
||||
.Nm sudo
|
||||
front end will then pass this value to any registered audit plugins.
|
||||
.Pp
|
||||
NOTE: the
|
||||
.Em errstr
|
||||
parameter is only available starting with
|
||||
API version 1.15.
|
||||
A plugin
|
||||
.Sy must
|
||||
check the API version specified by the
|
||||
.Nm sudo
|
||||
front end before using
|
||||
.Em errstr .
|
||||
Failure to do so may result in a crash.
|
||||
.It event_alloc
|
||||
.Bd -literal -compact
|
||||
struct sudo_plugin_event * (*event_alloc)(void);
|
||||
@@ -2930,6 +3287,13 @@ The
|
||||
field was added to the policy_plugin and io_plugin structs.
|
||||
.Pp
|
||||
The
|
||||
.Fa errstr
|
||||
argument was added to the policy and I/O plugin functions
|
||||
which the plugin function can use to return an error string.
|
||||
This string may be used by the audit plugin to report failure or
|
||||
error conditions set by the other plugins.
|
||||
.Pp
|
||||
The
|
||||
.Fn close
|
||||
function is now is called regardless of whether or not a command
|
||||
was actually executed.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2009-2018 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -162,17 +162,18 @@ struct policy_plugin {
|
||||
int (*open)(unsigned int version, sudo_conv_t conversation,
|
||||
sudo_printf_t sudo_printf, char * const settings[],
|
||||
char * const user_info[], char * const user_env[],
|
||||
char * const plugin_options[]);
|
||||
char * const plugin_options[], const char **errstr);
|
||||
void (*close)(int exit_status, int error); /* wait status or 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[]);
|
||||
char **argv_out[], char **user_env_out[], const char **errstr);
|
||||
int (*list)(int argc, char * const argv[], int verbose,
|
||||
const char *list_user);
|
||||
int (*validate)(void);
|
||||
const char *list_user, const char **errstr);
|
||||
int (*validate)(const char **errstr);
|
||||
void (*invalidate)(int remove);
|
||||
int (*init_session)(struct passwd *pwd, char **user_env_out[]);
|
||||
int (*init_session)(struct passwd *pwd, char **user_env_out[],
|
||||
const char **errstr);
|
||||
void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook));
|
||||
void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook));
|
||||
struct sudo_plugin_event * (*event_alloc)(void);
|
||||
@@ -187,19 +188,47 @@ struct io_plugin {
|
||||
sudo_printf_t sudo_printf, char * const settings[],
|
||||
char * const user_info[], char * const command_info[],
|
||||
int argc, char * const argv[], char * const user_env[],
|
||||
char * const plugin_options[]);
|
||||
char * const plugin_options[], const char **errstr);
|
||||
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);
|
||||
int (*log_ttyin)(const char *buf, unsigned int len, const char **errstr);
|
||||
int (*log_ttyout)(const char *buf, unsigned int len, const char **errstr);
|
||||
int (*log_stdin)(const char *buf, unsigned int len, const char **errstr);
|
||||
int (*log_stdout)(const char *buf, unsigned int len, const char **errstr);
|
||||
int (*log_stderr)(const char *buf, unsigned int len, const char **errstr);
|
||||
void (*register_hooks)(int version,
|
||||
int (*register_hook)(struct sudo_hook *hook));
|
||||
void (*deregister_hooks)(int version,
|
||||
int (*deregister_hook)(struct sudo_hook *hook));
|
||||
int (*change_winsize)(unsigned int line, unsigned int cols,
|
||||
const char **errstr);
|
||||
int (*log_suspend)(int signo, const char **errstr);
|
||||
struct sudo_plugin_event * (*event_alloc)(void);
|
||||
};
|
||||
|
||||
/* Audit plugin type and defines */
|
||||
struct audit_plugin {
|
||||
#define SUDO_AUDIT_PLUGIN 3
|
||||
unsigned int type; /* always SUDO_AUDIT_PLUGIN */
|
||||
unsigned int version; /* always SUDO_API_VERSION */
|
||||
int (*open)(unsigned int version, sudo_conv_t conversation,
|
||||
sudo_printf_t sudo_printf, char * const settings[],
|
||||
char * const user_info[], int submit_optind,
|
||||
char * const submit_argv[], char * const submit_envp[],
|
||||
char * const plugin_options[], const char **errstr);
|
||||
void (*close)(int exit_status, int error);
|
||||
int (*accept)(const char *plugin_name, unsigned int plugin_type,
|
||||
char * const command_info[], char * const run_argv[],
|
||||
char * const run_envp[], const char **errstr);
|
||||
int (*reject)(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *audit_msg, char * const command_info[],
|
||||
const char **errstr);
|
||||
int (*error)(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *audit_msg, char * const command_info[],
|
||||
const char **errstr);
|
||||
int (*show_version)(int verbose);
|
||||
void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook));
|
||||
void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook));
|
||||
int (*change_winsize)(unsigned int line, unsigned int cols);
|
||||
int (*log_suspend)(int signo);
|
||||
struct sudo_plugin_event * (*event_alloc)(void);
|
||||
};
|
||||
|
||||
/* Sudoers group plugin version major/minor */
|
||||
|
@@ -201,6 +201,7 @@ static bool
|
||||
log_ttyin(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
bool ret = true;
|
||||
debug_decl(log_ttyin, SUDO_DEBUG_EXEC);
|
||||
@@ -211,11 +212,17 @@ log_ttyin(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->log_ttyin(buf, n);
|
||||
rc = plugin->u.io->log_ttyin(buf, n, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->log_ttyin = NULL;
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("I/O plugin error"), NULL);
|
||||
} else {
|
||||
audit_reject(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by I/O plugin"),
|
||||
NULL);
|
||||
}
|
||||
ret = false;
|
||||
break;
|
||||
@@ -233,6 +240,7 @@ static bool
|
||||
log_stdin(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
bool ret = true;
|
||||
debug_decl(log_stdin, SUDO_DEBUG_EXEC);
|
||||
@@ -243,11 +251,17 @@ log_stdin(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->log_stdin(buf, n);
|
||||
rc = plugin->u.io->log_stdin(buf, n, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->log_stdin = NULL;
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("I/O plugin error"), NULL);
|
||||
} else {
|
||||
audit_reject(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by I/O plugin"),
|
||||
NULL);
|
||||
}
|
||||
ret = false;
|
||||
break;
|
||||
@@ -265,6 +279,7 @@ static bool
|
||||
log_ttyout(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
bool ret = true;
|
||||
debug_decl(log_ttyout, SUDO_DEBUG_EXEC);
|
||||
@@ -275,11 +290,17 @@ log_ttyout(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->log_ttyout(buf, n);
|
||||
rc = plugin->u.io->log_ttyout(buf, n, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->log_ttyout = NULL;
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("I/O plugin error"), NULL);
|
||||
} else {
|
||||
audit_reject(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by I/O plugin"),
|
||||
NULL);
|
||||
}
|
||||
ret = false;
|
||||
break;
|
||||
@@ -308,6 +329,7 @@ static bool
|
||||
log_stdout(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
bool ret = true;
|
||||
debug_decl(log_stdout, SUDO_DEBUG_EXEC);
|
||||
@@ -318,11 +340,17 @@ log_stdout(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->log_stdout(buf, n);
|
||||
rc = plugin->u.io->log_stdout(buf, n, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->log_stdout = NULL;
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("I/O plugin error"), NULL);
|
||||
} else {
|
||||
audit_reject(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by I/O plugin"),
|
||||
NULL);
|
||||
}
|
||||
ret = false;
|
||||
break;
|
||||
@@ -351,6 +379,7 @@ static bool
|
||||
log_stderr(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
bool ret = true;
|
||||
debug_decl(log_stderr, SUDO_DEBUG_EXEC);
|
||||
@@ -361,11 +390,17 @@ log_stderr(const char *buf, unsigned int n, struct io_buffer *iob)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->log_stderr(buf, n);
|
||||
rc = plugin->u.io->log_stderr(buf, n, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->log_stderr = NULL;
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("I/O plugin error"), NULL);
|
||||
} else {
|
||||
audit_reject(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by I/O plugin"),
|
||||
NULL);
|
||||
}
|
||||
ret = false;
|
||||
break;
|
||||
@@ -394,6 +429,7 @@ static void
|
||||
log_suspend(int signo)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
debug_decl(log_suspend, SUDO_DEBUG_EXEC);
|
||||
|
||||
@@ -405,12 +441,12 @@ log_suspend(int signo)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->log_suspend(signo);
|
||||
rc = plugin->u.io->log_suspend(signo, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->log_suspend = NULL;
|
||||
}
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("error logging suspend"), NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -426,6 +462,7 @@ static void
|
||||
log_winchange(unsigned int rows, unsigned int cols)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
sigset_t omask;
|
||||
debug_decl(log_winchange, SUDO_DEBUG_EXEC);
|
||||
|
||||
@@ -437,12 +474,12 @@ log_winchange(unsigned int rows, unsigned int cols)
|
||||
int rc;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
rc = plugin->u.io->change_winsize(rows, cols);
|
||||
rc = plugin->u.io->change_winsize(rows, cols, &errstr);
|
||||
if (rc <= 0) {
|
||||
if (rc < 0) {
|
||||
/* Error: disable plugin's I/O function. */
|
||||
plugin->u.io->change_winsize = NULL;
|
||||
}
|
||||
audit_error(plugin->name, SUDO_IO_PLUGIN,
|
||||
errstr ? errstr : _("error changing window size"), NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -242,7 +242,8 @@ cleanup:
|
||||
*/
|
||||
static bool
|
||||
sudo_load_plugin(struct plugin_container *policy_plugin,
|
||||
struct plugin_container_list *io_plugins, struct plugin_info *info)
|
||||
struct plugin_container_list *io_plugins,
|
||||
struct plugin_container_list *audit_plugins, struct plugin_info *info)
|
||||
{
|
||||
struct plugin_container *container = NULL;
|
||||
struct generic_plugin *plugin;
|
||||
@@ -315,6 +316,20 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
|
||||
goto done;
|
||||
TAILQ_INSERT_TAIL(io_plugins, container, entries);
|
||||
break;
|
||||
case SUDO_AUDIT_PLUGIN:
|
||||
if (plugin_exists(audit_plugins, info)) {
|
||||
plugin = sudo_plugin_try_to_clone(handle, info->symbol_name);
|
||||
if (plugin == NULL) {
|
||||
sudo_warnx(U_("ignoring duplicate audit plugin \"%s\" in %s, line %d"),
|
||||
info->symbol_name, _PATH_SUDO_CONF, info->lineno);
|
||||
ret = true;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if ((container = new_container(handle, path, plugin, info)) == NULL)
|
||||
goto done;
|
||||
TAILQ_INSERT_TAIL(audit_plugins, container, entries);
|
||||
break;
|
||||
default:
|
||||
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
|
||||
_PATH_SUDO_CONF, info->lineno, info->symbol_name);
|
||||
@@ -354,7 +369,8 @@ free_plugin_info(struct plugin_info *info)
|
||||
*/
|
||||
bool
|
||||
sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||
struct plugin_container_list *io_plugins)
|
||||
struct plugin_container_list *io_plugins,
|
||||
struct plugin_container_list *audit_plugins)
|
||||
{
|
||||
struct plugin_container *container;
|
||||
struct plugin_info_list *plugins;
|
||||
@@ -365,7 +381,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||
/* Walk the plugin list from sudo.conf, if any and free it. */
|
||||
plugins = sudo_conf_plugins();
|
||||
TAILQ_FOREACH_SAFE(info, plugins, entries, next) {
|
||||
ret = sudo_load_plugin(policy_plugin, io_plugins, info);
|
||||
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins, info);
|
||||
if (!ret)
|
||||
goto done;
|
||||
free_plugin_info(info);
|
||||
@@ -391,7 +407,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||
goto done;
|
||||
}
|
||||
/* info->options = NULL; */
|
||||
ret = sudo_load_plugin(policy_plugin, io_plugins, info);
|
||||
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins, info);
|
||||
free_plugin_info(info);
|
||||
if (!ret)
|
||||
goto done;
|
||||
@@ -411,7 +427,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||
goto done;
|
||||
}
|
||||
/* info->options = NULL; */
|
||||
ret = sudo_load_plugin(policy_plugin, io_plugins, info);
|
||||
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins, info);
|
||||
free_plugin_info(info);
|
||||
if (!ret)
|
||||
goto done;
|
||||
|
@@ -240,7 +240,7 @@ parse_env_list(struct environment *e, char *list)
|
||||
* for the command to be run (if we are running one).
|
||||
*/
|
||||
int
|
||||
parse_args(int argc, char **argv, int *nargc, char ***nargv,
|
||||
parse_args(int argc, char **argv, int *old_optind, int *nargc, char ***nargv,
|
||||
struct sudo_settings **settingsp, char ***env_addp)
|
||||
{
|
||||
struct environment extra_env;
|
||||
@@ -501,6 +501,7 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
*old_optind = optind;
|
||||
|
||||
if (!mode) {
|
||||
/* Defer -k mode setting until we know whether it is a flag or not */
|
||||
@@ -617,12 +618,29 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
|
||||
argc = ac;
|
||||
}
|
||||
|
||||
/*
|
||||
* For sudoedit we need to rewrite argv
|
||||
*/
|
||||
if (mode == MODE_EDIT) {
|
||||
#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
|
||||
char **av;
|
||||
int ac;
|
||||
|
||||
av = reallocarray(NULL, argc + 2, sizeof(char *));
|
||||
if (av == NULL)
|
||||
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
if (!gc_add(GC_PTR, av))
|
||||
exit(1);
|
||||
|
||||
/* Must have the command in argv[0]. */
|
||||
argc++;
|
||||
argv--;
|
||||
argv[0] = "sudoedit";
|
||||
av[0] = "sudoedit";
|
||||
for (ac = 0; argv[ac] != NULL; ac++) {
|
||||
av[ac + 1] = argv[ac];
|
||||
}
|
||||
av[++ac] = NULL;
|
||||
|
||||
argv = av;
|
||||
argc = ac;
|
||||
#else
|
||||
sudo_fatalx(U_("sudoedit is not supported on this platform"));
|
||||
#endif
|
||||
|
503
src/sudo.c
503
src/sudo.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2009-2019 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -75,6 +75,7 @@
|
||||
*/
|
||||
struct plugin_container policy_plugin;
|
||||
struct plugin_container_list io_plugins = TAILQ_HEAD_INITIALIZER(io_plugins);
|
||||
struct plugin_container_list audit_plugins = TAILQ_HEAD_INITIALIZER(audit_plugins);
|
||||
struct user_details user_details;
|
||||
const char *list_user; /* extern for parse_args.c */
|
||||
int sudo_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
|
||||
@@ -106,15 +107,15 @@ static void command_info_to_details(char * const info[],
|
||||
static void gc_init(void);
|
||||
|
||||
/* Policy plugin convenience functions. */
|
||||
static int policy_open(struct sudo_settings *settings,
|
||||
static void policy_open(struct sudo_settings *settings,
|
||||
char * const user_info[], char * const user_env[]);
|
||||
static void policy_close(int exit_status, int error);
|
||||
static int policy_show_version(int verbose);
|
||||
static int policy_check(int argc, char * const argv[], char *env_add[],
|
||||
static void policy_check(int argc, char * const argv[], char *env_add[],
|
||||
char **command_info[], char **argv_out[], char **user_env_out[]);
|
||||
static int policy_list(int argc, char * const argv[], int verbose,
|
||||
const char *list_user);
|
||||
static int policy_validate(void);
|
||||
static void policy_list(int argc, char * const argv[],
|
||||
int verbose, const char *list_user, char * const envp[]);
|
||||
static void policy_validate(char * const argv[], char * const envp[]);
|
||||
static void policy_invalidate(int remove);
|
||||
|
||||
/* I/O log plugin convenience functions. */
|
||||
@@ -125,18 +126,28 @@ static void iolog_close(int exit_status, int error);
|
||||
static void iolog_show_version(int verbose, struct sudo_settings *settings,
|
||||
char * const user_info[], int argc, char * const argv[],
|
||||
char * const user_env[]);
|
||||
static void iolog_unlink(struct plugin_container *plugin);
|
||||
static void unlink_plugin(struct plugin_container_list *plugin_list, struct plugin_container *plugin);
|
||||
static void free_plugin_container(struct plugin_container *plugin, bool ioplugin);
|
||||
|
||||
/* Audit plugin convenience functions. */
|
||||
static void audit_open(struct sudo_settings *settings, char * const user_info[],
|
||||
int submit_optind, char * const submit_argv[], char * const submit_envp[]);
|
||||
static void audit_close(int exit_status, int error);
|
||||
static void audit_show_version(int verbose);
|
||||
static void audit_accept(const char *plugin_name,
|
||||
unsigned int plugin_type, char * const command_info[],
|
||||
char * const run_argv[], char * const run_envp[]);
|
||||
|
||||
__dso_public int main(int argc, char *argv[], char *envp[]);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
int nargc, ok, status = 0;
|
||||
char **nargv, **env_add;
|
||||
char **user_info, **command_info, **argv_out, **user_env_out;
|
||||
int nargc, status = 0;
|
||||
char **nargv, **env_add, **user_info;
|
||||
char **command_info = NULL, **argv_out = NULL, **user_env_out = NULL;
|
||||
struct sudo_settings *settings;
|
||||
int submit_optind;
|
||||
sigset_t mask;
|
||||
debug_decl_vars(main, SUDO_DEBUG_MAIN);
|
||||
|
||||
@@ -194,7 +205,8 @@ main(int argc, char *argv[], char *envp[])
|
||||
disable_coredump();
|
||||
|
||||
/* Parse command line arguments. */
|
||||
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
|
||||
sudo_mode = parse_args(argc, argv, &submit_optind, &nargc, &nargv,
|
||||
&settings, &env_add);
|
||||
sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_mode %d", sudo_mode);
|
||||
|
||||
/* Print sudo version early, in case of plugin init failure. */
|
||||
@@ -208,54 +220,44 @@ main(int argc, char *argv[], char *envp[])
|
||||
sudo_warn_set_conversation(sudo_conversation);
|
||||
|
||||
/* Load plugins. */
|
||||
if (!sudo_load_plugins(&policy_plugin, &io_plugins))
|
||||
if (!sudo_load_plugins(&policy_plugin, &io_plugins, &audit_plugins))
|
||||
sudo_fatalx(U_("fatal error, unable to load plugins"));
|
||||
|
||||
/* Allocate event base so plugin can use it. */
|
||||
if ((sudo_event_base = sudo_ev_base_alloc()) == NULL)
|
||||
sudo_fatalx("%s", U_("unable to allocate memory"));
|
||||
|
||||
/* Open policy plugin. */
|
||||
ok = policy_open(settings, user_info, envp);
|
||||
if (ok != 1) {
|
||||
if (ok == -2)
|
||||
usage(1);
|
||||
else
|
||||
sudo_fatalx(U_("unable to initialize policy plugin"));
|
||||
}
|
||||
/* Open policy and audit plugins. */
|
||||
/* XXX - audit policy_open errors */
|
||||
audit_open(settings, user_info, submit_optind, argv, envp);
|
||||
policy_open(settings, user_info, envp);
|
||||
|
||||
switch (sudo_mode & MODE_MASK) {
|
||||
case MODE_VERSION:
|
||||
policy_show_version(!user_details.uid);
|
||||
iolog_show_version(!user_details.uid, settings, user_info,
|
||||
nargc, nargv, envp);
|
||||
audit_show_version(!user_details.uid);
|
||||
break;
|
||||
case MODE_VALIDATE:
|
||||
case MODE_VALIDATE|MODE_INVALIDATE:
|
||||
ok = policy_validate();
|
||||
exit(ok != 1);
|
||||
policy_validate(nargv, envp);
|
||||
break;
|
||||
case MODE_KILL:
|
||||
case MODE_INVALIDATE:
|
||||
policy_invalidate(sudo_mode == MODE_KILL);
|
||||
exit(0);
|
||||
break;
|
||||
case MODE_CHECK:
|
||||
case MODE_CHECK|MODE_INVALIDATE:
|
||||
case MODE_LIST:
|
||||
case MODE_LIST|MODE_INVALIDATE:
|
||||
ok = policy_list(nargc, nargv, ISSET(sudo_mode, MODE_LONG_LIST),
|
||||
list_user);
|
||||
exit(ok != 1);
|
||||
policy_list(nargc, nargv, ISSET(sudo_mode, MODE_LONG_LIST),
|
||||
list_user, envp);
|
||||
break;
|
||||
case MODE_EDIT:
|
||||
case MODE_RUN:
|
||||
ok = policy_check(nargc, nargv, env_add, &command_info, &argv_out,
|
||||
policy_check(nargc, nargv, env_add, &command_info, &argv_out,
|
||||
&user_env_out);
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "policy plugin returns %d", ok);
|
||||
if (ok != 1) {
|
||||
if (ok == -2)
|
||||
usage(1);
|
||||
exit(EXIT_FAILURE); /* plugin printed error message */
|
||||
}
|
||||
|
||||
/* Reset nargv/nargc based on argv_out. */
|
||||
/* XXX - leaks old nargv in shell mode */
|
||||
@@ -264,10 +266,14 @@ main(int argc, char *argv[], char *envp[])
|
||||
if (nargc == 0)
|
||||
sudo_fatalx(U_("plugin did not return a command to execute"));
|
||||
|
||||
/* Open I/O plugins once policy plugin succeeds. */
|
||||
/* Open I/O plugin once policy plugin succeeds. */
|
||||
iolog_open(settings, user_info, command_info, nargc, nargv,
|
||||
user_env_out);
|
||||
|
||||
/* Audit command we are going to run. */
|
||||
audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN, command_info,
|
||||
nargv, user_env_out);
|
||||
|
||||
/* Setup command details and run command/edit. */
|
||||
command_info_to_details(command_info, &command_details);
|
||||
command_details.tty = user_details.tty;
|
||||
@@ -941,6 +947,7 @@ run_command(struct command_details *details)
|
||||
/* exec_setup() or execve() returned an error. */
|
||||
policy_close(0, cstat.val);
|
||||
iolog_close(0, cstat.val);
|
||||
audit_close(0, cstat.val);
|
||||
break;
|
||||
case CMD_WSTATUS:
|
||||
/* Command ran, exited or was killed. */
|
||||
@@ -951,6 +958,7 @@ run_command(struct command_details *details)
|
||||
#endif
|
||||
policy_close(status, 0);
|
||||
iolog_close(status, 0);
|
||||
audit_close(status, 0);
|
||||
break;
|
||||
default:
|
||||
sudo_warnx(U_("unexpected child termination condition: %d"), cstat.type);
|
||||
@@ -1022,20 +1030,19 @@ bad:
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
policy_open(struct sudo_settings *settings, char * const user_info[],
|
||||
char * const user_env[])
|
||||
{
|
||||
char **plugin_settings;
|
||||
int ret;
|
||||
const char *errstr = NULL;
|
||||
int ok;
|
||||
debug_decl(policy_open, SUDO_DEBUG_PCOMM);
|
||||
|
||||
/* Convert struct sudo_settings to plugin_settings[] */
|
||||
plugin_settings = format_plugin_settings(&policy_plugin, settings);
|
||||
if (plugin_settings == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
debug_return_int(-1);
|
||||
}
|
||||
if (plugin_settings == NULL)
|
||||
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
|
||||
/*
|
||||
* Backwards compatibility for older API versions
|
||||
@@ -1044,21 +1051,30 @@ policy_open(struct sudo_settings *settings, char * const user_info[],
|
||||
switch (policy_plugin.u.generic->version) {
|
||||
case SUDO_API_MKVERSION(1, 0):
|
||||
case SUDO_API_MKVERSION(1, 1):
|
||||
ret = policy_plugin.u.policy_1_0->open(policy_plugin.u.io_1_0->version,
|
||||
ok = policy_plugin.u.policy_1_0->open(policy_plugin.u.io_1_0->version,
|
||||
sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
|
||||
user_info, user_env);
|
||||
break;
|
||||
default:
|
||||
ret = policy_plugin.u.policy->open(SUDO_API_VERSION, sudo_conversation,
|
||||
ok = policy_plugin.u.policy->open(SUDO_API_VERSION, sudo_conversation,
|
||||
sudo_conversation_printf, plugin_settings, user_info, user_env,
|
||||
policy_plugin.options);
|
||||
policy_plugin.options, &errstr);
|
||||
}
|
||||
|
||||
/* Stash plugin debug instance ID if set in open() function. */
|
||||
policy_plugin.debug_instance = sudo_debug_get_active_instance();
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
|
||||
debug_return_int(ret);
|
||||
if (ok != 1) {
|
||||
if (ok == -2)
|
||||
usage(1);
|
||||
else {
|
||||
/* XXX - audit */
|
||||
sudo_fatalx(U_("unable to initialize policy plugin"));
|
||||
}
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1083,33 +1099,35 @@ policy_close(int exit_status, int error_code)
|
||||
errno = error_code;
|
||||
sudo_warn(U_("unable to execute %s"), command_details.command);
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static int
|
||||
policy_show_version(int verbose)
|
||||
{
|
||||
int ret;
|
||||
int ret = true;
|
||||
debug_decl(policy_show_version, SUDO_DEBUG_PCOMM);
|
||||
|
||||
if (policy_plugin.u.policy->show_version == NULL)
|
||||
debug_return_int(true);
|
||||
sudo_debug_set_active_instance(policy_plugin.debug_instance);
|
||||
if (policy_plugin.u.policy->show_version != NULL)
|
||||
ret = policy_plugin.u.policy->show_version(verbose);
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15)) {
|
||||
if (policy_plugin.u.policy->close != NULL)
|
||||
policy_plugin.u.policy->close(0, 0);
|
||||
}
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
policy_check(int argc, char * const argv[],
|
||||
char *env_add[], char **command_info[], char **argv_out[],
|
||||
char **user_env_out[])
|
||||
{
|
||||
int ret;
|
||||
const char *errstr = NULL;
|
||||
int ok;
|
||||
debug_decl(policy_check, SUDO_DEBUG_PCOMM);
|
||||
|
||||
if (policy_plugin.u.policy->check_policy == NULL) {
|
||||
@@ -1117,65 +1135,132 @@ policy_check(int argc, char * const argv[],
|
||||
policy_plugin.name);
|
||||
}
|
||||
sudo_debug_set_active_instance(policy_plugin.debug_instance);
|
||||
ret = policy_plugin.u.policy->check_policy(argc, argv, env_add,
|
||||
command_info, argv_out, user_env_out);
|
||||
/* On success, the close method will be called by sudo_edit/run_command. */
|
||||
if (ret != 1) {
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15)) {
|
||||
if (policy_plugin.u.policy->close != NULL)
|
||||
policy_plugin.u.policy->close(0, 0);
|
||||
}
|
||||
}
|
||||
ok = policy_plugin.u.policy->check_policy(argc, argv, env_add,
|
||||
command_info, argv_out, user_env_out, &errstr);
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
debug_return_int(ret);
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "policy plugin returns %d (%s)",
|
||||
ok, errstr ? errstr : "");
|
||||
|
||||
/* On success, the close method will be called by sudo_edit/run_command. */
|
||||
if (ok != 1) {
|
||||
switch (ok) {
|
||||
case 0:
|
||||
audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by policy"),
|
||||
*command_info);
|
||||
break;
|
||||
case -1:
|
||||
audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
errstr ? errstr : _("policy plugin error"),
|
||||
*command_info);
|
||||
break;
|
||||
case -2:
|
||||
usage(1);
|
||||
break;
|
||||
}
|
||||
|
||||
static int
|
||||
policy_list(int argc, char * const argv[], int verbose, const char *list_user)
|
||||
/* Policy must be closed after auditing to avoid use after free. */
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
|
||||
policy_close(0, 0);
|
||||
exit(EXIT_FAILURE); /* policy plugin printed error message */
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static void
|
||||
policy_list(int argc, char * const argv[], int verbose,
|
||||
const char *list_user, char * const envp[])
|
||||
{
|
||||
int ret;
|
||||
const char *errstr = NULL;
|
||||
/* TODO: add list_user */
|
||||
char * const command_info[] = {
|
||||
"command=list",
|
||||
NULL
|
||||
};
|
||||
int ok;
|
||||
debug_decl(policy_list, SUDO_DEBUG_PCOMM);
|
||||
|
||||
if (policy_plugin.u.policy->list == NULL) {
|
||||
sudo_warnx(U_("policy plugin %s does not support listing privileges"),
|
||||
sudo_fatalx(U_("policy plugin %s does not support listing privileges"),
|
||||
policy_plugin.name);
|
||||
debug_return_int(false);
|
||||
}
|
||||
sudo_debug_set_active_instance(policy_plugin.debug_instance);
|
||||
ret = policy_plugin.u.policy->list(argc, argv, verbose, list_user);
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15)) {
|
||||
if (policy_plugin.u.policy->close != NULL)
|
||||
policy_plugin.u.policy->close(0, 0);
|
||||
}
|
||||
ok = policy_plugin.u.policy->list(argc, argv, verbose, list_user, &errstr);
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
debug_return_int(ret);
|
||||
|
||||
switch (ok) {
|
||||
case 1:
|
||||
audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
command_info, argv, envp);
|
||||
break;
|
||||
case 0:
|
||||
audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by policy"),
|
||||
command_info);
|
||||
break;
|
||||
default:
|
||||
audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
errstr ? errstr : _("policy plugin error"),
|
||||
command_info);
|
||||
break;
|
||||
}
|
||||
|
||||
static int
|
||||
policy_validate(void)
|
||||
/* Policy must be closed after auditing to avoid use after free. */
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
|
||||
policy_close(0, 0);
|
||||
|
||||
exit(ok != 1);
|
||||
}
|
||||
|
||||
static void
|
||||
policy_validate(char * const argv[], char * const envp[])
|
||||
{
|
||||
int ret;
|
||||
const char *errstr = NULL;
|
||||
char * const command_info[] = {
|
||||
"command=validate",
|
||||
NULL
|
||||
};
|
||||
int ok = 0;
|
||||
debug_decl(policy_validate, SUDO_DEBUG_PCOMM);
|
||||
|
||||
if (policy_plugin.u.policy->validate == NULL) {
|
||||
sudo_warnx(U_("policy plugin %s does not support the -v option"),
|
||||
sudo_fatalx(U_("policy plugin %s does not support the -v option"),
|
||||
policy_plugin.name);
|
||||
debug_return_int(false);
|
||||
}
|
||||
sudo_debug_set_active_instance(policy_plugin.debug_instance);
|
||||
ret = policy_plugin.u.policy->validate();
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15)) {
|
||||
if (policy_plugin.u.policy->close != NULL)
|
||||
policy_plugin.u.policy->close(0, 0);
|
||||
}
|
||||
ok = policy_plugin.u.policy->validate(&errstr);
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
debug_return_int(ret);
|
||||
|
||||
switch (ok) {
|
||||
case 1:
|
||||
audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN, command_info,
|
||||
argv, envp);
|
||||
break;
|
||||
case 0:
|
||||
audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
errstr ? errstr : _("command rejected by policy"),
|
||||
command_info);
|
||||
break;
|
||||
default:
|
||||
audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||
errstr ? errstr : _("policy plugin error"),
|
||||
command_info);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Policy must be closed after auditing to avoid use after free. */
|
||||
if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
|
||||
policy_close(0, 0);
|
||||
|
||||
exit(ok != 1);
|
||||
}
|
||||
|
||||
static void
|
||||
policy_invalidate(int remove)
|
||||
{
|
||||
debug_decl(policy_invalidate, SUDO_DEBUG_PCOMM);
|
||||
|
||||
if (policy_plugin.u.policy->invalidate == NULL) {
|
||||
sudo_fatalx(U_("policy plugin %s does not support the -k/-K options"),
|
||||
policy_plugin.name);
|
||||
@@ -1187,12 +1272,14 @@ policy_invalidate(int remove)
|
||||
policy_plugin.u.policy->close(0, 0);
|
||||
}
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
debug_return;
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
policy_init_session(struct command_details *details)
|
||||
{
|
||||
const char *errstr = NULL;
|
||||
int ret = true;
|
||||
debug_decl(policy_init_session, SUDO_DEBUG_PCOMM);
|
||||
|
||||
@@ -1223,9 +1310,10 @@ policy_init_session(struct command_details *details)
|
||||
break;
|
||||
default:
|
||||
ret = policy_plugin.u.policy->init_session(details->pw,
|
||||
&details->envp);
|
||||
&details->envp, &errstr);
|
||||
}
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
/* TODO: audit on error */
|
||||
}
|
||||
done:
|
||||
debug_return_int(ret);
|
||||
@@ -1234,7 +1322,7 @@ done:
|
||||
static int
|
||||
iolog_open_int(struct plugin_container *plugin, struct sudo_settings *settings,
|
||||
char * const user_info[], char * const command_info[],
|
||||
int argc, char * const argv[], char * const user_env[])
|
||||
int argc, char * const argv[], char * const user_env[], const char **errstr)
|
||||
{
|
||||
char **plugin_settings;
|
||||
int ret;
|
||||
@@ -1265,7 +1353,7 @@ iolog_open_int(struct plugin_container *plugin, struct sudo_settings *settings,
|
||||
default:
|
||||
ret = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
|
||||
sudo_conversation_printf, plugin_settings, user_info, command_info,
|
||||
argc, argv, user_env, plugin->options);
|
||||
argc, argv, user_env, plugin->options, errstr);
|
||||
}
|
||||
|
||||
/* Stash plugin debug instance ID if set in open() function. */
|
||||
@@ -1281,22 +1369,26 @@ iolog_open(struct sudo_settings *settings, char * const user_info[],
|
||||
char * const user_env[])
|
||||
{
|
||||
struct plugin_container *plugin, *next;
|
||||
const char *errstr = NULL;
|
||||
debug_decl(iolog_open, SUDO_DEBUG_PCOMM);
|
||||
|
||||
/* XXX - iolog_open should audit errors */
|
||||
TAILQ_FOREACH_SAFE(plugin, &io_plugins, entries, next) {
|
||||
int ok = iolog_open_int(plugin, settings, user_info,
|
||||
command_info, argc, argv, user_env);
|
||||
command_info, argc, argv, user_env, &errstr);
|
||||
switch (ok) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
/* I/O plugin asked to be disabled, remove and free. */
|
||||
iolog_unlink(plugin);
|
||||
/* XXX - audit */
|
||||
unlink_plugin(&io_plugins, plugin);
|
||||
break;
|
||||
case -2:
|
||||
usage(1);
|
||||
break;
|
||||
default:
|
||||
/* XXX - audit error */
|
||||
sudo_fatalx(U_("error initializing I/O plugin %s"),
|
||||
plugin->name);
|
||||
}
|
||||
@@ -1336,17 +1428,19 @@ iolog_show_version(int verbose, struct sudo_settings *settings,
|
||||
char * const user_info[], int argc, char * const argv[],
|
||||
char * const user_env[])
|
||||
{
|
||||
const char *errstr = NULL;
|
||||
struct plugin_container *plugin;
|
||||
debug_decl(iolog_show_version, SUDO_DEBUG_PCOMM);
|
||||
|
||||
TAILQ_FOREACH(plugin, &io_plugins, entries) {
|
||||
int ok = iolog_open_int(plugin, settings, user_info, NULL,
|
||||
argc, argv, user_env);
|
||||
argc, argv, user_env, &errstr);
|
||||
if (ok != -1) {
|
||||
if (plugin->u.io->show_version != NULL) {
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
if (plugin->u.io->show_version != NULL) {
|
||||
/* Return value of show_version currently ignored. */
|
||||
plugin->u.io->show_version(verbose);
|
||||
}
|
||||
if (plugin->u.io->version >= SUDO_API_MKVERSION(1, 15)) {
|
||||
if (plugin->u.io->close != NULL)
|
||||
plugin->u.io->close(0, 0);
|
||||
@@ -1354,32 +1448,239 @@ iolog_show_version(int verbose, struct sudo_settings *settings,
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the specified plugin from the plugins list.
|
||||
* Deregisters any hooks before unlinking, then frees the container.
|
||||
*/
|
||||
static void
|
||||
unlink_plugin(struct plugin_container_list *plugin_list,
|
||||
struct plugin_container *plugin)
|
||||
{
|
||||
void (*deregister_hooks)(int , int (*)(struct sudo_hook *)) = NULL;
|
||||
debug_decl(unlink_plugin, SUDO_DEBUG_PCOMM);
|
||||
|
||||
/* Deregister hooks, if any. */
|
||||
if (plugin->u.generic->version >= SUDO_API_MKVERSION(1, 2)) {
|
||||
switch (plugin->u.generic->type) {
|
||||
case SUDO_IO_PLUGIN:
|
||||
deregister_hooks = plugin->u.io->deregister_hooks;
|
||||
break;
|
||||
case SUDO_AUDIT_PLUGIN:
|
||||
deregister_hooks = plugin->u.audit->deregister_hooks;
|
||||
break;
|
||||
default:
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||
"%s: unsupported plugin type %d", __func__,
|
||||
plugin->u.generic->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (deregister_hooks != NULL) {
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
deregister_hooks(SUDO_HOOK_VERSION, deregister_hook);
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
|
||||
/* Remove from plugin list and free. */
|
||||
TAILQ_REMOVE(plugin_list, plugin, entries);
|
||||
free_plugin_container(plugin, true);
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static int
|
||||
audit_open_int(struct plugin_container *plugin, struct sudo_settings *settings,
|
||||
char * const user_info[], int submit_optind, char * const submit_argv[],
|
||||
char * const submit_envp[], const char **errstr)
|
||||
{
|
||||
char **plugin_settings;
|
||||
int ret;
|
||||
debug_decl(audit_open_int, SUDO_DEBUG_PCOMM);
|
||||
|
||||
/* Convert struct sudo_settings to plugin_settings[] */
|
||||
plugin_settings = format_plugin_settings(plugin, settings);
|
||||
if (plugin_settings == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
ret = plugin->u.audit->open(SUDO_API_VERSION, sudo_conversation,
|
||||
sudo_conversation_printf, plugin_settings, user_info,
|
||||
submit_optind, submit_argv, submit_envp, plugin->options, errstr);
|
||||
|
||||
/* Stash plugin debug instance ID if set in open() function. */
|
||||
plugin->debug_instance = sudo_debug_get_active_instance();
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
audit_open(struct sudo_settings *settings, char * const user_info[],
|
||||
int submit_optind, char * const submit_argv[], char * const submit_envp[])
|
||||
{
|
||||
struct plugin_container *plugin, *next;
|
||||
const char *errstr = NULL;
|
||||
debug_decl(audit_open, SUDO_DEBUG_PCOMM);
|
||||
|
||||
TAILQ_FOREACH_SAFE(plugin, &audit_plugins, entries, next) {
|
||||
int ok = audit_open_int(plugin, settings, user_info,
|
||||
submit_optind, submit_argv, submit_envp, &errstr);
|
||||
switch (ok) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
/* Audit plugin asked to be disabled, remove and free. */
|
||||
unlink_plugin(&audit_plugins, plugin);
|
||||
break;
|
||||
case -2:
|
||||
usage(1);
|
||||
break;
|
||||
default:
|
||||
/* TODO: pass error message to other audit plugins */
|
||||
sudo_fatalx(U_("error initializing audit plugin %s"),
|
||||
plugin->name);
|
||||
}
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static void
|
||||
audit_close(int exit_status, int error_code)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
debug_decl(audit_close, SUDO_DEBUG_PCOMM);
|
||||
|
||||
TAILQ_FOREACH(plugin, &audit_plugins, entries) {
|
||||
if (plugin->u.audit->close != NULL) {
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
plugin->u.audit->close(exit_status, error_code);
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static void
|
||||
audit_show_version(int verbose)
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
debug_decl(audit_show_version, SUDO_DEBUG_PCOMM);
|
||||
|
||||
TAILQ_FOREACH(plugin, &audit_plugins, entries) {
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
if (plugin->u.audit->show_version != NULL) {
|
||||
/* Return value of show_version currently ignored. */
|
||||
plugin->u.audit->show_version(verbose);
|
||||
}
|
||||
if (plugin->u.audit->close != NULL)
|
||||
plugin->u.audit->close(0, 0);
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the specified I/O logging plugin from the io_plugins list.
|
||||
* Deregisters any hooks before unlinking, then frees the container.
|
||||
* Command accepted by policy.
|
||||
* See command_info[] for additional info.
|
||||
* XXX - actual environment may be updated by policy_init_session().
|
||||
*/
|
||||
static void
|
||||
iolog_unlink(struct plugin_container *plugin)
|
||||
audit_accept(const char *plugin_name, unsigned int plugin_type,
|
||||
char * const command_info[], char * const run_argv[],
|
||||
char * const run_envp[])
|
||||
{
|
||||
debug_decl(iolog_unlink, SUDO_DEBUG_PCOMM);
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
int ok;
|
||||
debug_decl(audit_accept, SUDO_DEBUG_PCOMM);
|
||||
|
||||
/* XXX - kill command if can't audit accept event */
|
||||
TAILQ_FOREACH(plugin, &audit_plugins, entries) {
|
||||
if (plugin->u.audit->accept == NULL)
|
||||
continue;
|
||||
|
||||
/* Deregister hooks, if any. */
|
||||
if (plugin->u.io->version >= SUDO_API_MKVERSION(1, 2)) {
|
||||
if (plugin->u.io->deregister_hooks != NULL) {
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
plugin->u.io->deregister_hooks(SUDO_HOOK_VERSION,
|
||||
deregister_hook);
|
||||
ok = plugin->u.audit->accept(plugin_name, plugin_type,
|
||||
command_info, run_argv, run_envp, &errstr);
|
||||
if (ok != 1) {
|
||||
/* XXX - fatal error? log error with other audit modules? */
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||
"%s: plugin %s accept failed, ret %d", __func__,
|
||||
plugin->name, ok);
|
||||
}
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command rejected by policy or I/O plugin.
|
||||
*/
|
||||
void
|
||||
audit_reject(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *audit_msg, char * const command_info[])
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
int ok;
|
||||
debug_decl(audit_reject, SUDO_DEBUG_PCOMM);
|
||||
|
||||
TAILQ_FOREACH(plugin, &audit_plugins, entries) {
|
||||
if (plugin->u.audit->reject == NULL)
|
||||
continue;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
ok = plugin->u.audit->reject(plugin_name, plugin_type,
|
||||
audit_msg, command_info, &errstr);
|
||||
if (ok != 1) {
|
||||
/* TODO: notify other audit plugins of the error. */
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||
"%s: plugin %s reject failed, ret %d", __func__,
|
||||
plugin->name, ok);
|
||||
}
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Error from policy or I/O plugin.
|
||||
*/
|
||||
void
|
||||
audit_error(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *audit_msg, char * const command_info[])
|
||||
{
|
||||
struct plugin_container *plugin;
|
||||
const char *errstr = NULL;
|
||||
int ok;
|
||||
debug_decl(audit_error, SUDO_DEBUG_PCOMM);
|
||||
|
||||
TAILQ_FOREACH(plugin, &audit_plugins, entries) {
|
||||
if (plugin->u.audit->error == NULL)
|
||||
continue;
|
||||
|
||||
sudo_debug_set_active_instance(plugin->debug_instance);
|
||||
ok = plugin->u.audit->error(plugin_name, plugin_type,
|
||||
audit_msg, command_info, &errstr);
|
||||
if (ok != 1) {
|
||||
/* TODO: notify other audit plugins of the error. */
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||
"%s: plugin %s error failed, ret %d", __func__,
|
||||
plugin->name, ok);
|
||||
}
|
||||
sudo_debug_set_active_instance(sudo_debug_instance);
|
||||
}
|
||||
/* Remove from io_plugins list and free. */
|
||||
TAILQ_REMOVE(&io_plugins, plugin, entries);
|
||||
free_plugin_container(plugin, true);
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
@@ -207,8 +207,8 @@ char *tgetpass(const char *prompt, int timeout, int flags,
|
||||
int sudo_execute(struct command_details *details, struct command_status *cstat);
|
||||
|
||||
/* parse_args.c */
|
||||
int parse_args(int argc, char **argv, int *nargc, char ***nargv,
|
||||
struct sudo_settings **settingsp, char ***env_addp);
|
||||
int parse_args(int argc, char **argv, int *old_optind, int *nargc,
|
||||
char ***nargv, struct sudo_settings **settingsp, char ***env_addp);
|
||||
extern int tgetpass_flags;
|
||||
|
||||
/* get_pty.c */
|
||||
@@ -221,6 +221,10 @@ int os_init_common(int argc, char *argv[], char *envp[]);
|
||||
bool gc_add(enum sudo_gc_types type, void *v);
|
||||
bool set_user_groups(struct command_details *details);
|
||||
struct sudo_plugin_event *sudo_plugin_event_alloc(void);
|
||||
void audit_reject(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *audit_msg, char * const command_info[]);
|
||||
void audit_error(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *audit_msg, char * const command_info[]);
|
||||
extern const char *list_user;
|
||||
extern struct user_details user_details;
|
||||
extern int sudo_debug_instance;
|
||||
|
@@ -100,6 +100,7 @@ struct plugin_container {
|
||||
struct io_plugin *io;
|
||||
struct io_plugin_1_0 *io_1_0;
|
||||
struct io_plugin_1_1 *io_1_1;
|
||||
struct audit_plugin *audit;
|
||||
} u;
|
||||
};
|
||||
TAILQ_HEAD(plugin_container_list, plugin_container);
|
||||
@@ -117,6 +118,7 @@ struct sudo_plugin_event_int {
|
||||
|
||||
extern struct plugin_container policy_plugin;
|
||||
extern struct plugin_container_list io_plugins;
|
||||
extern struct plugin_container_list audit_plugins;
|
||||
|
||||
int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
|
||||
@@ -125,6 +127,7 @@ int sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
int sudo_conversation_printf(int msg_type, const char *fmt, ...);
|
||||
|
||||
bool sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||
struct plugin_container_list *io_plugins);
|
||||
struct plugin_container_list *io_plugins,
|
||||
struct plugin_container_list *audit_plugins);
|
||||
|
||||
#endif /* SUDO_PLUGIN_INT_H */
|
||||
|
Reference in New Issue
Block a user