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 "sudoers.h"
|
||||||
#include "sudo_auth.h"
|
#include "sudo_auth.h"
|
||||||
|
#include "check.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
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))
|
if (IS_NONINTERACTIVE(auth))
|
||||||
debug_return_int(AUTH_NONINTERACTIVE);
|
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 */
|
/* Try to just check the password */
|
||||||
ka_StringToKey(pass, NULL, &afs_key);
|
ka_StringToKey(pass, NULL, &afs_key);
|
||||||
if (ka_GetAdminToken(pw->pw_name, /* name */
|
if (ka_GetAdminToken(pw->pw_name, /* name */
|
||||||
|
@@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
#include "sudoers.h"
|
#include "sudoers.h"
|
||||||
#include "sudo_auth.h"
|
#include "sudo_auth.h"
|
||||||
|
#include "check.h"
|
||||||
|
|
||||||
static int check_dce_status(error_status_t, char *);
|
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))
|
if (IS_NONINTERACTIVE(auth))
|
||||||
debug_return_int(AUTH_NONINTERACTIVE);
|
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
|
* Create the local context of the DCE principal necessary
|
||||||
* to perform authenticated network operations. The network
|
* to perform authenticated network operations. The network
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include "sudoers.h"
|
#include "sudoers.h"
|
||||||
#include "sudo_auth.h"
|
#include "sudo_auth.h"
|
||||||
#include "insults.h"
|
#include "insults.h"
|
||||||
|
#include "check.h"
|
||||||
|
|
||||||
static sudo_auth auth_switch[] = {
|
static sudo_auth auth_switch[] = {
|
||||||
/* Standalone entries first */
|
/* Standalone entries first */
|
||||||
@@ -443,6 +444,9 @@ auth_getpass(const char *prompt, int type, struct sudo_conv_callback *callback)
|
|||||||
sigset_t mask, omask;
|
sigset_t mask, omask;
|
||||||
debug_decl(auth_getpass, SUDOERS_DEBUG_AUTH);
|
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. */
|
/* Mask user input if pwfeedback set and echo is off. */
|
||||||
if (type == SUDO_CONV_PROMPT_ECHO_OFF && def_pwfeedback)
|
if (type == SUDO_CONV_PROMPT_ECHO_OFF && def_pwfeedback)
|
||||||
type = SUDO_CONV_PROMPT_MASK;
|
type = SUDO_CONV_PROMPT_MASK;
|
||||||
|
@@ -42,15 +42,15 @@
|
|||||||
#include "sudoers.h"
|
#include "sudoers.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
static bool display_lecture(int);
|
|
||||||
static struct passwd *get_authpw(int);
|
|
||||||
|
|
||||||
struct getpass_closure {
|
struct getpass_closure {
|
||||||
int tstat;
|
int tstat;
|
||||||
|
int lectured;
|
||||||
void *cookie;
|
void *cookie;
|
||||||
struct passwd *auth_pw;
|
struct passwd *auth_pw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct passwd *get_authpw(int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when getpass is suspended so we can drop the lock.
|
* Called when getpass is suspended so we can drop the lock.
|
||||||
*/
|
*/
|
||||||
@@ -87,26 +87,30 @@ getpass_resume(int signo, void *vclosure)
|
|||||||
static int
|
static int
|
||||||
check_user_interactive(int validated, int mode, struct getpass_closure *closure)
|
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;
|
int ret = -1;
|
||||||
char *prompt;
|
char *prompt;
|
||||||
bool lectured;
|
|
||||||
debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH);
|
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. */
|
/* Open, lock and read time stamp file if we are using it. */
|
||||||
if (!ISSET(mode, MODE_IGNORE_TICKET)) {
|
if (!ISSET(mode, MODE_IGNORE_TICKET)) {
|
||||||
/* Open time stamp file and check its status. */
|
/* Open time stamp file and check its status. */
|
||||||
closure->cookie = timestamp_open(user_name, user_sid);
|
closure->cookie = timestamp_open(user_name, user_sid);
|
||||||
if (timestamp_lock(closure->cookie, closure->auth_pw))
|
if (closure->cookie != NULL) {
|
||||||
closure->tstat = timestamp_status(closure->cookie, closure->auth_pw);
|
if (timestamp_lock(closure->cookie, closure->auth_pw)) {
|
||||||
|
closure->tstat = timestamp_status(closure->cookie,
|
||||||
/* Construct callback for getpass function. */
|
closure->auth_pw);
|
||||||
memset(&cb, 0, sizeof(cb));
|
}
|
||||||
cb.version = SUDO_CONV_CALLBACK_VERSION;
|
callback.on_suspend = getpass_suspend;
|
||||||
cb.closure = closure;
|
callback.on_resume = getpass_resume;
|
||||||
cb.on_suspend = getpass_suspend;
|
}
|
||||||
cb.on_resume = getpass_resume;
|
|
||||||
callback = &cb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (closure->tstat) {
|
switch (closure->tstat) {
|
||||||
@@ -131,17 +135,14 @@ check_user_interactive(int validated, int mode, struct getpass_closure *closure)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX - should not lecture if askpass helper is being used. */
|
|
||||||
lectured = display_lecture(closure->tstat);
|
|
||||||
|
|
||||||
/* Expand any escapes in the prompt. */
|
/* Expand any escapes in the prompt. */
|
||||||
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
|
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
|
||||||
closure->auth_pw->pw_name);
|
closure->auth_pw->pw_name);
|
||||||
if (prompt == NULL)
|
if (prompt == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
ret = verify_user(closure->auth_pw, prompt, validated, callback);
|
ret = verify_user(closure->auth_pw, prompt, validated, &callback);
|
||||||
if (ret == true && lectured)
|
if (ret == true && closure->lectured)
|
||||||
(void)set_lectured(); /* lecture error not fatal */
|
(void)set_lectured(); /* lecture error not fatal */
|
||||||
free(prompt);
|
free(prompt);
|
||||||
break;
|
break;
|
||||||
@@ -228,9 +229,10 @@ done:
|
|||||||
* Display sudo lecture (standard or custom).
|
* Display sudo lecture (standard or custom).
|
||||||
* Returns true if the user was lectured, else false.
|
* Returns true if the user was lectured, else false.
|
||||||
*/
|
*/
|
||||||
static bool
|
void
|
||||||
display_lecture(int status)
|
display_lecture(struct sudo_conv_callback *callback)
|
||||||
{
|
{
|
||||||
|
struct getpass_closure *closure = callback->closure;
|
||||||
struct sudo_conv_message msg;
|
struct sudo_conv_message msg;
|
||||||
struct sudo_conv_reply repl;
|
struct sudo_conv_reply repl;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
@@ -239,9 +241,11 @@ display_lecture(int status)
|
|||||||
int fd;
|
int fd;
|
||||||
debug_decl(lecture, SUDOERS_DEBUG_AUTH);
|
debug_decl(lecture, SUDOERS_DEBUG_AUTH);
|
||||||
|
|
||||||
if (def_lecture == never ||
|
if (closure->lectured)
|
||||||
(def_lecture == once && already_lectured(status)))
|
debug_return;
|
||||||
debug_return_bool(false);
|
|
||||||
|
if (def_lecture == never || (def_lecture == once && already_lectured()))
|
||||||
|
debug_return;
|
||||||
|
|
||||||
memset(&msg, 0, sizeof(msg));
|
memset(&msg, 0, sizeof(msg));
|
||||||
memset(&repl, 0, sizeof(repl));
|
memset(&repl, 0, sizeof(repl));
|
||||||
@@ -257,13 +261,12 @@ display_lecture(int status)
|
|||||||
msg.msg = buf;
|
msg.msg = buf;
|
||||||
sudo_conv(1, &msg, &repl, NULL);
|
sudo_conv(1, &msg, &repl, NULL);
|
||||||
}
|
}
|
||||||
|
if (nread == 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
if (nread == -1) {
|
goto done;
|
||||||
|
}
|
||||||
log_warning(SLOG_RAW_MSG,
|
log_warning(SLOG_RAW_MSG,
|
||||||
N_("error reading lecture file %s"), def_lecture_file);
|
N_("error reading lecture file %s"), def_lecture_file);
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
|
||||||
} else {
|
} else {
|
||||||
log_warningx(SLOG_RAW_MSG,
|
log_warningx(SLOG_RAW_MSG,
|
||||||
N_("ignoring lecture file %s: not a regular file"),
|
N_("ignoring lecture file %s: not a regular file"),
|
||||||
@@ -286,7 +289,10 @@ display_lecture(int status)
|
|||||||
" #2) Think before you type.\n"
|
" #2) Think before you type.\n"
|
||||||
" #3) With great power comes great responsibility.\n\n");
|
" #3) With great power comes great responsibility.\n\n");
|
||||||
sudo_conv(1, &msg, &repl, NULL);
|
sudo_conv(1, &msg, &repl, NULL);
|
||||||
debug_return_bool(true);
|
|
||||||
|
done:
|
||||||
|
closure->lectured = true;
|
||||||
|
debug_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* 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>
|
* 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
|
||||||
@@ -83,8 +83,9 @@ bool timestamp_lock(void *vcookie, struct passwd *pw);
|
|||||||
bool timestamp_update(void *vcookie, struct passwd *pw);
|
bool timestamp_update(void *vcookie, struct passwd *pw);
|
||||||
int timestamp_status(void *vcookie, struct passwd *pw);
|
int timestamp_status(void *vcookie, struct passwd *pw);
|
||||||
int get_starttime(pid_t pid, struct timespec *starttime);
|
int get_starttime(pid_t pid, struct timespec *starttime);
|
||||||
bool already_lectured(int status);
|
bool already_lectured(void);
|
||||||
int set_lectured(void);
|
int set_lectured(void);
|
||||||
|
void display_lecture(struct sudo_conv_callback *callback);
|
||||||
int create_admin_success_flag(void);
|
int create_admin_success_flag(void);
|
||||||
|
|
||||||
#endif /* SUDOERS_CHECK_H */
|
#endif /* SUDOERS_CHECK_H */
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* 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
|
* 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
|
||||||
@@ -1033,7 +1033,7 @@ done:
|
|||||||
* Returns true if the user has already been lectured.
|
* Returns true if the user has already been lectured.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
already_lectured(int unused)
|
already_lectured(void)
|
||||||
{
|
{
|
||||||
char status_file[PATH_MAX];
|
char status_file[PATH_MAX];
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
Reference in New Issue
Block a user