Read logsrvd.conf in two steps: first read, then apply if OK.

This fixes a problem where when logsrvd.conf was reloaded while
running (due to SIGHUP) and there was an error we could end up with
a partial config.
This commit is contained in:
Todd C. Miller
2019-10-24 20:04:33 -06:00
parent 1df3230c2a
commit aaf5d0dc6e
4 changed files with 286 additions and 189 deletions

View File

@@ -123,12 +123,6 @@ bool iolog_mkdtemp(char *path);
bool iolog_nextid(char *iolog_dir, char sessid[7]); bool iolog_nextid(char *iolog_dir, char sessid[7]);
bool iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode); bool iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode);
bool iolog_rename(const char *from, const char *to); bool iolog_rename(const char *from, const char *to);
bool iolog_set_compress(const char *str);
bool iolog_set_flush(const char *str);
bool iolog_set_group(const struct group *gr);
bool iolog_set_maxseq(const char *maxval);
bool iolog_set_mode(mode_t mode);
bool iolog_set_user(const struct passwd *pw);
bool iolog_write_info_file(int dfd, const char *parent, struct iolog_info *log_info, char * const argv[]); bool iolog_write_info_file(int dfd, const char *parent, struct iolog_info *log_info, char * const argv[]);
char *iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes, const char **errsttr); char *iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes, const char **errsttr);
const char *iolog_fd_to_name(int iofd); const char *iolog_fd_to_name(int iofd);
@@ -138,6 +132,12 @@ size_t mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize);
ssize_t iolog_read(struct iolog_file *iol, void *buf, size_t nbytes, const char **errstr); ssize_t iolog_read(struct iolog_file *iol, void *buf, size_t nbytes, const char **errstr);
ssize_t iolog_write(struct iolog_file *iol, const void *buf, size_t len, const char **errstr); ssize_t iolog_write(struct iolog_file *iol, const void *buf, size_t len, const char **errstr);
void iolog_rewind(struct iolog_file *iol); void iolog_rewind(struct iolog_file *iol);
void iolog_set_compress(bool);
void iolog_set_defaults(void); void iolog_set_defaults(void);
void iolog_set_flush(bool);
void iolog_set_group(const struct group *gr);
void iolog_set_maxseq(unsigned int maxval);
void iolog_set_mode(mode_t mode);
void iolog_set_user(const struct passwd *pw);
#endif /* SUDO_IOLOG_H */ #endif /* SUDO_IOLOG_H */

View File

@@ -296,31 +296,23 @@ iolog_set_defaults(void)
/* /*
* Set max sequence number (aka session ID) * Set max sequence number (aka session ID)
*/ */
bool void
iolog_set_maxseq(const char *maxval) iolog_set_maxseq(unsigned int newval)
{ {
const char *errstr;
unsigned int value;
debug_decl(iolog_set_maxseq, SUDO_DEBUG_UTIL) debug_decl(iolog_set_maxseq, SUDO_DEBUG_UTIL)
value = sudo_strtonum(maxval, 0, SESSID_MAX, &errstr); /* Clamp to SESSID_MAX as documented. */
if (errstr != NULL) { if (newval > SESSID_MAX)
if (errno != ERANGE) { newval = SESSID_MAX;
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sessid_max = newval;
"bad maxseq: %s: %s", maxval, errstr);
debug_return_bool(false); debug_return;
}
/* Out of range, clamp to SESSID_MAX as documented. */
value = SESSID_MAX;
}
sessid_max = value;
debug_return_bool(true);
} }
/* /*
* Set iolog_uid (and iolog_gid if iolog_group not specified). * Set iolog_uid (and iolog_gid if iolog_group not specified).
*/ */
bool void
iolog_set_user(const struct passwd *pw) iolog_set_user(const struct passwd *pw)
{ {
debug_decl(iolog_set_user, SUDO_DEBUG_UTIL) debug_decl(iolog_set_user, SUDO_DEBUG_UTIL)
@@ -336,13 +328,13 @@ iolog_set_user(const struct passwd *pw)
iolog_gid = ROOT_GID; iolog_gid = ROOT_GID;
} }
debug_return_bool(true); debug_return;
} }
/* /*
* Set iolog_gid. * Set iolog_gid.
*/ */
bool void
iolog_set_group(const struct group *gr) iolog_set_group(const struct group *gr)
{ {
debug_decl(iolog_set_group, SUDO_DEBUG_UTIL) debug_decl(iolog_set_group, SUDO_DEBUG_UTIL)
@@ -356,13 +348,13 @@ iolog_set_group(const struct group *gr)
iolog_gid_set = false; iolog_gid_set = false;
} }
debug_return_bool(true); debug_return;
} }
/* /*
* Set iolog_filemode and iolog_dirmode. * Set iolog_filemode and iolog_dirmode.
*/ */
bool void
iolog_set_mode(mode_t mode) iolog_set_mode(mode_t mode)
{ {
debug_decl(iolog_set_mode, SUDO_DEBUG_UTIL) debug_decl(iolog_set_mode, SUDO_DEBUG_UTIL)
@@ -380,39 +372,29 @@ iolog_set_mode(mode_t mode)
if (iolog_dirmode & (S_IROTH|S_IWOTH)) if (iolog_dirmode & (S_IROTH|S_IWOTH))
iolog_dirmode |= S_IXOTH; iolog_dirmode |= S_IXOTH;
debug_return_bool(true); debug_return;
} }
/* /*
* Set iolog_compress * Set iolog_compress
*/ */
bool void
iolog_set_compress(const char *str) iolog_set_compress(bool newval)
{ {
int result;
debug_decl(iolog_set_compress, SUDO_DEBUG_UTIL) debug_decl(iolog_set_compress, SUDO_DEBUG_UTIL)
iolog_compress = newval;
if ((result = sudo_strtobool(str)) == -1) debug_return;
debug_return_bool(false);
iolog_compress = result;
debug_return_bool(true);
} }
/* /*
* Set iolog_flush * Set iolog_flush
*/ */
bool void
iolog_set_flush(const char *str) iolog_set_flush(bool newval)
{ {
int result;
debug_decl(iolog_set_flush, SUDO_DEBUG_UTIL) debug_decl(iolog_set_flush, SUDO_DEBUG_UTIL)
iolog_flush = newval;
if ((result = sudo_strtobool(str)) == -1) debug_return;
debug_return_bool(false);
iolog_flush = result;
debug_return_bool(true);
} }
/* /*

View File

@@ -52,7 +52,8 @@
#include "pathnames.h" #include "pathnames.h"
#include "logsrvd.h" #include "logsrvd.h"
typedef bool (*logsrvd_conf_cb_t)(const char *); struct logsrvd_config;
typedef bool (*logsrvd_conf_cb_t)(struct logsrvd_config *config, const char *);
struct logsrvd_config_entry { struct logsrvd_config_entry {
char *conf_str; char *conf_str;
@@ -69,9 +70,14 @@ static struct logsrvd_config {
struct listen_address_list addresses; struct listen_address_list addresses;
} server; } server;
struct logsrvd_config_iolog { struct logsrvd_config_iolog {
/* XXX - others private to iolog */ bool compress;
bool flush;
mode_t mode;
unsigned int maxseq;
char *iolog_dir; char *iolog_dir;
char *iolog_file; char *iolog_file;
struct passwd user;
struct group group;
} iolog; } iolog;
struct logsrvd_config_eventlog { struct logsrvd_config_eventlog {
enum logsrvd_eventlog_type log_type; enum logsrvd_eventlog_type log_type;
@@ -88,121 +94,93 @@ static struct logsrvd_config {
char *path; char *path;
char *time_format; char *time_format;
} logfile; } logfile;
} logsrvd_config = { } *logsrvd_config;
{ TAILQ_HEAD_INITIALIZER(logsrvd_config.server.addresses) }
};
/* iolog getters */ /* iolog getters */
const char * const char *
logsrvd_conf_iolog_dir(void) logsrvd_conf_iolog_dir(void)
{ {
return logsrvd_config.iolog.iolog_dir; return logsrvd_config->iolog.iolog_dir;
} }
const char * const char *
logsrvd_conf_iolog_file(void) logsrvd_conf_iolog_file(void)
{ {
return logsrvd_config.iolog.iolog_file; return logsrvd_config->iolog.iolog_file;
} }
/* server getters */ /* server getters */
struct listen_address_list * struct listen_address_list *
logsrvd_conf_listen_address(void) logsrvd_conf_listen_address(void)
{ {
return &logsrvd_config.server.addresses; return &logsrvd_config->server.addresses;
} }
/* eventlog getters */ /* eventlog getters */
enum logsrvd_eventlog_type enum logsrvd_eventlog_type
logsrvd_conf_eventlog_type(void) logsrvd_conf_eventlog_type(void)
{ {
return logsrvd_config.eventlog.log_type; return logsrvd_config->eventlog.log_type;
} }
enum logsrvd_eventlog_format enum logsrvd_eventlog_format
logsrvd_conf_eventlog_format(void) logsrvd_conf_eventlog_format(void)
{ {
return logsrvd_config.eventlog.log_format; return logsrvd_config->eventlog.log_format;
} }
/* syslog getters */ /* syslog getters */
unsigned int unsigned int
logsrvd_conf_syslog_maxlen(void) logsrvd_conf_syslog_maxlen(void)
{ {
return logsrvd_config.syslog.maxlen; return logsrvd_config->syslog.maxlen;
} }
int int
logsrvd_conf_syslog_facility(void) logsrvd_conf_syslog_facility(void)
{ {
return logsrvd_config.syslog.facility; return logsrvd_config->syslog.facility;
} }
int int
logsrvd_conf_syslog_acceptpri(void) logsrvd_conf_syslog_acceptpri(void)
{ {
return logsrvd_config.syslog.acceptpri; return logsrvd_config->syslog.acceptpri;
} }
int int
logsrvd_conf_syslog_rejectpri(void) logsrvd_conf_syslog_rejectpri(void)
{ {
return logsrvd_config.syslog.rejectpri; return logsrvd_config->syslog.rejectpri;
} }
int int
logsrvd_conf_syslog_alertpri(void) logsrvd_conf_syslog_alertpri(void)
{ {
return logsrvd_config.syslog.alertpri; return logsrvd_config->syslog.alertpri;
} }
/* logfile getters */ /* logfile getters */
const char * const char *
logsrvd_conf_logfile_path(void) logsrvd_conf_logfile_path(void)
{ {
return logsrvd_config.logfile.path; return logsrvd_config->logfile.path;
} }
const char * const char *
logsrvd_conf_logfile_time_format(void) logsrvd_conf_logfile_time_format(void)
{ {
return logsrvd_config.logfile.time_format; return logsrvd_config->logfile.time_format;
}
/*
* Reset logsrvd_config to default values and reset I/O log values.
*/
static void
logsrvd_conf_reset(void)
{
struct listen_address *addr;
debug_decl(logsrvd_conf_reset, SUDO_DEBUG_UTIL)
iolog_set_defaults();
free(logsrvd_config.iolog.iolog_dir);
logsrvd_config.iolog.iolog_dir = NULL;
free(logsrvd_config.iolog.iolog_file);
logsrvd_config.iolog.iolog_file = NULL;
while ((addr = TAILQ_FIRST(&logsrvd_config.server.addresses))) {
TAILQ_REMOVE(&logsrvd_config.server.addresses, addr, entries);
free(addr);
}
free(logsrvd_config.logfile.path);
free(logsrvd_config.logfile.time_format);
debug_return;
} }
/* I/O log callbacks */ /* I/O log callbacks */
static bool static bool
cb_iolog_dir(const char *path) cb_iolog_dir(struct logsrvd_config *config, const char *path)
{ {
debug_decl(cb_iolog_dir, SUDO_DEBUG_UTIL) debug_decl(cb_iolog_dir, SUDO_DEBUG_UTIL)
free(logsrvd_config.iolog.iolog_dir); free(config->iolog.iolog_dir);
if ((logsrvd_config.iolog.iolog_dir = strdup(path)) == NULL) { if ((config->iolog.iolog_dir = strdup(path)) == NULL) {
sudo_warn(NULL); sudo_warn(NULL);
debug_return_bool(false); debug_return_bool(false);
} }
@@ -210,12 +188,12 @@ cb_iolog_dir(const char *path)
} }
static bool static bool
cb_iolog_file(const char *path) cb_iolog_file(struct logsrvd_config *config, const char *path)
{ {
debug_decl(cb_iolog_file, SUDO_DEBUG_UTIL) debug_decl(cb_iolog_file, SUDO_DEBUG_UTIL)
free(logsrvd_config.iolog.iolog_file); free(config->iolog.iolog_file);
if ((logsrvd_config.iolog.iolog_file = strdup(path)) == NULL) { if ((config->iolog.iolog_file = strdup(path)) == NULL) {
sudo_warn(NULL); sudo_warn(NULL);
debug_return_bool(false); debug_return_bool(false);
} }
@@ -223,19 +201,33 @@ cb_iolog_file(const char *path)
} }
static bool static bool
cb_iolog_compress(const char *str) cb_iolog_compress(struct logsrvd_config *config, const char *str)
{ {
return iolog_set_compress(str); int val;
debug_decl(cb_iolog_compress, SUDO_DEBUG_UTIL)
if ((val = sudo_strtobool(str)) == -1)
debug_return_bool(false);
config->iolog.compress = val;
debug_return_bool(true);
} }
static bool static bool
cb_iolog_flush(const char *str) cb_iolog_flush(struct logsrvd_config *config, const char *str)
{ {
return iolog_set_flush(str); int val;
debug_decl(cb_iolog_flush, SUDO_DEBUG_UTIL)
if ((val = sudo_strtobool(str)) == -1)
debug_return_bool(false);
config->iolog.flush = val;
debug_return_bool(true);
} }
static bool static bool
cb_iolog_user(const char *user) cb_iolog_user(struct logsrvd_config *config, const char *user)
{ {
struct passwd *pw; struct passwd *pw;
debug_decl(cb_iolog_user, SUDO_DEBUG_UTIL) debug_decl(cb_iolog_user, SUDO_DEBUG_UTIL)
@@ -245,12 +237,14 @@ cb_iolog_user(const char *user)
"unknown user %s", user); "unknown user %s", user);
debug_return_bool(false); debug_return_bool(false);
} }
config->iolog.user.pw_uid = pw->pw_uid;
config->iolog.user.pw_gid = pw->pw_gid;
debug_return_bool(iolog_set_user(pw)); debug_return_bool(true);
} }
static bool static bool
cb_iolog_group(const char *group) cb_iolog_group(struct logsrvd_config *config, const char *group)
{ {
struct group *gr; struct group *gr;
debug_decl(cb_iolog_group, SUDO_DEBUG_UTIL) debug_decl(cb_iolog_group, SUDO_DEBUG_UTIL)
@@ -260,12 +254,13 @@ cb_iolog_group(const char *group)
"unknown group %s", group); "unknown group %s", group);
debug_return_bool(false); debug_return_bool(false);
} }
config->iolog.group.gr_gid = gr->gr_gid;
debug_return_bool(iolog_set_group(gr)); debug_return_bool(true);
} }
static bool static bool
cb_iolog_mode(const char *str) cb_iolog_mode(struct logsrvd_config *config, const char *str)
{ {
const char *errstr; const char *errstr;
mode_t mode; mode_t mode;
@@ -277,19 +272,35 @@ cb_iolog_mode(const char *str)
"unable to parse iolog mode %s", str); "unable to parse iolog mode %s", str);
debug_return_bool(false); debug_return_bool(false);
} }
debug_return_bool(iolog_set_mode(mode)); config->iolog.mode = mode;
debug_return_bool(true);
} }
static bool static bool
cb_iolog_maxseq(const char *str) cb_iolog_maxseq(struct logsrvd_config *config, const char *str)
{ {
return iolog_set_maxseq(str); const char *errstr;
unsigned int value;
debug_decl(cb_iolog_maxseq, SUDO_DEBUG_UTIL)
value = sudo_strtonum(str, 0, SESSID_MAX, &errstr);
if (errstr != NULL) {
if (errno != ERANGE) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"bad maxseq: %s: %s", str, errstr);
debug_return_bool(false);
}
/* Out of range, clamp to SESSID_MAX as documented. */
value = SESSID_MAX;
}
config->iolog.maxseq = value;
debug_return_bool(true);
} }
/* Server callbacks */ /* Server callbacks */
/* TODO: unit test */ /* TODO: unit test */
static bool static bool
cb_listen_address(const char *str) cb_listen_address(struct logsrvd_config *config, const char *str)
{ {
struct addrinfo hints, *res, *res0 = NULL; struct addrinfo hints, *res, *res0 = NULL;
char *copy, *host, *port; char *copy, *host, *port;
@@ -351,7 +362,7 @@ cb_listen_address(const char *str)
} }
memcpy(&addr->sa_un, res->ai_addr, res->ai_addrlen); memcpy(&addr->sa_un, res->ai_addr, res->ai_addrlen);
addr->sa_len = res->ai_addrlen; addr->sa_len = res->ai_addrlen;
TAILQ_INSERT_TAIL(&logsrvd_config.server.addresses, addr, entries); TAILQ_INSERT_TAIL(&config->server.addresses, addr, entries);
} }
ret = true; ret = true;
@@ -364,16 +375,16 @@ done:
/* eventlog callbacks */ /* eventlog callbacks */
static bool static bool
cb_eventlog_type(const char *str) cb_eventlog_type(struct logsrvd_config *config, const char *str)
{ {
debug_decl(cb_eventlog_type, SUDO_DEBUG_UTIL) debug_decl(cb_eventlog_type, SUDO_DEBUG_UTIL)
if (strcmp(str, "none") == 0) if (strcmp(str, "none") == 0)
logsrvd_config.eventlog.log_type = EVLOG_NONE; config->eventlog.log_type = EVLOG_NONE;
else if (strcmp(str, "syslog") == 0) else if (strcmp(str, "syslog") == 0)
logsrvd_config.eventlog.log_type = EVLOG_SYSLOG; config->eventlog.log_type = EVLOG_SYSLOG;
else if (strcmp(str, "logfile") == 0) else if (strcmp(str, "logfile") == 0)
logsrvd_config.eventlog.log_type = EVLOG_FILE; config->eventlog.log_type = EVLOG_FILE;
else else
debug_return_bool(false); debug_return_bool(false);
@@ -381,12 +392,12 @@ cb_eventlog_type(const char *str)
} }
static bool static bool
cb_eventlog_format(const char *str) cb_eventlog_format(struct logsrvd_config *config, const char *str)
{ {
debug_decl(cb_eventlog_format, SUDO_DEBUG_UTIL) debug_decl(cb_eventlog_format, SUDO_DEBUG_UTIL)
if (strcmp(str, "sudo") == 0) if (strcmp(str, "sudo") == 0)
logsrvd_config.eventlog.log_format = EVLOG_SUDO; config->eventlog.log_format = EVLOG_SUDO;
else else
debug_return_bool(false); debug_return_bool(false);
@@ -395,7 +406,7 @@ cb_eventlog_format(const char *str)
/* syslog callbacks */ /* syslog callbacks */
static bool static bool
cb_syslog_maxlen(const char *str) cb_syslog_maxlen(struct logsrvd_config *config, const char *str)
{ {
unsigned int maxlen; unsigned int maxlen;
const char *errstr; const char *errstr;
@@ -405,13 +416,13 @@ cb_syslog_maxlen(const char *str)
if (errstr != NULL) if (errstr != NULL)
debug_return_bool(false); debug_return_bool(false);
logsrvd_config.syslog.maxlen = maxlen; config->syslog.maxlen = maxlen;
debug_return_bool(true); debug_return_bool(true);
} }
static bool static bool
cb_syslog_facility(const char *str) cb_syslog_facility(struct logsrvd_config *config, const char *str)
{ {
int logfac; int logfac;
debug_decl(cb_syslog_facility, SUDO_DEBUG_UTIL) debug_decl(cb_syslog_facility, SUDO_DEBUG_UTIL)
@@ -422,13 +433,13 @@ cb_syslog_facility(const char *str)
debug_return_bool(false); debug_return_bool(false);
} }
logsrvd_config.syslog.facility = logfac; config->syslog.facility = logfac;
debug_return_bool(true); debug_return_bool(true);
} }
static bool static bool
cb_syslog_acceptpri(const char *str) cb_syslog_acceptpri(struct logsrvd_config *config, const char *str)
{ {
int logpri; int logpri;
debug_decl(cb_syslog_acceptpri, SUDO_DEBUG_UTIL) debug_decl(cb_syslog_acceptpri, SUDO_DEBUG_UTIL)
@@ -439,13 +450,13 @@ cb_syslog_acceptpri(const char *str)
debug_return_bool(false); debug_return_bool(false);
} }
logsrvd_config.syslog.acceptpri = logpri; config->syslog.acceptpri = logpri;
debug_return_bool(true); debug_return_bool(true);
} }
static bool static bool
cb_syslog_rejectpri(const char *str) cb_syslog_rejectpri(struct logsrvd_config *config, const char *str)
{ {
int logpri; int logpri;
debug_decl(cb_syslog_rejectpri, SUDO_DEBUG_UTIL) debug_decl(cb_syslog_rejectpri, SUDO_DEBUG_UTIL)
@@ -453,13 +464,13 @@ cb_syslog_rejectpri(const char *str)
if (!sudo_str2logpri(str, &logpri)) if (!sudo_str2logpri(str, &logpri))
debug_return_bool(false); debug_return_bool(false);
logsrvd_config.syslog.rejectpri = logpri; config->syslog.rejectpri = logpri;
debug_return_bool(true); debug_return_bool(true);
} }
static bool static bool
cb_syslog_alertpri(const char *str) cb_syslog_alertpri(struct logsrvd_config *config, const char *str)
{ {
int logpri; int logpri;
debug_decl(cb_syslog_alertpri, SUDO_DEBUG_UTIL) debug_decl(cb_syslog_alertpri, SUDO_DEBUG_UTIL)
@@ -470,14 +481,14 @@ cb_syslog_alertpri(const char *str)
debug_return_bool(false); debug_return_bool(false);
} }
logsrvd_config.syslog.alertpri = logpri; config->syslog.alertpri = logpri;
debug_return_bool(true); debug_return_bool(true);
} }
/* logfile callbacks */ /* logfile callbacks */
static bool static bool
cb_logfile_path(const char *str) cb_logfile_path(struct logsrvd_config *config, const char *str)
{ {
char *copy = NULL; char *copy = NULL;
debug_decl(cb_logfile_path, SUDO_DEBUG_UTIL) debug_decl(cb_logfile_path, SUDO_DEBUG_UTIL)
@@ -492,14 +503,14 @@ cb_logfile_path(const char *str)
debug_return_bool(false); debug_return_bool(false);
} }
free(logsrvd_config.logfile.path); free(config->logfile.path);
logsrvd_config.logfile.path = copy; config->logfile.path = copy;
debug_return_bool(true); debug_return_bool(true);
} }
static bool static bool
cb_logfile_time_format(const char *str) cb_logfile_time_format(struct logsrvd_config *config, const char *str)
{ {
char *copy = NULL; char *copy = NULL;
debug_decl(cb_logfile_time_format, SUDO_DEBUG_UTIL) debug_decl(cb_logfile_time_format, SUDO_DEBUG_UTIL)
@@ -509,8 +520,8 @@ cb_logfile_time_format(const char *str)
debug_return_bool(false); debug_return_bool(false);
} }
free(logsrvd_config.logfile.time_format); free(config->logfile.time_format);
logsrvd_config.logfile.time_format = copy; config->logfile.time_format = copy;
debug_return_bool(true); debug_return_bool(true);
} }
@@ -563,7 +574,7 @@ static struct logsrvd_config_section logsrvd_config_sections[] = {
}; };
static bool static bool
logsrvd_conf_parse(FILE *fp, const char *path) logsrvd_conf_parse(struct logsrvd_config *config, FILE *fp, const char *path)
{ {
struct logsrvd_config_section *conf_section = NULL; struct logsrvd_config_section *conf_section = NULL;
unsigned int lineno = 0; unsigned int lineno = 0;
@@ -623,7 +634,7 @@ logsrvd_conf_parse(FILE *fp, const char *path)
*ep = '\0'; *ep = '\0';
for (entry = conf_section->entries; entry->conf_str != NULL; entry++) { for (entry = conf_section->entries; entry->conf_str != NULL; entry++) {
if (strcasecmp(line, entry->conf_str) == 0) { if (strcasecmp(line, entry->conf_str) == 0) {
if (!entry->setter(val)) { if (!entry->setter(config, val)) {
sudo_warnx(U_("invalid value for %s: %s"), sudo_warnx(U_("invalid value for %s: %s"),
entry->conf_str, val); entry->conf_str, val);
goto done; goto done;
@@ -643,39 +654,137 @@ done:
debug_return_bool(ret); debug_return_bool(ret);
} }
/* Free the specified struct logsrvd_config and its contents. */
void
logsrvd_conf_free(struct logsrvd_config *config)
{
struct listen_address *addr;
debug_decl(logsrvd_conf_free, SUDO_DEBUG_UTIL)
if (config == NULL)
debug_return;
/* struct logsrvd_config_server */
while ((addr = TAILQ_FIRST(&config->server.addresses))) {
TAILQ_REMOVE(&config->server.addresses, addr, entries);
free(addr);
}
/* struct logsrvd_config_iolog */
free(config->iolog.iolog_dir);
free(config->iolog.iolog_file);
/* struct logsrvd_config_logfile */
free(config->logfile.path);
free(config->logfile.time_format);
free(config);
debug_return;
}
/* Allocate a new struct logsrvd_config and set default values. */
struct logsrvd_config *
logsrvd_conf_alloc(void)
{
struct logsrvd_config *config;
debug_decl(logsrvd_conf_alloc, SUDO_DEBUG_UTIL)
if ((config = calloc(1, sizeof(*config))) == NULL) {
sudo_warn(NULL);
debug_return_ptr(NULL);
}
/* Server defaults */
TAILQ_INIT(&config->server.addresses);
/* I/O log defaults */
config->iolog.compress = false;
config->iolog.flush = true;
config->iolog.mode = S_IRUSR|S_IWUSR;
config->iolog.maxseq = SESSID_MAX;
if (!cb_iolog_dir(config, _PATH_SUDO_IO_LOGDIR))
goto bad;
if (!cb_iolog_file(config, "%{seq}"))
goto bad;
config->iolog.user.pw_uid = ROOT_UID;
config->iolog.user.pw_gid = ROOT_GID;
config->iolog.group.gr_gid = ROOT_GID;
/* Event log defaults */
config->eventlog.log_type = EVLOG_SYSLOG;
config->eventlog.log_format = EVLOG_SUDO;
/* Syslog defaults */
config->syslog.maxlen = 960;
if (!cb_syslog_facility(config, LOGFAC)) {
sudo_warnx(U_("unknown syslog facility %s"), LOGFAC);
goto bad;
}
if (!cb_syslog_acceptpri(config, PRI_SUCCESS)) {
sudo_warnx(U_("unknown syslog priority %s"), PRI_SUCCESS);
goto bad;
}
if (!cb_syslog_rejectpri(config, PRI_FAILURE)) {
sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
goto bad;
}
if (!cb_syslog_alertpri(config, PRI_FAILURE)) {
sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
goto bad;
}
/* Log file defaults */
if (!cb_logfile_time_format(config, "%h %e %T"))
goto bad;
if (!cb_logfile_path(config, _PATH_SUDO_LOGFILE))
goto bad;
debug_return_ptr(config);
bad:
logsrvd_conf_free(config);
debug_return_ptr(NULL);
}
bool
logsrvd_conf_apply(struct logsrvd_config *config)
{
debug_decl(logsrvd_conf_apply, SUDO_DEBUG_UTIL)
/* There can be multiple addresses so we can't set a default earlier. */
if (TAILQ_EMPTY(&config->server.addresses)) {
if (!cb_listen_address(config, "*:30344"))
debug_return_bool(false);
}
/* Set I/O log library settings */
iolog_set_defaults();
iolog_set_compress(config->iolog.compress);
iolog_set_flush(config->iolog.flush);
iolog_set_user(&config->iolog.user);
iolog_set_group(&config->iolog.group);
iolog_set_mode(config->iolog.mode);
iolog_set_maxseq(config->iolog.maxseq);
logsrvd_conf_free(logsrvd_config);
logsrvd_config = config;
debug_return_bool(true);
}
/* /*
* Read .ini style logsrvd.conf file. * Read .ini style logsrvd.conf file.
* Note that we use '#' not ';' for the comment character. * Note that we use '#' not ';' for the comment character.
*/ */
/* XXX - split into read and apply so we don't overwrite good config with bad */
bool bool
logsrvd_conf_read(const char *path) logsrvd_conf_read(const char *path)
{ {
struct logsrvd_config *config;
bool ret = false; bool ret = false;
FILE *fp = NULL; FILE *fp = NULL;
debug_decl(logsrvd_conf_read, SUDO_DEBUG_UTIL) debug_decl(logsrvd_conf_read, SUDO_DEBUG_UTIL)
/* Initialize default values for settings that take int values. */ config = logsrvd_conf_alloc();
logsrvd_conf_reset();
logsrvd_config.eventlog.log_type = EVLOG_SYSLOG;
logsrvd_config.eventlog.log_format = EVLOG_SUDO;
logsrvd_config.syslog.maxlen = 960;
if (!cb_syslog_facility(LOGFAC)) {
sudo_warnx(U_("unknown syslog facility %s"), LOGFAC);
goto done;
}
if (!cb_syslog_acceptpri(PRI_SUCCESS)) {
sudo_warnx(U_("unknown syslog priority %s"), PRI_SUCCESS);
goto done;
}
if (!cb_syslog_rejectpri(PRI_FAILURE)) {
sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
goto done;
}
if (!cb_syslog_alertpri(PRI_FAILURE)) {
sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
goto done;
}
if ((fp = fopen(path, "r")) == NULL) { if ((fp = fopen(path, "r")) == NULL) {
if (errno != ENOENT) { if (errno != ENOENT) {
@@ -683,34 +792,18 @@ logsrvd_conf_read(const char *path)
goto done; goto done;
} }
} else { } else {
if (!logsrvd_conf_parse(fp, path)) if (!logsrvd_conf_parse(config, fp, path))
goto done; goto done;
} }
/* For settings with pointer values we can tell what is unset. */ /* Install new config */
if (logsrvd_config.iolog.iolog_dir == NULL) { if (logsrvd_conf_apply(config)) {
if (!cb_iolog_dir(_PATH_SUDO_IO_LOGDIR)) config = NULL;
goto done;
}
if (logsrvd_config.iolog.iolog_file == NULL) {
if (!cb_iolog_file("%{seq}"))
goto done;
}
if (TAILQ_EMPTY(&logsrvd_config.server.addresses)) {
if (!cb_listen_address("*:30344"))
goto done;
}
if (logsrvd_config.logfile.time_format == NULL) {
if (!cb_logfile_time_format("%h %e %T"))
goto done;
}
if (logsrvd_config.logfile.path == NULL) {
if (!cb_logfile_path(_PATH_SUDO_LOGFILE))
goto done;
}
ret = true; ret = true;
}
done: done:
logsrvd_conf_free(config);
if (fp != NULL) if (fp != NULL)
fclose(fp); fclose(fp);
debug_return_bool(ret); debug_return_bool(ret);

View File

@@ -83,7 +83,22 @@ extern __dso_public struct io_plugin sudoers_io;
bool bool
cb_maxseq(const union sudo_defs_val *sd_un) cb_maxseq(const union sudo_defs_val *sd_un)
{ {
return iolog_set_maxseq(sd_un->str); const char *errstr;
unsigned int value;
debug_decl(cb_maxseq, SUDO_DEBUG_UTIL)
value = sudo_strtonum(sd_un->str, 0, SESSID_MAX, &errstr);
if (errstr != NULL) {
if (errno != ERANGE) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"bad maxseq: %s: %s", sd_un->str, errstr);
debug_return_bool(false);
}
/* Out of range, clamp to SESSID_MAX as documented. */
value = SESSID_MAX;
}
iolog_set_maxseq(value);
debug_return_bool(true);
} }
/* /*
@@ -94,7 +109,6 @@ cb_iolog_user(const union sudo_defs_val *sd_un)
{ {
const char *name = sd_un->str; const char *name = sd_un->str;
struct passwd *pw = NULL; struct passwd *pw = NULL;
bool ret;
debug_decl(cb_iolog_user, SUDOERS_DEBUG_UTIL) debug_decl(cb_iolog_user, SUDOERS_DEBUG_UTIL)
/* NULL name means reset to default. */ /* NULL name means reset to default. */
@@ -104,11 +118,11 @@ cb_iolog_user(const union sudo_defs_val *sd_un)
debug_return_bool(false); debug_return_bool(false);
} }
} }
ret = iolog_set_user(pw); iolog_set_user(pw);
if (pw != NULL) if (pw != NULL)
sudo_pw_delref(pw); sudo_pw_delref(pw);
debug_return_bool(ret); debug_return_bool(true);
} }
/* /*
@@ -119,7 +133,6 @@ cb_iolog_group(const union sudo_defs_val *sd_un)
{ {
const char *name = sd_un->str; const char *name = sd_un->str;
struct group *gr = NULL; struct group *gr = NULL;
bool ret;
debug_decl(cb_iolog_group, SUDOERS_DEBUG_UTIL) debug_decl(cb_iolog_group, SUDOERS_DEBUG_UTIL)
/* NULL name means reset to default. */ /* NULL name means reset to default. */
@@ -129,11 +142,11 @@ cb_iolog_group(const union sudo_defs_val *sd_un)
debug_return_bool(false); debug_return_bool(false);
} }
} }
ret = iolog_set_group(gr); iolog_set_group(gr);
if (gr != NULL) if (gr != NULL)
sudo_gr_delref(gr); sudo_gr_delref(gr);
debug_return_bool(ret); debug_return_bool(true);
} }
/* /*
@@ -142,7 +155,8 @@ cb_iolog_group(const union sudo_defs_val *sd_un)
bool bool
cb_iolog_mode(const union sudo_defs_val *sd_un) cb_iolog_mode(const union sudo_defs_val *sd_un)
{ {
return iolog_set_mode(sd_un->mode); iolog_set_mode(sd_un->mode);
return true;
} }
/* /*
@@ -249,14 +263,20 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
continue; continue;
} }
if (strncmp(*cur, "iolog_compress=", sizeof("iolog_compress=") - 1) == 0) { if (strncmp(*cur, "iolog_compress=", sizeof("iolog_compress=") - 1) == 0) {
if (!iolog_set_compress(*cur + sizeof("iolog_compress=") - 1)) { int val = sudo_strtobool(*cur + sizeof("iolog_compress=") - 1);
if (val != -1) {
iolog_set_compress(val);
} else {
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN,
"%s: unable to parse %s", __func__, *cur); "%s: unable to parse %s", __func__, *cur);
} }
continue; continue;
} }
if (strncmp(*cur, "iolog_flush=", sizeof("iolog_flush=") - 1) == 0) { if (strncmp(*cur, "iolog_flush=", sizeof("iolog_flush=") - 1) == 0) {
if (!iolog_set_flush(*cur + sizeof("iolog_flush=") - 1)) { int val = sudo_strtobool(*cur + sizeof("iolog_flush=") - 1);
if (val != -1) {
iolog_set_flush(val);
} else {
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN,
"%s: unable to parse %s", __func__, *cur); "%s: unable to parse %s", __func__, *cur);
} }
@@ -299,7 +319,9 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
break; break;
case 'm': case 'm':
if (strncmp(*cur, "maxseq=", sizeof("maxseq=") - 1) == 0) { if (strncmp(*cur, "maxseq=", sizeof("maxseq=") - 1) == 0) {
iolog_set_maxseq(*cur + sizeof("maxseq=") - 1); union sudo_defs_val sd_un;
sd_un.str = *cur + sizeof("maxseq=") - 1;
cb_maxseq(&sd_un);
continue; continue;
} }
break; break;