mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-02-03 20:29:28 -05:00
- auth zone zonefiles can be in a chroot, the chroot directory
components are removed before use. git-svn-id: file:///svn/unbound/trunk@4972 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
c97bb52d77
commit
692caffe2c
5 changed files with 37 additions and 21 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue