]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
0x20 document, checkconf fix.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 14 Apr 2008 14:48:17 +0000 (14:48 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 14 Apr 2008 14:48:17 +0000 (14:48 +0000)
git-svn-id: file:///svn/unbound/trunk@1037 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
doc/TODO
doc/example.conf
doc/unbound.conf.5
smallapp/unbound-checkconf.c
testdata/07-confroot.tpkg [new file with mode: 0644]

index 2c333fa8635974fe0ec01230819d21394f7eedea..41ea0f352509449cb773b59e6b1ba50f3ef0414a 100644 (file)
@@ -1,6 +1,8 @@
 14 April 2008: Wouter
        - got update for parseunbound.pl statistics script from Kai Storbeck.
        - tpkg tests for udp wait list.
+       - documented 0x20 status.
+       - fixup chroot and checkconf, it is much smarter now.
 
 11 April 2008: Wouter
        - random port selection out of the configged ports.
index 36c656a2908da1083f331a4ba090e91c9fad1c42..19d939b96ba7aae88dadd3cab21ca820e5bbf0fa 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -46,3 +46,4 @@ o (option) for extended statistics. If enabled (not by default) collect print
        bits(RD, CD, DO, EDNS-present, AD)query, (Secure, Bogus)reply.
 o overhaul outside-network servicedquery to merge with udpwait and tcpwait,
   to make timers in servicedquery independent of udpwait queues.
+o 0x20 fallback so it can be enabled without trouble.
index 2d6e42af9477fe3e52c5b827a25734609ecfaadb..0af9c7571dba193deac368673dd352b3c3f3a800 100644 (file)
@@ -211,6 +211,8 @@ server:
        # Disabled by default, because some caching forwarders may not
        # support this (if you have forward-zones). Most authority servers do.
        # This feature is an experimental implementation of draft dns-0x20.
+       # It is known that some authority servers do not support 0x20, and
+       # resolution will fail for them. A solution is on the TODO list.
        # use-caps-for-id: no
        
        # Do not query the following addresses. No DNS queries are sent there.
index 5d43de9ce3b32ac41a2a994d93e546ee627ef193..3caca1e0cf0d27bec469a64e30f8d0ca32bb88e4 100644 (file)
@@ -345,10 +345,9 @@ downgrade attack that disables security for a zone. Default is on.
 Use 0x20-encoded random bits in the query to foil spoof attempts.
 This perturbs the lowercase and uppercase of query names sent to 
 authority servers and checks if the reply still has the correct casing. 
-Use together with a large outgoing port range to obtain a high spoof resistance.
 Disabled by default, because some caching forwarders may not
-support this. If you have no forward\-zones it should be possible to enable
-this without problem, it works with most authority servers.
+support this. It is known that some authority servers do not support 0x20, 
+and resolution will fail for them. A solution is on the TODO list.
 This feature is an experimental implementation of draft dns\-0x20.
 .TP
 .B do\-not\-query\-address: \fI<IP address>
@@ -631,7 +630,7 @@ server:
        num\-threads: 1
        outgoing\-num\-tcp: 1   # this limits TCP service, uses less buffers.
        incoming\-num\-tcp: 1
-       outgoing\-range: 1      # uses less memory, but less port randomness.
+       outgoing\-range: 16     # uses less memory, but less performance.
        msg\-buffer\-size: 8192   # note this limits service, 'no huge stuff'.
        msg\-cache\-size: 100k
        msg\-cache\-slabs: 1
index a3ac7ac40da6b22d99168e7654e4bce72be707f3..1fb997d832bd996717ddd83ffcfba14085844281 100644 (file)
@@ -52,6 +52,9 @@
 #include "validator/validator.h"
 #include "services/localzone.h"
 #include <pwd.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
 
 /** Give checkconf usage, and exit (1). */
 static void
@@ -171,18 +174,117 @@ aclchecks(struct config_file* cfg)
        }
 }
 
+/** true if fname is a file */
+static int
+is_file(const char* fname) 
+{
+       struct stat buf;
+       if(stat(fname, &buf) < 0) {
+               if(errno==EACCES) {
+                       printf("warning: no search permission for one of the directories in path: %s\n", fname);
+                       return 1;
+               }
+               perror(fname);
+               return 0;
+       }
+       if(S_ISDIR(buf.st_mode)) {
+               printf("%s is not a file\n", fname);
+               return 0;
+       }
+       return 1;
+}
+
+/** true if fname is a directory */
+static int
+is_dir(const char* fname) 
+{
+       struct stat buf;
+       if(stat(fname, &buf) < 0) {
+               if(errno==EACCES) {
+                       printf("warning: no search permission for one of the directories in path: %s\n", fname);
+                       return 1;
+               }
+               perror(fname);
+               return 0;
+       }
+       if(!(S_ISDIR(buf.st_mode))) {
+               printf("%s is not a directory\n", fname);
+               return 0;
+       }
+       return 1;
+}
+
+/** convert a filename to full pathname in original filesys. return static */
+static char*
+fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
+{
+       static char buf[1024];
+       int slashit = 0;
+       buf[0] = 0;
+       if(cfg->chrootdir && cfg->chrootdir[0] && 
+               strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) {
+               /* already full pathname, return it */
+               strncpy(buf, fname, sizeof(buf)-1);
+               buf[sizeof(buf)-1] = 0;
+               return buf;
+       }
+       /* chroot */
+       if(cfg->chrootdir && cfg->chrootdir[0]) {
+               /* start with chrootdir */
+               strncpy(buf, cfg->chrootdir, sizeof(buf)-1);
+               slashit = 1;
+       }
+       /* chdir */
+       if(fname[0] == '/' || !use_chdir) {
+               /* full path, no chdir */
+       } else if(cfg->directory && cfg->directory[0]) {
+               /* prepend chdir */
+               if(slashit && cfg->directory[0] != '/')
+                       strncat(buf, "/", sizeof(buf)-1);
+               if(strncmp(cfg->chrootdir, cfg->directory, 
+                       strlen(cfg->chrootdir)) == 0)
+                       strncat(buf, cfg->directory+strlen(cfg->chrootdir), 
+                               sizeof(buf)-1);
+               else strncat(buf, cfg->directory, sizeof(buf)-1);
+               slashit = 1;
+       }
+       /* fname */
+       if(slashit && fname[0] != '/')
+               strncat(buf, "/", sizeof(buf)-1);
+       strncat(buf, fname, sizeof(buf)-1);
+       buf[sizeof(buf)-1] = 0;
+       return buf;
+}
+
+/** get base dir of a fname */
+static char*
+basedir(const char* fname, struct config_file* cfg)
+{
+       char* d = fname_after_chroot(fname, cfg, 1);
+       char* rev = strrchr(d, '/');
+       if(!rev) return NULL;
+       if(d == rev) return NULL;
+       rev[0] = 0;
+       return d;
+}
+
 /** check file list, every file must be inside the chroot location */
 static void
 check_chroot_filelist(const char* desc, struct config_strlist* list,
-       const char* chrootdir)
+       const char* chrootdir, struct config_file* cfg)
 {
        struct config_strlist* p;
-       if(!chrootdir) return;
+       char* old;
        for(p=list; p; p=p->next) {
-               if(p->str && p->str[0] && strncmp(chrootdir, p->str,
-                       strlen(chrootdir)) != 0) {
-                       fatal_exit("%s: \"%s\" not in chrootdir %s", 
-                               desc, p->str, chrootdir);
+               if(p->str && p->str[0]) {
+                       if(!is_file(fname_after_chroot(p->str, cfg, 1))) {
+                               fatal_exit("%s: \"%s\" does not exist in chrootdir %s", 
+                                       desc, p->str, chrootdir);
+                       }
+                       old = p->str;
+                       /* put in a new full path for continued checking */
+                       p->str = strdup(fname_after_chroot(p->str, cfg, 1));
+                       free(old);
                }
        }
 }
@@ -209,26 +311,37 @@ morechecks(struct config_file* cfg)
                cfg->chrootdir[strlen(cfg->chrootdir)-1] == '/')
                fatal_exit("chootdir %s has trailing slash '/' please remove.",
                        cfg->chrootdir);
-       if(cfg->chrootdir && strncmp(cfg->chrootdir, cfg->directory,
-               strlen(cfg->chrootdir)) != 0)
-               fatal_exit("working directory %s not in chrootdir %s",
-                       cfg->directory, cfg->chrootdir);
-       if(cfg->chrootdir && cfg->pidfile && cfg->pidfile[0] &&
-               strncmp(cfg->chrootdir, cfg->pidfile,
-                       strlen(cfg->chrootdir)) != 0)
-               fatal_exit("pid file %s not in chrootdir %s",
-                       cfg->pidfile, cfg->chrootdir);
-       if(cfg->chrootdir && cfg->logfile && cfg->logfile[0] &&
-               strncmp(cfg->chrootdir, cfg->logfile,
-                       strlen(cfg->chrootdir)) != 0)
-               fatal_exit("log file %s not in chrootdir %s",
-                       cfg->logfile, cfg->chrootdir);
+       if(cfg->chrootdir && cfg->chrootdir[0] && 
+               !is_dir(cfg->chrootdir)) {
+               fatal_exit("bad chroot 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]) ||
+           (cfg->directory && cfg->directory[0])) {
+               if(cfg->pidfile && cfg->pidfile[0] &&
+                  basedir(cfg->pidfile, cfg) &&
+                  !is_dir(basedir(cfg->pidfile, cfg))) {
+                       fatal_exit("pidfile directory does not exist");
+               }
+               if(cfg->logfile && cfg->logfile[0] &&
+                  basedir(cfg->logfile, cfg) &&
+                  !is_dir(basedir(cfg->logfile, cfg))) {
+                       fatal_exit("pidfile directory does not exist");
+               }
+       }
+
        check_chroot_filelist("file with root-hints", 
-               cfg->root_hints, cfg->chrootdir);
+               cfg->root_hints, cfg->chrootdir, cfg);
        check_chroot_filelist("trust-anchor-file", 
-               cfg->trust_anchor_file_list, cfg->chrootdir);
+               cfg->trust_anchor_file_list, cfg->chrootdir, cfg);
        check_chroot_filelist("trusted-keys-file", 
-               cfg->trusted_keys_file_list, cfg->chrootdir);
+               cfg->trusted_keys_file_list, cfg->chrootdir, cfg);
+       /* remove chroot setting so that modules are not stripping pathnames*/
+       free(cfg->chrootdir);
+       cfg->chrootdir = NULL;
        
        if(strcmp(cfg->module_conf, "iterator") != 0 &&
                strcmp(cfg->module_conf, "validator iterator") != 0) {
diff --git a/testdata/07-confroot.tpkg b/testdata/07-confroot.tpkg
new file mode 100644 (file)
index 0000000..76ee43e
Binary files /dev/null and b/testdata/07-confroot.tpkg differ