]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- auth zone zonefiles can be in a chroot, the chroot directory
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 22 Nov 2018 15:51:09 +0000 (15:51 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 22 Nov 2018 15:51:09 +0000 (15:51 +0000)
  components are removed before use.

git-svn-id: file:///svn/unbound/trunk@4972 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/remote.c
doc/Changelog
services/authzone.c
services/authzone.h
testcode/unitauth.c

index 3971e4540510ba08f93b36d1e458d32675d0fd5a..84b90a95d5d4eddbfe42436849e7705203b5756d 100644 (file)
@@ -2456,7 +2456,7 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
                (void)ssl_printf(ssl, "error no auth-zone %s\n", arg);
                return;
        }
-       if(!auth_zone_read_zonefile(z)) {
+       if(!auth_zone_read_zonefile(z, worker->env.cfg)) {
                lock_rw_unlock(&z->lock);
                (void)ssl_printf(ssl, "error failed to read %s\n", arg);
                return;
index e056a4a338930796f2639ea16dbaf6af04ae1e46..50c86f38028f929ed6cbdb7e71a6b126a92c562f 100644 (file)
@@ -6,6 +6,8 @@
        - ignore debug python module for test in doxygen output.
        - review fixes for python module.
        - Fix #4209: Crash in libunbound when called from getdns.
+       - auth zone zonefiles can be in a chroot, the chroot directory
+         components are removed before use.
 
 21 November 2018: Wouter
        - Scrub NS records from NODATA responses as well.
index 1f29c3ae90800cdb260865c888d8252911b00799..a25106bd2fa56a3501c724b24ab3ba6d7e2a04d6 100644 (file)
@@ -1450,11 +1450,13 @@ az_remove_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
  *     The lineno is set at 1 and then increased by the function.
  * @param fname: file name.
  * @param depth: recursion depth for includes
+ * @param cfg: config for chroot.
  * returns false on failure, has printed an error message
  */
 static int
 az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
-       struct sldns_file_parse_state* state, char* fname, int depth)
+       struct sldns_file_parse_state* state, char* fname, int depth,
+       struct config_file* cfg)
 {
        size_t rr_len, dname_len;
        int status;
@@ -1480,6 +1482,8 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                                /* skip spaces */
                                while(*incfile == ' ' || *incfile == '\t')
                                        incfile++;
+                               /* adjust for chroot on include file */
+                               incfile = fname_after_chroot(incfile, cfg, 1);
                                incfile = strdup(incfile);
                                if(!incfile) {
                                        log_err("malloc failure");
@@ -1490,7 +1494,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                                inc = fopen(incfile, "r");
                                if(!inc) {
                                        log_err("%s:%d cannot open include "
-                                               "file %s: %s", z->zonefile,
+                                               "file %s: %s", fname,
                                                lineno_orig, incfile,
                                                strerror(errno));
                                        free(incfile);
@@ -1498,7 +1502,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                                }
                                /* recurse read that file now */
                                if(!az_parse_file(z, inc, rr, rrbuflen,
-                                       state, incfile, depth+1)) {
+                                       state, incfile, depth+1, cfg)) {
                                        log_err("%s:%d cannot parse include "
                                                "file %s", fname,
                                                lineno_orig, incfile);
@@ -1538,30 +1542,32 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
 }
 
 int
-auth_zone_read_zonefile(struct auth_zone* z)
+auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg)
 {
        uint8_t rr[LDNS_RR_BUF_SIZE];
        struct sldns_file_parse_state state;
+       char* zfilename;
        FILE* in;
        if(!z || !z->zonefile || z->zonefile[0]==0)
                return 1; /* no file, or "", nothing to read */
+       zfilename = fname_after_chroot(z->zonefile, cfg, 1);
        if(verbosity >= VERB_ALGO) {
                char nm[255+1];
                dname_str(z->name, nm);
-               verbose(VERB_ALGO, "read zonefile %s for %s", z->zonefile, nm);
+               verbose(VERB_ALGO, "read zonefile %s for %s", zfilename, nm);
        }
-       in = fopen(z->zonefile, "r");
+       in = fopen(zfilename, "r");
        if(!in) {
                char* n = sldns_wire2str_dname(z->name, z->namelen);
                if(z->zone_is_slave && errno == ENOENT) {
                        /* we fetch the zone contents later, no file yet */
                        verbose(VERB_ALGO, "no zonefile %s for %s",
-                               z->zonefile, n?n:"error");
+                               zfilename, n?n:"error");
                        free(n);
                        return 1;
                }
                log_err("cannot open zonefile %s for %s: %s",
-                       z->zonefile, n?n:"error", strerror(errno));
+                       zfilename, n?n:"error", strerror(errno));
                free(n);
                return 0;
        }
@@ -1579,10 +1585,10 @@ auth_zone_read_zonefile(struct auth_zone* z)
                state.origin_len = z->namelen;
        }
        /* parse the (toplevel) file */
-       if(!az_parse_file(z, in, rr, sizeof(rr), &state, z->zonefile, 0)) {
+       if(!az_parse_file(z, in, rr, sizeof(rr), &state, zfilename, 0, cfg)) {
                char* n = sldns_wire2str_dname(z->name, z->namelen);
                log_err("error parsing zonefile %s for %s",
-                       z->zonefile, n?n:"error");
+                       zfilename, n?n:"error");
                free(n);
                fclose(in);
                return 0;
@@ -1710,13 +1716,13 @@ int auth_zone_write_file(struct auth_zone* z, const char* fname)
 
 /** read all auth zones from file (if they have) */
 static int
-auth_zones_read_zones(struct auth_zones* az)
+auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg)
 {
        struct auth_zone* z;
        lock_rw_wrlock(&az->lock);
        RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
                lock_rw_wrlock(&z->lock);
-               if(!auth_zone_read_zonefile(z)) {
+               if(!auth_zone_read_zonefile(z, cfg)) {
                        lock_rw_unlock(&z->lock);
                        lock_rw_unlock(&az->lock);
                        return 0;
@@ -1953,7 +1959,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
                }
        }
        az_delete_deleted_zones(az);
-       if(!auth_zones_read_zones(az))
+       if(!auth_zones_read_zones(az, cfg))
                return 0;
        if(setup) {
                if(!auth_zones_setup_zones(az))
@@ -4775,6 +4781,7 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
 {
        struct auth_zone* z;
        char tmpfile[1024];
+       char* zfilename;
        lock_basic_unlock(&xfr->lock);
 
        /* get lock again, so it is a readlock and concurrently queries
@@ -4797,15 +4804,16 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
                /* no write needed, no zonefile set */
                return;
        }
+       zfilename = fname_after_chroot(z->zonefile, env->cfg, 1);
 
        /* write to tempfile first */
-       if((size_t)strlen(z->zonefile) + 16 > sizeof(tmpfile)) {
+       if((size_t)strlen(zfilename) + 16 > sizeof(tmpfile)) {
                verbose(VERB_ALGO, "tmpfilename too long, cannot update "
-                       " zonefile %s", z->zonefile);
+                       " zonefile %s", zfilename);
                lock_rw_unlock(&z->lock);
                return;
        }
-       snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", z->zonefile,
+       snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", zfilename,
                (unsigned)getpid());
        if(xfr->task_transfer->master->http) {
                /* use the stored chunk list to write them */
@@ -4818,8 +4826,8 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
                lock_rw_unlock(&z->lock);
                return;
        }
-       if(rename(tmpfile, z->zonefile) < 0) {
-               log_err("could not rename(%s, %s): %s", tmpfile, z->zonefile,
+       if(rename(tmpfile, zfilename) < 0) {
+               log_err("could not rename(%s, %s): %s", tmpfile, zfilename,
                        strerror(errno));
                unlink(tmpfile);
                lock_rw_unlock(&z->lock);
index 8c636eaa446c9476b8b014c1f912e367f62f001c..243f3e4a01e8822b34762f858dd19cfa97fe722e 100644 (file)
@@ -599,7 +599,7 @@ int auth_zones_startprobesequence(struct auth_zones* az,
        struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t dclass);
 
 /** read auth zone from zonefile. caller must lock zone. false on failure */
-int auth_zone_read_zonefile(struct auth_zone* z);
+int auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg);
 
 /** find serial number of zone or false if none (no SOA record) */
 int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial);
index c162e7ef9648643c0ec557b8e2b749a2ccd500c7..4b3410c9ef7ce1ecacda21b9a25cfb77866912f1 100644 (file)
@@ -42,6 +42,7 @@
 #include "testcode/unitmain.h"
 #include "util/regional.h"
 #include "util/net_help.h"
+#include "util/config_file.h"
 #include "util/data/msgreply.h"
 #include "services/cache/dns.h"
 #include "sldns/str2wire.h"
@@ -522,6 +523,7 @@ addzone(struct auth_zones* az, const char* name, char* fname)
        struct auth_zone* z;
        size_t nmlen;
        uint8_t* nm = sldns_str2wire_dname(name, &nmlen);
+       struct config_file* cfg;
        if(!nm) fatal_exit("out of memory");
        lock_rw_wrlock(&az->lock);
        z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN);
@@ -529,12 +531,16 @@ addzone(struct auth_zones* az, const char* name, char* fname)
        if(!z) fatal_exit("cannot find zone");
        auth_zone_set_zonefile(z, fname);
        z->for_upstream = 1;
+       cfg = config_create();
+       free(cfg->chrootdir);
+       cfg->chrootdir = NULL;
 
-       if(!auth_zone_read_zonefile(z)) {
+       if(!auth_zone_read_zonefile(z, cfg)) {
                fatal_exit("parse failure for auth zone %s", name);
        }
        lock_rw_unlock(&z->lock);
        free(nm);
+       config_delete(cfg);
        return z;
 }