From: Todd C. Miller Date: Mon, 23 Feb 2015 18:12:45 +0000 (-0700) Subject: Pam conversation function changes: X-Git-Tag: SUDO_1_8_13^2~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a604f0f02dcaace062750d3f5b83d1dd4c3c7ef6;p=sudo Pam conversation function changes: o use PAM_BUF_ERR as the return value when calloc() fails. o sanity check the value of num_msg o remove the workaround for old Apple PAM o PAM_AUTH_ERR is not a valid PAM conversation function return value If getpass_error is set after a call to pam_verify (usually because the user pressed ^C), return AUTH_INTR immediately instead of checking the pam_verify return value. --- diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index d60e6a323..635d5adc4 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -78,20 +78,19 @@ static int converse(int, PAM_CONST struct pam_message **, struct pam_response **, void *); +static struct pam_conv pam_conv = { converse, NULL }; static char *def_prompt = PASSPROMPT; -static int getpass_error; +static bool getpass_error; static pam_handle_t *pamh; int sudo_pam_init(struct passwd *pw, sudo_auth *auth) { - static struct pam_conv pam_conv; static int pam_status; debug_decl(sudo_pam_init, SUDOERS_DEBUG_AUTH) /* Initial PAM setup */ auth->data = (void *) &pam_status; - pam_conv.conv = converse; 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) { @@ -136,9 +135,14 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) debug_decl(sudo_pam_verify, SUDOERS_DEBUG_AUTH) def_prompt = prompt; /* for converse */ + getpass_error = false; /* set by converse if user presses ^C */ /* PAM_SILENT prevents the authentication service from generating output. */ *pam_status = pam_authenticate(pamh, PAM_SILENT); + if (getpass_error) { + /* error or ^C from tgetpass() */ + debug_return_int(AUTH_INTR); + } switch (*pam_status) { case PAM_SUCCESS: *pam_status = pam_acct_mgmt(pamh, PAM_SILENT); @@ -174,11 +178,6 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) /* FALLTHROUGH */ case PAM_AUTH_ERR: case PAM_AUTHINFO_UNAVAIL: - if (getpass_error) { - /* error or ^C from tgetpass() */ - debug_return_int(AUTH_INTR); - } - /* FALLTHROUGH */ case PAM_MAXTRIES: case PAM_PERM_DENIED: debug_return_int(AUTH_FAILURE); @@ -262,7 +261,7 @@ sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth) /* Merge pam env with user env. */ env_init(*user_envp); if (!env_merge(pam_envp)) - status = PAM_SYSTEM_ERR; + status = AUTH_FAILURE; *user_envp = env_get(); env_init(NULL); sudo_efree(pam_envp); @@ -325,11 +324,14 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, const char *prompt; char *pass; int n, type; - int ret = PAM_AUTH_ERR; + int ret = PAM_SUCCESS; debug_decl(converse, SUDOERS_DEBUG_AUTH) + if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) + debug_return_int(PAM_CONV_ERR); + if ((*response = calloc(num_msg, sizeof(struct pam_response))) == NULL) - debug_return_int(PAM_SYSTEM_ERR); + debug_return_int(PAM_BUF_ERR); for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) { type = SUDO_CONV_PROMPT_ECHO_OFF; @@ -365,12 +367,12 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, pass = auth_getpass(prompt, def_passwd_timeout * 60, type); if (pass == NULL) { /* Error (or ^C) reading password, don't try again. */ - getpass_error = 1; -#if (defined(__darwin__) || defined(__APPLE__)) && !defined(OPENPAM_VERSION) - pass = ""; -#else + getpass_error = true; + goto done; + } + if (strlen(pass) >= PAM_MAX_RESP_SIZE) { + ret = PAM_CONV_ERR; goto done; -#endif } pr->resp = sudo_estrdup(pass); memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); @@ -390,7 +392,6 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, goto done; } } - ret = PAM_SUCCESS; done: if (ret != PAM_SUCCESS) {