diff --git a/src/parse_args.c b/src/parse_args.c index a2e065fe0..f80896675 100644 --- a/src/parse_args.c +++ b/src/parse_args.c @@ -65,10 +65,7 @@ static void usage_excl(int); /* * Mapping of command line flags to name/value settings. */ -static struct sudo_settings { - const char *name; - const char *value; -} sudo_settings[] = { +static struct sudo_settings sudo_settings[] = { #define ARG_BSDAUTH_TYPE 0 { "bsdauth_type" }, #define ARG_LOGIN_CLASS 1 @@ -169,14 +166,14 @@ static struct option long_opts[] = { * for the command to be run (if we are running one). */ int -parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp, - char ***env_addp) +parse_args(int argc, char **argv, int *nargc, char ***nargv, + struct sudo_settings **settingsp, char ***env_addp) { int mode = 0; /* what mode is sudo to be run in? */ int flags = 0; /* mode flags */ int valid_flags = DEFAULT_VALID_FLAGS; - int ch, i, j; - char *cp, **env_add, **settings; + int ch, i; + char *cp, **env_add; const char *runas_user = NULL; const char *runas_group = NULL; const char *debug_flags; @@ -449,6 +446,9 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp, SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL)); sudo_settings[ARG_IMPLIED_SHELL].value = "true"; } +#ifdef _PATH_SUDO_PLUGIN_DIR + sudo_settings[ARG_PLUGIN_DIR].value = sudo_conf_plugin_dir_path(); +#endif if (mode == MODE_HELP) help(); @@ -495,26 +495,6 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp, argc = ac; } - /* - * Format setting_pairs into settings array. - */ -#ifdef _PATH_SUDO_PLUGIN_DIR - sudo_settings[ARG_PLUGIN_DIR].value = sudo_conf_plugin_dir_path(); -#endif - settings = sudo_emallocarray(NUM_SETTINGS + 1, sizeof(char *)); - for (i = 0, j = 0; i < NUM_SETTINGS; i++) { - if (sudo_settings[i].value) { - sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s=%s", - sudo_settings[i].name, sudo_settings[i].value); - settings[j] = sudo_new_key_val(sudo_settings[i].name, - sudo_settings[i].value); - if (settings[j] == NULL) - sudo_fatal(NULL); - j++; - } - } - settings[j] = NULL; - if (mode == MODE_EDIT) { #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) /* Must have the command in argv[0]. */ @@ -526,7 +506,7 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp, #endif } - *settingsp = settings; + *settingsp = sudo_settings; *env_addp = env_add; *nargc = argc; *nargv = argv; diff --git a/src/sudo.c b/src/sudo.c index ee306774a..85a889fd6 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -109,7 +109,8 @@ static void command_info_to_details(char * const info[], struct command_details *details); /* Policy plugin convenience functions. */ -static int policy_open(struct plugin_container *plugin, char * const settings[], +static int policy_open(struct plugin_container *plugin, + struct sudo_settings *settings, char * const user_info[], char * const user_env[]); static void policy_close(struct plugin_container *plugin, int exit_status, int error); @@ -123,9 +124,10 @@ static int policy_validate(struct plugin_container *plugin); static void policy_invalidate(struct plugin_container *plugin, int remove); /* I/O log plugin convenience functions. */ -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 int iolog_open(struct plugin_container *plugin, + struct sudo_settings *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); static int iolog_show_version(struct plugin_container *plugin, int verbose); @@ -144,8 +146,9 @@ int main(int argc, char *argv[], char *envp[]) { int nargc, ok, exitcode = 0; - char **nargv, **settings, **env_add; + char **nargv, **env_add; char **user_info, **command_info, **argv_out, **user_env_out; + struct sudo_settings *settings; struct plugin_container *plugin, *next; sigset_t mask; debug_decl(main, SUDO_DEBUG_MAIN) @@ -1075,13 +1078,55 @@ run_command(struct command_details *details) debug_return_int(exitcode); } +/* + * Format struct sudo_settings as name=value pairs for the plugin + * to consume. Returns a NULL-terminated plugin-style array of pairs. + */ +static char ** +format_plugin_settings(struct plugin_container *plugin, + struct sudo_settings *settings) +{ + char **plugin_settings; + size_t plugin_settings_size = 32, num_plugin_settings = 0; + debug_decl(format_plugin_settings, SUDO_DEBUG_PCOMM) + + plugin_settings = sudo_emallocarray(plugin_settings_size, sizeof(char *)); + while (settings->name != NULL) { + if (settings->value != NULL) { + sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s=%s", + settings->name, settings->value); + /* Expand plugin_settings as needed. */ + if (num_plugin_settings == plugin_settings_size) { + plugin_settings_size *= 2; + plugin_settings = sudo_ereallocarray(plugin_settings, + plugin_settings_size, sizeof(char *)); + } + plugin_settings[num_plugin_settings] = + sudo_new_key_val(settings->name, settings->value); + if (plugin_settings[num_plugin_settings] == NULL) + sudo_fatal(NULL); + num_plugin_settings++; + } + settings++; + } + plugin_settings[num_plugin_settings] = NULL; + + debug_return_ptr(plugin_settings); +} + static int -policy_open(struct plugin_container *plugin, char * const settings[], +policy_open(struct plugin_container *plugin, struct sudo_settings *settings, char * const user_info[], char * const user_env[]) { + char **plugin_settings; int rval; debug_decl(policy_open, SUDO_DEBUG_PCOMM) + /* Convert struct sudo_settings to plugin_settings[] */ + plugin_settings = format_plugin_settings(plugin, settings); + if (plugin_settings == NULL) + debug_return_bool(-1); + /* * Backwards compatibility for older API versions */ @@ -1089,12 +1134,12 @@ policy_open(struct plugin_container *plugin, char * const settings[], case SUDO_API_MKVERSION(1, 0): case SUDO_API_MKVERSION(1, 1): rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version, - sudo_conversation, sudo_conversation_printf, settings, + sudo_conversation, sudo_conversation_printf, plugin_settings, user_info, user_env); break; default: rval = plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation, - sudo_conversation_printf, settings, user_info, user_env, + sudo_conversation_printf, plugin_settings, user_info, user_env, plugin->options); } @@ -1198,30 +1243,36 @@ policy_init_session(struct command_details *details) } static int -iolog_open(struct plugin_container *plugin, char * const settings[], +iolog_open(struct plugin_container *plugin, struct sudo_settings *settings, char * const user_info[], char * const command_info[], int argc, char * const argv[], char * const user_env[]) { + char **plugin_settings; int rval; debug_decl(iolog_open, SUDO_DEBUG_PCOMM) + /* Convert struct sudo_settings to plugin_settings[] */ + plugin_settings = format_plugin_settings(plugin, settings); + if (plugin_settings == NULL) + debug_return_bool(-1); + /* * Backwards compatibility for older API versions */ 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_conversation_printf, settings, + sudo_conversation, sudo_conversation_printf, plugin_settings, user_info, argc, argv, user_env); break; case SUDO_API_MKVERSION(1, 1): rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version, - sudo_conversation, sudo_conversation_printf, settings, + sudo_conversation, sudo_conversation_printf, plugin_settings, user_info, command_info, argc, argv, user_env); break; default: rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation, - sudo_conversation_printf, settings, user_info, command_info, + sudo_conversation_printf, plugin_settings, user_info, command_info, argc, argv, user_env, plugin->options); } debug_return_bool(rval); diff --git a/src/sudo.h b/src/sudo.h index 19d34cc87..f61e98305 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -85,6 +85,12 @@ #define TGP_MASK 0x08 /* mask user input when reading */ #define TGP_NOECHO_TRY 0x10 /* turn off echo if possible */ +/* name/value pairs for command line settings. */ +struct sudo_settings { + const char *name; + const char *value; +}; + struct user_details { pid_t pid; pid_t ppid; @@ -186,7 +192,7 @@ int sudo_execute(struct command_details *details, struct command_status *cstat); /* parse_args.c */ int parse_args(int argc, char **argv, int *nargc, char ***nargv, - char ***settingsp, char ***env_addp); + struct sudo_settings **settingsp, char ***env_addp); extern int tgetpass_flags; /* get_pty.c */