From 2f7bd7725067752ba6f496541a9f6259c49a746e Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Mon, 14 Apr 2008 14:48:17 +0000 Subject: [PATCH] 0x20 document, checkconf fix. git-svn-id: file:///svn/unbound/trunk@1037 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 2 + doc/TODO | 1 + doc/example.conf | 2 + doc/unbound.conf.5 | 7 +- smallapp/unbound-checkconf.c | 159 ++++++++++++++++++++++++++++++----- testdata/07-confroot.tpkg | Bin 0 -> 2260 bytes 6 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 testdata/07-confroot.tpkg diff --git a/doc/Changelog b/doc/Changelog index 2c333fa86..41ea0f352 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/doc/TODO b/doc/TODO index 36c656a29..19d939b96 100644 --- 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. diff --git a/doc/example.conf b/doc/example.conf index 2d6e42af9..0af9c7571 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -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. diff --git a/doc/unbound.conf.5 b/doc/unbound.conf.5 index 5d43de9ce..3caca1e0c 100644 --- a/doc/unbound.conf.5 +++ b/doc/unbound.conf.5 @@ -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 @@ -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 diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c index a3ac7ac40..1fb997d83 100644 --- a/smallapp/unbound-checkconf.c +++ b/smallapp/unbound-checkconf.c @@ -52,6 +52,9 @@ #include "validator/validator.h" #include "services/localzone.h" #include +#ifdef HAVE_SYS_STAT_H +#include +#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 index 0000000000000000000000000000000000000000..76ee43e6a51042ac50afd6863c60b95f9bc60d14 GIT binary patch literal 2260 zc-jHf2rKs=iwFQ*ZUaaF1MQrBY#V1C#~)f~n`dm4w=xyhKGD-plrRh>e z+Nw>h0t`h43@F24KSJ$HV-{@p#lyExVzN#}Dzc0TVKnXDZZ zS3oh;-Q8K9c6C%teTjISpIu$u@nk~8;>l!ZLa5Fwu`|^wI<9FeB_{Gk*Rto1n{W9N zRjjK2D_%S4#&%leV)3w=~1G99N}Btn{cCtR}MV2rs>r6!tM>k8PP=>1B&wF*`)<1l~vw?1pEkdnJ>iywK1xB>RH;qqvAZ?C=lLmoEmLq={aXSrkMpu=x-#2qegFzVRpXfZdK zFXl2)*DmHpqn^<+rfWuPosPVq1|GSV)-|M}I~3V)y+|hFv2f`9>YeY{d$spSOG`^j zOG`^jOG~TCatq7E>r9uyF?f^Da=0H3`>(aMw6wIew6wIew6wIew3e>Sj1b+mRi86JTN$b$*}@Ciu5`{1?f zh4>qsgI~dO@KqRwkHPJ*7XI~CA)bMs!qe~sOu$B13BS2ch{s_+Y=pINNeb~7_%S>R zUx7T_4eQ}O@Ge*dE8$X`5dVe0!wc|RcnVI#x8Msf41I7X#2^X+{;*1jlkh!w2=>8; zpdG@n4F0)Nh*NM9z6;-kZ@|OwB`Cr;d=|DtA4K6sxU_CKzI0lcwBg?AHXx*1}y{CSx^hjQXcHR{d zLs`*Qnj2?Yn%gt=>{)(jDo}OI7plBzcDUk!wQSDGW-P@jLuPi&%7jFAsQiFi`|T={ zvs7%Oa!0J3Xy3KFck+pq$n?W+rN^VZ--PJhxlOdWcF}RIOk~tL|V>_Rp(c?^Ch z8O-w9V|6R-mL4DsmA6KCx%Zi4goI<+_gZ#Jq)k_Sbh<;;rcGXtif}lrcJ$sopay#P z3{3k{C6}JvmX6z+WVS2mwdgFfwWlXC3w2vUyG^^Tp3Jrwv&FBn*~$%u*yY)sP_|di zki`5UwIZfXTqB@n8&j6`m#2+V-;n`sJ=aFi;5?@jTrypY+-5>zG3`zOOZSF zsDN$EXtr{l!GQL9`f9f~IMp7Jv=^|AS?x`(V+ORheMjx~%&GQhEMNn(8Z$*0XN_8_ zFml@W-q5He<4S${B>AdItVqv zJ3%u3pyMsIErP?5$gDqvQISZvH2&Ym*lzcV^7!Ao=YNqg{wwez{1JW)r{G8MHTWD1 z!X2;$J`A_OtBmc>!gt^VJODdE`Q!fg!mEty&%;SL0mtDe9D#@6^Dqt;+yftn?GS?- z;S%Hi7vTkX7S6y?uwXN6f;DjAIw5`rPr+$828W>+HbV*wh`@SS2dhB9zoif_!+AIh zr{D;<;J~M0KYRpUYh%0%e}W&vgRmQRKtJ3H?}nFF5wogXGk6Yu38&#nI1Z1)7vX+5 z1P7oGZUG5xaB(I50%zbTjKV?K3Txm3efTn*_v;1U2OAE;FzkmOih8K6@Z17F3I^EWcKe(^`{V(xk zvMXNo{SRHqWQYF#hh}K*(vYmD#3UD5$dYx}%w&BMv zoas3@e0G?;oO4KU&|Igb;OMzddD81VS$%s#)_a3PF5+&AT)^EMxrn<(ashXzv`&*q*xo943yoIG3KXx$AQ7+mpu)-pqamdj{M;Jmqk_d}MSOS$&G;af{f iOG`^jOG`^jOG`^jOG`^jOH1oo)c*nVR{Y!mcmM!jLx&3h literal 0 Hc-jL100001 -- 2.47.2