Treat an authentication failure as a reject, not an alert.
This matters when logging via sudo_logsrvd. It also lets us remove a special case in vlog_warning().
This commit is contained in:
@@ -54,22 +54,40 @@
|
|||||||
|
|
||||||
#include "sudoers.h"
|
#include "sudoers.h"
|
||||||
|
|
||||||
/* Special message for log_warning() so we know to use ngettext() */
|
|
||||||
#define INCORRECT_PASSWORD_ATTEMPT ((char *)0x01)
|
|
||||||
|
|
||||||
static bool should_mail(int);
|
static bool should_mail(int);
|
||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log a reject event to syslog, a log file, sudo_logsrvd and/or email.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
log_reject(const char *message, bool logit, bool mailit)
|
||||||
|
{
|
||||||
|
int evl_flags = 0;
|
||||||
|
struct eventlog evlog;
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_reject, SUDOERS_DEBUG_LOGGING);
|
||||||
|
|
||||||
|
if (mailit) {
|
||||||
|
SET(evl_flags, EVLOG_MAIL);
|
||||||
|
if (!logit)
|
||||||
|
SET(evl_flags, EVLOG_MAIL_ONLY);
|
||||||
|
}
|
||||||
|
sudoers_to_eventlog(&evlog);
|
||||||
|
if (!eventlog_reject(&evlog, evl_flags, message, NULL, NULL))
|
||||||
|
ret = false;
|
||||||
|
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Log, audit and mail the denial message, optionally informing the user.
|
* Log, audit and mail the denial message, optionally informing the user.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
log_denial(int status, bool inform_user)
|
log_denial(int status, bool inform_user)
|
||||||
{
|
{
|
||||||
struct eventlog evlog;
|
|
||||||
const char *message;
|
const char *message;
|
||||||
int oldlocale;
|
int oldlocale;
|
||||||
int evl_flags = 0;
|
|
||||||
bool mailit, ret = true;
|
bool mailit, ret = true;
|
||||||
debug_decl(log_denial, SUDOERS_DEBUG_LOGGING);
|
debug_decl(log_denial, SUDOERS_DEBUG_LOGGING);
|
||||||
|
|
||||||
@@ -91,20 +109,14 @@ log_denial(int status, bool inform_user)
|
|||||||
/* Log and mail messages should be in the sudoers locale. */
|
/* Log and mail messages should be in the sudoers locale. */
|
||||||
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
||||||
|
|
||||||
if (mailit) {
|
if (!log_reject(message, def_log_denied, mailit))
|
||||||
SET(evl_flags, EVLOG_MAIL);
|
|
||||||
if (!def_log_denied)
|
|
||||||
SET(evl_flags, EVLOG_MAIL_ONLY);
|
|
||||||
}
|
|
||||||
sudoers_to_eventlog(&evlog);
|
|
||||||
if (!eventlog_reject(&evlog, evl_flags, message, NULL, NULL))
|
|
||||||
ret = false;
|
ret = false;
|
||||||
|
|
||||||
/* Restore locale. */
|
/* Restore locale. */
|
||||||
sudoers_setlocale(oldlocale, NULL);
|
sudoers_setlocale(oldlocale, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inform the user if they failed to authenticate (in their locale). */
|
/* Inform the user of the failure (in their locale). */
|
||||||
if (inform_user) {
|
if (inform_user) {
|
||||||
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
|
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
|
||||||
|
|
||||||
@@ -164,90 +176,13 @@ log_failure(int status, int flags)
|
|||||||
debug_return_bool(ret);
|
debug_return_bool(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Log and audit that user was not able to authenticate themselves.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
log_auth_failure(int status, unsigned int tries)
|
|
||||||
{
|
|
||||||
int flags = 0;
|
|
||||||
bool ret = true;
|
|
||||||
debug_decl(log_auth_failure, SUDOERS_DEBUG_LOGGING);
|
|
||||||
|
|
||||||
/* Do auditing first (audit_failure() handles the locale itself). */
|
|
||||||
audit_failure(NewArgv, "%s", N_("authentication failure"));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do we need to send mail?
|
|
||||||
* We want to avoid sending multiple messages for the same command
|
|
||||||
* so if we are going to send an email about the denial, that takes
|
|
||||||
* precedence.
|
|
||||||
*/
|
|
||||||
if (ISSET(status, VALIDATE_SUCCESS)) {
|
|
||||||
/* Command allowed, auth failed; do we need to send mail? */
|
|
||||||
if (def_mail_badpass || def_mail_always)
|
|
||||||
SET(flags, SLOG_SEND_MAIL);
|
|
||||||
} else {
|
|
||||||
/* Command denied, auth failed; make sure we don't send mail twice. */
|
|
||||||
if (def_mail_badpass && !should_mail(status))
|
|
||||||
SET(flags, SLOG_SEND_MAIL);
|
|
||||||
/* Don't log the bad password message, we'll log a denial instead. */
|
|
||||||
SET(flags, SLOG_NO_LOG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If sudoers denied the command we'll log that separately.
|
|
||||||
*/
|
|
||||||
if (ISSET(status, FLAG_BAD_PASSWORD))
|
|
||||||
ret = log_warningx(flags, INCORRECT_PASSWORD_ATTEMPT, tries);
|
|
||||||
else if (ISSET(status, FLAG_NON_INTERACTIVE))
|
|
||||||
ret = log_warningx(flags, N_("a password is required"));
|
|
||||||
|
|
||||||
debug_return_bool(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Log and potentially mail the allowed command.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
log_allowed(void)
|
|
||||||
{
|
|
||||||
struct eventlog evlog;
|
|
||||||
int oldlocale;
|
|
||||||
int evl_flags = 0;
|
|
||||||
bool mailit, ret = true;
|
|
||||||
debug_decl(log_allowed, SUDOERS_DEBUG_LOGGING);
|
|
||||||
|
|
||||||
/* Send mail based on status. */
|
|
||||||
mailit = should_mail(VALIDATE_SUCCESS);
|
|
||||||
|
|
||||||
if (def_log_allowed || mailit) {
|
|
||||||
/* Log and mail messages should be in the sudoers locale. */
|
|
||||||
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
|
||||||
|
|
||||||
sudoers_to_eventlog(&evlog);
|
|
||||||
if (mailit) {
|
|
||||||
SET(evl_flags, EVLOG_MAIL);
|
|
||||||
if (!def_log_allowed)
|
|
||||||
SET(evl_flags, EVLOG_MAIL_ONLY);
|
|
||||||
}
|
|
||||||
if (!eventlog_accept(&evlog, evl_flags, NULL, NULL))
|
|
||||||
ret = false;
|
|
||||||
|
|
||||||
sudoers_setlocale(oldlocale, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_return_bool(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format an authentication failure message, using either
|
* Format an authentication failure message, using either
|
||||||
* authfail_message from sudoers or a locale-specific message.
|
* authfail_message from sudoers or a locale-specific message.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
fmt_authfail_message(char **str, va_list ap)
|
fmt_authfail_message(char **str, unsigned int tries)
|
||||||
{
|
{
|
||||||
unsigned int tries = va_arg(ap, unsigned int);
|
|
||||||
char *src, *dst0, *dst, *dst_end;
|
char *src, *dst0, *dst, *dst_end;
|
||||||
size_t size;
|
size_t size;
|
||||||
int len;
|
int len;
|
||||||
@@ -296,6 +231,122 @@ done:
|
|||||||
debug_return_int(dst - dst0);
|
debug_return_int(dst - dst0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log and audit that user was not able to authenticate themselves.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
log_auth_failure(int status, unsigned int tries)
|
||||||
|
{
|
||||||
|
char *message = NULL;
|
||||||
|
int oldlocale;
|
||||||
|
bool ret = true;
|
||||||
|
bool mailit = false;
|
||||||
|
bool logit = true;
|
||||||
|
debug_decl(log_auth_failure, SUDOERS_DEBUG_LOGGING);
|
||||||
|
|
||||||
|
/* Do auditing first (audit_failure() handles the locale itself). */
|
||||||
|
audit_failure(NewArgv, "%s", N_("authentication failure"));
|
||||||
|
|
||||||
|
/* If sudoers denied the command we'll log that separately. */
|
||||||
|
if (!ISSET(status, FLAG_BAD_PASSWORD|FLAG_NON_INTERACTIVE))
|
||||||
|
logit = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do we need to send mail?
|
||||||
|
* We want to avoid sending multiple messages for the same command
|
||||||
|
* so if we are going to send an email about the denial, that takes
|
||||||
|
* precedence.
|
||||||
|
*/
|
||||||
|
if (ISSET(status, VALIDATE_SUCCESS)) {
|
||||||
|
/* Command allowed, auth failed; do we need to send mail? */
|
||||||
|
if (def_mail_badpass || def_mail_always)
|
||||||
|
mailit = true;
|
||||||
|
if (!def_log_denied)
|
||||||
|
logit = false;
|
||||||
|
} else {
|
||||||
|
/* Command denied, auth failed; make sure we don't send mail twice. */
|
||||||
|
if (def_mail_badpass && !should_mail(status))
|
||||||
|
mailit = true;
|
||||||
|
/* Don't log the bad password message, we'll log a denial instead. */
|
||||||
|
logit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logit || mailit) {
|
||||||
|
/* Log and mail messages should be in the sudoers locale. */
|
||||||
|
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
||||||
|
|
||||||
|
if (ISSET(status, FLAG_BAD_PASSWORD)) {
|
||||||
|
if (fmt_authfail_message(&message, tries) == -1) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__,
|
||||||
|
U_("unable to allocate memory"));
|
||||||
|
ret = false;
|
||||||
|
} else {
|
||||||
|
ret = log_reject(message, logit, mailit);
|
||||||
|
free(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = log_reject(_("a password is required"), logit, mailit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore locale. */
|
||||||
|
sudoers_setlocale(oldlocale, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inform the user if they failed to authenticate (in their locale). */
|
||||||
|
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
|
||||||
|
|
||||||
|
if (ISSET(status, FLAG_BAD_PASSWORD)) {
|
||||||
|
if (fmt_authfail_message(&message, tries) == -1) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__,
|
||||||
|
U_("unable to allocate memory"));
|
||||||
|
ret = false;
|
||||||
|
} else {
|
||||||
|
sudo_warnx("%s", message);
|
||||||
|
free(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sudo_warnx("%s", _("a password is required"));
|
||||||
|
}
|
||||||
|
|
||||||
|
sudoers_setlocale(oldlocale, NULL);
|
||||||
|
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log and potentially mail the allowed command.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
log_allowed(void)
|
||||||
|
{
|
||||||
|
struct eventlog evlog;
|
||||||
|
int oldlocale;
|
||||||
|
int evl_flags = 0;
|
||||||
|
bool mailit, ret = true;
|
||||||
|
debug_decl(log_allowed, SUDOERS_DEBUG_LOGGING);
|
||||||
|
|
||||||
|
/* Send mail based on status. */
|
||||||
|
mailit = should_mail(VALIDATE_SUCCESS);
|
||||||
|
|
||||||
|
if (def_log_allowed || mailit) {
|
||||||
|
/* Log and mail messages should be in the sudoers locale. */
|
||||||
|
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
||||||
|
|
||||||
|
sudoers_to_eventlog(&evlog);
|
||||||
|
if (mailit) {
|
||||||
|
SET(evl_flags, EVLOG_MAIL);
|
||||||
|
if (!def_log_allowed)
|
||||||
|
SET(evl_flags, EVLOG_MAIL_ONLY);
|
||||||
|
}
|
||||||
|
if (!eventlog_accept(&evlog, evl_flags, NULL, NULL))
|
||||||
|
ret = false;
|
||||||
|
|
||||||
|
sudoers_setlocale(oldlocale, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform logging for log_warning()/log_warningx().
|
* Perform logging for log_warning()/log_warningx().
|
||||||
*/
|
*/
|
||||||
@@ -325,12 +376,8 @@ vlog_warning(int flags, int errnum, const char *fmt, va_list ap)
|
|||||||
/* Log messages should be in the sudoers locale. */
|
/* Log messages should be in the sudoers locale. */
|
||||||
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
||||||
|
|
||||||
/* Expand printf-style format + args (with a special case). */
|
/* Expand printf-style format + args. */
|
||||||
if (fmt == INCORRECT_PASSWORD_ATTEMPT) {
|
len = vasprintf(&message, _(fmt), ap);
|
||||||
len = fmt_authfail_message(&message, ap);
|
|
||||||
} else {
|
|
||||||
len = vasprintf(&message, _(fmt), ap);
|
|
||||||
}
|
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
ret = false;
|
ret = false;
|
||||||
@@ -372,24 +419,13 @@ vlog_warning(int flags, int errnum, const char *fmt, va_list ap)
|
|||||||
*/
|
*/
|
||||||
if (!ISSET(flags, SLOG_NO_STDERR)) {
|
if (!ISSET(flags, SLOG_NO_STDERR)) {
|
||||||
sudoers_setlocale(SUDOERS_LOCALE_USER, NULL);
|
sudoers_setlocale(SUDOERS_LOCALE_USER, NULL);
|
||||||
if (fmt == INCORRECT_PASSWORD_ATTEMPT) {
|
if (ISSET(flags, SLOG_USE_ERRNO)) {
|
||||||
len = fmt_authfail_message(&message, ap2);
|
errno = errnum;
|
||||||
if (len == -1) {
|
sudo_vwarn_nodebug(_(fmt), ap2);
|
||||||
sudo_warnx(U_("%s: %s"), __func__,
|
} else if (ISSET(flags, SLOG_GAI_ERRNO)) {
|
||||||
U_("unable to allocate memory"));
|
sudo_gai_vwarn_nodebug(errnum, _(fmt), ap2);
|
||||||
ret = false;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
sudo_warnx_nodebug("%s", message);
|
|
||||||
free(message);
|
|
||||||
} else {
|
} else {
|
||||||
if (ISSET(flags, SLOG_USE_ERRNO)) {
|
sudo_vwarnx_nodebug(_(fmt), ap2);
|
||||||
errno = errnum;
|
|
||||||
sudo_vwarn_nodebug(_(fmt), ap2);
|
|
||||||
} else if (ISSET(flags, SLOG_GAI_ERRNO)) {
|
|
||||||
sudo_gai_vwarn_nodebug(errnum, _(fmt), ap2);
|
|
||||||
} else
|
|
||||||
sudo_vwarnx_nodebug(_(fmt), ap2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user