I'm not sure if this is of enough interest to complicate switch_user(), but I'll send it for consideration anyway.
Signed-off-by: Stuart Henderson <[email protected]> --- etc/nsca-ng.cfg | 1 + man/nsca-ng.cfg.in | 15 +++++++++++++++ src/server/conf.c | 1 + src/server/nsca-ng.c | 19 +++++++++++-------- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/etc/nsca-ng.cfg b/etc/nsca-ng.cfg index bcfc035..7c94f86 100644 --- a/etc/nsca-ng.cfg +++ b/etc/nsca-ng.cfg @@ -18,6 +18,7 @@ command_file = "/usr/local/nagios/var/rw/nagios.cmd" # temp_directory = "/dev/shm" # Default: "/tmp". # tls_ciphers = "PSK-AES256-CBC-SHA" # Default: see nsca-ng.cfg(5). # user = "nagios" # Default: don't switch user. +# chroot = "/usr/local/nagios/var" # Default: don't chroot(2). # log_level = 2 # Default: 3. # max_command_size = 65536 # Default: 16384. # max_queue_size = 128 # Default: 1024. diff --git a/man/nsca-ng.cfg.in b/man/nsca-ng.cfg.in index d77d854..9cdcb5c 100644 --- a/man/nsca-ng.cfg.in +++ b/man/nsca-ng.cfg.in @@ -116,6 +116,21 @@ The server recognizes the following global variables. . .TP +\fBchroot\fP\ =\ <\fIstring\fP> +. +Perform a +.BR chroot (2) +operation to the specified directory before dropping privileges. +By default, +.BR nsca\-ng (8) +does not call chroot. +If this option is used, +.B temp_directory +and +.B command_file +must be specified relative to this directory. +. +.TP \fBcommand_file\fP\ =\ <\fIstring\fP> . Submit monitoring commands to the specified path name. diff --git a/src/server/conf.c b/src/server/conf.c index d94e720..5d9f45a 100644 --- a/src/server/conf.c +++ b/src/server/conf.c @@ -88,6 +88,7 @@ conf_parse(const char *path) CFG_STR("tls_ciphers", DEFAULT_TLS_CIPHERS, CFGF_NONE), CFG_FLOAT("timeout", DEFAULT_TIMEOUT, CFGF_NONE), CFG_STR("user", NULL, CFGF_NODEFAULT), + CFG_STR("chroot", NULL, CFGF_NODEFAULT), CFG_SEC("authorize", auth_opts, CFGF_MULTI | CFGF_TITLE | CFGF_NO_TITLE_DUPES), CFG_END() diff --git a/src/server/nsca-ng.c b/src/server/nsca-ng.c index 09cab8d..10fbeed 100644 --- a/src/server/nsca-ng.c +++ b/src/server/nsca-ng.c @@ -77,7 +77,7 @@ static ev_signal sighup_watcher, sigint_watcher, sigterm_watcher; static options *get_options(int, char **); static void free_options(options *); -static void switch_user(const char *); +static void switch_user(const char *, const char *); static void remove_pidfile(void); static void forget_config(void); static void signal_cb(EV_P_ ev_signal *, int __attribute__((__unused__))); @@ -104,8 +104,9 @@ main(int argc, char **argv) cfg = conf_parse(opt->conf_file != NULL ? opt->conf_file : DEFAULT_CONF_FILE); - if (cfg_size(cfg, "user") > 0) - switch_user(cfg_getstr(cfg, "user")); + if (cfg_size(cfg, "user") > 0 || cfg_size(cfg, "chroot") > 0) + switch_user(cfg_getstr(cfg, "user"), + cfg_getstr(cfg, "chroot")); if (opt->log_target == -1) opt->log_target = opt->foreground ? @@ -290,21 +291,23 @@ free_options(options *opt) } static void -switch_user(const char *user) +switch_user(const char *user, const char *newroot) { struct passwd *pw; errno = 0; - if ((pw = getpwnam(user)) == NULL) { + if (user && (pw = getpwnam(user)) == NULL) { if (errno == 0) die("Cannot find user %s in password database", user); else die("Cannot lookup user %s in password database: %m", user); } - if (initgroups(user, pw->pw_gid) == -1 - || setgid(pw->pw_gid) == -1 - || setuid(pw->pw_uid) == -1) + if (user && initgroups(user, pw->pw_gid) == -1) + die("Cannot switch to user %s: %m", user); + if (newroot && chroot(newroot) != 0 || chdir("/") != 0) + die("Cannot chroot to %s: %m", newroot); + if (user && setgid(pw->pw_gid) == -1 || setuid(pw->pw_uid) == -1) die("Cannot switch to user %s: %m", user); } -- 1.8.1.3
