version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.3, 2013/07/22 10:46:12
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 1999-2005, 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 1999-2005, 2007-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 21
|
Line 21
|
#include <config.h> |
#include <config.h> |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> |
|
#include <stdio.h> |
#include <stdio.h> |
#ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
# include <stdlib.h> |
# include <stdlib.h> |
Line 57
|
Line 56
|
# endif |
# endif |
#endif |
#endif |
|
|
|
/* We don't want to translate the strings in the calls to dgt(). */ |
|
#ifdef PAM_TEXT_DOMAIN |
|
# define dgt(d, t) dgettext(d, t) |
|
#endif |
|
|
#include "sudoers.h" |
#include "sudoers.h" |
#include "sudo_auth.h" |
#include "sudo_auth.h" |
|
|
Line 68
|
Line 72
|
# define PAM_CONST |
# define PAM_CONST |
#endif |
#endif |
|
|
static int converse(int, PAM_CONST struct pam_message **, |
|
struct pam_response **, void *); |
|
static char *def_prompt = "Password:"; |
|
static int getpass_error; |
|
|
|
#ifndef PAM_DATA_SILENT |
#ifndef PAM_DATA_SILENT |
#define PAM_DATA_SILENT 0 |
#define PAM_DATA_SILENT 0 |
#endif |
#endif |
|
|
|
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; |
static pam_handle_t *pamh; |
|
|
int |
int |
Line 97 sudo_pam_init(struct passwd *pw, sudo_auth *auth)
|
Line 102 sudo_pam_init(struct passwd *pw, sudo_auth *auth)
|
#endif |
#endif |
pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); |
pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); |
if (pam_status != PAM_SUCCESS) { |
if (pam_status != PAM_SUCCESS) { |
log_error(USE_ERRNO|NO_MAIL, _("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 139 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_error(NO_MAIL, _("account validation failure, " | log_warning(NO_MAIL, N_("account validation failure, " |
"is your account locked?")); |
"is your account locked?")); |
debug_return_int(AUTH_FATAL); |
debug_return_int(AUTH_FATAL); |
case PAM_NEW_AUTHTOK_REQD: |
case PAM_NEW_AUTHTOK_REQD: |
log_error(NO_MAIL, _("Account or password is " | log_warning(NO_MAIL, N_("Account or password is " |
"expired, reset your password and try again")); |
"expired, reset your password and try again")); |
*pam_status = pam_chauthtok(pamh, |
*pam_status = pam_chauthtok(pamh, |
PAM_CHANGE_EXPIRED_AUTHTOK); |
PAM_CHANGE_EXPIRED_AUTHTOK); |
if (*pam_status == PAM_SUCCESS) |
if (*pam_status == PAM_SUCCESS) |
debug_return_int(AUTH_SUCCESS); |
debug_return_int(AUTH_SUCCESS); |
if ((s = pam_strerror(pamh, *pam_status))) | if ((s = pam_strerror(pamh, *pam_status)) != NULL) { |
log_error(NO_MAIL, _("pam_chauthtok: %s"), s); | log_warning(NO_MAIL, |
| N_("unable to change expired password: %s"), s); |
| } |
debug_return_int(AUTH_FAILURE); |
debug_return_int(AUTH_FAILURE); |
case PAM_AUTHTOK_EXPIRED: |
case PAM_AUTHTOK_EXPIRED: |
log_error(NO_MAIL, | log_warning(NO_MAIL, |
_("Password expired, contact your system administrator")); | N_("Password expired, contact your system administrator")); |
debug_return_int(AUTH_FATAL); |
debug_return_int(AUTH_FATAL); |
case PAM_ACCT_EXPIRED: |
case PAM_ACCT_EXPIRED: |
log_error(NO_MAIL, | log_warning(NO_MAIL, |
_("Account expired or PAM config lacks an \"account\" " | N_("Account expired or PAM config lacks an \"account\" " |
"section for sudo, contact your system administrator")); |
"section for sudo, contact your system administrator")); |
debug_return_int(AUTH_FATAL); |
debug_return_int(AUTH_FATAL); |
} |
} |
Line 176 sudo_pam_verify(struct passwd *pw, char *prompt, sudo_
|
Line 184 sudo_pam_verify(struct passwd *pw, char *prompt, sudo_
|
case PAM_PERM_DENIED: |
case PAM_PERM_DENIED: |
debug_return_int(AUTH_FAILURE); |
debug_return_int(AUTH_FAILURE); |
default: |
default: |
if ((s = pam_strerror(pamh, *pam_status))) | if ((s = pam_strerror(pamh, *pam_status)) != NULL) |
log_error(NO_MAIL, _("pam_authenticate: %s"), s); | log_warning(NO_MAIL, N_("PAM authentication error: %s"), s); |
debug_return_int(AUTH_FATAL); |
debug_return_int(AUTH_FATAL); |
} |
} |
} |
} |
Line 230 sudo_pam_begin_session(struct passwd *pw, char **user_
|
Line 238 sudo_pam_begin_session(struct passwd *pw, char **user_
|
* this is not set and so pam_setcred() returns PAM_PERM_DENIED. |
* 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. |
* We can't call pam_acct_mgmt() with Linux-PAM for a similar reason. |
*/ |
*/ |
(void) pam_setcred(pamh, PAM_ESTABLISH_CRED); | 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; |
| } |
|
|
#ifdef HAVE_PAM_GETENVLIST |
#ifdef HAVE_PAM_GETENVLIST |
/* |
/* |
Line 252 sudo_pam_begin_session(struct passwd *pw, char **user_
|
Line 268 sudo_pam_begin_session(struct passwd *pw, char **user_
|
} |
} |
#endif /* HAVE_PAM_GETENVLIST */ |
#endif /* HAVE_PAM_GETENVLIST */ |
|
|
#ifndef NO_PAM_SESSION | if (def_pam_session) { |
status = pam_open_session(pamh, 0); | status = pam_open_session(pamh, 0); |
if (status != PAM_SUCCESS) { | if (status != PAM_SUCCESS) { |
(void) pam_end(pamh, status | PAM_DATA_SILENT); | (void) pam_end(pamh, status | PAM_DATA_SILENT); |
pamh = NULL; | pamh = NULL; |
| } |
} |
} |
#endif |
|
|
|
done: |
done: |
debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); |
debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); |
Line 277 sudo_pam_end_session(struct passwd *pw, sudo_auth *aut
|
Line 293 sudo_pam_end_session(struct passwd *pw, sudo_auth *aut
|
* XXX - still needed now that session init is in parent? |
* XXX - still needed now that session init is in parent? |
*/ |
*/ |
(void) pam_set_item(pamh, PAM_USER, pw->pw_name); |
(void) pam_set_item(pamh, PAM_USER, pw->pw_name); |
#ifndef NO_PAM_SESSION | if (def_pam_session) |
(void) pam_close_session(pamh, PAM_SILENT); | (void) pam_close_session(pamh, PAM_SILENT); |
#endif | if (sudo_pam_cred_established) |
(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); |
status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); |
pamh = NULL; |
pamh = NULL; |
} |
} |
Line 321 converse(int num_msg, PAM_CONST struct pam_message **m
|
Line 337 converse(int num_msg, PAM_CONST struct pam_message **m
|
if (getpass_error) |
if (getpass_error) |
goto done; |
goto done; |
|
|
/* Is the sudo prompt standard? (If so, we'l just use PAM's) */ | /* Is the sudo prompt standard? (If so, we'll just use PAM's) */ |
std_prompt = strncmp(def_prompt, "Password:", 9) == 0 && |
std_prompt = strncmp(def_prompt, "Password:", 9) == 0 && |
(def_prompt[9] == '\0' || |
(def_prompt[9] == '\0' || |
(def_prompt[9] == ' ' && def_prompt[10] == '\0')); |
(def_prompt[9] == ' ' && def_prompt[10] == '\0')); |
Line 329 converse(int num_msg, PAM_CONST struct pam_message **m
|
Line 345 converse(int num_msg, PAM_CONST struct pam_message **m
|
/* Only override PAM prompt if it matches /^Password: ?/ */ |
/* Only override PAM prompt if it matches /^Password: ?/ */ |
#if defined(PAM_TEXT_DOMAIN) && defined(HAVE_LIBINTL_H) |
#if defined(PAM_TEXT_DOMAIN) && defined(HAVE_LIBINTL_H) |
if (!def_passprompt_override && (std_prompt || |
if (!def_passprompt_override && (std_prompt || |
(strcmp(pm->msg, dgettext(PAM_TEXT_DOMAIN, "Password: ")) && | (strcmp(pm->msg, dgt(PAM_TEXT_DOMAIN, "Password: ")) && |
strcmp(pm->msg, dgettext(PAM_TEXT_DOMAIN, "Password:"))))) | strcmp(pm->msg, dgt(PAM_TEXT_DOMAIN, "Password:"))))) |
prompt = pm->msg; |
prompt = pm->msg; |
#else |
#else |
if (!def_passprompt_override && (std_prompt || |
if (!def_passprompt_override && (std_prompt || |