Modify the authentication API such that the init and cleanup functions

are always called, regardless of whether or not we are going to
verify a password.  This is needed for proper PAM session support.
This commit is contained in:
Todd C. Miller
2011-09-27 13:18:46 -04:00
parent c21595044d
commit bceb5df158
15 changed files with 163 additions and 116 deletions

View File

@@ -86,7 +86,7 @@ static sudo_auth auth_switch[] = {
AUTH_ENTRY("kerb4", 0, kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL)
#endif
#ifdef HAVE_KERB5
AUTH_ENTRY("kerb5", 0, kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL)
AUTH_ENTRY("kerb5", 0, kerb5_init, kerb5_setup, kerb5_verify, kerb5_cleanup, NULL, NULL)
#endif
#ifdef HAVE_SKEY
AUTH_ENTRY("S/Key", 0, NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
@@ -97,35 +97,19 @@ static sudo_auth auth_switch[] = {
AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL)
};
static int standalone;
extern char **NewArgv; /* XXX - for auditing */
static void pass_warn(void);
int
verify_user(struct passwd *pw, char *prompt)
sudo_auth_init(struct passwd *pw)
{
int counter = def_passwd_tries + 1;
int success = AUTH_FAILURE;
int flags, status, standalone, rval;
char *p;
sudo_auth *auth;
sigaction_t sa, osa;
/* Enable suspend during password entry. */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL;
(void) sigaction(SIGTSTP, &sa, &osa);
/* Make sure we have at least one auth method. */
if (auth_switch[0].name == NULL) {
audit_failure(NewArgv, "no authentication methods");
log_error(0,
_("There are no authentication methods compiled into sudo! "
"If you want to turn off authentication, use the "
"--disable-authentication configure option."));
return -1;
}
if (auth_switch[0].name == NULL)
return AUTH_SUCCESS;
/* Make sure we haven't mixed standalone and shared auth methods. */
standalone = IS_STANDALONE(&auth_switch[0]);
@@ -146,10 +130,36 @@ verify_user(struct passwd *pw, char *prompt)
if (NEEDS_USER(auth))
set_perms(PERM_USER);
status = (auth->init)(pw, &prompt, auth);
if (status == AUTH_FAILURE)
SET(auth->flags, FLAG_DISABLED);
else if (status == AUTH_FATAL) { /* XXX log */
switch ((auth->init)(pw, auth)) {
case AUTH_FAILURE:
SET(auth->flags, FLAG_DISABLED);
break;
case AUTH_FATAL:
/* XXX log */
audit_failure(NewArgv, "authentication failure");
return -1; /* assume error msg already printed */
}
if (NEEDS_USER(auth))
restore_perms();
}
}
return AUTH_SUCCESS;
}
int
sudo_auth_cleanup(struct passwd *pw)
{
sudo_auth *auth;
/* Call cleanup routines. */
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) {
if (NEEDS_USER(auth))
set_perms(PERM_USER);
if ((auth->cleanup)(pw, auth) == AUTH_FATAL) {
/* XXX log */
audit_failure(NewArgv, "authentication failure");
return -1; /* assume error msg already printed */
}
@@ -158,6 +168,35 @@ verify_user(struct passwd *pw, char *prompt)
restore_perms();
}
}
return AUTH_SUCCESS;
}
int
verify_user(struct passwd *pw, char *prompt)
{
int counter = def_passwd_tries + 1;
int success = AUTH_FAILURE;
int flags, status, rval;
char *p;
sudo_auth *auth;
sigaction_t sa, osa;
/* Enable suspend during password entry. */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL;
(void) sigaction(SIGTSTP, &sa, &osa);
/* Make sure we have at least one auth method. */
/* XXX - check FLAG_DISABLED too */
if (auth_switch[0].name == NULL) {
audit_failure(NewArgv, "no authentication methods");
log_error(0,
_("There are no authentication methods compiled into sudo! "
"If you want to turn off authentication, use the "
"--disable-authentication configure option."));
return -1;
}
while (--counter) {
/* Do any per-method setup and unconfigure the method if needed */
@@ -203,31 +242,14 @@ verify_user(struct passwd *pw, char *prompt)
restore_perms();
if (auth->status != AUTH_FAILURE)
goto cleanup;
goto done;
}
if (!standalone)
zero_bytes(p, strlen(p));
pass_warn();
}
cleanup:
/* Call cleanup routines. */
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) {
if (NEEDS_USER(auth))
set_perms(PERM_USER);
status = (auth->cleanup)(pw, auth);
if (status == AUTH_FATAL) { /* XXX log */
audit_failure(NewArgv, "authentication failure");
return -1; /* assume error msg already printed */
}
if (NEEDS_USER(auth))
restore_perms();
}
}
done:
switch (success) {
case AUTH_SUCCESS:
(void) sigaction(SIGTSTP, &osa, NULL);
@@ -257,7 +279,8 @@ cleanup:
return rval;
}
int auth_begin_session(struct passwd *pw)
int
sudo_auth_begin_session(struct passwd *pw)
{
sudo_auth *auth;
int status;
@@ -274,7 +297,8 @@ int auth_begin_session(struct passwd *pw)
return TRUE;
}
int auth_end_session(struct passwd *pw)
int
sudo_auth_end_session(struct passwd *pw)
{
sudo_auth *auth;
int status;