From: Wouter Wijngaards Date: Thu, 11 Jun 2009 09:43:23 +0000 (+0000) Subject: recommit 9 June 2009. X-Git-Tag: release-1.3.1~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2c56564e4eae228a305647336b6822bb3ce296f7;p=thirdparty%2Funbound.git recommit 9 June 2009. git-svn-id: file:///svn/unbound/trunk@1646 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/daemon.c b/daemon/daemon.c index 9ce791a06..d3ad913e2 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -462,6 +462,7 @@ daemon_cleanup(struct daemon* daemon) local_zones_delete(daemon->local_zones); daemon->local_zones = NULL; /* key cache is cleared by module desetup during next daemon_init() */ + daemon_remote_clear(daemon->rc); for(i=0; inum; i++) worker_delete(daemon->workers[i]); free(daemon->workers); @@ -476,6 +477,7 @@ daemon_delete(struct daemon* daemon) if(!daemon) return; modstack_desetup(&daemon->mods, daemon->env); + daemon_remote_delete(daemon->rc); listening_ports_free(daemon->ports); listening_ports_free(daemon->rc_ports); if(daemon->env) { diff --git a/daemon/daemon.h b/daemon/daemon.h index dd12454a4..c170eeda6 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -57,6 +57,7 @@ struct rrset_cache; struct acl_list; struct local_zones; struct ub_randstate; +struct daemon_remote; /** * Structure holding worker list. @@ -73,10 +74,12 @@ struct daemon { int listening_port; /** listening ports, opened, to be shared by threads */ struct listen_port* ports; - /** port number fore remote that has ports opened. */ + /** port number for remote that has ports opened. */ int rc_port; /** listening ports for remote control */ struct listen_port* rc_ports; + /** remote control connections management (for first worker) */ + struct daemon_remote* rc; /** num threads allocated */ int num; /** the worker entries */ diff --git a/daemon/remote.c b/daemon/remote.c index b5bfddfe2..baf1599ff 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -136,18 +136,16 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d) } struct daemon_remote* -daemon_remote_create(struct worker* worker) +daemon_remote_create(struct config_file* cfg) { char* s_cert; char* s_key; - struct config_file* cfg = worker->daemon->cfg; struct daemon_remote* rc = (struct daemon_remote*)calloc(1, sizeof(*rc)); if(!rc) { log_err("out of memory in daemon_remote_create"); return NULL; } - rc->worker = worker; rc->max_active = 10; if(!cfg->remote_control_enable) { @@ -166,50 +164,62 @@ daemon_remote_create(struct worker* worker) daemon_remote_delete(rc); return NULL; } - s_cert = cfg->server_cert_file; - s_key = cfg->server_key_file; - if(cfg->chrootdir && cfg->chrootdir[0]) { - if(strncmp(s_cert, cfg->chrootdir, strlen(cfg->chrootdir))==0) - s_cert += strlen(cfg->chrootdir); - if(strncmp(s_key, cfg->chrootdir, strlen(cfg->chrootdir))==0) - s_key += strlen(cfg->chrootdir); + s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1); + s_key = fname_after_chroot(cfg->server_key_file, cfg, 1); + if(!s_cert || !s_key) { + log_err("out of memory in remote control fname"); + free(s_cert); + free(s_key); + daemon_remote_delete(rc); + return NULL; } verbose(VERB_ALGO, "setup SSL certificates"); if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) { log_err("Error for server-cert-file: %s", s_cert); log_crypto_err("Error in SSL_CTX use_certificate_file"); + free(s_cert); + free(s_key); daemon_remote_delete(rc); return NULL; } if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) { log_err("Error for server-key-file: %s", s_key); log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); + free(s_cert); + free(s_key); daemon_remote_delete(rc); return NULL; } if(!SSL_CTX_check_private_key(rc->ctx)) { log_err("Error for server-key-file: %s", s_key); log_crypto_err("Error in SSL_CTX check_private_key"); + free(s_cert); + free(s_key); daemon_remote_delete(rc); return NULL; } if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) { log_crypto_err("Error setting up SSL_CTX verify locations"); + free(s_cert); + free(s_key); daemon_remote_delete(rc); return NULL; } SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert)); SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL); + free(s_cert); + free(s_key); return rc; } -void daemon_remote_delete(struct daemon_remote* rc) +void daemon_remote_clear(struct daemon_remote* rc) { struct rc_state* p, *np; if(!rc) return; /* but do not close the ports */ listen_list_delete(rc->accept_list); + rc->accept_list = NULL; /* do close these sockets */ p = rc->busy_list; while(p) { @@ -220,6 +230,15 @@ void daemon_remote_delete(struct daemon_remote* rc) free(p); p = np; } + rc->busy_list = NULL; + rc->active = 0; + rc->worker = NULL; +} + +void daemon_remote_delete(struct daemon_remote* rc) +{ + if(!rc) return; + daemon_remote_clear(rc); if(rc->ctx) { SSL_CTX_free(rc->ctx); } @@ -348,9 +367,10 @@ accept_open(struct daemon_remote* rc, int fd) } int daemon_remote_open_accept(struct daemon_remote* rc, - struct listen_port* ports) + struct listen_port* ports, struct worker* worker) { struct listen_port* p; + rc->worker = worker; for(p = ports; p; p = p->next) { if(!accept_open(rc, p->fd)) { log_err("could not create accept comm point"); @@ -1034,6 +1054,22 @@ do_lookup(SSL* ssl, struct worker* worker, char* arg) free(nm); } +/** flush something from rrset and msg caches */ +static void +do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen, + uint16_t t, uint16_t c) +{ + hashvalue_t h; + struct query_info k; + rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, 0); + k.qname = nm; + k.qname_len = nmlen; + k.qtype = t; + k.qclass = c; + h = query_info_hash(&k); + slabhash_remove(worker->env.msg_cache, h, &k); +} + /** flush a type */ static void do_flush_type(SSL* ssl, struct worker* worker, char* arg) @@ -1048,8 +1084,7 @@ do_flush_type(SSL* ssl, struct worker* worker, char* arg) if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) return; t = ldns_get_rr_type_by_name(arg2); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - t, LDNS_RR_CLASS_IN, 0); + do_cache_remove(worker, nm, nmlen, t, LDNS_RR_CLASS_IN); free(nm); send_ok(ssl); @@ -1179,33 +1214,23 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg) /** remove name rrset from cache */ static void -do_flush_name(SSL* ssl, struct worker* worker, char* arg) +do_flush_name(SSL* ssl, struct worker* w, char* arg) { uint8_t* nm; int nmlabs; size_t nmlen; if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) return; - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN, 0); - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, - LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN, 0); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN); free(nm); send_ok(ssl); diff --git a/daemon/remote.h b/daemon/remote.h index f47a9c62d..cdbab9ba8 100644 --- a/daemon/remote.h +++ b/daemon/remote.h @@ -96,10 +96,10 @@ struct daemon_remote { /** * Create new remote control state for the daemon. - * @param worker: worker with communication base. and links to command channels. + * @param cfg: config file with key file settings. * @return new state, or NULL on failure. */ -struct daemon_remote* daemon_remote_create(struct worker* worker); +struct daemon_remote* daemon_remote_create(struct config_file* cfg); /** * remote control state to delete. @@ -107,6 +107,13 @@ struct daemon_remote* daemon_remote_create(struct worker* worker); */ void daemon_remote_delete(struct daemon_remote* rc); +/** + * remote control state to clear up. Busy and accept points are closed. + * Does not delete the rc itself, or the ssl context (with its keys). + * @param rc: state to clear. + */ +void daemon_remote_clear(struct daemon_remote* rc); + /** * Open and create listening ports for remote control. * @param cfg: config options. @@ -119,10 +126,11 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg); * Setup comm points for accepting remote control connections. * @param rc: state * @param ports: already opened ports. + * @param worker: worker with communication base. and links to command channels. * @return false on error. */ int daemon_remote_open_accept(struct daemon_remote* rc, - struct listen_port* ports); + struct listen_port* ports, struct worker* worker); /** * Handle nonthreaded remote cmd execution. diff --git a/daemon/unbound.c b/daemon/unbound.c index 128ae839d..d516bef4b 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -43,6 +43,7 @@ #include "config.h" #include "util/log.h" #include "daemon/daemon.h" +#include "daemon/remote.h" #include "util/config_file.h" #include "util/storage/slabhash.h" #include "services/listen_dnsport.h" @@ -366,6 +367,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, * So, using a logfile, the user does not see errors unless -d is * given to unbound on the commandline. */ + /* read ssl keys while superuser and outside chroot */ + if(!(daemon->rc = daemon_remote_create(cfg))) + fatal_exit("could not set up remote-control"); + #ifdef HAVE_KILL /* check old pid file before forking */ if(cfg->pidfile && cfg->pidfile[0]) { diff --git a/daemon/worker.c b/daemon/worker.c index 2aa64a44c..ac50a52a3 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1038,12 +1038,8 @@ worker_init(struct worker* worker, struct config_file *cfg, return 0; } #endif /* LIBEVENT_SIGNAL_PROBLEM */ - if(!(worker->rc = daemon_remote_create(worker))) { - worker_delete(worker); - return 0; - } - if(!daemon_remote_open_accept(worker->rc, - worker->daemon->rc_ports)) { + if(!daemon_remote_open_accept(worker->daemon->rc, + worker->daemon->rc_ports, worker)) { worker_delete(worker); return 0; } @@ -1052,7 +1048,6 @@ worker_init(struct worker* worker, struct config_file *cfg, #endif /* UB_ON_WINDOWS */ } else { /* !do_sigs */ worker->comsig = NULL; - worker->rc = NULL; } seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ (((unsigned int)worker->thread_num)<<17); @@ -1172,7 +1167,6 @@ worker_delete(struct worker* worker) comm_signal_delete(worker->comsig); tube_delete(worker->cmd); comm_timer_delete(worker->stat_timer); - daemon_remote_delete(worker->rc); free(worker->ports); if(worker->thread_num == 0) { log_set_time(NULL); diff --git a/daemon/worker.h b/daemon/worker.h index 2afda7434..874a64ddb 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -101,8 +101,6 @@ struct worker { struct comm_point* cmd_com; /** timer for statistics */ struct comm_timer* stat_timer; - /** remote control state (for first thread only) */ - struct daemon_remote* rc; /** number of requests that can be handled by this worker */ size_t request_size; diff --git a/doc/Changelog b/doc/Changelog index 33a63f5c8..9d035be03 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +9 June 2009: Wouter + - openssl key files are opened apache-style, when user is root and + before chrooting. This makes permissions on remote-control key + files easier to set up. Fixes bug #251. + - flush_type and flush_name remove msg cache entries. + 8 June 2009: Wouter - Removed RFC5011 REVOKE flag support. Partial 5011 support may cause inadvertant behaviour. diff --git a/doc/TODO b/doc/TODO index 28a5d947c..ef9cc4615 100644 --- a/doc/TODO +++ b/doc/TODO @@ -67,11 +67,13 @@ o infra and lame cache: easier size config (in Mb), show usage in graphs. x2 on bogus(18 tries), x8 backoff on lameness(6 tries), when servfail for DNSKEY. remove entry when validated as secure. + delegptspoofrecheck on lameness when harden-referral-path NS + query has servfail, then build chain of trust down (check DS, + then perform DNSKEY query) if that DNSKEY query fails servfail, + perform the x8 lameness retry fallback. - winevent - poll if too many fds -- ssl open apache style -- fwd above stub, make hole in fwds +- fwd above stub, make hole in fwds. config non-forwarded-domain names. - fix indent # ifs -- flush_* remove msg cache entry if one. - do not flush/delete callback queries or call error on callback at least. later diff --git a/testcode/testbound.c b/testcode/testbound.c index 1ed7fc5d1..3c62f1737 100644 --- a/testcode/testbound.c +++ b/testcode/testbound.c @@ -287,7 +287,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file* return NULL; } -struct daemon_remote* daemon_remote_create(struct worker* ATTR_UNUSED(worker)) +struct daemon_remote* daemon_remote_create(struct config_file* ATTR_UNUSED(cfg)) { return (struct daemon_remote*)calloc(1,1); } @@ -297,8 +297,14 @@ void daemon_remote_delete(struct daemon_remote* rc) free(rc); } +void daemon_remote_clear(struct daemon_remote* ATTR_UNUSED(rc)) +{ + /* nothing */ +} + int daemon_remote_open_accept(struct daemon_remote* ATTR_UNUSED(rc), - struct listen_port* ATTR_UNUSED(ports)) + struct listen_port* ATTR_UNUSED(ports), + struct worker* ATTR_UNUSED(worker)) { return 1; }