Add support for "accept" audit events sent by the sudo front-end.

With this change, the sudo front-end will send an "accept" audit
event to the audit plugins after all the I/O logging plugins have
been initialized.  This can be used by an audit plugin that does
not care about the result of the individual policy and approval
plugins and only wants to receive a single "accept" event if all
policy and approval plugins have succeeded.  The plugin_type argument
for events sent by the front-end is SUDO_FRONT_END (0).
This commit is contained in:
Todd C. Miller
2020-06-02 09:07:44 -06:00
parent a380709215
commit f0dc48548c
8 changed files with 252 additions and 61 deletions

View File

@@ -16,7 +16,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.
.\" .\"
.TH "SUDO_PLUGIN" "5" "April 1, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .TH "SUDO_PLUGIN" "5" "May 26, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -2926,16 +2926,44 @@ int (*accept)(const char *plugin_name, unsigned int plugin_type,
.sp .sp
The The
\fBaccept\fR() \fBaccept\fR()
function is called when a command or action is accepted by the policy function is called when a command or action is accepted by a policy
plugin. or approval plugin.
The function arguments are as follows: The function arguments are as follows:
.TP 6n .TP 6n
plugin_name plugin_name
The name of the plugin that accepted the command. The name of the plugin that accepted the command or
\(lqsudo\(rq
for the
\fBsudo\fR
front-end.
.TP 6n .TP 6n
plugin_type plugin_type
The type of plugin that accepted the command, currently always The type of plugin that accepted the command, currently either
\fRSUDO_POLICY_PLUGIN\fR. \fRSUDO_POLICY_PLUGIN\fR,
\fRSUDO_POLICY_APPROVAL\fR
or
\fRSUDO_FRONT_END\fR.
The
\fBaccept\fR()
function is called multiple times--once for each policy or approval
plugin that succeeds and once for the sudo front-end.
When called on behalf of the sudo front-end,
\fIcommand_info\fR
may include information from an I/O logging plugin as well.
.sp
Typically, an audit plugin is interested in either the accept status from
the
\fBsudo\fR
front-end or from the various policy and approval plugins, but not both.
It is possible for the policy plugin to accept a command that is
later rejected by an approval plugin, in which case the audit
plugin's
\fBaccept\fR()
and
\fBreject\fR()
functions will
\fIboth\fR
be called.
.TP 6n .TP 6n
command_info command_info
A vector of information describing the command being run in the form of A vector of information describing the command being run in the form of
@@ -3025,13 +3053,22 @@ function is called when a command or action is rejected by a plugin.
The function arguments are as follows: The function arguments are as follows:
.TP 6n .TP 6n
plugin_name plugin_name
The name of the plugin that accepted the command. The name of the plugin that rejected the command.
.TP 6n .TP 6n
plugin_type plugin_type
The type of plugin that accepted the command, currently either The type of plugin that rejected the command, currently either
\fRSUDO_POLICY_PLUGIN\fR \fRSUDO_POLICY_PLUGIN\fR,
\fRSUDO_APPROVAL_PLUGIN\fR
or or
\fRSUDO_IO_PLUGIN\fR. \fRSUDO_IO_PLUGIN\fR.
.sp
Unlike the
\fBaccept\fR()
function, the
\fBreject\fR()
function is not called on behalf of the
\fBsudo\fR
front-end.
.TP 6n .TP 6n
audit_msg audit_msg
An optional string describing the reason the command was rejected An optional string describing the reason the command was rejected
@@ -3099,17 +3136,24 @@ int (*error)(const char *plugin_name, unsigned int plugin_type,
.sp .sp
The The
\fBerror\fR() \fBerror\fR()
function is called when a plugin returns an error. function is called when a plugin or the
\fBsudo\fR
front-end returns an error.
The function arguments are as follows: The function arguments are as follows:
.TP 6n .TP 6n
plugin_name plugin_name
The name of the plugin that accepted the command. The name of the plugin that generated the error or
\(lqsudo\(rq
for the
\fBsudo\fR
front-end.
.TP 6n .TP 6n
plugin_type plugin_type
The type of plugin that accepted the command, currently either The type of plugin that generated the error, or
\fRSUDO_POLICY_PLUGIN\fR \fRSUDO_FRONT_END\fR
or for the
\fRSUDO_IO_PLUGIN\fR. \fBsudo\fR
front-end.
.TP 6n .TP 6n
audit_msg audit_msg
An optional string describing the plugin error. An optional string describing the plugin error.

View File

@@ -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 April 1, 2020 .Dd May 26, 2020
.Dt SUDO_PLUGIN @mansectform@ .Dt SUDO_PLUGIN @mansectform@
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -2607,15 +2607,43 @@ int (*accept)(const char *plugin_name, unsigned int plugin_type,
.Pp .Pp
The The
.Fn accept .Fn accept
function is called when a command or action is accepted by the policy function is called when a command or action is accepted by a policy
plugin. or approval plugin.
The function arguments are as follows: The function arguments are as follows:
.Bl -tag -width 4n .Bl -tag -width 4n
.It plugin_name .It plugin_name
The name of the plugin that accepted the command. The name of the plugin that accepted the command or
.Dq sudo
for the
.Nm sudo
front-end.
.It plugin_type .It plugin_type
The type of plugin that accepted the command, currently always The type of plugin that accepted the command, currently either
.Dv SUDO_POLICY_PLUGIN . .Dv SUDO_POLICY_PLUGIN ,
.Dv SUDO_POLICY_APPROVAL
or
.Dv SUDO_FRONT_END .
The
.Fn accept
function is called multiple times--once for each policy or approval
plugin that succeeds and once for the sudo front-end.
When called on behalf of the sudo front-end,
.Fa command_info
may include information from an I/O logging plugin as well.
.Pp
Typically, an audit plugin is interested in either the accept status from
the
.Nm sudo
front-end or from the various policy and approval plugins, but not both.
It is possible for the policy plugin to accept a command that is
later rejected by an approval plugin, in which case the audit
plugin's
.Fn accept
and
.Fn reject
functions will
.Em both
be called.
.It command_info .It command_info
A vector of information describing the command being run in the form of A vector of information describing the command being run in the form of
.Dq name=value .Dq name=value
@@ -2694,12 +2722,21 @@ function is called when a command or action is rejected by a plugin.
The function arguments are as follows: The function arguments are as follows:
.Bl -tag -width 4n .Bl -tag -width 4n
.It plugin_name .It plugin_name
The name of the plugin that accepted the command. The name of the plugin that rejected the command.
.It plugin_type .It plugin_type
The type of plugin that accepted the command, currently either The type of plugin that rejected the command, currently either
.Dv SUDO_POLICY_PLUGIN .Dv SUDO_POLICY_PLUGIN ,
.Dv SUDO_APPROVAL_PLUGIN
or or
.Dv SUDO_IO_PLUGIN . .Dv SUDO_IO_PLUGIN .
.Pp
Unlike the
.Fn accept
function, the
.Fn reject
function is not called on behalf of the
.Nm sudo
front-end.
.It audit_msg .It audit_msg
An optional string describing the reason the command was rejected An optional string describing the reason the command was rejected
by the plugin. by the plugin.
@@ -2756,16 +2793,23 @@ int (*error)(const char *plugin_name, unsigned int plugin_type,
.Pp .Pp
The The
.Fn error .Fn error
function is called when a plugin returns an error. function is called when a plugin or the
.Nm sudo
front-end returns an error.
The function arguments are as follows: The function arguments are as follows:
.Bl -tag -width 4n .Bl -tag -width 4n
.It plugin_name .It plugin_name
The name of the plugin that accepted the command. The name of the plugin that generated the error or
.Dq sudo
for the
.Nm sudo
front-end.
.It plugin_type .It plugin_type
The type of plugin that accepted the command, currently either The type of plugin that generated the error, or
.Dv SUDO_POLICY_PLUGIN .Dv SUDO_FRONT_END
or for the
.Dv SUDO_IO_PLUGIN . .Nm sudo
front-end.
.It audit_msg .It audit_msg
An optional string describing the plugin error. An optional string describing the plugin error.
If the plugin did not provide a description, If the plugin did not provide a description,

View File

@@ -1008,16 +1008,44 @@ accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
.fi .fi
.RS 6n .RS 6n
.sp .sp
This function is called when a command or action is accepted by the policy This function is called when a command or action is accepted by a policy
plugin. or approval plugin.
The function arguments are as follows: The function arguments are as follows:
.TP 6n .TP 6n
plugin_name plugin_name
The name of the plugin that accepted the command. The name of the plugin that accepted the command or
\(lqsudo\(rq
for the
\fBsudo\fR
front-end.
.TP 6n .TP 6n
plugin_type plugin_type
The type of plugin that accepted the command, currently always The type of plugin that accepted the command, currently either
\fRsudo.PLUGIN_TYPE.POLICY\fR. \fRsudo.PLUGIN_TYPE.POLICY\fR,
\fRsudo.PLUGIN_TYPE.APPROVAL\fR
or
\fRsudo.PLUGIN_TYPE.SUDO\fR.
The
\fBaccept\fR()
function is called multiple times--once for each policy or approval
plugin that succeeds and once for the sudo front-end.
When called on behalf of the sudo front-end,
\fIcommand_info\fR
may include information from an I/O logging plugin as well.
.sp
Typically, an audit plugin is interested in either the accept status from
the
\fBsudo\fR
front-end or from the various policy and approval plugins, but not both.
It is possible for the policy plugin to accept a command that is
later rejected by an approval plugin, in which case the audit
plugin's
\fBaccept\fR()
and
\fBreject\fR()
functions will
\fIboth\fR
be called.
.TP 6n .TP 6n
command_info command_info
A vector of information describing the command being run. A vector of information describing the command being run.
@@ -1049,11 +1077,22 @@ plugin.
The function arguments are as follows: The function arguments are as follows:
.TP 6n .TP 6n
plugin_name plugin_name
The name of the plugin that accepted the command. The name of the plugin that rejected the command.
.TP 6n .TP 6n
plugin_type plugin_type
The type of plugin that accepted the command, currently always The type of plugin that rejected the command, currently either
\fRsudo.PLUGIN_TYPE.POLICY\fR. \fRsudo.PLUGIN_TYPE.POLICY\fR,
\fRsudo.PLUGIN_TYPE.APPROVAL\fR
or
\fRsudo.PLUGIN_TYPE.IO\fR.
.sp
Unlike the
\fBaccept\fR()
function, the
\fBreject\fR()
function is not called on behalf of the
\fBsudo\fR
front-end.
.TP 6n .TP 6n
audit_msg audit_msg
An optional string describing the reason the command was rejected by the plugin. An optional string describing the reason the command was rejected by the plugin.
@@ -1080,17 +1119,24 @@ error(self, plugin_name: str, plugin_type: int, audit_msg: str,
.fi .fi
.RS 6n .RS 6n
.sp .sp
This function is called when a plugin returns an error. This function is called when a plugin or the
\fBsudo\fR
front-end returns an error.
The function arguments are as follows: The function arguments are as follows:
.TP 6n .TP 6n
plugin_name plugin_name
The name of the plugin that accepted the command. The name of the plugin that generated the error or
\(lqsudo\(rq
for the
\fBsudo\fR
front-end.
.TP 6n .TP 6n
plugin_type plugin_type
The type of plugin that accepted the command, currently The type of plugin that generated the error, or
\fRsudo.PLUGIN_TYPE.POLICY\fR \fRSUDO_FRONT_END\fR
or for the
\fRsudo.PLUGIN_TYPE.IO\fR \fBsudo\fR
front-end.
.TP 6n .TP 6n
audit_msg audit_msg
An optional string describing the plugin error. An optional string describing the plugin error.

View File

@@ -804,15 +804,43 @@ accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int
.Ed .Ed
.Pp .Pp
This function is called when a command or action is accepted by the policy This function is called when a command or action is accepted by a policy
plugin. or approval plugin.
The function arguments are as follows: The function arguments are as follows:
.Bl -tag -width 4n .Bl -tag -width 4n
.It plugin_name .It plugin_name
The name of the plugin that accepted the command. The name of the plugin that accepted the command or
.Dq sudo
for the
.Nm sudo
front-end.
.It plugin_type .It plugin_type
The type of plugin that accepted the command, currently always The type of plugin that accepted the command, currently either
.Dv sudo.PLUGIN_TYPE.POLICY . .Dv sudo.PLUGIN_TYPE.POLICY ,
.Dv sudo.PLUGIN_TYPE.APPROVAL
or
.Dv sudo.PLUGIN_TYPE.SUDO .
The
.Fn accept
function is called multiple times--once for each policy or approval
plugin that succeeds and once for the sudo front-end.
When called on behalf of the sudo front-end,
.Fa command_info
may include information from an I/O logging plugin as well.
.Pp
Typically, an audit plugin is interested in either the accept status from
the
.Nm sudo
front-end or from the various policy and approval plugins, but not both.
It is possible for the policy plugin to accept a command that is
later rejected by an approval plugin, in which case the audit
plugin's
.Fn accept
and
.Fn reject
functions will
.Em both
be called.
.It command_info .It command_info
A vector of information describing the command being run. A vector of information describing the command being run.
See the See the
@@ -834,10 +862,21 @@ plugin.
The function arguments are as follows: The function arguments are as follows:
.Bl -tag -width 4n .Bl -tag -width 4n
.It plugin_name .It plugin_name
The name of the plugin that accepted the command. The name of the plugin that rejected the command.
.It plugin_type .It plugin_type
The type of plugin that accepted the command, currently always The type of plugin that rejected the command, currently either
.Dv sudo.PLUGIN_TYPE.POLICY . .Dv sudo.PLUGIN_TYPE.POLICY ,
.Dv sudo.PLUGIN_TYPE.APPROVAL
or
.Dv sudo.PLUGIN_TYPE.IO .
.Pp
Unlike the
.Fn accept
function, the
.Fn reject
function is not called on behalf of the
.Nm sudo
front-end.
.It audit_msg .It audit_msg
An optional string describing the reason the command was rejected by the plugin. An optional string describing the reason the command was rejected by the plugin.
If the plugin did not provide a reason, audit_msg will be If the plugin did not provide a reason, audit_msg will be
@@ -855,17 +894,23 @@ error(self, plugin_name: str, plugin_type: int, audit_msg: str,
command_info: Tuple[str, ...]) -> int command_info: Tuple[str, ...]) -> int
.Ed .Ed
.Pp .Pp
This function is called when a plugin returns an error. This function is called when a plugin or the
.Nm sudo
front-end returns an error.
The function arguments are as follows: The function arguments are as follows:
.Bl -tag -width 4n .Bl -tag -width 4n
.It plugin_name .It plugin_name
The name of the plugin that accepted the command. The name of the plugin that generated the error or
.Dq sudo
for the
.Nm sudo
front-end.
.It plugin_type .It plugin_type
The type of plugin that accepted the command, currently The type of plugin that generated the error, or
.Dv sudo.PLUGIN_TYPE.POLICY .Dv SUDO_FRONT_END
or for the
.Dv sudo.PLUGIN_TYPE.IO .Nm sudo
. front-end.
.It audit_msg .It audit_msg
An optional string describing the plugin error. An optional string describing the plugin error.
If the plugin did not provide a description, it will be If the plugin did not provide a description, it will be

View File

@@ -35,6 +35,9 @@
*(vp) = (*(vp) & 0xffff0000U) | (n); \ *(vp) = (*(vp) & 0xffff0000U) | (n); \
} while(0) } while(0)
/* "plugin type" for the sudo front end, as passed to an audit plugin */
#define SUDO_FRONT_END 0
/* Conversation function types and defines */ /* Conversation function types and defines */
struct sudo_conv_message { struct sudo_conv_message {
#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */

View File

@@ -514,7 +514,7 @@ audit_write_record(const char *audit_str, const char *plugin_name,
goto oom; goto oom;
switch (plugin_type) { switch (plugin_type) {
case 0: case SUDO_FRONT_END:
json_value.u.string = "front-end"; json_value.u.string = "front-end";
break; break;
case SUDO_POLICY_PLUGIN: case SUDO_POLICY_PLUGIN:
@@ -604,6 +604,10 @@ audit_json_accept(const char *plugin_name, unsigned int plugin_type,
int ret; int ret;
debug_decl(audit_json_accept, SUDO_DEBUG_PLUGIN); debug_decl(audit_json_accept, SUDO_DEBUG_PLUGIN);
/* Ignore the extra accept event from the sudo front-end. */
if (plugin_type == SUDO_FRONT_END)
debug_return_int(true);
state.accepted = true; state.accepted = true;
ret = audit_write_record("accept", plugin_name, plugin_type, NULL, ret = audit_write_record("accept", plugin_name, plugin_type, NULL,

View File

@@ -582,7 +582,8 @@ sudo_module_init(void)
{"POLICY", SUDO_POLICY_PLUGIN}, {"POLICY", SUDO_POLICY_PLUGIN},
{"AUDIT", SUDO_AUDIT_PLUGIN}, {"AUDIT", SUDO_AUDIT_PLUGIN},
{"IO", SUDO_IO_PLUGIN}, {"IO", SUDO_IO_PLUGIN},
{"APPROVAL", SUDO_APPROVAL_PLUGIN} {"APPROVAL", SUDO_APPROVAL_PLUGIN},
{"SUDO", SUDO_FRONT_END}
}; };
MODULE_REGISTER_ENUM("PLUGIN_TYPE", constants_plugin_types); MODULE_REGISTER_ENUM("PLUGIN_TYPE", constants_plugin_types);

View File

@@ -282,6 +282,10 @@ main(int argc, char *argv[], char *envp[])
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 the accept event on behalf of the sudo front-end. */
audit_accept("sudo", SUDO_FRONT_END, 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;