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

Reply via email to