diff --git a/contrib/fastrpz.patch b/contrib/fastrpz.patch index 2cd6a7182..aacd5ab82 100644 --- a/contrib/fastrpz.patch +++ b/contrib/fastrpz.patch @@ -2,7 +2,7 @@ Description: based on the included patch contrib/fastrpz.patch Author: fastrpz@farsightsecurity.com --- diff --git a/Makefile.in b/Makefile.in -index 1a2e2c54..028b6cf3 100644 +index a20058cc..495779cc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c @@ -14,7 +14,7 @@ index 1a2e2c54..028b6cf3 100644 DNSCRYPT_SRC=@DNSCRYPT_SRC@ DNSCRYPT_OBJ=@DNSCRYPT_OBJ@ WITH_PYTHONMODULE=@WITH_PYTHONMODULE@ -@@ -126,7 +128,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \ +@@ -127,7 +129,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \ edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \ edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \ cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \ @@ -23,7 +23,7 @@ index 1a2e2c54..028b6cf3 100644 COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \ as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \ iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \ -@@ -139,7 +141,7 @@ autotrust.lo val_anchor.lo \ +@@ -140,7 +142,7 @@ autotrust.lo val_anchor.lo rpz.lo \ validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \ val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \ $(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \ @@ -32,7 +32,7 @@ index 1a2e2c54..028b6cf3 100644 COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \ outside_network.lo COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo -@@ -409,6 +411,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \ +@@ -410,6 +412,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \ $(srcdir)/util/config_file.h $(srcdir)/util/log.h \ $(srcdir)/util/netevent.h @@ -62,7 +62,7 @@ index 78d47fed..e33073e4 100644 +/** turn on fastrpz response policy zones */ +#undef ENABLE_FASTRPZ diff --git a/configure.ac b/configure.ac -index 9a32c577..cc4344ff 100644 +index 2b91dd3c..e6063d17 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,7 @@ sinclude(ax_pthread.m4) @@ -84,7 +84,7 @@ index 9a32c577..cc4344ff 100644 # on openBSD, the implicit rule make $< work. # on Solaris, it does not work ($? is changed sources, $^ lists dependencies). diff --git a/daemon/daemon.c b/daemon/daemon.c -index 0b1200a2..5857c18b 100644 +index 8b0fc348..7ffb9221 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -91,6 +91,9 @@ @@ -112,7 +112,7 @@ index 0b1200a2..5857c18b 100644 #endif } for(i=0; inum; i++) { -@@ -724,6 +735,9 @@ daemon_cleanup(struct daemon* daemon) +@@ -731,6 +742,9 @@ daemon_cleanup(struct daemon* daemon) #ifdef USE_DNSCRYPT dnsc_delete(daemon->dnscenv); daemon->dnscenv = NULL; @@ -123,10 +123,10 @@ index 0b1200a2..5857c18b 100644 daemon->cfg = NULL; } diff --git a/daemon/daemon.h b/daemon/daemon.h -index 5749dbef..64ce230f 100644 +index 3effbafb..4d4c34da 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h -@@ -136,6 +136,11 @@ struct daemon { +@@ -138,6 +138,11 @@ struct daemon { /** the dnscrypt environment */ struct dnsc_env* dnscenv; #endif @@ -139,10 +139,10 @@ index 5749dbef..64ce230f 100644 /** diff --git a/daemon/worker.c b/daemon/worker.c -index aa16650e..c7c05828 100644 +index eb7fdf2f..1982228d 100644 --- a/daemon/worker.c +++ b/daemon/worker.c -@@ -75,6 +75,9 @@ +@@ -76,6 +76,9 @@ #include "libunbound/context.h" #include "libunbound/libworker.h" #include "sldns/sbuffer.h" @@ -152,7 +152,7 @@ index aa16650e..c7c05828 100644 #include "sldns/wire2str.h" #include "util/shm_side/shm_main.h" #include "dnscrypt/dnscrypt.h" -@@ -533,8 +536,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, +@@ -534,8 +537,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, /* not secure */ secure = 0; break; @@ -180,10 +180,10 @@ index aa16650e..c7c05828 100644 /* return this delegation from the cache */ edns_bak = *edns; edns->edns_version = EDNS_ADVERTISED_VERSION; -@@ -699,6 +721,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, - secure = 0; +@@ -710,6 +732,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, + *is_secure_answer = 0; } - } else secure = 0; + } else *is_secure_answer = 0; +#ifdef ENABLE_FASTRPZ + if(repinfo->rpz) { + /* Scan the cached answer for RPZ hits. @@ -204,7 +204,7 @@ index aa16650e..c7c05828 100644 edns_bak = *edns; edns->edns_version = EDNS_ADVERTISED_VERSION; -@@ -1410,6 +1449,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error, +@@ -1435,6 +1474,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error, log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from", &repinfo->addr, repinfo->addrlen); goto send_reply; @@ -220,14 +220,14 @@ index aa16650e..c7c05828 100644 } /* If we've found a local alias, replace the qname with the alias -@@ -1458,12 +1506,21 @@ lookup_cache: +@@ -1485,12 +1533,21 @@ lookup_cache: h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2)); if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) { /* answer from cache - we have acquired a readlock on it */ - if(answer_from_cache(worker, &qinfo, + ret = answer_from_cache(worker, &qinfo, - cinfo, &need_drop, &alias_rrset, &partial_rep, - (struct reply_info*)e->data, + cinfo, &need_drop, &is_expired_answer, &is_secure_answer, + &alias_rrset, &partial_rep, (struct reply_info*)e->data, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), sldns_buffer_read_u16_at(c->buffer, 2), repinfo, - &edns)) { @@ -244,7 +244,7 @@ index aa16650e..c7c05828 100644 /* prefetch it if the prefetch TTL expired. * Note that if there is more than one pass * its qname must be that used for cache -@@ -1520,11 +1577,19 @@ lookup_cache: +@@ -1547,11 +1604,19 @@ lookup_cache: lock_rw_unlock(&e->lock); } if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) { @@ -267,10 +267,10 @@ index aa16650e..c7c05828 100644 } verbose(VERB_ALGO, "answer norec from cache -- " diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in -index 6292f0d4..7e91a91f 100644 +index 38c2d298..3b07f392 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in -@@ -1811,6 +1811,81 @@ List domain for which the AAAA records are ignored and the A record is +@@ -1828,6 +1828,81 @@ List domain for which the AAAA records are ignored and the A record is used by dns64 processing instead. Can be entered multiple times, list a new domain for which it applies, one per line. Applies also to names underneath the name given. @@ -3106,10 +3106,10 @@ index a2f1b570..e1e4a738 100644 * Count number of time-outs. Used to prevent resolving failures when * the QNAME minimisation QTYPE is blocked. */ diff --git a/services/cache/dns.c b/services/cache/dns.c -index aa4efec7..5dd3412e 100644 +index 2a5bca4a..6de8863a 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c -@@ -945,6 +945,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, +@@ -967,6 +967,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, struct regional* region, uint32_t flags) { struct reply_info* rep = NULL; @@ -3125,10 +3125,10 @@ index aa4efec7..5dd3412e 100644 rep = reply_info_copy(msgrep, env->alloc, NULL); if(!rep) diff --git a/services/mesh.c b/services/mesh.c -index d4f814d5..624a9d95 100644 +index 9114ef4c..3dc518e5 100644 --- a/services/mesh.c +++ b/services/mesh.c -@@ -60,6 +60,9 @@ +@@ -61,6 +61,9 @@ #include "sldns/wire2str.h" #include "services/localzone.h" #include "util/data/dname.h" @@ -3138,7 +3138,7 @@ index d4f814d5..624a9d95 100644 #include "respip/respip.h" #include "services/listen_dnsport.h" -@@ -1076,6 +1079,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, +@@ -1195,6 +1198,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, else secure = 0; if(!rep && rcode == LDNS_RCODE_NOERROR) rcode = LDNS_RCODE_SERVFAIL; @@ -3152,7 +3152,7 @@ index d4f814d5..624a9d95 100644 /* send the reply */ /* We don't reuse the encoded answer if either the previous or current * response has a local alias. We could compare the alias records -@@ -1255,6 +1265,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh, +@@ -1415,6 +1425,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh, key.s.is_valrec = valrec; key.s.qinfo = *qinfo; key.s.query_flags = qflags; @@ -3160,7 +3160,7 @@ index d4f814d5..624a9d95 100644 /* We are searching for a similar mesh state when we DO want to * aggregate the state. Thus unique is set to NULL. (default when we * desire aggregation).*/ -@@ -1301,6 +1312,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, +@@ -1461,6 +1472,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, if(!r) return 0; r->query_reply = *rep; @@ -3172,10 +3172,10 @@ index d4f814d5..624a9d95 100644 if(edns->opt_list) { r->edns.opt_list = edns_opt_copy_region(edns->opt_list, diff --git a/util/config_file.c b/util/config_file.c -index 104c3f83..a5015594 100644 +index 52ca5a18..0660248f 100644 --- a/util/config_file.c +++ b/util/config_file.c -@@ -1434,6 +1434,8 @@ config_delete(struct config_file* cfg) +@@ -1460,6 +1460,8 @@ config_delete(struct config_file* cfg) free(cfg->dnstap_socket_path); free(cfg->dnstap_identity); free(cfg->dnstap_version); @@ -3185,10 +3185,10 @@ index 104c3f83..a5015594 100644 config_deldblstrlist(cfg->ratelimit_below_domain); config_delstrlist(cfg->python_script); diff --git a/util/config_file.h b/util/config_file.h -index b3ef930a..56173b80 100644 +index 8739ca2a..a2dcf215 100644 --- a/util/config_file.h +++ b/util/config_file.h -@@ -494,6 +494,11 @@ struct config_file { +@@ -499,6 +499,11 @@ struct config_file { /** true to disable DNSSEC lameness check in iterator */ int disable_dnssec_lame_check; @@ -3201,10 +3201,10 @@ index b3ef930a..56173b80 100644 int ip_ratelimit; /** number of slabs for ip_ratelimit cache */ diff --git a/util/configlexer.lex b/util/configlexer.lex -index a86ddf55..b56bcfb4 100644 +index deedffa5..301458a3 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex -@@ -438,6 +438,10 @@ dnstap-log-forwarder-query-messages{COLON} { +@@ -446,6 +446,10 @@ dnstap-log-forwarder-query-messages{COLON} { YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) } dnstap-log-forwarder-response-messages{COLON} { YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) } @@ -3216,7 +3216,7 @@ index a86ddf55..b56bcfb4 100644 ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) } ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) } diff --git a/util/configparser.y b/util/configparser.y -index 8be6bd3e..74d885ad 100644 +index d471babe..cb6b1d63 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -125,6 +125,7 @@ extern struct config_parser_state* cfg_parser; @@ -3227,7 +3227,7 @@ index 8be6bd3e..74d885ad 100644 %token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA %token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT %token VAR_DISABLE_DNSSEC_LAME_CHECK -@@ -171,7 +172,7 @@ extern struct config_parser_state* cfg_parser; +@@ -173,7 +174,7 @@ extern struct config_parser_state* cfg_parser; %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; @@ -3236,7 +3236,7 @@ index 8be6bd3e..74d885ad 100644 forwardstart contents_forward | pythonstart contents_py | rcstart contents_rc | dtstart contents_dt | viewstart contents_view | dnscstart contents_dnsc | cachedbstart contents_cachedb | -@@ -2728,6 +2729,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES +@@ -2837,6 +2838,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES free($2); } ; @@ -3288,10 +3288,10 @@ index 8be6bd3e..74d885ad 100644 { OUTYY(("\nP(python:)\n")); diff --git a/util/data/msgencode.c b/util/data/msgencode.c -index a51a4b9b..475dfce9 100644 +index be69f628..f10773aa 100644 --- a/util/data/msgencode.c +++ b/util/data/msgencode.c -@@ -590,6 +590,35 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs, +@@ -592,6 +592,35 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs, return RETVAL_OK; } @@ -3327,7 +3327,7 @@ index a51a4b9b..475dfce9 100644 /** store query section in wireformat buffer, return RETVAL */ static int insert_query(struct query_info* qinfo, struct compress_tree_node** tree, -@@ -777,6 +806,19 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep, +@@ -779,6 +808,19 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep, } sldns_buffer_write_u16_at(buffer, 10, arcount); } @@ -3348,10 +3348,10 @@ index a51a4b9b..475dfce9 100644 sldns_buffer_flip(buffer); return 1; diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c -index 7b9d5494..e44b2ce5 100644 +index 4b0294f9..3b3838f6 100644 --- a/util/data/packed_rrset.c +++ b/util/data/packed_rrset.c -@@ -255,6 +255,10 @@ sec_status_to_string(enum sec_status s) +@@ -256,6 +256,10 @@ sec_status_to_string(enum sec_status s) case sec_status_insecure: return "sec_status_insecure"; case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail"; case sec_status_secure: return "sec_status_secure"; @@ -3363,7 +3363,7 @@ index 7b9d5494..e44b2ce5 100644 return "unknown_sec_status_value"; } diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h -index 3a5335dd..20113217 100644 +index 729877ba..ccd1a0c2 100644 --- a/util/data/packed_rrset.h +++ b/util/data/packed_rrset.h @@ -193,7 +193,15 @@ enum sec_status { diff --git a/daemon/unbound.c b/daemon/unbound.c index beffb5700..af76fc84f 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -259,21 +259,10 @@ checkrlimits(struct config_file* cfg) #endif /* S_SPLINT_S */ } -/** set default logfile identity based on value from argv[0] at startup **/ -static void -log_ident_set_fromdefault(struct config_file* cfg, - const char *log_default_identity) -{ - if(cfg->log_identity == NULL || cfg->log_identity[0] == 0) - log_ident_set(log_default_identity); - else - log_ident_set(cfg->log_identity); -} - /** set verbosity, check rlimits, cache settings */ static void -apply_settings(struct daemon* daemon, struct config_file* cfg, - int cmdline_verbose, int debug_mode, const char* log_default_identity) +apply_settings(struct daemon* daemon, struct config_file* cfg, + int cmdline_verbose, int debug_mode) { /* apply if they have changed */ verbosity = cmdline_verbose + cfg->verbosity; @@ -289,7 +278,7 @@ apply_settings(struct daemon* daemon, struct config_file* cfg, log_warn("use-systemd and do-daemonize should not be enabled at the same time"); } - log_ident_set_fromdefault(cfg, log_default_identity); + log_ident_set_or_default(cfg->log_identity); } #ifdef HAVE_KILL @@ -639,11 +628,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, * @param cmdline_verbose: verbosity resulting from commandline -v. * These increase verbosity as specified in the config file. * @param debug_mode: if set, do not daemonize. - * @param log_default_identity: Default identity to report in logs * @param need_pidfile: if false, no pidfile is checked or created. */ static void -run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile) +run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pidfile) { struct config_file* cfg = NULL; struct daemon* daemon = NULL; @@ -667,7 +655,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* "or unbound-checkconf", cfgfile); log_warn("Continuing with default config settings"); } - apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity); + apply_settings(daemon, cfg, cmdline_verbose, debug_mode); if(!done_setup) config_lookup_uid(cfg); @@ -733,6 +721,7 @@ main(int argc, char* argv[]) log_init(NULL, 0, NULL); log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0]; + log_ident_set_default(log_ident_default); log_ident_set(log_ident_default); /* parse the options */ while( (c=getopt(argc, argv, "c:dhpvw:V")) != -1) { @@ -783,7 +772,7 @@ main(int argc, char* argv[]) return 1; } - run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile); + run_daemon(cfgfile, cmdline_verbose, debug_mode, need_pidfile); log_init(NULL, 0, NULL); /* close logfile */ #ifndef unbound_testbound if(log_get_lock()) { diff --git a/doc/Changelog b/doc/Changelog index b1a25d55a..6752a1475 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,29 @@ +12 February 2020: Wouter + - Fix with libnettle make test with dsa disabled. + - Fix contrib/fastrpz.patch to apply cleanly. Fix for serve-stale + fixes, but it does not compile, conflicts with new rpz code. + - Fix to clean memory leak of respip_addr.lock when ip_tree deleted. + - Fix compile warning when threads disabled. + +10 February 2020: George + - Document 'ub_result.was_ratelimited' in libunbound. + - Fix use after free on log-identity after a reload; Fixes #163. + +6 February 2020: George + - Fix num_reply_states and num_detached_states counting with + serve_expired_callback. + - Cleaner code in mesh_serve_expired_lookup. + - Document in unbound.conf manpage that configuration clauses can be + repeated in the configuration file. + +6 February 2020: Wouter + - Fix num_reply_addr counting in mesh and tcp drop due to size + after serve_stale commit. + - Fix to create and destroy rpz_lock in auth_zones structure. + - Fix to lock zone before adding rpz qname trigger. + - Fix to lock and release once in mesh_serve_expired_lookup. + - Fix to put braces around empty if body when threading is disabled. + 5 February 2020: George - Added serve-stale functionality as described in draft-ietf-dnsop-serve-stale-10. `serve-expired-*` options can be used diff --git a/doc/libunbound.3.in b/doc/libunbound.3.in index 5bd4ad8a1..548969142 100644 --- a/doc/libunbound.3.in +++ b/doc/libunbound.3.in @@ -396,12 +396,13 @@ The result of the DNS resolution and validation is returned as char* canonname; /* canonical name of result */ int rcode; /* additional error code in case of no data */ void* answer_packet; /* full network format answer packet */ - int answer_len; /* length of packet in octets */ + int answer_len; /* length of packet in octets */ int havedata; /* true if there is data */ int nxdomain; /* true if nodata because name does not exist */ - int secure; /* true if result is secure */ - int bogus; /* true if a security failure happened */ + int secure; /* true if result is secure */ + int bogus; /* true if a security failure happened */ char* why_bogus; /* string with error if bogus */ + int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */ int ttl; /* number of seconds the result is valid */ }; .fi diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index ebc202882..38c2d2984 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -63,8 +63,10 @@ server: access\-control: 2001:DB8::/64 allow .fi .SH "FILE FORMAT" -There must be whitespace between keywords. Attribute keywords end with a colon ':'. -An attribute is followed by its containing attributes, or a value. +There must be whitespace between keywords. Attribute keywords end with a +colon ':'. An attribute is followed by a value, or its containing attributes +in which case it is refered to as a clause. Clauses can be repeated throughout +the file (or included files) to group attributes under the same clause. .P Files can be included using the .B include: diff --git a/libunbound/unbound.h b/libunbound/unbound.h index 04661838c..ca9592d62 100644 --- a/libunbound/unbound.h +++ b/libunbound/unbound.h @@ -204,8 +204,9 @@ struct ub_result { char* why_bogus; /** - * If the query or one of its subqueries was ratelimited. Useful if - * ratelimiting is enabled and answer is SERVFAIL. + * If the query or one of its subqueries was ratelimited. Useful if + * ratelimiting is enabled and answer to the client is SERVFAIL as a + * result. */ int was_ratelimited; diff --git a/respip/respip.c b/respip/respip.c index ec7026add..f504f5579 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -69,12 +69,24 @@ respip_set_create(void) return set; } +/** helper traverse to delete resp_addr nodes */ +static void +resp_addr_del(rbnode_type* n, void* ATTR_UNUSED(arg)) +{ + struct resp_addr* r = (struct resp_addr*)n->key; + lock_rw_destroy(&r->lock); +#ifdef THREADS_DISABLED + (void)r; +#endif +} + void respip_set_delete(struct respip_set* set) { if(!set) return; lock_rw_destroy(&set->lock); + traverse_postorder(&set->ip_tree, resp_addr_del, NULL); regional_destroy(set->region); free(set); } @@ -1017,8 +1029,9 @@ respip_rewrite_reply(const struct query_info* qinfo, redirect_rrset, tag, ipset, search_only, region, rpz_used, rpz_log, log_name, rpz_cname_override); } - if(raddr) + if(raddr) { lock_rw_unlock(&raddr->lock); + } return ret; } diff --git a/services/authzone.c b/services/authzone.c index edff3e6dd..34170abaf 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -299,6 +299,8 @@ struct auth_zones* auth_zones_create(void) lock_protect(&az->lock, &az->ztree, sizeof(az->ztree)); lock_protect(&az->lock, &az->xtree, sizeof(az->xtree)); /* also lock protects the rbnode's in struct auth_zone, auth_xfer */ + lock_rw_init(&az->rpz_lock); + lock_protect(&az->rpz_lock, &az->rpz_first, sizeof(az->rpz_first)); return az; } @@ -2104,6 +2106,7 @@ void auth_zones_delete(struct auth_zones* az) { if(!az) return; lock_rw_destroy(&az->lock); + lock_rw_destroy(&az->rpz_lock); traverse_postorder(&az->ztree, auth_zone_del, NULL); traverse_postorder(&az->xtree, auth_xfer_del, NULL); free(az); diff --git a/services/mesh.c b/services/mesh.c index bcd84278b..9114ef4c4 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -354,7 +354,7 @@ mesh_serve_expired_lookup(struct module_qstate* qstate, hashvalue_type h; struct lruhash_entry* e; struct dns_msg* msg; - struct reply_info* rep, *data; + struct reply_info* data; struct msgreply_entry* key; time_t timenow = *qstate->env->now; int must_validate = (!(qstate->query_flags&BIT_CD) @@ -363,62 +363,39 @@ mesh_serve_expired_lookup(struct module_qstate* qstate, h = query_info_hash(lookup_qinfo, qstate->query_flags); e = slabhash_lookup(qstate->env->msg_cache, h, lookup_qinfo, 0); if(!e) return NULL; - rep = (struct reply_info*)e->data; - /* Check TTL */ - if(rep->ttl < timenow) { - /* Check if we need to serve expired now */ - if(qstate->env->cfg->serve_expired) { - if(qstate->env->cfg->serve_expired_ttl && - rep->serve_expired_ttl < timenow) - goto bail_out; - if(!rrset_array_lock(rep->ref, rep->rrset_count, 0)) - goto bail_out; - } else { - /* the rrsets may have been updated in the meantime. - * we will refetch the message format from the - * authoritative server - */ - goto bail_out; - } - } else { - if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow)) - goto bail_out; - } - - /* Check CNAME chain (if any) - * This is part of tomsg further down; no need to check now. */ - - /* Check security status of the cached answer. - * tomsg further down has a subset of these checks, so we are leaving - * these as is. - * In case of bogus or revalidation we don't care to reply here. */ - if(must_validate && (rep->security == sec_status_bogus || - rep->security == sec_status_secure_sentinel_fail)) { - verbose(VERB_ALGO, "Serve expired: bogus answer found in cache"); - goto bail_out_rrset; - } else if(rep->security == sec_status_unchecked && must_validate) { - verbose(VERB_ALGO, "Serve expired: unchecked entry needs " - "validation"); - goto bail_out_rrset; /* need to validate cache entry first */ - } else if(rep->security == sec_status_secure && - !reply_all_rrsets_secure(rep) && must_validate) { - verbose(VERB_ALGO, "Serve expired: secure entry" - " changed status"); - goto bail_out_rrset; /* rrset changed, re-verify */ - } key = (struct msgreply_entry*)e->key; data = (struct reply_info*)e->data; msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow, qstate->env->cfg->serve_expired, qstate->env->scratch); - rrset_array_unlock_touch(qstate->env->rrset_cache, - qstate->region, rep->ref, rep->rrset_count); + if(!msg) + goto bail_out; + + /* Check CNAME chain (if any) + * This is part of tomsg above; no need to check now. */ + + /* Check security status of the cached answer. + * tomsg above has a subset of these checks, so we are leaving + * these as is. + * In case of bogus or revalidation we don't care to reply here. */ + if(must_validate && (msg->rep->security == sec_status_bogus || + msg->rep->security == sec_status_secure_sentinel_fail)) { + verbose(VERB_ALGO, "Serve expired: bogus answer found in cache"); + goto bail_out; + } else if(msg->rep->security == sec_status_unchecked && must_validate) { + verbose(VERB_ALGO, "Serve expired: unchecked entry needs " + "validation"); + goto bail_out; /* need to validate cache entry first */ + } else if(msg->rep->security == sec_status_secure && + !reply_all_rrsets_secure(msg->rep) && must_validate) { + verbose(VERB_ALGO, "Serve expired: secure entry" + " changed status"); + goto bail_out; /* rrset changed, re-verify */ + } + lock_rw_unlock(&e->lock); return msg; -bail_out_rrset: - rrset_array_unlock_touch(qstate->env->rrset_cache, - qstate->region, rep->ref, rep->rrset_count); bail_out: lock_rw_unlock(&e->lock); return NULL; @@ -1307,7 +1284,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, void mesh_query_done(struct mesh_state* mstate) { - struct mesh_reply* r; + struct mesh_reply* r, *reply_list = NULL; struct mesh_reply* prev = NULL; struct sldns_buffer* prev_buffer = NULL; struct mesh_cb* c; @@ -1331,7 +1308,27 @@ void mesh_query_done(struct mesh_state* mstate) free(err); } } - for(r = mstate->reply_list; r; r = r->next) { + if(mstate->reply_list) { + /* set the reply_list to NULL during the mesh_query_done + * processing, so that calls back into the mesh from + * tcp_req_info (deciding to drop the reply and thus + * unregister the mesh_reply from the mstate) are stopped + * because the list is empty. + * The mstate is then likely not a reply_state, and maybe + * also a detached_state. + */ + reply_list = mstate->reply_list; + mstate->reply_list = NULL; + if(!mstate->reply_list && !mstate->cb_list) { + /* was a reply state, not anymore */ + log_assert(mstate->s.env->mesh->num_reply_states > 0); + mstate->s.env->mesh->num_reply_states--; + } + if(!mstate->reply_list && !mstate->cb_list && + mstate->super_set.count == 0) + mstate->s.env->mesh->num_detached_states++; + } + for(r = reply_list; r; r = r->next) { /* if a response-ip address block has been stored the * information should be logged for each client. */ if(mstate->s.respip_action_info && @@ -1951,6 +1948,13 @@ mesh_serve_expired_callback(void* arg) r = mstate->reply_list; mstate->reply_list = NULL; + if(!mstate->reply_list && !mstate->cb_list) { + log_assert(mesh->num_reply_states > 0); + mesh->num_reply_states--; + if(mstate->super_set.count == 0) { + mesh->num_detached_states++; + } + } for(; r; r = r->next) { /* If address info is returned, it means the action should be an * 'inform' variant and the information should be logged. */ @@ -1998,11 +2002,4 @@ mesh_serve_expired_callback(void* arg) qstate->env->mesh->num_detached_states++; mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c); } - if(!mstate->reply_list && !mstate->cb_list) { - log_assert(mesh->num_reply_states > 0); - mesh->num_reply_states--; - if(mstate->super_set.count == 0) { - mesh->num_detached_states++; - } - } } diff --git a/services/rpz.c b/services/rpz.c index 1047852ad..643b20c91 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -523,8 +523,10 @@ rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, lock_rw_unlock(&r->local_zones->lock); return; } + lock_rw_wrlock(&z->lock); local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype, rrclass, ttl, rdata, rdata_len, rrstr); + lock_rw_unlock(&z->lock); free(rrstr); } if(!newzone) diff --git a/testdata/tcp_req_size.tdir/tcp_req_size.test b/testdata/tcp_req_size.tdir/tcp_req_size.test index 0260b2117..441777156 100644 --- a/testdata/tcp_req_size.tdir/tcp_req_size.test +++ b/testdata/tcp_req_size.tdir/tcp_req_size.test @@ -95,6 +95,33 @@ else echo "result contents not OK" exit 1 fi +echo "OK" + +# check that the server is still up +echo "" +echo "> query www1.example.net. (again check if server up)" +$PRE/streamtcp -f 127.0.0.1@$UNBOUND_PORT www1.example.net. A IN >outfile 2>&1 +cat outfile +if test "$?" -ne 0; then + echo "exit status not OK" + echo "> cat logfiles" + cat outfile + cat fwd.log + cat unbound.log + echo "Not OK" + exit 1 +fi +if grep "www1.example.net" outfile | grep "1.2.3.1"; then + echo "content OK" +else + echo "result contents not OK" + echo "> cat logfiles" + cat outfile + cat fwd.log + cat unbound.log + echo "result contents not OK" + exit 1 +fi echo "OK" exit 0 diff --git a/util/config_file.c b/util/config_file.c index c7edba548..52ca5a184 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -1404,7 +1404,10 @@ config_delete(struct config_file* cfg) config_delstrlist(cfg->tls_session_ticket_keys.first); free(cfg->tls_ciphers); free(cfg->tls_ciphersuites); - free(cfg->log_identity); + if(cfg->log_identity) { + log_ident_revert_to_default(); + free(cfg->log_identity); + } config_del_strarray(cfg->ifs, cfg->num_ifs); config_del_strarray(cfg->out_ifs, cfg->num_out_ifs); config_delstubs(cfg->stubs); diff --git a/util/configparser.c b/util/configparser.c index 84312f0d3..69ee1cc1c 100644 --- a/util/configparser.c +++ b/util/configparser.c @@ -4582,7 +4582,7 @@ yyreduce: OUTYY(("P(server_fake_dsa:%s)\n", (yyvsp[0].str))); if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) yyerror("expected yes or no."); -#ifdef HAVE_SSL +#if defined(HAVE_SSL) || defined(HAVE_NETTLE) else fake_dsa = (strcmp((yyvsp[0].str), "yes")==0); if(fake_dsa) log_warn("test option fake_dsa is enabled"); @@ -4598,7 +4598,7 @@ yyreduce: OUTYY(("P(server_fake_sha1:%s)\n", (yyvsp[0].str))); if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) yyerror("expected yes or no."); -#ifdef HAVE_SSL +#if defined(HAVE_SSL) || defined(HAVE_NETTLE) else fake_sha1 = (strcmp((yyvsp[0].str), "yes")==0); if(fake_sha1) log_warn("test option fake_sha1 is enabled"); diff --git a/util/configparser.y b/util/configparser.y index d471babe6..798f4a972 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -1782,7 +1782,7 @@ server_fake_dsa: VAR_FAKE_DSA STRING_ARG OUTYY(("P(server_fake_dsa:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); -#ifdef HAVE_SSL +#if defined(HAVE_SSL) || defined(HAVE_NETTLE) else fake_dsa = (strcmp($2, "yes")==0); if(fake_dsa) log_warn("test option fake_dsa is enabled"); @@ -1795,7 +1795,7 @@ server_fake_sha1: VAR_FAKE_SHA1 STRING_ARG OUTYY(("P(server_fake_sha1:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); -#ifdef HAVE_SSL +#if defined(HAVE_SSL) || defined(HAVE_NETTLE) else fake_sha1 = (strcmp($2, "yes")==0); if(fake_sha1) log_warn("test option fake_sha1 is enabled"); diff --git a/util/log.c b/util/log.c index 8499d8c0a..dfbb23349 100644 --- a/util/log.c +++ b/util/log.c @@ -74,6 +74,7 @@ static lock_basic_type log_lock; #endif /** the identity of this executable/process */ static const char* ident="unbound"; +static const char* default_ident="unbound"; #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) /** are we using syslog(3) to log to */ static int logging_to_syslog = 0; @@ -181,6 +182,24 @@ void log_ident_set(const char* id) ident = id; } +void log_ident_set_default(const char* id) +{ + default_ident = id; +} + +void log_ident_revert_to_default() +{ + ident = default_ident; +} + +void log_ident_set_or_default(const char* identity) +{ + if(identity == NULL || identity[0] == 0) + log_ident_set(default_ident); + else + log_ident_set(identity); +} + void log_set_time_asc(int use_asc) { log_time_asc = use_asc; diff --git a/util/log.h b/util/log.h index 81d9d837d..098a850a5 100644 --- a/util/log.h +++ b/util/log.h @@ -107,11 +107,29 @@ void log_thread_set(int* num); int log_thread_get(void); /** - * Set identity to print, default is 'unbound'. + * Set identity to print, default is 'unbound'. * @param id: string to print. Name of executable. */ void log_ident_set(const char* id); +/** + * Set default identity to print, default is 'unbound'. + * @param id: string to print. Name of executable. + */ +void log_ident_set_default(const char* id); + +/** + * Revert identity to print, back to the recorded default value. + */ +void log_ident_revert_to_default(); + +/** + * Set identity to print if there is an identity, otherwise + * set the default. + * @param identity: the identity to set. + */ +void log_ident_set_or_default(const char* identity); + /** * Set if the time value is printed ascii or decimal in log entries. * @param use_asc: if true, ascii is printed, otherwise decimal. diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c index 5e02f6bdb..8f17c53e8 100644 --- a/validator/val_secalgo.c +++ b/validator/val_secalgo.c @@ -54,6 +54,11 @@ #error "Need crypto library to do digital signature cryptography" #endif +/** fake DSA support for unit tests */ +int fake_dsa = 0; +/** fake SHA1 support for unit tests */ +int fake_sha1 = 0; + /* OpenSSL implementation */ #ifdef HAVE_SSL #ifdef HAVE_OPENSSL_ERR_H @@ -72,11 +77,6 @@ #include #endif -/** fake DSA support for unit tests */ -int fake_dsa = 0; -/** fake SHA1 support for unit tests */ -int fake_sha1 = 0; - /** * Output a libcrypto openssl error to the logfile. * @param str: string to add to it. @@ -1509,13 +1509,21 @@ dnskey_algo_id_is_supported(int id) { /* uses libnettle */ switch(id) { -#if defined(USE_DSA) && defined(USE_SHA1) case LDNS_DSA: case LDNS_DSA_NSEC3: +#if defined(USE_DSA) && defined(USE_SHA1) + return 1; +#else + if(fake_dsa || fake_sha1) return 1; + return 0; #endif -#ifdef USE_SHA1 case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: +#ifdef USE_SHA1 + return 1; +#else + if(fake_sha1) return 1; + return 0; #endif #ifdef USE_SHA2 case LDNS_RSASHA256: @@ -1820,6 +1828,15 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, return sec_status_bogus; } +#ifndef USE_DSA + if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1)) + return sec_status_secure; +#endif +#ifndef USE_SHA1 + if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3)) + return sec_status_secure; +#endif + switch(algo) { #if defined(USE_DSA) && defined(USE_SHA1) case LDNS_DSA: