Change I/O log API to pass in command info to the I/O log open function.

Add iolog_file and iolog_dir parameters to command info.
This allows the policy plugin to specify the I/O log pathname.
Add convenience functions for calling plugin functions that
handle ABI backwards compatibility.
This commit is contained in:
Todd C. Miller
2010-12-20 16:20:11 -05:00
parent 30797ab8ae
commit 9948dae706
4 changed files with 93 additions and 14 deletions

View File

@@ -19,8 +19,9 @@
/* API version major/minor */
#define SUDO_API_VERSION_MAJOR 1
#define SUDO_API_VERSION_MINOR 0
#define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | SUDO_API_VERSION_MINOR)
#define SUDO_API_VERSION_MINOR 1
#define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR)
/* Getters and setters for API version */
#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
@@ -81,8 +82,8 @@ struct io_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 argc, char * const argv[],
char * const user_env[]);
char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[]);
void (*close)(int exit_status, int error); /* wait status or error */
int (*show_version)(int verbose);
int (*log_ttyin)(const char *buf, unsigned int len);

View File

@@ -108,6 +108,15 @@ static void disable_coredumps(void);
static char **get_user_info(struct user_details *);
static void command_info_to_details(char * const info[],
struct command_details *details);
static int policy_open(struct plugin_container *plugin, char * const settings[],
char * const user_info[], char * const user_env[]);
static void policy_close(struct plugin_container *plugin, int exit_status,
int error);
static int iolog_open(struct plugin_container *plugin, char * const settings[],
char * const user_info[], char * const command_details[],
int argc, char * const argv[], char * const user_env[]);
static void iolog_close(struct plugin_container *plugin, int exit_status,
int error);
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
static struct rlimit corelimit;
@@ -168,8 +177,7 @@ main(int argc, char *argv[], char *envp[])
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
/* Open policy plugin. */
ok = policy_plugin.u.policy->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, envp);
ok = policy_open(&policy_plugin, settings, user_info, envp);
if (ok != TRUE) {
if (ok == -2)
usage(1);
@@ -185,8 +193,8 @@ main(int argc, char *argv[], char *envp[])
(void) printf("Configure args: %s\n", CONFIGURE_ARGS);
policy_plugin.u.policy->show_version(!user_details.uid);
tq_foreach_fwd(&io_plugins, plugin) {
ok = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, nargc, nargv, envp);
ok = iolog_open(plugin, settings, user_info, NULL,
nargc, nargv, envp);
if (ok == TRUE)
plugin->u.io->show_version(user_details.uid == ROOT_UID);
}
@@ -237,8 +245,8 @@ main(int argc, char *argv[], char *envp[])
/* Open I/O plugins once policy plugin succeeds. */
for (plugin = io_plugins.first; plugin != NULL; plugin = next) {
next = plugin->next;
ok = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, nargc, nargv, envp);
ok = iolog_open(plugin, settings, user_info,
command_info, nargc, nargv, envp);
switch (ok) {
case TRUE:
break;
@@ -451,6 +459,10 @@ command_info_to_details(char * const info[], struct command_details *details)
break;
}
break;
case 'i':
SET_STRING("iolog_dir=", iolog_dir)
SET_STRING("iolog_file=", iolog_file)
break;
case 'l':
SET_STRING("login_class=", login_class)
break;
@@ -905,20 +917,20 @@ run_command(struct command_details *details, char *argv[], char *envp[])
case CMD_ERRNO:
/* exec_setup() or execve() returned an error. */
sudo_debug(9, "calling policy close with errno");
policy_plugin.u.policy->close(0, cstat.val);
policy_close(&policy_plugin, 0, cstat.val);
tq_foreach_fwd(&io_plugins, plugin) {
sudo_debug(9, "calling I/O close with errno");
plugin->u.io->close(0, cstat.val);
iolog_close(plugin, 0, cstat.val);
}
exitcode = 1;
break;
case CMD_WSTATUS:
/* Command ran, exited or was killed. */
sudo_debug(9, "calling policy close with wait status");
policy_plugin.u.policy->close(cstat.val, 0);
policy_close(&policy_plugin, cstat.val, 0);
tq_foreach_fwd(&io_plugins, plugin) {
sudo_debug(9, "calling I/O close with wait status");
plugin->u.io->close(cstat.val, 0);
iolog_close(plugin, cstat.val, 0);
}
if (WIFEXITED(cstat.val))
exitcode = WEXITSTATUS(cstat.val);
@@ -932,6 +944,50 @@ run_command(struct command_details *details, char *argv[], char *envp[])
return exitcode;
}
static int
policy_open(struct plugin_container *plugin, char * const settings[],
char * const user_info[], char * const user_env[])
{
return plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, user_env);
}
static void
policy_close(struct plugin_container *plugin, int exit_status, int error)
{
plugin->u.policy->close(exit_status, error);
}
static int
iolog_open(struct plugin_container *plugin, char * const settings[],
char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[])
{
int rval;
/*
* Backwards compatibility for API major 1, minor 0
*/
switch (plugin->u.generic->version) {
case SUDO_API_MKVERSION(1, 0):
rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version,
sudo_conversation, _sudo_printf, settings, user_info, argc, argv,
user_env);
break;
default:
rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
_sudo_printf, settings, user_info, command_info, argc, argv,
user_env);
}
return rval;
}
static void
iolog_close(struct plugin_container *plugin, int exit_status, int error)
{
plugin->u.io->close(exit_status, error);
}
/*
* Simple debugging/logging.
*/

View File

@@ -138,6 +138,8 @@ struct command_details {
const char *chroot;
const char *selinux_role;
const char *selinux_type;
const char *iolog_dir;
const char *iolog_file;
};
/* Status passed between parent and child via socketpair */

View File

@@ -17,6 +17,25 @@
#ifndef _SUDO_PLUGIN_INT_H
#define _SUDO_PLUGIN_INT_H
/*
* Backwards-compatible structures for API bumps.
*/
struct io_plugin_1_0 {
unsigned int type;
unsigned int version;
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], int argc, char * const argv[],
char * const user_env[]);
void (*close)(int exit_status, int error);
int (*show_version)(int verbose);
int (*log_ttyin)(const char *buf, unsigned int len);
int (*log_ttyout)(const char *buf, unsigned int len);
int (*log_stdin)(const char *buf, unsigned int len);
int (*log_stdout)(const char *buf, unsigned int len);
int (*log_stderr)(const char *buf, unsigned int len);
};
/*
* Sudo plugin internals.
*/
@@ -38,6 +57,7 @@ struct plugin_container {
struct generic_plugin *generic;
struct policy_plugin *policy;
struct io_plugin *io;
struct io_plugin_1_0 *io_1_0;
} u;
};
TQ_DECLARE(plugin_container)