Add sudoers open errors to the list of parse errors sent via mail.

Previously there would be one email for the open failure and a
separate one describing the parse error.  Now a single email message
contains everything.
This commit is contained in:
Todd C. Miller
2023-02-22 18:49:09 -07:00
parent 1641c30ed6
commit fb6740fa2e
3 changed files with 52 additions and 29 deletions

View File

@@ -637,6 +637,24 @@ done:
debug_return_bool(ret); debug_return_bool(ret);
} }
/*
* Add message to the parse error journal, which takes ownership of it.
* The message will be freed once the journal is processed.
*/
static bool
journal_parse_error(char *message)
{
struct parse_error *pe;
debug_decl(journal_parse_error, SUDOERS_DEBUG_LOGGING);
pe = malloc(sizeof(*pe));
if (pe == NULL)
debug_return_bool(false);
pe->errstr = message;
STAILQ_INSERT_TAIL(&parse_error_list, pe, entries);
debug_return_bool(false);
}
/* /*
* Perform logging for log_warning()/log_warningx(). * Perform logging for log_warning()/log_warningx().
*/ */
@@ -702,8 +720,19 @@ vlog_warning(int flags, int errnum, const char *fmt, va_list ap)
} }
sudoers_to_eventlog(&evlog, safe_cmnd, NewArgv, env_get(), sudoers_to_eventlog(&evlog, safe_cmnd, NewArgv, env_get(),
sudo_user.uuid_str); sudo_user.uuid_str);
eventlog_alert(&evlog, evl_flags, &now, message, errstr); if (!eventlog_alert(&evlog, evl_flags, &now, message, errstr))
log_server_alert(&evlog, &now, message, errstr); ret = false;
if (!log_server_alert(&evlog, &now, message, errstr))
ret = false;
}
if (ISSET(flags, SLOG_PARSE_ERROR)) {
/* Journal parse error for later mailing. */
char *copy = strdup(message);
if (copy != NULL) {
if (!journal_parse_error(copy))
ret = false;
}
} }
/* /*
@@ -838,10 +867,10 @@ log_parse_error(const char *file, int line, int column, const char *fmt,
va_list args) va_list args)
{ {
const int flags = SLOG_RAW_MSG|SLOG_NO_STDERR; const int flags = SLOG_RAW_MSG|SLOG_NO_STDERR;
char *tofree = NULL; char *message, *tofree = NULL;
const char *errstr; const char *errstr;
struct parse_error *pe;
bool ret; bool ret;
int len;
debug_decl(log_parse_error, SUDOERS_DEBUG_LOGGING); debug_decl(log_parse_error, SUDOERS_DEBUG_LOGGING);
if (fmt == NULL) { if (fmt == NULL) {
@@ -863,21 +892,15 @@ log_parse_error(const char *file, int line, int column, const char *fmt,
} }
/* Journal parse error for later mailing. */ /* Journal parse error for later mailing. */
pe = malloc(sizeof(*pe)); if (line > 0) {
if (pe != NULL) { len = asprintf(&message, _("%s:%d:%d: %s"), file, line, column, errstr);
int len; } else {
len = asprintf(&message, _("%s: %s"), file, errstr);
if (line > 0) { }
len = asprintf(&pe->errstr, _("%s:%d:%d: %s"), file, line, column, if (len != -1) {
errstr); journal_parse_error(message);
} else { } else {
len = asprintf(&pe->errstr, _("%s: %s"), file, errstr); ret = false;
}
if (len != -1) {
STAILQ_INSERT_TAIL(&parse_error_list, pe, entries);
} else {
free(pe);
}
} }
free(tofree); free(tofree);

View File

@@ -56,6 +56,7 @@ struct log_details {
#define SLOG_NO_STDERR 0x10 /* do not log via stderr */ #define SLOG_NO_STDERR 0x10 /* do not log via stderr */
#define SLOG_NO_LOG 0x20 /* do not log via file or syslog */ #define SLOG_NO_LOG 0x20 /* do not log via file or syslog */
#define SLOG_AUDIT 0x40 /* send message to audit as well */ #define SLOG_AUDIT 0x40 /* send message to audit as well */
#define SLOG_PARSE_ERROR 0x80 /* format as a parse error */
typedef bool (*sudoers_logger_t)(const char *file, int line, int column, const char *fmt, va_list args); typedef bool (*sudoers_logger_t)(const char *file, int line, int column, const char *fmt, va_list args);

View File

@@ -259,7 +259,7 @@ sudoers_init(void *info, sudoers_logger_t logger, char * const envp[])
/* Missing/invalid defaults is not a fatal error. */ /* Missing/invalid defaults is not a fatal error. */
if (nss->getdefs(nss) == -1) { if (nss->getdefs(nss) == -1) {
log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR, log_warningx(SLOG_PARSE_ERROR|SLOG_NO_STDERR,
N_("unable to get defaults from %s"), nss->source); N_("unable to get defaults from %s"), nss->source);
} else { } else {
(void)update_defaults(nss->parse_tree, NULL, (void)update_defaults(nss->parse_tree, NULL,
@@ -1174,12 +1174,11 @@ again:
* user with a reasonable error message (unlike the lexer). * user with a reasonable error message (unlike the lexer).
*/ */
if ((fp = fdopen(fd, "r")) == NULL) { if ((fp = fdopen(fd, "r")) == NULL) {
log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), file); log_warning(SLOG_PARSE_ERROR, N_("unable to open %s"), file);
close(fd); close(fd);
} else { } else {
if (sb.st_size != 0 && fgetc(fp) == EOF) { if (sb.st_size != 0 && fgetc(fp) == EOF) {
log_warning(SLOG_SEND_MAIL, log_warning(SLOG_PARSE_ERROR, N_("unable to read %s"), file);
N_("unable to read %s"), file);
fclose(fp); fclose(fp);
fp = NULL; fp = NULL;
} else { } else {
@@ -1204,22 +1203,22 @@ again:
} }
errno = serrno; errno = serrno;
} }
log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), file); log_warning(SLOG_PARSE_ERROR, N_("unable to open %s"), file);
break; break;
case SUDO_PATH_BAD_TYPE: case SUDO_PATH_BAD_TYPE:
log_warningx(SLOG_SEND_MAIL, log_warningx(SLOG_PARSE_ERROR,
N_("%s is not a regular file"), file); N_("%s is not a regular file"), file);
break; break;
case SUDO_PATH_WRONG_OWNER: case SUDO_PATH_WRONG_OWNER:
log_warningx(SLOG_SEND_MAIL, log_warningx(SLOG_PARSE_ERROR,
N_("%s is owned by uid %u, should be %u"), file, N_("%s is owned by uid %u, should be %u"), file,
(unsigned int) sb.st_uid, (unsigned int) sudoers_uid); (unsigned int) sb.st_uid, (unsigned int) sudoers_uid);
break; break;
case SUDO_PATH_WORLD_WRITABLE: case SUDO_PATH_WORLD_WRITABLE:
log_warningx(SLOG_SEND_MAIL, N_("%s is world writable"), file); log_warningx(SLOG_PARSE_ERROR, N_("%s is world writable"), file);
break; break;
case SUDO_PATH_GROUP_WRITABLE: case SUDO_PATH_GROUP_WRITABLE:
log_warningx(SLOG_SEND_MAIL, log_warningx(SLOG_PARSE_ERROR,
N_("%s is owned by gid %u, should be %u"), file, N_("%s is owned by gid %u, should be %u"), file,
(unsigned int) sb.st_gid, (unsigned int) sudoers_gid); (unsigned int) sb.st_gid, (unsigned int) sudoers_gid);
break; break;
@@ -1360,7 +1359,7 @@ cb_fqdn(const char *file, int line, int column,
/* First resolve user_host, setting user_host and user_shost. */ /* First resolve user_host, setting user_host and user_shost. */
if (resolve_host(user_host, &lhost, &shost) != 0) { if (resolve_host(user_host, &lhost, &shost) != 0) {
if ((rc = resolve_host(user_runhost, &lhost, &shost)) != 0) { if ((rc = resolve_host(user_runhost, &lhost, &shost)) != 0) {
gai_log_warning(SLOG_SEND_MAIL|SLOG_RAW_MSG, rc, gai_log_warning(SLOG_PARSE_ERROR|SLOG_RAW_MSG, rc,
N_("unable to resolve host %s"), user_host); N_("unable to resolve host %s"), user_host);
debug_return_bool(false); debug_return_bool(false);
} }