Only update the time stamp entry after the approval function has succeeded.

Bug #910
This commit is contained in:
Todd C. Miller
2019-12-04 12:38:22 -07:00
parent 049bbbfae1
commit 4b6de608c2

View File

@@ -51,6 +51,7 @@ static bool display_lecture(int);
static struct passwd *get_authpw(int);
struct getpass_closure {
int tstat;
void *cookie;
struct passwd *auth_pw;
};
@@ -89,27 +90,20 @@ getpass_resume(int signo, void *vclosure)
* or -1 on fatal error.
*/
static int
check_user_interactive(int validated, int mode, struct passwd *auth_pw)
check_user_interactive(int validated, int mode, struct getpass_closure *closure)
{
struct sudo_conv_callback cb, *callback = NULL;
struct getpass_closure closure;
int status = TS_ERROR;
int ret = -1;
char *prompt;
bool lectured;
debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH)
/* Setup closure for getpass_{suspend,resume} */
closure.auth_pw = auth_pw;
closure.cookie = NULL;
sudo_pw_addref(closure.auth_pw);
/* Open, lock and read time stamp file if we are using it. */
if (!ISSET(mode, MODE_IGNORE_TICKET)) {
/* Open time stamp file and check its status. */
closure.cookie = timestamp_open(user_name, user_sid);
if (timestamp_lock(closure.cookie, closure.auth_pw))
status = timestamp_status(closure.cookie, closure.auth_pw);
closure->cookie = timestamp_open(user_name, user_sid);
if (timestamp_lock(closure->cookie, closure->auth_pw))
closure->tstat = timestamp_status(closure->cookie, closure->auth_pw);
/* Construct callback for getpass function. */
memset(&cb, 0, sizeof(cb));
@@ -120,7 +114,7 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
callback = &cb;
}
switch (status) {
switch (closure->tstat) {
case TS_FATAL:
/* Fatal error (usually setuid failure), unsafe to proceed. */
goto done;
@@ -144,32 +138,22 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
}
/* XXX - should not lecture if askpass helper is being used. */
lectured = display_lecture(status);
lectured = display_lecture(closure->tstat);
/* Expand any escapes in the prompt. */
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
closure.auth_pw->pw_name);
closure->auth_pw->pw_name);
if (prompt == NULL)
goto done;
ret = verify_user(closure.auth_pw, prompt, validated, callback);
ret = verify_user(closure->auth_pw, prompt, validated, callback);
if (ret == true && lectured)
(void)set_lectured(); /* lecture error not fatal */
free(prompt);
break;
}
/*
* Only update time stamp if user was validated.
* Failure to update the time stamp is not a fatal error.
*/
if (ret == true && ISSET(validated, VALIDATE_SUCCESS) && status != TS_ERROR)
(void)timestamp_update(closure.cookie, closure.auth_pw);
done:
if (closure.cookie != NULL)
timestamp_close(closure.cookie);
sudo_pw_delref(closure.auth_pw);
debug_return_int(ret);
}
@@ -180,7 +164,7 @@ done:
int
check_user(int validated, int mode)
{
struct passwd *auth_pw;
struct getpass_closure closure = { TS_ERROR };
int ret = -1;
bool exempt = false;
debug_decl(check_user, SUDOERS_DEBUG_AUTH)
@@ -189,9 +173,9 @@ check_user(int validated, int mode)
* Init authentication system regardless of whether we need a password.
* Required for proper PAM session support.
*/
if ((auth_pw = get_authpw(mode)) == NULL)
if ((closure.auth_pw = get_authpw(mode)) == NULL)
goto done;
if (sudo_auth_init(auth_pw) == -1)
if (sudo_auth_init(closure.auth_pw) == -1)
goto done;
/*
@@ -222,15 +206,26 @@ check_user(int validated, int mode)
}
}
ret = check_user_interactive(validated, mode, auth_pw);
ret = check_user_interactive(validated, mode, &closure);
done:
if (ret == true) {
/* The approval function may disallow a user post-authentication. */
ret = sudo_auth_approval(auth_pw, validated, exempt);
ret = sudo_auth_approval(closure.auth_pw, validated, exempt);
/*
* Only update time stamp if user validated and was approved.
* Failure to update the time stamp is not a fatal error.
*/
if (ret == true && closure.tstat != TS_ERROR) {
if (ISSET(validated, VALIDATE_SUCCESS))
(void)timestamp_update(closure.cookie, closure.auth_pw);
}
}
sudo_auth_cleanup(auth_pw);
sudo_pw_delref(auth_pw);
timestamp_close(closure.cookie);
sudo_auth_cleanup(closure.auth_pw);
if (closure.auth_pw != NULL)
sudo_pw_delref(closure.auth_pw);
debug_return_int(ret);
}