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