Load the sudoers module as an audit plugin if loaded as a policy plugin.

Now that logging of successful commands is performed by sudoers as an
audit plugin we need to load sudoers_audit if sudoers_policy is also
loaded.  Otherwise, accpted commands will not be logged.
This commit is contained in:
Todd C. Miller
2020-06-02 14:54:04 -06:00
parent b519481912
commit 253e041d3b
3 changed files with 157 additions and 72 deletions

View File

@@ -2,7 +2,7 @@
.\"
.\" SPDX-License-Identifier: ISC
.\"
.\" Copyright (c) 2010-2019 Todd C. Miller <Todd.Miller@sudo.ws>
.\" Copyright (c) 2010-2020 Todd C. Miller <Todd.Miller@sudo.ws>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -17,7 +17,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.nr SL @SEMAN@
.TH "SUDO.CONF" "@mansectform@" "October 20, 2019" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDO.CONF" "@mansectform@" "June 1, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -105,10 +105,15 @@ to the dynamic shared object that contains the plugin.
The
\fIsymbol_name\fR
is the name of the
\fRstruct policy_plugin\fR
\fRapproval_plugin\fR,
\fRaudit_plugin\fR,
\fRio_plugin\fR,
or
\fRstruct io_plugin\fR
symbol contained in the plugin.
\fRpolicy_plugin\fR
struct contained in the plugin.
If a plugin implements multiple plugin types, there must be a
\fRPlugin\fR
line for each unique symbol name.
The
\fIpath\fR
may be fully qualified or relative.
@@ -180,17 +185,35 @@ file is present, or if it contains no
\fRPlugin\fR
lines, the
\fBsudoers\fR
plugin will be used as the default security policy and for I/O logging
(if enabled by the policy).
plugin will be used as the default security policy, for I/O logging
(if enabled by the policy) and for auditing.
This is equivalent to the following:
.nf
.sp
.RS 6n
Plugin sudoers_policy sudoers.so
Plugin sudoers_io sudoers.so
Plugin sudoers_audit sudoers.so
.RE
.fi
.PP
Starting with
\fBsudo\fR
version 1.9.1, some of the logging functionality of the
\fBsudoers\fR
plugin has been moved from the policy plugin to an audit plugin.
To maintain compatibility with
\fBsudo.conf\fR
files from older
\fBsudo\fR
versions, if
\fBsudoers\fR
is configured as the security policy, it will be used as an audit
plugin as well.
This guarantees that the logging behavior will be consistnet with that of
\fBsudo\fR
versions 1.9.0 and below.
.PP
For more information on the
\fBsudo\fR
plugin architecture, see the
@@ -687,6 +710,7 @@ front end configuration
# The sudoers plugin is used by default if no Plugin lines are present.
Plugin sudoers_policy sudoers.so
Plugin sudoers_io sudoers.so
Plugin sudoers_audit sudoers.so
#
# Sudo askpass:

View File

@@ -1,7 +1,7 @@
.\"
.\" SPDX-License-Identifier: ISC
.\"
.\" Copyright (c) 2010-2019 Todd C. Miller <Todd.Miller@sudo.ws>
.\" Copyright (c) 2010-2020 Todd C. Miller <Todd.Miller@sudo.ws>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -16,7 +16,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.nr SL @SEMAN@
.Dd October 20, 2019
.Dd June 1, 2020
.Dt SUDO.CONF @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -102,10 +102,15 @@ to the dynamic shared object that contains the plugin.
The
.Em symbol_name
is the name of the
.Li struct policy_plugin
.Li approval_plugin ,
.Li audit_plugin ,
.Li io_plugin ,
or
.Li struct io_plugin
symbol contained in the plugin.
.Li policy_plugin
struct contained in the plugin.
If a plugin implements multiple plugin types, there must be a
.Li Plugin
line for each unique symbol name.
The
.Em path
may be fully qualified or relative.
@@ -165,14 +170,32 @@ file is present, or if it contains no
.Li Plugin
lines, the
.Nm sudoers
plugin will be used as the default security policy and for I/O logging
(if enabled by the policy).
plugin will be used as the default security policy, for I/O logging
(if enabled by the policy) and for auditing.
This is equivalent to the following:
.Bd -literal -offset indent
Plugin sudoers_policy sudoers.so
Plugin sudoers_io sudoers.so
Plugin sudoers_audit sudoers.so
.Ed
.Pp
Starting with
.Nm sudo
version 1.9.1, some of the logging functionality of the
.Nm sudoers
plugin has been moved from the policy plugin to an audit plugin.
To maintain compatibility with
.Nm
files from older
.Nm sudo
versions, if
.Nm sudoers
is configured as the security policy, it will be used as an audit
plugin as well.
This guarantees that the logging behavior will be consistnet with that of
.Nm sudo
versions 1.9.0 and below.
.Pp
For more information on the
.Nm sudo
plugin architecture, see the
@@ -621,6 +644,7 @@ front end configuration
# The sudoers plugin is used by default if no Plugin lines are present.
Plugin sudoers_policy sudoers.so
Plugin sudoers_io sudoers.so
Plugin sudoers_audit sudoers.so
#
# Sudo askpass:

View File

@@ -198,13 +198,13 @@ bad:
}
static bool
plugin_exists(struct plugin_container_list *plugins, struct plugin_info *info)
plugin_exists(struct plugin_container_list *plugins, const char *symbol_name)
{
struct plugin_container *container;
debug_decl(find_plugin, SUDO_DEBUG_PLUGIN);
TAILQ_FOREACH(container, plugins, entries) {
if (strcmp(container->name, info->symbol_name) == 0)
if (strcmp(container->name, symbol_name) == 0)
debug_return_bool(true);
}
debug_return_bool(false);
@@ -241,7 +241,7 @@ sudo_insert_plugin(struct plugin_container_list *plugin_list, void *handle,
struct plugin_container *container;
debug_decl(sudo_insert_plugin, SUDO_DEBUG_PLUGIN);
if (plugin_exists(plugin_list, info)) {
if (plugin_exists(plugin_list, info->symbol_name)) {
plugin = sudo_plugin_try_to_clone(handle, info->symbol_name);
if (plugin == NULL) {
sudo_warnx(U_("ignoring duplicate plugin \"%s\" in %s, line %d"),
@@ -267,7 +267,7 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
struct plugin_container_list *io_plugins,
struct plugin_container_list *audit_plugins,
struct plugin_container_list *approval_plugins,
struct plugin_info *info)
struct plugin_info *info, bool quiet)
{
struct generic_plugin *plugin;
char path[PATH_MAX];
@@ -282,27 +282,34 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
/* Open plugin and map in symbol */
handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
if (!handle) {
if (!quiet) {
const char *errstr = sudo_dso_strerror();
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
_PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("unable to load %s: %s"), path,
errstr ? errstr : "unknown error");
}
goto done;
}
plugin = sudo_dso_findsym(handle, info->symbol_name);
if (!plugin) {
if (!quiet) {
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
_PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), info->symbol_name, path);
sudo_warnx(U_("unable to find symbol \"%s\" in %s"),
info->symbol_name, path);
}
goto done;
}
if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) {
if (!quiet) {
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
_PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("incompatible plugin major version %d (expected %d) found in %s"),
SUDO_API_VERSION_GET_MAJOR(plugin->version),
SUDO_API_VERSION_MAJOR, path);
}
goto done;
}
@@ -311,12 +318,16 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
if (policy_plugin->handle != NULL) {
/* Ignore duplicate entries. */
if (strcmp(policy_plugin->name, info->symbol_name) == 0) {
if (!quiet) {
sudo_warnx(U_("ignoring duplicate plugin \"%s\" in %s, line %d"),
info->symbol_name, _PATH_SUDO_CONF, info->lineno);
}
} else {
if (!quiet) {
sudo_warnx(U_("ignoring policy plugin \"%s\" in %s, line %d"),
info->symbol_name, _PATH_SUDO_CONF, info->lineno);
sudo_warnx(U_("only a single policy plugin may be specified"));
}
goto done;
}
ret = true;
@@ -338,9 +349,11 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
goto done;
break;
default:
if (!quiet) {
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
_PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("unknown plugin type %d found in %s"), plugin->type, path);
}
goto done;
}
@@ -427,6 +440,44 @@ sudo_init_event_alloc(struct plugin_container *policy_plugin,
debug_return;
}
/*
* Load the specified symbol from the sudoers plugin.
* Used to provide a default plugin when none are specified in sudo.conf.
*/
bool
sudo_load_sudoers_plugin(const char *symbol_name,
struct plugin_container *policy_plugin,
struct plugin_container_list *io_plugins,
struct plugin_container_list *audit_plugins,
struct plugin_container_list *approval_plugins,
bool optional)
{
struct plugin_info *info;
bool ret = false;
debug_decl(sudo_load_sudoers_plugin, SUDO_DEBUG_PLUGIN);
/* Default policy plugin */
info = calloc(1, sizeof(*info));
if (info == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto done;
}
info->symbol_name = strdup(symbol_name);
info->path = strdup(SUDOERS_PLUGIN);
if (info->symbol_name == NULL || info->path == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
free_plugin_info(info);
goto done;
}
/* info->options = NULL; */
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins,
approval_plugins, info, optional);
free_plugin_info(info);
done:
debug_return_bool(ret);
}
/*
* Load the plugins listed in sudo.conf.
*/
@@ -445,7 +496,7 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
plugins = sudo_conf_plugins();
TAILQ_FOREACH_SAFE(info, plugins, entries, next) {
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins,
approval_plugins, info);
approval_plugins, info, false);
if (!ret)
goto done;
free_plugin_info(info);
@@ -458,47 +509,33 @@ sudo_load_plugins(struct plugin_container *policy_plugin,
*/
if (policy_plugin->handle == NULL) {
/* Default policy plugin */
info = calloc(1, sizeof(*info));
if (info == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto done;
}
info->symbol_name = strdup("sudoers_policy");
info->path = strdup(SUDOERS_PLUGIN);
if (info->symbol_name == NULL || info->path == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
free_plugin_info(info);
goto done;
}
/* info->options = NULL; */
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins,
approval_plugins, info);
free_plugin_info(info);
ret = sudo_load_sudoers_plugin("sudoers_policy", policy_plugin,
io_plugins, audit_plugins, approval_plugins, false);
if (!ret)
goto done;
/* Default audit plugin, optional (sudoers < 1.9.1 lack this) */
(void)sudo_load_sudoers_plugin("sudoers_audit", policy_plugin,
io_plugins, audit_plugins, approval_plugins, true);
/* Default I/O plugin */
if (TAILQ_EMPTY(io_plugins)) {
info = calloc(1, sizeof(*info));
if (info == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto done;
}
info->symbol_name = strdup("sudoers_io");
info->path = strdup(SUDOERS_PLUGIN);
if (info->symbol_name == NULL || info->path == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
free_plugin_info(info);
goto done;
}
/* info->options = NULL; */
ret = sudo_load_plugin(policy_plugin, io_plugins, audit_plugins,
approval_plugins, info);
free_plugin_info(info);
ret = sudo_load_sudoers_plugin("sudoers_io", policy_plugin,
io_plugins, audit_plugins, approval_plugins, false);
if (!ret)
goto done;
}
} else if (strcmp(policy_plugin->name, "sudoers_policy") == 0) {
/*
* If policy plugin is sudoers_policy but there is no sudoers_audit
* loaded, load it too, if possible.
*/
if (!plugin_exists(audit_plugins, "sudoers_audit")) {
(void)sudo_load_sudoers_plugin("sudoers_audit", policy_plugin,
io_plugins, audit_plugins, approval_plugins, true);
}
}
/* TODO: check all plugins for open function too */
if (policy_plugin->u.policy->check_policy == NULL) {
sudo_warnx(U_("policy plugin %s does not include a check_policy method"),