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 (*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 (*verify)(struct passwd *pw, char *p, sudo_auth *auth, struct sudo_conv_callback *callback);
int (*approval)(struct passwd *pw, sudo_auth *auth); 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 (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
int (*end_session)(struct passwd *pw, struct sudo_auth *auth); int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
} sudo_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 For PAM, this calls pam_acct_mgmt(). For BSD auth, it calls
auth_approval(). 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 Function to do per-auth method cleanup. This is only run
at the end of the authentication process, after the user at the end of the authentication process, after the user
has completely failed or succeeded to authenticate. has completely failed or succeeded to authenticate.
The ``auth->status'' variable contains the result of the The ``auth->status'' variable contains the result of the
last authentication attempt which may be interesting. 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) 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 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 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); 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 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; struct bsdauth_state *state = auth->data;
debug_decl(bsdauth_cleanup, SUDOERS_DEBUG_AUTH); debug_decl(bsdauth_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -145,7 +145,7 @@ done:
} }
int 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); debug_decl(sudo_fwtk_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -268,7 +268,7 @@ done:
#endif #endif
int 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_context sudo_context;
krb5_principal princ; krb5_principal princ;

View File

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

View File

@@ -100,7 +100,7 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
} }
int 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; char *pw_epasswd = auth->data;
debug_decl(sudo_passwd_cleanup, SUDOERS_DEBUG_AUTH); 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 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; char *pw_epasswd = auth->data;
debug_decl(sudo_secureware_cleanup, SUDOERS_DEBUG_AUTH); 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 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; SIAENTITY *siah = auth->data;
debug_decl(sudo_sia_cleanup, SUDOERS_DEBUG_AUTH); debug_decl(sudo_sia_cleanup, SUDOERS_DEBUG_AUTH);

View File

@@ -1,7 +1,7 @@
/* /*
* SPDX-License-Identifier: ISC * 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 * 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
@@ -199,7 +199,7 @@ sudo_auth_approval(struct passwd *pw, int validated, bool exempt)
* Returns 0 on success and -1 on error. * Returns 0 on success and -1 on error.
*/ */
int int
sudo_auth_cleanup(struct passwd *pw) sudo_auth_cleanup(struct passwd *pw, bool force)
{ {
sudo_auth *auth; sudo_auth *auth;
debug_decl(sudo_auth_cleanup, SUDOERS_DEBUG_AUTH); debug_decl(sudo_auth_cleanup, SUDOERS_DEBUG_AUTH);
@@ -207,7 +207,7 @@ sudo_auth_cleanup(struct passwd *pw)
/* Call cleanup routines. */ /* Call cleanup routines. */
for (auth = auth_switch; auth->name; auth++) { for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) { if (auth->cleanup && !IS_DISABLED(auth)) {
int status = (auth->cleanup)(pw, auth); int status = (auth->cleanup)(pw, auth, force);
if (status == AUTH_FATAL) { if (status == AUTH_FATAL) {
/* Assume error msg already printed. */ /* Assume error msg already printed. */
debug_return_int(-1); 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 (*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 (*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 (*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 (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
int (*end_session)(struct passwd *pw, struct sudo_auth *auth); int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
} sudo_auth; } sudo_auth;
@@ -59,18 +59,18 @@ extern sudo_conv_t sudo_conv;
int bsdauth_init(struct passwd *pw, sudo_auth *auth); 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_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_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_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_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_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_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(struct passwd *pw, sudo_auth *auth);
int sudo_pam_init_quiet(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_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_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_begin_session(struct passwd *pw, char **user_env[], sudo_auth *auth);
int sudo_pam_end_session(struct passwd *pw, sudo_auth *auth); int sudo_pam_end_session(struct passwd *pw, sudo_auth *auth);
int sudo_securid_init(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_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_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_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); int sudo_sia_begin_session(struct passwd *pw, char **user_env[], sudo_auth *auth);
/* Prototypes for normal methods */ /* 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_init(struct passwd *pw, sudo_auth *auth);
int sudo_krb5_setup(struct passwd *pw, char **prompt, 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_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_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_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_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_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_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_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 */ /* Fields: name, flags, init, setup, verify, approval, cleanup, begin_sess, end_sess */
#define AUTH_ENTRY(n, f, i, s, v, a, c, b, e) \ #define AUTH_ENTRY(n, f, i, s, v, a, c, b, e) \

View File

@@ -223,7 +223,7 @@ done:
} }
} }
timestamp_close(closure.cookie); 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) if (closure.auth_pw != NULL)
sudo_pw_delref(closure.auth_pw); 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_end_session(struct passwd *pw);
int sudo_auth_init(struct passwd *pw); int sudo_auth_init(struct passwd *pw);
int sudo_auth_approval(struct passwd *pw, int validated, bool exempt); 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 */ /* set_perms.c */
bool rewind_perms(void); bool rewind_perms(void);