From 7a600fae37f946afc59f9c803a1f0f88d37b50ce Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 8 Jun 2010 15:56:49 -0400 Subject: [PATCH] Defer call to pam_close_session() until after the command finishes if there is a monitor process. --HG-- branch : 1.7 --- TODO | 8 ++------ auth/pam.c | 37 +++++++++++++++++++++---------------- exec.c | 4 ++-- exec_pty.c | 2 +- set_perms.c | 29 ++++++++++++++++++----------- sudo.c | 8 ++++++-- sudo.h | 6 ++++-- 7 files changed, 54 insertions(+), 40 deletions(-) diff --git a/TODO b/TODO index 5baf74c45..85a76d4a8 100644 --- a/TODO +++ b/TODO @@ -188,10 +188,6 @@ TODO list (most will be addressed in sudo 2.0) 65) See http://iase.disa.mil/stigs/whitepaper/sudowhitepaper-042304.doc -66) Add a session mode where sudo allocates a pty and logs everything - that occurs ala script(1). Logs should be replayable via - scriptreplay.pl. See linux script's -t option for timing info. +66) Update Active Directory instructions based on Alain Roy's info -67) Update Active Directory instructions based on Alain Roy's info - -68) Add support for multiple LDAP trees; from Joachim Henke +67) Add support for multiple LDAP trees; from Joachim Henke diff --git a/auth/pam.c b/auth/pam.c index f9fa26d34..57add9ff2 100644 --- a/auth/pam.c +++ b/auth/pam.c @@ -199,11 +199,12 @@ pam_cleanup(pw, auth) } int -pam_prep_user(pw) +pam_begin_session(pw) struct passwd *pw; { - int eval; + int status = PAM_SUCCESS; + /* If the user did not have to authenticate there is no pam handle yet. */ if (pamh == NULL) pam_init(pw, NULL, NULL); @@ -224,23 +225,27 @@ pam_prep_user(pw) (void) pam_setcred(pamh, PAM_ESTABLISH_CRED); #ifndef NO_PAM_SESSION - /* - * To fully utilize PAM sessions we would need to keep a - * sudo process around until the command exits. However, we - * can at least cause pam_limits to be run by opening and then - * immediately closing the session. - */ - if ((eval = pam_open_session(pamh, 0)) != PAM_SUCCESS) { - (void) pam_end(pamh, eval | PAM_DATA_SILENT); - return(AUTH_FAILURE); + status = pam_open_session(pamh, 0); + if (status != PAM_SUCCESS) { + (void) pam_end(pamh, status | PAM_DATA_SILENT); + pamh = NULL; } - (void) pam_close_session(pamh, 0); #endif + return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); +} - if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS) - return(AUTH_SUCCESS); - else - return(AUTH_FAILURE); +int +pam_end_session() +{ + int status = PAM_SUCCESS; + + if (pamh != NULL) { +#ifndef NO_PAM_SESSION + (void) pam_close_session(pamh, 0); +#endif + status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); + } + return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); } /* diff --git a/exec.c b/exec.c index 54aa145f5..6c0ae4c2a 100644 --- a/exec.c +++ b/exec.c @@ -127,7 +127,7 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled) if (rbac_enabled) selinux_setup(user_role, user_type, user_ttypath, -1); #endif - if (exec_setup() == TRUE) { + if (exec_setup(PERM_DOWAIT) == TRUE) { /* headed for execve() */ closefrom(def_closefrom); #ifdef HAVE_SELINUX @@ -187,7 +187,7 @@ sudo_execve(path, argv, envp, uid, cstat, dowait) * If we don't need to wait for the command to finish, just exec it. */ if (!dowait) { - exec_setup(); + exec_setup(0); closefrom(def_closefrom); my_execve(path, argv, envp); cstat->type = CMD_ERRNO; diff --git a/exec_pty.c b/exec_pty.c index c97abbec4..aefdd75b2 100644 --- a/exec_pty.c +++ b/exec_pty.c @@ -463,7 +463,7 @@ fork_pty(path, argv, envp, sv, rbac_enabled, maxfd) if (rbac_enabled) selinux_setup(user_role, user_type, slavename, io_fds[SFD_SLAVE]); #endif - if (exec_setup() == TRUE) { + if (exec_setup(PERM_DOWAIT) == TRUE) { /* Close the other end of the stdin/stdout/stderr pipes and exec. */ if (io_pipe[STDIN_FILENO][1]) close(io_pipe[STDIN_FILENO][1]); diff --git a/set_perms.c b/set_perms.c index 99b310d9c..535573021 100644 --- a/set_perms.c +++ b/set_perms.c @@ -60,7 +60,7 @@ /* * Prototypes */ -static void runas_setup __P((void)); +static void runas_setup __P((int)); static void runas_setgroups __P((void)); static void restore_groups __P((void)); @@ -78,9 +78,10 @@ set_perms(perm) int perm; { const char *errstr; - int noexit; + int noexit, dowait; noexit = ISSET(perm, PERM_NOEXIT); + dowait = ISSET(perm, PERM_DOWAIT); CLR(perm, PERM_MASK); if (perm == current_perm) @@ -127,7 +128,7 @@ set_perms(perm) case PERM_FULL_RUNAS: /* headed for exec(), assume euid == ROOT_UID */ - runas_setup(); + runas_setup(dowait); if (setresuid(def_stay_setuid ? user_uid : runas_pw->pw_uid, runas_pw->pw_uid, runas_pw->pw_uid)) { @@ -192,9 +193,10 @@ set_perms(perm) int perm; { const char *errstr; - int noexit; + int noexit, dowait; noexit = ISSET(perm, PERM_NOEXIT); + dowait = ISSET(perm, PERM_DOWAIT); CLR(perm, PERM_MASK); if (perm == current_perm) @@ -245,7 +247,7 @@ set_perms(perm) case PERM_FULL_RUNAS: /* headed for exec(), assume euid == ROOT_UID */ - runas_setup(); + runas_setup(dowait); if (setreuid(def_stay_setuid ? user_uid : runas_pw->pw_uid, runas_pw->pw_uid)) { errstr = "unable to change to runas uid"; @@ -307,9 +309,10 @@ set_perms(perm) int perm; { const char *errstr; - int noexit; + int noexit, dowait; noexit = ISSET(perm, PERM_NOEXIT); + dowait = ISSET(perm, PERM_DOWAIT); CLR(perm, PERM_MASK); if (perm == current_perm) @@ -366,7 +369,7 @@ set_perms(perm) case PERM_FULL_RUNAS: /* headed for exec() */ - runas_setup(); + runas_setup(dowait); if (setuid(runas_pw->pw_uid)) { errstr = "unable to change to runas uid"; goto bad; @@ -426,9 +429,10 @@ set_perms(perm) int perm; { const char *errstr; - int noexit; + int noexit, dowait; noexit = ISSET(perm, PERM_NOEXIT); + dowait = ISSET(perm, PERM_DOWAIT); CLR(perm, PERM_MASK); if (perm == current_perm) @@ -453,7 +457,7 @@ set_perms(perm) break; case PERM_FULL_RUNAS: - runas_setup(); + runas_setup(dowait); if (setuid(runas_pw->pw_uid)) { errstr = "unable to change to runas uid"; goto bad; @@ -538,7 +542,8 @@ restore_groups() #endif /* HAVE_INITGROUPS */ static void -runas_setup() +runas_setup(dowait) + int dowait; { gid_t gid; #ifdef HAVE_LOGIN_CAP_H @@ -552,7 +557,9 @@ runas_setup() aix_setlimits(runas_pw->pw_name); #endif #ifdef HAVE_PAM - pam_prep_user(runas_pw); + pam_begin_session(runas_pw); + if (!dowait) + pam_end_session(); #endif /* HAVE_PAM */ #ifdef HAVE_LOGIN_CAP_H diff --git a/sudo.c b/sudo.c index eaa388f5f..f3a05be0c 100644 --- a/sudo.c +++ b/sudo.c @@ -808,7 +808,8 @@ set_cmnd(sudo_mode) * Returns TRUE on success and FALSE on failure. */ int -exec_setup() +exec_setup(flags) + int flags; { int rval = FALSE; @@ -847,7 +848,7 @@ exec_setup() #endif /* RLIMIT_CORE && !SUDO_DEVEL */ if (ISSET(sudo_mode, MODE_RUN)) - set_perms(PERM_FULL_RUNAS); + set_perms(PERM_FULL_RUNAS|flags); if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { /* Change to target user's homedir. */ @@ -916,6 +917,9 @@ run_command(path, argv, envp, uid, dowait) warningx("unexpected child termination condition: %d", cstat.type); break; } +#ifdef HAVE_PAM + pam_end_session(); +#endif /* HAVE_PAM */ #ifdef _PATH_SUDO_IO_LOGDIR io_log_close(); #endif diff --git a/sudo.h b/sudo.h index e07876ef3..e9ea96217 100644 --- a/sudo.h +++ b/sudo.h @@ -148,6 +148,7 @@ struct command_status { #define PERM_FULL_RUNAS 0x05 #define PERM_TIMESTAMP 0x06 #define PERM_NOEXIT 0x10 /* flag */ +#define PERM_DOWAIT 0x20 /* flag */ #define PERM_MASK 0xf0 /* @@ -285,7 +286,8 @@ int sudo_ldap_display_bound_defaults __P((struct sudo_nss *, struct passwd *, st int sudo_ldap_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *)); /* pam.c */ -int pam_prep_user __P((struct passwd *)); +int pam_begin_session __P((struct passwd *)); +int pam_end_session __P((void)); /* parse.c */ int sudo_file_open __P((struct sudo_nss *)); @@ -330,7 +332,7 @@ int set_perms __P((int)); /* sudo.c */ FILE *open_sudoers __P((const char *, int, int *)); -int exec_setup __P((void)); +int exec_setup __P((int)); void cleanup __P((int)); void set_fqdn __P((void)); -- 2.40.0