Display the lecture immediately before prompting for a password.
This means we no longer display the lecture unless the user is going to enter a password. Authentication methods that don't interact with the user via the terminal don't trigger the lecture.
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "sudoers.h"
|
||||
#include "sudo_auth.h"
|
||||
#include "check.h"
|
||||
|
||||
int
|
||||
sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
@@ -53,6 +54,9 @@ sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv
|
||||
if (IS_NONINTERACTIVE(auth))
|
||||
debug_return_int(AUTH_NONINTERACTIVE);
|
||||
|
||||
/* Display lecture if needed and we haven't already done so. */
|
||||
display_lecture(callback);
|
||||
|
||||
/* Try to just check the password */
|
||||
ka_StringToKey(pass, NULL, &afs_key);
|
||||
if (ka_GetAdminToken(pw->pw_name, /* name */
|
||||
|
@@ -54,6 +54,7 @@
|
||||
|
||||
#include "sudoers.h"
|
||||
#include "sudo_auth.h"
|
||||
#include "check.h"
|
||||
|
||||
static int check_dce_status(error_status_t, char *);
|
||||
|
||||
@@ -71,6 +72,9 @@ sudo_dce_verify(struct passwd *pw, char *plain_pw, sudo_auth *auth, struct sudo_
|
||||
if (IS_NONINTERACTIVE(auth))
|
||||
debug_return_int(AUTH_NONINTERACTIVE);
|
||||
|
||||
/* Display lecture if needed and we haven't already done so. */
|
||||
display_lecture(callback);
|
||||
|
||||
/*
|
||||
* Create the local context of the DCE principal necessary
|
||||
* to perform authenticated network operations. The network
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include "sudoers.h"
|
||||
#include "sudo_auth.h"
|
||||
#include "insults.h"
|
||||
#include "check.h"
|
||||
|
||||
static sudo_auth auth_switch[] = {
|
||||
/* Standalone entries first */
|
||||
@@ -443,6 +444,9 @@ auth_getpass(const char *prompt, int type, struct sudo_conv_callback *callback)
|
||||
sigset_t mask, omask;
|
||||
debug_decl(auth_getpass, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
/* Display lecture if needed and we haven't already done so. */
|
||||
display_lecture(callback);
|
||||
|
||||
/* Mask user input if pwfeedback set and echo is off. */
|
||||
if (type == SUDO_CONV_PROMPT_ECHO_OFF && def_pwfeedback)
|
||||
type = SUDO_CONV_PROMPT_MASK;
|
||||
|
@@ -42,15 +42,15 @@
|
||||
#include "sudoers.h"
|
||||
#include "check.h"
|
||||
|
||||
static bool display_lecture(int);
|
||||
static struct passwd *get_authpw(int);
|
||||
|
||||
struct getpass_closure {
|
||||
int tstat;
|
||||
int lectured;
|
||||
void *cookie;
|
||||
struct passwd *auth_pw;
|
||||
};
|
||||
|
||||
static struct passwd *get_authpw(int);
|
||||
|
||||
/*
|
||||
* Called when getpass is suspended so we can drop the lock.
|
||||
*/
|
||||
@@ -87,26 +87,30 @@ getpass_resume(int signo, void *vclosure)
|
||||
static int
|
||||
check_user_interactive(int validated, int mode, struct getpass_closure *closure)
|
||||
{
|
||||
struct sudo_conv_callback cb, *callback = NULL;
|
||||
struct sudo_conv_callback callback;
|
||||
int ret = -1;
|
||||
char *prompt;
|
||||
bool lectured;
|
||||
debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
/* Construct callback for getpass function. */
|
||||
memset(&callback, 0, sizeof(callback));
|
||||
callback.version = SUDO_CONV_CALLBACK_VERSION;
|
||||
callback.closure = closure;
|
||||
callback.on_suspend = getpass_suspend;
|
||||
callback.on_resume = getpass_resume;
|
||||
|
||||
/* 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))
|
||||
closure->tstat = timestamp_status(closure->cookie, closure->auth_pw);
|
||||
|
||||
/* Construct callback for getpass function. */
|
||||
memset(&cb, 0, sizeof(cb));
|
||||
cb.version = SUDO_CONV_CALLBACK_VERSION;
|
||||
cb.closure = closure;
|
||||
cb.on_suspend = getpass_suspend;
|
||||
cb.on_resume = getpass_resume;
|
||||
callback = &cb;
|
||||
if (closure->cookie != NULL) {
|
||||
if (timestamp_lock(closure->cookie, closure->auth_pw)) {
|
||||
closure->tstat = timestamp_status(closure->cookie,
|
||||
closure->auth_pw);
|
||||
}
|
||||
callback.on_suspend = getpass_suspend;
|
||||
callback.on_resume = getpass_resume;
|
||||
}
|
||||
}
|
||||
|
||||
switch (closure->tstat) {
|
||||
@@ -131,17 +135,14 @@ check_user_interactive(int validated, int mode, struct getpass_closure *closure)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* XXX - should not lecture if askpass helper is being used. */
|
||||
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);
|
||||
if (prompt == NULL)
|
||||
goto done;
|
||||
|
||||
ret = verify_user(closure->auth_pw, prompt, validated, callback);
|
||||
if (ret == true && lectured)
|
||||
ret = verify_user(closure->auth_pw, prompt, validated, &callback);
|
||||
if (ret == true && closure->lectured)
|
||||
(void)set_lectured(); /* lecture error not fatal */
|
||||
free(prompt);
|
||||
break;
|
||||
@@ -228,9 +229,10 @@ done:
|
||||
* Display sudo lecture (standard or custom).
|
||||
* Returns true if the user was lectured, else false.
|
||||
*/
|
||||
static bool
|
||||
display_lecture(int status)
|
||||
void
|
||||
display_lecture(struct sudo_conv_callback *callback)
|
||||
{
|
||||
struct getpass_closure *closure = callback->closure;
|
||||
struct sudo_conv_message msg;
|
||||
struct sudo_conv_reply repl;
|
||||
char buf[BUFSIZ];
|
||||
@@ -239,9 +241,11 @@ display_lecture(int status)
|
||||
int fd;
|
||||
debug_decl(lecture, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
if (def_lecture == never ||
|
||||
(def_lecture == once && already_lectured(status)))
|
||||
debug_return_bool(false);
|
||||
if (closure->lectured)
|
||||
debug_return;
|
||||
|
||||
if (def_lecture == never || (def_lecture == once && already_lectured()))
|
||||
debug_return;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
@@ -257,13 +261,12 @@ display_lecture(int status)
|
||||
msg.msg = buf;
|
||||
sudo_conv(1, &msg, &repl, NULL);
|
||||
}
|
||||
close(fd);
|
||||
if (nread == -1) {
|
||||
log_warning(SLOG_RAW_MSG,
|
||||
N_("error reading lecture file %s"), def_lecture_file);
|
||||
debug_return_bool(false);
|
||||
if (nread == 0) {
|
||||
close(fd);
|
||||
goto done;
|
||||
}
|
||||
debug_return_bool(true);
|
||||
log_warning(SLOG_RAW_MSG,
|
||||
N_("error reading lecture file %s"), def_lecture_file);
|
||||
} else {
|
||||
log_warningx(SLOG_RAW_MSG,
|
||||
N_("ignoring lecture file %s: not a regular file"),
|
||||
@@ -286,7 +289,10 @@ display_lecture(int status)
|
||||
" #2) Think before you type.\n"
|
||||
" #3) With great power comes great responsibility.\n\n");
|
||||
sudo_conv(1, &msg, &repl, NULL);
|
||||
debug_return_bool(true);
|
||||
|
||||
done:
|
||||
closure->lectured = true;
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1993-1996,1998-2005, 2007-2014
|
||||
* Copyright (c) 1993-1996, 1998-2005, 2007-2015, 2017-2018, 2021-2022
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -83,8 +83,9 @@ bool timestamp_lock(void *vcookie, struct passwd *pw);
|
||||
bool timestamp_update(void *vcookie, struct passwd *pw);
|
||||
int timestamp_status(void *vcookie, struct passwd *pw);
|
||||
int get_starttime(pid_t pid, struct timespec *starttime);
|
||||
bool already_lectured(int status);
|
||||
bool already_lectured(void);
|
||||
int set_lectured(void);
|
||||
void display_lecture(struct sudo_conv_callback *callback);
|
||||
int create_admin_success_flag(void);
|
||||
|
||||
#endif /* SUDOERS_CHECK_H */
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2014-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
* Copyright (c) 2014-2022 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
|
||||
@@ -1033,7 +1033,7 @@ done:
|
||||
* Returns true if the user has already been lectured.
|
||||
*/
|
||||
bool
|
||||
already_lectured(int unused)
|
||||
already_lectured(void)
|
||||
{
|
||||
char status_file[PATH_MAX];
|
||||
struct stat sb;
|
||||
|
Reference in New Issue
Block a user