diff options
Diffstat (limited to '')
-rw-r--r-- | external/unbound/daemon/cachedump.c | 16 | ||||
-rw-r--r-- | external/unbound/daemon/daemon.c | 2 | ||||
-rw-r--r-- | external/unbound/daemon/remote.c | 139 | ||||
-rw-r--r-- | external/unbound/daemon/remote.h | 2 | ||||
-rw-r--r-- | external/unbound/daemon/stats.c | 12 | ||||
-rw-r--r-- | external/unbound/daemon/stats.h | 2 | ||||
-rw-r--r-- | external/unbound/daemon/unbound.c | 47 | ||||
-rw-r--r-- | external/unbound/daemon/worker.c | 4 |
8 files changed, 163 insertions, 61 deletions
diff --git a/external/unbound/daemon/cachedump.c b/external/unbound/daemon/cachedump.c index 20a46ae4d..4b0a583a6 100644 --- a/external/unbound/daemon/cachedump.c +++ b/external/unbound/daemon/cachedump.c @@ -56,9 +56,9 @@ #include "iterator/iter_utils.h" #include "iterator/iter_fwd.h" #include "iterator/iter_hints.h" -#include "ldns/sbuffer.h" -#include "ldns/wire2str.h" -#include "ldns/str2wire.h" +#include "sldns/sbuffer.h" +#include "sldns/wire2str.h" +#include "sldns/str2wire.h" /** dump one rrset zonefile line */ static int @@ -223,6 +223,8 @@ copy_msg(struct regional* region, struct lruhash_entry* e, struct query_info** k, struct reply_info** d) { struct reply_info* rep = (struct reply_info*)e->data; + if(rep->rrset_count > RR_COUNT_MAX) + return 0; /* to protect against integer overflow */ *d = (struct reply_info*)regional_alloc_init(region, e->data, sizeof(struct reply_info) + sizeof(struct rrset_ref) * (rep->rrset_count-1) + @@ -470,6 +472,10 @@ load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker) log_warn("bad rrset without contents"); return 0; } + if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) { + log_warn("bad rrset with too many rrs"); + return 0; + } d->count = (size_t)rr_count; d->rrsig_count = (size_t)rrsig_count; d->security = (enum sec_status)security; @@ -646,6 +652,10 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker) rep.ttl = (time_t)ttl; rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl); rep.security = (enum sec_status)security; + if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) { + log_warn("error too many rrsets"); + return 0; /* protect against integer overflow in alloc */ + } rep.an_numrrsets = (size_t)an; rep.ns_numrrsets = (size_t)ns; rep.ar_numrrsets = (size_t)ar; diff --git a/external/unbound/daemon/daemon.c b/external/unbound/daemon/daemon.c index f693a0285..0cd37ae82 100644 --- a/external/unbound/daemon/daemon.c +++ b/external/unbound/daemon/daemon.c @@ -84,7 +84,7 @@ #include "util/random.h" #include "util/tube.h" #include "util/net_help.h" -#include "ldns/keyraw.h" +#include "sldns/keyraw.h" #include <signal.h> /** How many quit requests happened. */ diff --git a/external/unbound/daemon/remote.c b/external/unbound/daemon/remote.c index ff3d769d4..24008bf17 100644 --- a/external/unbound/daemon/remote.c +++ b/external/unbound/daemon/remote.c @@ -46,6 +46,10 @@ #ifdef HAVE_OPENSSL_ERR_H #include <openssl/err.h> #endif +#ifndef HEADER_DH_H +#include <openssl/dh.h> +#endif + #include <ctype.h> #include "daemon/remote.h" #include "daemon/worker.h" @@ -74,14 +78,17 @@ #include "iterator/iter_delegpt.h" #include "services/outbound_list.h" #include "services/outside_network.h" -#include "ldns/str2wire.h" -#include "ldns/parseutil.h" -#include "ldns/wire2str.h" -#include "ldns/sbuffer.h" +#include "sldns/str2wire.h" +#include "sldns/parseutil.h" +#include "sldns/wire2str.h" +#include "sldns/sbuffer.h" #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #ifdef HAVE_NETDB_H #include <netdb.h> #endif @@ -131,6 +138,41 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d) #endif } +/* + * The following function was generated using the openssl utility, using + * the command : "openssl dhparam -dsaparam -C 512" + */ +#ifndef S_SPLINT_S +DH *get_dh512() +{ + static unsigned char dh512_p[]={ + 0xC9,0xD7,0x05,0xDA,0x5F,0xAB,0x14,0xE8,0x11,0x56,0x77,0x85, + 0xB1,0x24,0x2C,0x95,0x60,0xEA,0xE2,0x10,0x6F,0x0F,0x84,0xEC, + 0xF4,0x45,0xE8,0x90,0x7A,0xA7,0x03,0xFF,0x5B,0x88,0x53,0xDE, + 0xC4,0xDE,0xBC,0x42,0x78,0x71,0x23,0x7E,0x24,0xA5,0x5E,0x4E, + 0xEF,0x6F,0xFF,0x5F,0xAF,0xBE,0x8A,0x77,0x62,0xB4,0x65,0x82, + 0x7E,0xC9,0xED,0x2F, + }; + static unsigned char dh512_g[]={ + 0x8D,0x3A,0x52,0xBC,0x8A,0x71,0x94,0x33,0x2F,0xE1,0xE8,0x4C, + 0x73,0x47,0x03,0x4E,0x7D,0x40,0xE5,0x84,0xA0,0xB5,0x6D,0x10, + 0x6F,0x90,0x43,0x05,0x1A,0xF9,0x0B,0x6A,0xD1,0x2A,0x9C,0x25, + 0x0A,0xB9,0xD1,0x14,0xDC,0x35,0x1C,0x48,0x7C,0xC6,0x0C,0x6D, + 0x32,0x1D,0xD3,0xC8,0x10,0xA8,0x82,0x14,0xA2,0x1C,0xF4,0x53, + 0x23,0x3B,0x1C,0xB9, + }; + DH *dh; + + if ((dh=DH_new()) == NULL) return(NULL); + dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); + dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); + if ((dh->p == NULL) || (dh->g == NULL)) + { DH_free(dh); return(NULL); } + dh->length = 160; + return(dh); +} +#endif /* SPLINT */ + struct daemon_remote* daemon_remote_create(struct config_file* cfg) { @@ -165,6 +207,24 @@ daemon_remote_create(struct config_file* cfg) daemon_remote_delete(rc); return NULL; } + + if (cfg->remote_control_use_cert == 0) { + /* No certificates are requested */ + if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) { + log_crypto_err("Failed to set aNULL cipher list"); + return NULL; + } + + /* Since we have no certificates and hence no source of + * DH params, let's generate and set them + */ + if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh512())) { + log_crypto_err("Wanted to set DH param, but failed"); + return NULL; + } + return rc; + } + rc->use_cert = 1; 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) { @@ -241,10 +301,12 @@ void daemon_remote_delete(struct daemon_remote* rc) * @param nr: port nr * @param list: list head * @param noproto_is_err: if lack of protocol support is an error. + * @param cfg: config with username for chown of unix-sockets. * @return false on failure. */ static int -add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err) +add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err, + struct config_file* cfg) { struct addrinfo hints; struct addrinfo* res; @@ -255,29 +317,52 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err) snprintf(port, sizeof(port), "%d", nr); port[sizeof(port)-1]=0; memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) { -#ifdef USE_WINSOCK - if(!noproto_is_err && r == EAI_NONAME) { - /* tried to lookup the address as name */ - return 1; /* return success, but do nothing */ + + if(ip[0] == '/') { + /* This looks like a local socket */ + fd = create_local_accept_sock(ip, &noproto); + /* + * Change socket ownership and permissions so users other + * than root can access it provided they are in the same + * group as the user we run as. + */ + if(fd != -1) { +#ifdef HAVE_CHOWN + if (cfg->username && cfg->username[0] && + cfg_uid != (uid_t)-1) + chown(ip, cfg_uid, cfg_gid); + chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); +#else + (void)cfg; +#endif } + } else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) { +#ifdef USE_WINSOCK + if(!noproto_is_err && r == EAI_NONAME) { + /* tried to lookup the address as name */ + return 1; /* return success, but do nothing */ + } #endif /* USE_WINSOCK */ - log_err("control interface %s:%s getaddrinfo: %s %s", - ip?ip:"default", port, gai_strerror(r), + log_err("control interface %s:%s getaddrinfo: %s %s", + ip?ip:"default", port, gai_strerror(r), #ifdef EAI_SYSTEM - r==EAI_SYSTEM?(char*)strerror(errno):"" + r==EAI_SYSTEM?(char*)strerror(errno):"" #else - "" + "" #endif ); - return 0; + return 0; + } + + /* open fd */ + fd = create_tcp_accept_sock(res, 1, &noproto, 0, + cfg->ip_transparent); + freeaddrinfo(res); } - /* open fd */ - fd = create_tcp_accept_sock(res, 1, &noproto, 0); - freeaddrinfo(res); if(fd == -1 && noproto) { if(!noproto_is_err) return 1; /* return success, but do nothing */ @@ -314,7 +399,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg) if(cfg->control_ifs) { struct config_strlist* p; for(p = cfg->control_ifs; p; p = p->next) { - if(!add_open(p->str, cfg->control_port, &l, 1)) { + if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) { listening_ports_free(l); return NULL; } @@ -322,12 +407,12 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg) } else { /* defaults */ if(cfg->do_ip6 && - !add_open("::1", cfg->control_port, &l, 0)) { + !add_open("::1", cfg->control_port, &l, 0, cfg)) { listening_ports_free(l); return NULL; } if(cfg->do_ip4 && - !add_open("127.0.0.1", cfg->control_port, &l, 1)) { + !add_open("127.0.0.1", cfg->control_port, &l, 1, cfg)) { listening_ports_free(l); return NULL; } @@ -641,6 +726,8 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s) (long long)avg.tv_sec, (int)avg.tv_usec)) return 0; if(!ssl_printf(ssl, "%s.recursion.time.median"SQ"%g\n", nm, s->mesh_time_median)) return 0; + if(!ssl_printf(ssl, "%s.tcpusage"SQ"%lu\n", nm, + (unsigned long)s->svr.tcp_accept_usage)) return 0; return 1; } @@ -1990,7 +2077,7 @@ dump_infra_host(struct lruhash_entry* e, void* arg) d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto, d->timeout_A, d->timeout_AAAA, d->timeout_other, (int)d->edns_lame_known, (int)d->edns_version, - (int)(a->now<d->probedelay?d->probedelay-a->now:0), + (int)(a->now<d->probedelay?(d->probedelay - a->now):0), (int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A, (int)d->lame_other)) { a->ssl_failed = 1; @@ -2434,7 +2521,9 @@ int remote_control_callback(struct comm_point* c, void* arg, int err, s->shake_state = rc_none; /* once handshake has completed, check authentication */ - if(SSL_get_verify_result(s->ssl) == X509_V_OK) { + if (!rc->use_cert) { + verbose(VERB_ALGO, "unauthenticated remote control connection"); + } else if(SSL_get_verify_result(s->ssl) == X509_V_OK) { X509* x = SSL_get_peer_certificate(s->ssl); if(!x) { verbose(VERB_DETAIL, "remote control connection " diff --git a/external/unbound/daemon/remote.h b/external/unbound/daemon/remote.h index cc670b701..b25bfb1af 100644 --- a/external/unbound/daemon/remote.h +++ b/external/unbound/daemon/remote.h @@ -89,6 +89,8 @@ struct daemon_remote { struct worker* worker; /** commpoints for accepting remote control connections */ struct listen_list* accept_list; + /* if certificates are used */ + int use_cert; /** number of active commpoints that are handling remote control */ int active; /** max active commpoints */ diff --git a/external/unbound/daemon/stats.c b/external/unbound/daemon/stats.c index d3f41de03..838cf05ae 100644 --- a/external/unbound/daemon/stats.c +++ b/external/unbound/daemon/stats.c @@ -50,12 +50,13 @@ #include "daemon/daemon.h" #include "services/mesh.h" #include "services/outside_network.h" +#include "services/listen_dnsport.h" #include "util/config_file.h" #include "util/tube.h" #include "util/timehist.h" #include "util/net_help.h" #include "validator/validator.h" -#include "ldns/sbuffer.h" +#include "sldns/sbuffer.h" #include "services/cache/rrset.h" #include "services/cache/infra.h" #include "validator/val_kcache.h" @@ -140,6 +141,7 @@ void server_stats_compile(struct worker* worker, struct stats_info* s, int reset) { int i; + struct listen_list* lp; s->svr = worker->stats; s->mesh_num_states = worker->env.mesh->all.count; @@ -174,6 +176,13 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset) s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab); else s->svr.key_cache_count = 0; + /* get tcp accept usage */ + s->svr.tcp_accept_usage = 0; + for(lp = worker->front->cps; lp; lp = lp->next) { + if(lp->com->type == comm_tcp_accept) + s->svr.tcp_accept_usage += lp->com->cur_tcp_count; + } + if(reset && !worker->env.cfg->stat_cumulative) { worker_stats_clear(worker); } @@ -247,6 +256,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a) total->svr.rrset_bogus += a->svr.rrset_bogus; total->svr.unwanted_replies += a->svr.unwanted_replies; total->svr.unwanted_queries += a->svr.unwanted_queries; + total->svr.tcp_accept_usage += a->svr.tcp_accept_usage; for(i=0; i<STATS_QTYPE_NUM; i++) total->svr.qtype[i] += a->svr.qtype[i]; for(i=0; i<STATS_QCLASS_NUM; i++) diff --git a/external/unbound/daemon/stats.h b/external/unbound/daemon/stats.h index 5ea00a0da..6985446ce 100644 --- a/external/unbound/daemon/stats.h +++ b/external/unbound/daemon/stats.h @@ -129,6 +129,8 @@ struct server_stats { size_t unwanted_replies; /** unwanted traffic received on client-facing ports */ size_t unwanted_queries; + /** usage of tcp accept list */ + size_t tcp_accept_usage; /** histogram data exported to array * if the array is the same size, no data is lost, and diff --git a/external/unbound/daemon/unbound.c b/external/unbound/daemon/unbound.c index 5ded5a964..8e07c3895 100644 --- a/external/unbound/daemon/unbound.c +++ b/external/unbound/daemon/unbound.c @@ -443,18 +443,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, { #ifdef HAVE_GETPWNAM struct passwd *pwd = NULL; - uid_t uid; - gid_t gid; - /* initialize, but not to 0 (root) */ - memset(&uid, 112, sizeof(uid)); - memset(&gid, 112, sizeof(gid)); - log_assert(cfg); if(cfg->username && cfg->username[0]) { if((pwd = getpwnam(cfg->username)) == NULL) fatal_exit("user '%s' does not exist.", cfg->username); - uid = pwd->pw_uid; - gid = pwd->pw_gid; /* endpwent below, in case we need pwd for setusercontext */ } #endif @@ -511,33 +503,28 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, #ifdef HAVE_KILL if(cfg->pidfile && cfg->pidfile[0]) { writepid(daemon->pidfile, getpid()); - if(!(cfg->chrootdir && cfg->chrootdir[0]) || - (cfg->chrootdir && cfg->chrootdir[0] && - strncmp(daemon->pidfile, cfg->chrootdir, - strlen(cfg->chrootdir))==0)) { - /* delete of pidfile could potentially work, - * chown to get permissions */ - if(cfg->username && cfg->username[0]) { - if(chown(daemon->pidfile, uid, gid) == -1) { + if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { +# ifdef HAVE_CHOWN + if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) { log_err("cannot chown %u.%u %s: %s", - (unsigned)uid, (unsigned)gid, + (unsigned)cfg_uid, (unsigned)cfg_gid, daemon->pidfile, strerror(errno)); - } } +# endif /* HAVE_CHOWN */ } } #else (void)daemon; -#endif +#endif /* HAVE_KILL */ /* Set user context */ #ifdef HAVE_GETPWNAM - if(cfg->username && cfg->username[0]) { + if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { #ifdef HAVE_SETUSERCONTEXT /* setusercontext does initgroups, setuid, setgid, and * also resource limits from login config, but we * still call setresuid, setresgid to be sure to set all uid*/ - if(setusercontext(NULL, pwd, uid, (unsigned) + if(setusercontext(NULL, pwd, cfg_uid, (unsigned) LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0) log_warn("unable to setusercontext %s: %s", cfg->username, strerror(errno)); @@ -599,29 +586,29 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, /* drop permissions after chroot, getpwnam, pidfile, syslog done*/ #ifdef HAVE_GETPWNAM - if(cfg->username && cfg->username[0]) { + if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { # ifdef HAVE_INITGROUPS - if(initgroups(cfg->username, gid) != 0) + if(initgroups(cfg->username, cfg_gid) != 0) log_warn("unable to initgroups %s: %s", cfg->username, strerror(errno)); # endif /* HAVE_INITGROUPS */ endpwent(); #ifdef HAVE_SETRESGID - if(setresgid(gid,gid,gid) != 0) + if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0) #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID) - if(setregid(gid,gid) != 0) + if(setregid(cfg_gid,cfg_gid) != 0) #else /* use setgid */ - if(setgid(gid) != 0) + if(setgid(cfg_gid) != 0) #endif /* HAVE_SETRESGID */ fatal_exit("unable to set group id of %s: %s", cfg->username, strerror(errno)); #ifdef HAVE_SETRESUID - if(setresuid(uid,uid,uid) != 0) + if(setresuid(cfg_uid,cfg_uid,cfg_uid) != 0) #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID) - if(setreuid(uid,uid) != 0) + if(setreuid(cfg_uid,cfg_uid) != 0) #else /* use setuid */ - if(setuid(uid) != 0) + if(setuid(cfg_uid) != 0) #endif /* HAVE_SETRESUID */ fatal_exit("unable to set user id of %s: %s", cfg->username, strerror(errno)); @@ -666,6 +653,8 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode) log_warn("Continuing with default config settings"); } apply_settings(daemon, cfg, cmdline_verbose, debug_mode); + if(!done_setup) + config_lookup_uid(cfg); /* prepare */ if(!daemon_open_shared_ports(daemon)) diff --git a/external/unbound/daemon/worker.c b/external/unbound/daemon/worker.c index 59ae9dfce..93481354f 100644 --- a/external/unbound/daemon/worker.c +++ b/external/unbound/daemon/worker.c @@ -71,7 +71,7 @@ #include "validator/val_anchor.h" #include "libunbound/context.h" #include "libunbound/libworker.h" -#include "ldns/sbuffer.h" +#include "sldns/sbuffer.h" #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> @@ -900,7 +900,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, goto send_reply; } if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns, - c->buffer, worker->scratchpad)) { + c->buffer, worker->scratchpad, repinfo)) { regional_free_all(worker->scratchpad); if(sldns_buffer_limit(c->buffer) == 0) { comm_point_drop_reply(repinfo); |