Add a force flag to sudo_auth_cleanup() to force immediate cleanup.

This is used for PAM authentication to make sure pam_end() is called
via sudo_auth_cleanup() when the user authenticates successfully but
sudoers denies the command.  Debian bug #669687
This commit is contained in:
Todd C. Miller
2020-04-01 14:41:38 -06:00
parent 5e95c24d81
commit ec3fdd3aa8
13 changed files with 26 additions and 25 deletions

View File

@@ -16,7 +16,7 @@ typedef struct sudo_auth {
int (*setup)(struct passwd *pw, char **prompt, sudo_auth *auth);
int (*verify)(struct passwd *pw, char *p, sudo_auth *auth, struct sudo_conv_callback *callback);
int (*approval)(struct passwd *pw, sudo_auth *auth);
int (*cleanup)(struct passwd *pw, sudo_auth *auth);
int (*cleanup)(struct passwd *pw, sudo_auth *auth, bool force);
int (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
} sudo_auth;
@@ -88,12 +88,13 @@ The functions in the struct are as follows:
For PAM, this calls pam_acct_mgmt(). For BSD auth, it calls
auth_approval().
int cleanup(struct passwd *pw, sudo_auth *auth)
int cleanup(struct passwd *pw, sudo_auth *auth, bool force)
Function to do per-auth method cleanup. This is only run
at the end of the authentication process, after the user
has completely failed or succeeded to authenticate.
The ``auth->status'' variable contains the result of the
last authentication attempt which may be interesting.
If the force flag is set, cleanup should happen immediately.
int begin_session(struct passwd *pw, char **user_env[], struct sudo_auth *auth)
Function to begin a user session. This is used for session handling

View File

@@ -300,7 +300,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_co
}
int
sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
debug_decl(sudo_aix_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -191,7 +191,7 @@ bsdauth_approval(struct passwd *pw, sudo_auth *auth, bool exempt)
}
int
bsdauth_cleanup(struct passwd *pw, sudo_auth *auth)
bsdauth_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
struct bsdauth_state *state = auth->data;
debug_decl(bsdauth_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -145,7 +145,7 @@ done:
}
int
sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
debug_decl(sudo_fwtk_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -268,7 +268,7 @@ done:
#endif
int
sudo_krb5_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_krb5_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
krb5_context sudo_context;
krb5_principal princ;

View File

@@ -394,13 +394,13 @@ sudo_pam_approval(struct passwd *pw, sudo_auth *auth, bool exempt)
}
int
sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
int *pam_status = (int *) auth->data;
debug_decl(sudo_pam_cleanup, SUDOERS_DEBUG_AUTH);
/* If successful, we can't close the session until sudo_pam_end_session() */
if (*pam_status != PAM_SUCCESS || auth->end_session == NULL) {
if (force || *pam_status != PAM_SUCCESS || auth->end_session == NULL) {
*pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
pamh = NULL;
}

View File

@@ -100,7 +100,7 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
}
int
sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
char *pw_epasswd = auth->data;
debug_decl(sudo_passwd_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -101,7 +101,7 @@ sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct su
}
int
sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
char *pw_epasswd = auth->data;
debug_decl(sudo_secureware_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -106,7 +106,7 @@ sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth,
}
int
sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth)
sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
{
SIAENTITY *siah = auth->data;
debug_decl(sudo_sia_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 1999-2005, 2008-2018 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 1999-2005, 2008-2020 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -199,7 +199,7 @@ sudo_auth_approval(struct passwd *pw, int validated, bool exempt)
* Returns 0 on success and -1 on error.
*/
int
sudo_auth_cleanup(struct passwd *pw)
sudo_auth_cleanup(struct passwd *pw, bool force)
{
sudo_auth *auth;
debug_decl(sudo_auth_cleanup, SUDOERS_DEBUG_AUTH);
@@ -207,7 +207,7 @@ sudo_auth_cleanup(struct passwd *pw)
/* Call cleanup routines. */
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) {
int status = (auth->cleanup)(pw, auth);
int status = (auth->cleanup)(pw, auth, force);
if (status == AUTH_FATAL) {
/* Assume error msg already printed. */
debug_return_int(-1);

View File

@@ -34,7 +34,7 @@ typedef struct sudo_auth {
int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth, struct sudo_conv_callback *callback);
int (*approval)(struct passwd *pw, struct sudo_auth *auth, bool exempt);
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth, bool force);
int (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
} sudo_auth;
@@ -59,18 +59,18 @@ extern sudo_conv_t sudo_conv;
int bsdauth_init(struct passwd *pw, sudo_auth *auth);
int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
int bsdauth_approval(struct passwd *pw, sudo_auth *auth, bool exempt);
int bsdauth_cleanup(struct passwd *pw, sudo_auth *auth);
int bsdauth_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_aix_init(struct passwd *pw, sudo_auth *auth);
int sudo_aix_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_fwtk_init(struct passwd *pw, sudo_auth *auth);
int sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_pam_init(struct passwd *pw, sudo_auth *auth);
int sudo_pam_init_quiet(struct passwd *pw, sudo_auth *auth);
int sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_pam_approval(struct passwd *pw, sudo_auth *auth, bool exempt);
int sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_pam_begin_session(struct passwd *pw, char **user_env[], sudo_auth *auth);
int sudo_pam_end_session(struct passwd *pw, sudo_auth *auth);
int sudo_securid_init(struct passwd *pw, sudo_auth *auth);
@@ -78,7 +78,7 @@ int sudo_securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_sia_begin_session(struct passwd *pw, char **user_env[], sudo_auth *auth);
/* Prototypes for normal methods */
@@ -87,15 +87,15 @@ int sudo_dce_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_
int sudo_krb5_init(struct passwd *pw, sudo_auth *auth);
int sudo_krb5_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_krb5_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_krb5_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_passwd_init(struct passwd *pw, sudo_auth *auth);
int sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
int sudo_rfc1938_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_secureware_init(struct passwd *pw, sudo_auth *auth);
int sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth, bool force);
/* Fields: name, flags, init, setup, verify, approval, cleanup, begin_sess, end_sess */
#define AUTH_ENTRY(n, f, i, s, v, a, c, b, e) \

View File

@@ -223,7 +223,7 @@ done:
}
}
timestamp_close(closure.cookie);
sudo_auth_cleanup(closure.auth_pw);
sudo_auth_cleanup(closure.auth_pw, !ISSET(validated, VALIDATE_SUCCESS));
if (closure.auth_pw != NULL)
sudo_pw_delref(closure.auth_pw);

View File

@@ -272,7 +272,7 @@ int sudo_auth_begin_session(struct passwd *pw, char **user_env[]);
int sudo_auth_end_session(struct passwd *pw);
int sudo_auth_init(struct passwd *pw);
int sudo_auth_approval(struct passwd *pw, int validated, bool exempt);
int sudo_auth_cleanup(struct passwd *pw);
int sudo_auth_cleanup(struct passwd *pw, bool force);
/* set_perms.c */
bool rewind_perms(void);