From 27be96c9cd766e15d41d51a5f0c805be857147bf Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 26 May 2010 17:57:47 -0400 Subject: [PATCH] Add open/close session to sudo auth, only used by PAM. This allows us to open (and close) the PAM session from sudoers. --- plugins/sudoers/auth/pam.c | 33 ++++++++++------- plugins/sudoers/auth/sudo_auth.c | 62 ++++++++++++++++++++++++-------- plugins/sudoers/auth/sudo_auth.h | 22 +++++++----- plugins/sudoers/set_perms.c | 51 -------------------------- plugins/sudoers/sudoers.c | 10 ++++++ plugins/sudoers/sudoers.h | 3 +- 6 files changed, 94 insertions(+), 87 deletions(-) diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 3c569c908..62727defb 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -81,7 +81,7 @@ static int gotintr; #define PAM_DATA_SILENT 0 #endif -static pam_handle_t *pamh; /* global due to pam_prep_user() */ +static pam_handle_t *pamh; int pam_init(pw, promptp, auth) @@ -189,7 +189,7 @@ pam_cleanup(pw, auth) { int *pam_status = (int *) auth->data; - /* If successful, we can't close the session until pam_prep_user() */ + /* If successful, we can't close the session until pam_end_session() */ if (auth->status == AUTH_SUCCESS) return(AUTH_SUCCESS); @@ -198,10 +198,11 @@ pam_cleanup(pw, auth) } int -pam_prep_user(pw) +pam_begin_session(pw, auth) struct passwd *pw; + sudo_auth *auth; { - int eval; + int status; if (pamh == NULL) pam_init(pw, NULL, NULL); @@ -229,17 +230,25 @@ pam_prep_user(pw) * 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, PAM_SUCCESS | PAM_DATA_SILENT); +#endif + return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); +} + +int +pam_end_session(auth) + sudo_auth *auth; +{ + int status; + +#ifndef NO_PAM_SESSION (void) pam_close_session(pamh, 0); #endif - if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS) - return(AUTH_SUCCESS); - else - return(AUTH_FAILURE); + status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); + return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); } /* diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c index 3990d7e7b..75436dbf6 100644 --- a/plugins/sudoers/auth/sudo_auth.c +++ b/plugins/sudoers/auth/sudo_auth.c @@ -57,33 +57,37 @@ sudo_auth auth_switch[] = { AUTH_STANDALONE #else # ifndef WITHOUT_PASSWD - AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL) + AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL, NULL, NULL) # endif # if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD) - AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL) + AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL, NULL, NULL) # endif # ifdef HAVE_AFS - AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL) + AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL, NULL, NULL) # endif # ifdef HAVE_DCE - AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL) + AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL, NULL, NULL) # endif # ifdef HAVE_KERB4 - AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL) + AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL) # endif # ifdef HAVE_KERB5 - AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup) + AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL) # endif # ifdef HAVE_SKEY - AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL) + AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) # endif # ifdef HAVE_OPIE - AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL) + AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) # endif #endif /* AUTH_STANDALONE */ - AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL) + AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL) }; +extern char **NewArgv; /* XXX - for auditing */ + +static void pass_warn(void); + int verify_user(struct passwd *pw, char *prompt) { @@ -93,7 +97,6 @@ verify_user(struct passwd *pw, char *prompt) char *p; sudo_auth *auth; sigaction_t sa, osa; - extern char **NewArgv; /* XXX */ /* Enable suspend during password entry. */ sigemptyset(&sa.sa_mask); @@ -181,9 +184,7 @@ verify_user(struct passwd *pw, char *prompt) if (p) zero_bytes(p, strlen(p)); #endif - /* XXX - need way to know if askpass was used */ - //if (!ISSET(tgetpass_flags, TGP_ASKPASS)) - pass_warn(); + pass_warn(); } cleanup: @@ -233,7 +234,40 @@ cleanup: return rval; } -void +int begin_session(struct passwd *pw) +{ + sudo_auth *auth; + int status; + + for (auth = auth_switch; auth->name; auth++) { + if (auth->begin_session && IS_CONFIGURED(auth)) { + status = (auth->begin_session)(pw, auth); + if (status == AUTH_FATAL) { /* XXX log */ + audit_failure(NewArgv, "authentication failure"); + return -1; /* assume error msg already printed */ + } + } + } + return TRUE; +} + +int end_session(void) +{ + sudo_auth *auth; + int status; + + for (auth = auth_switch; auth->name; auth++) { + if (auth->end_session && IS_CONFIGURED(auth)) { + status = (auth->end_session)(auth); + if (status == AUTH_FATAL) { /* XXX log */ + return -1; /* assume error msg already printed */ + } + } + } + return TRUE; +} + +static void pass_warn(void) { struct sudo_conv_message msg[2]; diff --git a/plugins/sudoers/auth/sudo_auth.h b/plugins/sudoers/auth/sudo_auth.h index 494b98eb6..ef1bad2e7 100644 --- a/plugins/sudoers/auth/sudo_auth.h +++ b/plugins/sudoers/auth/sudo_auth.h @@ -32,6 +32,8 @@ typedef struct sudo_auth { int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth); int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth); int (*cleanup)(struct passwd *pw, struct sudo_auth *auth); + int (*begin_session)(struct passwd *pw, struct sudo_auth *auth); + int (*end_session)(struct sudo_auth *auth); } sudo_auth; /* Values for sudo_auth.flags. */ @@ -58,6 +60,8 @@ int fwtk_cleanup(struct passwd *pw, sudo_auth *auth); int pam_init(struct passwd *pw, char **prompt, sudo_auth *auth); int pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth); int pam_cleanup(struct passwd *pw, sudo_auth *auth); +int pam_begin_session(struct passwd *pw, sudo_auth *auth); +int pam_end_session(sudo_auth *auth); int sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth); int sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth); int sia_cleanup(struct passwd *pw, sudo_auth *auth); @@ -86,34 +90,34 @@ int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth); int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth); /* Fields: need_root, name, init, setup, verify, cleanup */ -#define AUTH_ENTRY(r, n, i, s, v, c) \ - { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c }, +#define AUTH_ENTRY(r, n, i, s, v, c, b, e) \ + { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c , b, e }, -/* Some methods cannots (or should not) interoperate with any others */ +/* Some methods cannot (or should not) interoperate with any others */ #if defined(HAVE_PAM) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "pam", \ - pam_init, NULL, pam_verify, pam_cleanup) + pam_init, NULL, pam_verify, pam_cleanup, pam_begin_session, pam_end_session) #elif defined(HAVE_SECURID) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "SecurId", \ - securid_init, securid_setup, securid_verify, NULL) + securid_init, securid_setup, securid_verify, NULL, NULL, NULL) #elif defined(HAVE_SIA_SES_INIT) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "sia", \ - NULL, sia_setup, sia_verify, sia_cleanup) + NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL) #elif defined(HAVE_AIXAUTH) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "aixauth", \ - NULL, NULL, aixauth_verify, aixauth_cleanup) + NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL) #elif defined(HAVE_FWTK) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "fwtk", \ - fwtk_init, NULL, fwtk_verify, fwtk_cleanup) + fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL) #elif defined(HAVE_BSD_AUTH_H) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "bsdauth", \ - bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup) + bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL) #endif #endif /* SUDO_AUTH_H */ diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c index a9e12344a..ff149c5df 100644 --- a/plugins/sudoers/set_perms.c +++ b/plugins/sudoers/set_perms.c @@ -60,9 +60,6 @@ /* * Prototypes */ -#if 0 -static void runas_setup(void); -#endif static void runas_setgroups(void); /* @@ -969,51 +966,3 @@ runas_setgroups() } #endif /* HAVE_INITGROUPS */ - -#if 0 -static void -runas_setup() -{ - gid_t gid; -#ifdef HAVE_LOGIN_CAP_H - int flags; - extern login_cap_t *lc; -#endif - - if (runas_pw->pw_name != NULL) { - gid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; -#ifdef HAVE_GETUSERATTR - aix_setlimits(runas_pw->pw_name); -#endif -#ifdef HAVE_PAM - /* XXX - move this */ - pam_prep_user(runas_pw); -#endif /* HAVE_PAM */ - -#ifdef HAVE_LOGIN_CAP_H - if (def_use_loginclass) { - /* - * We only use setusercontext() to set the nice value and rlimits. - */ - flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; - if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) { - if (runas_pw->pw_uid != ROOT_UID) - error(1, "unable to set user context"); - else - warning("unable to set user context"); - } - } -#endif /* HAVE_LOGIN_CAP_H */ - /* - * Initialize group vector - */ - runas_setgroups(); -#ifdef HAVE_SETEUID - if (setegid(gid)) - warning("cannot set egid to runas gid"); -#endif - if (setgid(gid)) - warning("cannot set gid to runas gid"); - } -} -#endif diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index b867d81bb..a729f2ade 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -276,6 +276,7 @@ sudoers_policy_close(int exit_status, int error_code) /* We do not currently log the exit status. */ if (error_code) warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code)); + end_session(); } static int @@ -627,6 +628,15 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], restore_perms(); + /* + * Ideally we would like to do session setup (currently only PAM) + * from inside sudo itself, but this should be close enough. + */ + if (ISSET(sudo_mode, MODE_RUN)) + rval = begin_session(runas_pw); + if (ISSET(sudo_mode, MODE_EDIT)) + rval = begin_session(sudo_user.pw); + done: return rval; } diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 0b7661702..c7252d052 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -210,7 +210,8 @@ int user_is_exempt(void); /* sudo_auth.c */ int verify_user(struct passwd *, char *); -void pass_warn(void); +int begin_session(struct passwd *); +int end_session(); #ifdef HAVE_LDAP /* ldap.c */ -- 2.40.0