From 3651377e124e12e1e613dd886cc7f032a4f77d69 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" <Todd.Miller@courtesan.com> Date: Thu, 25 Oct 2012 13:16:58 -0400 Subject: [PATCH] Refactor command_info setting into its own function. --- plugins/sudoers/iolog.c | 1 - plugins/sudoers/sudoers.c | 245 +++++++++++++++++++++----------------- 2 files changed, 136 insertions(+), 110 deletions(-) diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 45dd0aed0..4332d035b 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -53,7 +53,6 @@ #include "sudoers.h" -/* plugin_error.c */ extern sigjmp_buf error_jmp; union io_fd { diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 594796095..36530e746 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -311,15 +311,136 @@ sudoers_policy_init_session(struct passwd *pwd, char **user_env[]) debug_return_bool(sudo_auth_begin_session(pwd, user_env)); } +/* + * Build up command_info list. + * XXX - convert into setter function that takes care + * of command_info, argv_out and user_env_out + */ +static char ** +build_command_info(mode_t cmnd_umask, char *iolog_path) +{ + char **command_info; + int info_len = 0; + debug_decl(build_command_info, SUDO_DEBUG_PLUGIN) + + /* Increase the length of command_info as needed, it is *not* checked. */ + command_info = ecalloc(32, sizeof(char **)); + + command_info[info_len++] = fmt_string("command", safe_cmnd); + if (def_log_input || def_log_output) { + if (iolog_path) + command_info[info_len++] = iolog_path; + if (def_log_input) { + command_info[info_len++] = estrdup("iolog_stdin=true"); + command_info[info_len++] = estrdup("iolog_ttyin=true"); + } + if (def_log_output) { + command_info[info_len++] = estrdup("iolog_stdout=true"); + command_info[info_len++] = estrdup("iolog_stderr=true"); + command_info[info_len++] = estrdup("iolog_ttyout=true"); + } + if (def_compress_io) { + command_info[info_len++] = estrdup("iolog_compress=true"); + } + } + if (ISSET(sudo_mode, MODE_EDIT)) + command_info[info_len++] = estrdup("sudoedit=true"); + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + /* Set cwd to run user's homedir. */ + command_info[info_len++] = fmt_string("cwd", runas_pw->pw_dir); + } + if (def_stay_setuid) { + easprintf(&command_info[info_len++], "runas_uid=%u", + (unsigned int)user_uid); + easprintf(&command_info[info_len++], "runas_gid=%u", + (unsigned int)user_gid); + easprintf(&command_info[info_len++], "runas_euid=%u", + (unsigned int)runas_pw->pw_uid); + easprintf(&command_info[info_len++], "runas_egid=%u", + runas_gr ? (unsigned int)runas_gr->gr_gid : + (unsigned int)runas_pw->pw_gid); + } else { + easprintf(&command_info[info_len++], "runas_uid=%u", + (unsigned int)runas_pw->pw_uid); + easprintf(&command_info[info_len++], "runas_gid=%u", + runas_gr ? (unsigned int)runas_gr->gr_gid : + (unsigned int)runas_pw->pw_gid); + } + if (def_preserve_groups) { + command_info[info_len++] = "preserve_groups=true"; + } else { + int i, len; + gid_t egid; + size_t glsize; + char *cp, *gid_list; + struct group_list *grlist = sudo_get_grlist(runas_pw); + + /* We reserve an extra spot in the list for the effective gid. */ + glsize = sizeof("runas_groups=") - 1 + + ((grlist->ngids + 1) * (MAX_UID_T_LEN + 1)); + gid_list = emalloc(glsize); + memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1); + cp = gid_list + sizeof("runas_groups=") - 1; + + /* On BSD systems the effective gid is the first group in the list. */ + egid = runas_gr ? (unsigned int)runas_gr->gr_gid : + (unsigned int)runas_pw->pw_gid; + len = snprintf(cp, glsize - (cp - gid_list), "%u", egid); + if (len < 0 || len >= glsize - (cp - gid_list)) + errorx(1, _("internal error, %s overflow"), "runas_groups"); + cp += len; + for (i = 0; i < grlist->ngids; i++) { + if (grlist->gids[i] != egid) { + len = snprintf(cp, glsize - (cp - gid_list), ",%u", + (unsigned int) grlist->gids[i]); + if (len < 0 || len >= glsize - (cp - gid_list)) + errorx(1, _("internal error, %s overflow"), "runas_groups"); + cp += len; + } + } + command_info[info_len++] = gid_list; + sudo_grlist_delref(grlist); + } + if (def_closefrom >= 0) + easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom); + if (def_noexec) + command_info[info_len++] = estrdup("noexec=true"); + if (def_set_utmp) + command_info[info_len++] = estrdup("set_utmp=true"); + if (def_use_pty) + command_info[info_len++] = estrdup("use_pty=true"); + if (def_utmp_runas) + command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name); + if (cmnd_umask != 0777) + easprintf(&command_info[info_len++], "umask=0%o", (unsigned int)cmnd_umask); +#ifdef HAVE_LOGIN_CAP_H + if (def_use_loginclass) + command_info[info_len++] = fmt_string("login_class", login_class); +#endif /* HAVE_LOGIN_CAP_H */ +#ifdef HAVE_SELINUX + if (user_role != NULL) + command_info[info_len++] = fmt_string("selinux_role", user_role); + if (user_type != NULL) + command_info[info_len++] = fmt_string("selinux_type", user_type); +#endif /* HAVE_SELINUX */ +#ifdef HAVE_PRIV_SET + if (runas_privs != NULL) + command_info[info_len++] = fmt_string("runas_privs", runas_privs); + if (runas_limitprivs != NULL) + command_info[info_len++] = fmt_string("runas_limitprivs", runas_limitprivs); +#endif /* HAVE_SELINUX */ + debug_return_ptr(command_info); +} + static int sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], char **command_infop[], char **argv_out[], char **user_env_out[]) { - static char *command_info[32]; /* XXX */ char **edit_argv = NULL; + char *iolog_path = NULL; + mode_t cmnd_umask = 0777; struct sudo_nss *nss; int cmnd_status = -1, validated; - volatile int info_len = 0; volatile int rval = true; debug_decl(sudoers_policy_main, SUDO_DEBUG_PLUGIN) @@ -512,23 +633,12 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], validate_env_vars(sudo_user.env_vars); } - if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) { - if (def_iolog_file && def_iolog_dir) { - command_info[info_len++] = expand_iolog_path("iolog_path=", - def_iolog_dir, def_iolog_file, &sudo_user.iolog_file); + if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) { + if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) { + iolog_path = expand_iolog_path("iolog_path=", def_iolog_dir, + def_iolog_file, &sudo_user.iolog_file); sudo_user.iolog_file++; } - if (def_log_input) { - command_info[info_len++] = estrdup("iolog_stdin=true"); - command_info[info_len++] = estrdup("iolog_ttyin=true"); - } - if (def_log_output) { - command_info[info_len++] = estrdup("iolog_stdout=true"); - command_info[info_len++] = estrdup("iolog_stderr=true"); - command_info[info_len++] = estrdup("iolog_ttyout=true"); - } - if (def_compress_io) - command_info[info_len++] = estrdup("iolog_compress=true"); } log_allowed(validated); @@ -555,13 +665,12 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], * unless umask_override is set. */ if (def_umask != 0777) { - mode_t mask = def_umask; + cmnd_umask = def_umask; if (!def_umask_override) { - mode_t omask = umask(mask); - mask |= omask; + mode_t omask = umask(cmnd_umask); + cmnd_umask |= omask; umask(omask); } - easprintf(&command_info[info_len++], "umask=0%o", (unsigned int)mask); } if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { @@ -573,9 +682,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], *p = '-'; NewArgv[0] = p; - /* Set cwd to run user's homedir. */ - command_info[info_len++] = fmt_string("cwd", runas_pw->pw_dir); - /* * Newer versions of bash require the --login option to be used * in conjunction with the -c option even if the shell name starts @@ -620,97 +726,18 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); if (ISSET(sudo_mode, MODE_EDIT)) { - char *editor = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv); - if (editor == NULL) + efree(safe_cmnd); + safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv); + if (safe_cmnd == NULL) goto bad; - command_info[info_len++] = fmt_string("command", editor); - command_info[info_len++] = estrdup("sudoedit=true"); - } else { - command_info[info_len++] = fmt_string("command", safe_cmnd); } - if (def_stay_setuid) { - easprintf(&command_info[info_len++], "runas_uid=%u", - (unsigned int)user_uid); - easprintf(&command_info[info_len++], "runas_gid=%u", - (unsigned int)user_gid); - easprintf(&command_info[info_len++], "runas_euid=%u", - (unsigned int)runas_pw->pw_uid); - easprintf(&command_info[info_len++], "runas_egid=%u", - runas_gr ? (unsigned int)runas_gr->gr_gid : - (unsigned int)runas_pw->pw_gid); - } else { - easprintf(&command_info[info_len++], "runas_uid=%u", - (unsigned int)runas_pw->pw_uid); - easprintf(&command_info[info_len++], "runas_gid=%u", - runas_gr ? (unsigned int)runas_gr->gr_gid : - (unsigned int)runas_pw->pw_gid); - } - if (def_preserve_groups) { - command_info[info_len++] = "preserve_groups=true"; - } else { - int i, len; - gid_t egid; - size_t glsize; - char *cp, *gid_list; - struct group_list *grlist = sudo_get_grlist(runas_pw); - - /* We reserve an extra spot in the list for the effective gid. */ - glsize = sizeof("runas_groups=") - 1 + - ((grlist->ngids + 1) * (MAX_UID_T_LEN + 1)); - gid_list = emalloc(glsize); - memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1); - cp = gid_list + sizeof("runas_groups=") - 1; - - /* On BSD systems the effective gid is the first group in the list. */ - egid = runas_gr ? (unsigned int)runas_gr->gr_gid : - (unsigned int)runas_pw->pw_gid; - len = snprintf(cp, glsize - (cp - gid_list), "%u", egid); - if (len < 0 || len >= glsize - (cp - gid_list)) - errorx(1, _("internal error, %s overflow"), "runas_groups"); - cp += len; - for (i = 0; i < grlist->ngids; i++) { - if (grlist->gids[i] != egid) { - len = snprintf(cp, glsize - (cp - gid_list), ",%u", - (unsigned int) grlist->gids[i]); - if (len < 0 || len >= glsize - (cp - gid_list)) - errorx(1, _("internal error, %s overflow"), "runas_groups"); - cp += len; - } - } - command_info[info_len++] = gid_list; - sudo_grlist_delref(grlist); - } - if (def_closefrom >= 0) - easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom); - if (def_noexec) - command_info[info_len++] = estrdup("noexec=true"); - if (def_set_utmp) - command_info[info_len++] = estrdup("set_utmp=true"); - if (def_use_pty) - command_info[info_len++] = estrdup("use_pty=true"); - if (def_utmp_runas) - command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name); -#ifdef HAVE_LOGIN_CAP_H - if (def_use_loginclass) - command_info[info_len++] = fmt_string("login_class", login_class); -#endif /* HAVE_LOGIN_CAP_H */ -#ifdef HAVE_SELINUX - if (user_role != NULL) - command_info[info_len++] = fmt_string("selinux_role", user_role); - if (user_type != NULL) - command_info[info_len++] = fmt_string("selinux_type", user_type); -#endif /* HAVE_SELINUX */ -#ifdef HAVE_PRIV_SET - if (runas_privs != NULL) - command_info[info_len++] = fmt_string("runas_privs", runas_privs); - if (runas_limitprivs != NULL) - command_info[info_len++] = fmt_string("runas_limitprivs", runas_limitprivs); -#endif /* HAVE_SELINUX */ /* Must audit before uid change. */ audit_success(NewArgv); - *command_infop = command_info; + /* XXX - use a setter that is passed instead of setting + command_infop, argv_out and user_env_out directly */ + *command_infop = build_command_info(cmnd_umask, iolog_path); *argv_out = edit_argv ? edit_argv : NewArgv; -- 2.40.0