]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
chroot more tests and more documentation.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 24 Apr 2008 12:37:01 +0000 (12:37 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 24 Apr 2008 12:37:01 +0000 (12:37 +0000)
git-svn-id: file:///svn/unbound/trunk@1067 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/unbound.c
doc/Changelog
doc/example.conf
doc/unbound.conf.5
smallapp/unbound-checkconf.c
testdata/07-confroot.tpkg

index 74b49bae27d04a21f9d9bc21bdc29071aa02e340..9a328ceec671944b261351ebcc59b18513e3b25f 100644 (file)
@@ -295,13 +295,6 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
        log_assert(cfg);
 
        /* daemonize last to be able to print error to user */
-       if(cfg->directory && cfg->directory[0]) {
-               if(chdir(cfg->directory)) {
-                       fatal_exit("Could not chdir to %s: %s",
-                               cfg->directory, strerror(errno));
-               }
-               verbose(VERB_QUERY, "chdir to %s", cfg->directory);
-       }
        if(cfg->username && cfg->username[0]) {
                struct passwd *pwd;
                if((pwd = getpwnam(cfg->username)) == NULL)
@@ -311,6 +304,11 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
                endpwent();
        }
        if(cfg->chrootdir && cfg->chrootdir[0]) {
+               if(chdir(cfg->chrootdir)) {
+                       fatal_exit("unable to chdir to chroot %s: %s",
+                               cfg->chrootdir, strerror(errno));
+               }
+               verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir);
                if(chroot(cfg->chrootdir))
                        fatal_exit("unable to chroot to %s: %s", 
                                cfg->chrootdir, strerror(errno));
@@ -319,6 +317,18 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
                        strlen(cfg->chrootdir)) == 0) 
                        (*cfgfile) += strlen(cfg->chrootdir);
        }
+       if(cfg->directory && cfg->directory[0]) {
+               char* dir = cfg->directory;
+               if(cfg->chrootdir && cfg->chrootdir[0] &&
+                       strncmp(dir, cfg->chrootdir, 
+                       strlen(cfg->chrootdir)) == 0)
+                       dir += strlen(cfg->chrootdir);
+               if(chdir(dir)) {
+                       fatal_exit("Could not chdir to %s: %s",
+                               dir, strerror(errno));
+               }
+               verbose(VERB_QUERY, "chdir to %s", dir);
+       }
        if(cfg->username && cfg->username[0]) {
                if(setgid(gid) != 0)
                        fatal_exit("unable to set group id of %s: %s", 
index 28da373aa4b8a900d22ce34f9079a8e2ff85eb67..af2251213d813a4e1c5f12caeba190472cc50508 100644 (file)
@@ -1,3 +1,7 @@
+24 April 2008: Wouter
+       - chroot checks improved. working directory relative to chroot.
+         checks if config file path is inside chroot. Documentation on it.
+
 23 April 2008: Wouter
        - parseunbound.pl contrib update from Kai Storbeck for threads.
        - iana ports update
index 0d2f5c5ffe4ec5a0caa09f964ce1e33c338ae8ef..694a53ee509347ad6bf8fc2595eebadf8cf168a3 100644 (file)
@@ -144,7 +144,23 @@ server:
        # if given, a chroot(2) is done to the given directory.
        # i.e. you can chroot to the working directory, for example,
        # for extra security, but make sure all files are in that directory.
-       # If you give "" no chroot is performed.
+       #
+       # If chroot is enabled, you should pass the configfile (from the
+       # commandline) as a full path from the original root. After the
+       # chroot has been performed the now defunct portion of the config 
+       # file path is removed to be able to reread the config after a reload. 
+       #
+       # All other file paths (working dir, pidfile, logfile, roothints,
+       # key files) can be specified in several ways:
+       #       o as an absolute path relative to the new root.
+       #       o as a relative path to the working directory.
+       #       o as an absolute path relative to the original root.
+       # In the last case the path is adjusted to remove the unused portion.
+       #
+       # Additionally, unbound may need to access /dev/random (for entropy)
+       # and to /dev/log (if you use syslog) from inside the chroot.
+       #
+       # If you give "" no chroot is performed. The path must not end in a /.
        # chroot: "/usr/local/etc/unbound"
 
        # if given, user privileges are dropped (after binding port),
@@ -152,7 +168,7 @@ server:
        # If you give "" no privileges are dropped.
        # username: "unbound"
 
-       # the working directory.
+       # the working directory. "" disables.
        # directory: "/usr/local/etc/unbound"
 
        # the log file, "" means log to stderr. 
index 3caca1e0cf0d27bec469a64e30f8d0ca32bb88e4..22bcc43c5dd435d65c4e293fea83a1634f25519c 100644 (file)
@@ -238,8 +238,23 @@ is not designed to handle dropped packets due to policy, and dropping may
 result in (possibly excessive) retried queries.
 .TP
 .B chroot: \fI<directory>
+If chroot is enabled, you should pass the configfile (from the
+commandline) as a full path from the original root. After the
+chroot has been performed the now defunct portion of the config 
+file path is removed to be able to reread the config after a reload. 
+.IP
+All other file paths (working dir, pidfile, logfile, roothints,
+key files) can be specified in several ways:
+as an absolute path relative to the new root,
+as a relative path to the working directory, or
+as an absolute path relative to the original root.
+In the last case the path is adjusted to remove the unused portion.
+.IP
+Additionally, unbound may need to access /dev/random (for entropy)
+and to /dev/log (if you use syslog) from inside the chroot.
+.IP
 If given a chroot is done to the given directory. The default is 
-"/etc/unbound". If you give "" no chroot is performed.
+"/usr/local/etc/unbound". If you give "" no chroot is performed.
 .TP
 .B username: \fI<name>
 If given, after binding the port the user privileges are dropped. Default is
@@ -271,14 +286,14 @@ The logfile setting is overridden when use\-syslog is turned on.
 The default is to log to syslog.
 .TP
 .B pidfile: \fI<filename>
-The process id is written to the file. Default is "/etc/unbound/unbound.pid". 
+The process id is written to the file. Default is "/usr/local/etc/unbound/unbound.pid". 
 So,
 .nf
-kill \-HUP `cat /etc/unbound/unbound.pid` 
+kill \-HUP `cat /usr/local/etc/unbound/unbound.pid` 
 .fi
 triggers a reload,
 .nf
-kill \-QUIT `cat /etc/unbound/unbound.pid` 
+kill \-QUIT `cat /usr/local/etc/unbound/unbound.pid` 
 .fi
 gracefully terminates.
 .TP
@@ -648,7 +663,7 @@ server:
 .fi
 .SH "FILES"
 .TP
-.I /etc/unbound
+.I /usr/local/etc/unbound
 default unbound working directory and default 
 \fIchroot\fR(2)
 location.
index 73aaea3006c016fe2373f31086d933a1bd5bb689..44e7344644d3e73e9af457443d3a1c8f88bd5ef1 100644 (file)
@@ -297,7 +297,7 @@ check_chroot_filelist(const char* desc, struct config_strlist* list,
 
 /** check configuration for errors */
 static void
-morechecks(struct config_file* cfg)
+morechecks(struct config_file* cfg, char* fname)
 {
        warn_hosts("stub-host", cfg->stubs);
        warn_hosts("forward-host", cfg->forwards);
@@ -321,14 +321,21 @@ morechecks(struct config_file* cfg)
                !is_dir(cfg->chrootdir)) {
                fatal_exit("bad chroot directory");
        }
-       if((cfg->chrootdir && cfg->chrootdir[0]) 
-           && (cfg->directory && cfg->directory[0])
-           && strncmp(cfg->chrootdir, cfg->directory, 
-               strlen(cfg->chrootdir)) != 0) {
-               fatal_exit("chdir directory '%s' not inside the chroot "
-                       "directory '%s'", cfg->directory, cfg->chrootdir);
+       if(cfg->chrootdir && cfg->chrootdir[0]) {
+               char buf[10240];
+               buf[0] = 0;
+               if(fname[0] != '/') {
+                       if(getcwd(buf, sizeof(buf)) == NULL)
+                               fatal_exit("getcwd: %s", strerror(errno));
+                       strncat(buf, "/", sizeof(buf));
+               }
+               strncat(buf, fname, sizeof(buf));
+               if(strncmp(buf, cfg->chrootdir, strlen(cfg->chrootdir)) != 0)
+                       fatal_exit("config file %s is not inside chroot %s",
+                               buf, cfg->chrootdir);
        }
-       if(cfg->directory && cfg->directory[0] && !is_dir(cfg->directory)) {
+       if(cfg->directory && cfg->directory[0] && !is_dir(
+               fname_after_chroot(cfg->directory, cfg, 0))) {
                fatal_exit("bad chdir directory");
        }
        if( (cfg->chrootdir && cfg->chrootdir[0]) ||
@@ -341,7 +348,7 @@ morechecks(struct config_file* cfg)
                if(cfg->logfile && cfg->logfile[0] &&
                   basedir(cfg->logfile, cfg) &&
                   !is_dir(basedir(cfg->logfile, cfg))) {
-                       fatal_exit("pidfile directory does not exist");
+                       fatal_exit("logfile directory does not exist");
                }
        }
 
@@ -382,7 +389,7 @@ checkconf(char* cfgfile)
                config_delete(cfg);
                exit(1);
        }
-       morechecks(cfg);
+       morechecks(cfg, cfgfile);
        check_mod(cfg, iter_get_funcblock());
        check_mod(cfg, val_get_funcblock());
        config_delete(cfg);
index e25b089baeca0301af5fa82d908f448ed67daaef..21a97efcd20229a5adadd0ded5834f8dda10575d 100644 (file)
Binary files a/testdata/07-confroot.tpkg and b/testdata/07-confroot.tpkg differ