--- embedaddon/sudo/plugins/sudoers/auth/pam.c 2013/07/22 10:46:12 1.1.1.3 +++ embedaddon/sudo/plugins/sudoers/auth/pam.c 2014/06/15 16:12:54 1.1.1.5 @@ -79,8 +79,6 @@ static int converse(int, PAM_CONST struct pam_message **, struct pam_response **, void *); static char *def_prompt = "Password:"; -static bool sudo_pam_cred_established; -static bool sudo_pam_authenticated; static int getpass_error; static pam_handle_t *pamh; @@ -92,15 +90,10 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth) debug_decl(sudo_pam_init, SUDO_DEBUG_AUTH) /* Initial PAM setup */ - if (auth != NULL) - auth->data = (void *) &pam_status; + auth->data = (void *) &pam_status; pam_conv.conv = converse; -#ifdef HAVE_PAM_LOGIN - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) - pam_status = pam_start("sudo-i", pw->pw_name, &pam_conv, &pamh); - else -#endif - pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); + pam_status = pam_start(ISSET(sudo_mode, MODE_LOGIN_SHELL) ? + def_pam_login_service : def_pam_service, pw->pw_name, &pam_conv, &pamh); if (pam_status != PAM_SUCCESS) { log_warning(USE_ERRNO|NO_MAIL, N_("unable to initialize PAM")); debug_return_int(AUTH_FATAL); @@ -125,6 +118,13 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth) else (void) pam_set_item(pamh, PAM_TTY, user_ttypath); + /* + * If PAM session and setcred support is disabled we don't + * need to keep a sudo process around to close the session. + */ + if (!def_pam_session && !def_pam_setcred) + auth->end_session = NULL; + debug_return_int(AUTH_SUCCESS); } @@ -144,7 +144,6 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_ *pam_status = pam_acct_mgmt(pamh, PAM_SILENT); switch (*pam_status) { case PAM_SUCCESS: - sudo_pam_authenticated = true; debug_return_int(AUTH_SUCCESS); case PAM_AUTH_ERR: log_warning(NO_MAIL, N_("account validation failure, " @@ -196,19 +195,19 @@ sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth) int *pam_status = (int *) auth->data; debug_decl(sudo_pam_cleanup, SUDO_DEBUG_AUTH) - /* If successful, we can't close the session until pam_end_session() */ - if (*pam_status == AUTH_SUCCESS) - debug_return_int(AUTH_SUCCESS); - - *pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT); - pamh = NULL; + /* If successful, we can't close the session until sudo_pam_end_session() */ + if (*pam_status != PAM_SUCCESS || auth->end_session == NULL) { + *pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT); + pamh = NULL; + } debug_return_int(*pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); } int sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth) { - int status = PAM_SUCCESS; + int status = AUTH_SUCCESS; + int *pam_status = (int *) auth->data; debug_decl(sudo_pam_begin_session, SUDO_DEBUG_AUTH) /* @@ -231,21 +230,24 @@ sudo_pam_begin_session(struct passwd *pw, char **user_ (void) pam_set_item(pamh, PAM_USER, pw->pw_name); /* - * Set credentials (may include resource limits, device ownership, etc). - * We don't check the return value here because in Linux-PAM 0.75 - * it returns the last saved return code, not the return code - * for the setcred module. Because we haven't called pam_authenticate(), - * this is not set and so pam_setcred() returns PAM_PERM_DENIED. - * We can't call pam_acct_mgmt() with Linux-PAM for a similar reason. + * Reinitialize credentials when changing the user. + * We don't worry about a failure from pam_setcred() since with + * stacked PAM auth modules a failure from one module may override + * PAM_SUCCESS from another. For example, given a non-local user, + * pam_unix will fail but pam_ldap or pam_sss may succeed, but if + * pam_unix is first in the stack, pam_setcred() will fail. */ - status = pam_setcred(pamh, PAM_ESTABLISH_CRED); - if (status == PAM_SUCCESS) { - sudo_pam_cred_established = true; - } else if (sudo_pam_authenticated) { - const char *s = pam_strerror(pamh, status); - if (s != NULL) - log_warning(NO_MAIL, N_("unable to establish credentials: %s"), s); - goto done; + if (def_pam_setcred) + (void) pam_setcred(pamh, PAM_REINITIALIZE_CRED); + + if (def_pam_session) { + *pam_status = pam_open_session(pamh, 0); + if (*pam_status != PAM_SUCCESS) { + (void) pam_end(pamh, *pam_status | PAM_DATA_SILENT); + pamh = NULL; + status = AUTH_FAILURE; + goto done; + } } #ifdef HAVE_PAM_GETENVLIST @@ -257,9 +259,9 @@ sudo_pam_begin_session(struct passwd *pw, char **user_ if (user_envp != NULL) { char **pam_envp = pam_getenvlist(pamh); if (pam_envp != NULL) { - /* Merge pam env with user env but do not overwrite. */ + /* Merge pam env with user env. */ env_init(*user_envp); - env_merge(pam_envp, false); + env_merge(pam_envp); *user_envp = env_get(); env_init(NULL); efree(pam_envp); @@ -268,22 +270,14 @@ sudo_pam_begin_session(struct passwd *pw, char **user_ } #endif /* HAVE_PAM_GETENVLIST */ - if (def_pam_session) { - status = pam_open_session(pamh, 0); - if (status != PAM_SUCCESS) { - (void) pam_end(pamh, status | PAM_DATA_SILENT); - pamh = NULL; - } - } - done: - debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); + debug_return_int(status); } int sudo_pam_end_session(struct passwd *pw, sudo_auth *auth) { - int status = PAM_SUCCESS; + int status = AUTH_SUCCESS; debug_decl(sudo_pam_end_session, SUDO_DEBUG_AUTH) if (pamh != NULL) { @@ -295,13 +289,14 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *aut (void) pam_set_item(pamh, PAM_USER, pw->pw_name); if (def_pam_session) (void) pam_close_session(pamh, PAM_SILENT); - if (sudo_pam_cred_established) + if (def_pam_setcred) (void) pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); - status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); + if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) != PAM_SUCCESS) + status = AUTH_FAILURE; pamh = NULL; } - debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); + debug_return_int(status); } /* @@ -322,7 +317,7 @@ converse(int num_msg, PAM_CONST struct pam_message **m if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL) debug_return_int(PAM_SYSTEM_ERR); - zero_bytes(*response, num_msg * sizeof(struct pam_response)); + memset(*response, 0, num_msg * sizeof(struct pam_response)); for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) { type = SUDO_CONV_PROMPT_ECHO_OFF; @@ -366,7 +361,7 @@ converse(int num_msg, PAM_CONST struct pam_message **m #endif } pr->resp = estrdup(pass); - zero_bytes(pass, strlen(pass)); + memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); break; case PAM_TEXT_INFO: if (pm->msg) @@ -390,12 +385,11 @@ done: /* Zero and free allocated memory and return an error. */ for (pr = *response, n = num_msg; n--; pr++) { if (pr->resp != NULL) { - zero_bytes(pr->resp, strlen(pr->resp)); + memset_s(pr->resp, SUDO_CONV_REPL_MAX, 0, strlen(pr->resp)); free(pr->resp); pr->resp = NULL; } } - zero_bytes(*response, num_msg * sizeof(struct pam_response)); free(*response); *response = NULL; }