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