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.
This commit is contained in:
@@ -78,20 +78,19 @@
|
|||||||
|
|
||||||
static int converse(int, PAM_CONST struct pam_message **,
|
static int converse(int, PAM_CONST struct pam_message **,
|
||||||
struct pam_response **, void *);
|
struct pam_response **, void *);
|
||||||
|
static struct pam_conv pam_conv = { converse, NULL };
|
||||||
static char *def_prompt = PASSPROMPT;
|
static char *def_prompt = PASSPROMPT;
|
||||||
static int getpass_error;
|
static bool getpass_error;
|
||||||
static pam_handle_t *pamh;
|
static pam_handle_t *pamh;
|
||||||
|
|
||||||
int
|
int
|
||||||
sudo_pam_init(struct passwd *pw, sudo_auth *auth)
|
sudo_pam_init(struct passwd *pw, sudo_auth *auth)
|
||||||
{
|
{
|
||||||
static struct pam_conv pam_conv;
|
|
||||||
static int pam_status;
|
static int pam_status;
|
||||||
debug_decl(sudo_pam_init, SUDOERS_DEBUG_AUTH)
|
debug_decl(sudo_pam_init, SUDOERS_DEBUG_AUTH)
|
||||||
|
|
||||||
/* Initial PAM setup */
|
/* Initial PAM setup */
|
||||||
auth->data = (void *) &pam_status;
|
auth->data = (void *) &pam_status;
|
||||||
pam_conv.conv = converse;
|
|
||||||
pam_status = pam_start(ISSET(sudo_mode, MODE_LOGIN_SHELL) ?
|
pam_status = pam_start(ISSET(sudo_mode, MODE_LOGIN_SHELL) ?
|
||||||
def_pam_login_service : def_pam_service, pw->pw_name, &pam_conv, &pamh);
|
def_pam_login_service : def_pam_service, pw->pw_name, &pam_conv, &pamh);
|
||||||
if (pam_status != PAM_SUCCESS) {
|
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)
|
debug_decl(sudo_pam_verify, SUDOERS_DEBUG_AUTH)
|
||||||
|
|
||||||
def_prompt = prompt; /* for converse */
|
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_SILENT prevents the authentication service from generating output. */
|
||||||
*pam_status = pam_authenticate(pamh, PAM_SILENT);
|
*pam_status = pam_authenticate(pamh, PAM_SILENT);
|
||||||
|
if (getpass_error) {
|
||||||
|
/* error or ^C from tgetpass() */
|
||||||
|
debug_return_int(AUTH_INTR);
|
||||||
|
}
|
||||||
switch (*pam_status) {
|
switch (*pam_status) {
|
||||||
case PAM_SUCCESS:
|
case PAM_SUCCESS:
|
||||||
*pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
|
*pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
|
||||||
@@ -174,11 +178,6 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
|||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case PAM_AUTH_ERR:
|
case PAM_AUTH_ERR:
|
||||||
case PAM_AUTHINFO_UNAVAIL:
|
case PAM_AUTHINFO_UNAVAIL:
|
||||||
if (getpass_error) {
|
|
||||||
/* error or ^C from tgetpass() */
|
|
||||||
debug_return_int(AUTH_INTR);
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case PAM_MAXTRIES:
|
case PAM_MAXTRIES:
|
||||||
case PAM_PERM_DENIED:
|
case PAM_PERM_DENIED:
|
||||||
debug_return_int(AUTH_FAILURE);
|
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. */
|
/* Merge pam env with user env. */
|
||||||
env_init(*user_envp);
|
env_init(*user_envp);
|
||||||
if (!env_merge(pam_envp))
|
if (!env_merge(pam_envp))
|
||||||
status = PAM_SYSTEM_ERR;
|
status = AUTH_FAILURE;
|
||||||
*user_envp = env_get();
|
*user_envp = env_get();
|
||||||
env_init(NULL);
|
env_init(NULL);
|
||||||
sudo_efree(pam_envp);
|
sudo_efree(pam_envp);
|
||||||
@@ -325,11 +324,14 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
|
|||||||
const char *prompt;
|
const char *prompt;
|
||||||
char *pass;
|
char *pass;
|
||||||
int n, type;
|
int n, type;
|
||||||
int ret = PAM_AUTH_ERR;
|
int ret = PAM_SUCCESS;
|
||||||
debug_decl(converse, SUDOERS_DEBUG_AUTH)
|
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)
|
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++) {
|
for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {
|
||||||
type = SUDO_CONV_PROMPT_ECHO_OFF;
|
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);
|
pass = auth_getpass(prompt, def_passwd_timeout * 60, type);
|
||||||
if (pass == NULL) {
|
if (pass == NULL) {
|
||||||
/* Error (or ^C) reading password, don't try again. */
|
/* Error (or ^C) reading password, don't try again. */
|
||||||
getpass_error = 1;
|
getpass_error = true;
|
||||||
#if (defined(__darwin__) || defined(__APPLE__)) && !defined(OPENPAM_VERSION)
|
goto done;
|
||||||
pass = "";
|
}
|
||||||
#else
|
if (strlen(pass) >= PAM_MAX_RESP_SIZE) {
|
||||||
|
ret = PAM_CONV_ERR;
|
||||||
goto done;
|
goto done;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
pr->resp = sudo_estrdup(pass);
|
pr->resp = sudo_estrdup(pass);
|
||||||
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(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;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = PAM_SUCCESS;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (ret != PAM_SUCCESS) {
|
if (ret != PAM_SUCCESS) {
|
||||||
|
Reference in New Issue
Block a user