diff --git a/daemon/remote.c b/daemon/remote.c index 11c3cf34c..c58e36189 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1941,6 +1941,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names) struct delegpt* dp = delegpt_create_mlc(nm); struct sockaddr_storage addr; socklen_t addrlen; + char* auth_name; if(!dp) { (void)ssl_printf(ssl, "error out of memory\n"); return NULL; @@ -1953,7 +1954,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names) p = skipwhite(p); /* position at next spot */ } /* parse address */ - if(!extstrtoaddr(todo, &addr, &addrlen)) { + if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) { if(allow_names) { uint8_t* n = NULL; size_t ln; @@ -1981,7 +1982,8 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names) } } else { /* add address */ - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0, + auth_name)) { (void)ssl_printf(ssl, "error out of memory\n"); delegpt_free_mlc(dp); return NULL; diff --git a/daemon/worker.c b/daemon/worker.c index 77ac9e8e8..91f7558d6 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1875,7 +1875,7 @@ struct outbound_entry* worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream, - struct module_qstate* q) + char* tls_auth_name, struct module_qstate* q) { struct worker* worker = q->env->worker; struct outbound_entry* e = (struct outbound_entry*)regional_alloc( @@ -1885,7 +1885,7 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, e->qstate = q; e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec, want_dnssec, nocaps, q->env->cfg->tcp_upstream, - ssl_upstream, addr, addrlen, zone, zonelen, q, + ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q, worker_handle_service_reply, e, worker->back->udp_buff, q->env); if(!e->qsent) { return NULL; @@ -1932,7 +1932,8 @@ struct outbound_entry* libworker_send_query( int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), - int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q)) + int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), + struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; diff --git a/doc/Changelog b/doc/Changelog index f53bcc96f..be8e800d9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +19 April 2018: Wouter + - Can set tls authentication with forward-addr: IP#tls.auth.name + And put the public cert bundle in tls-cert-bundle: "ca-bundle.pem". + 18 April 2018: Wouter - Fix auth-zone retry timer to be on schedule with retry timeout, with backoff. Also time a refresh at the zone expiry. diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c index ecf88b293..f88b3e115 100644 --- a/iterator/iter_delegpt.c +++ b/iterator/iter_delegpt.c @@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) } for(a = dp->target_list; a; a = a->next_target) { if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, - a->bogus, a->lame)) + a->bogus, a->lame, a->tls_auth_name)) return NULL; } return copy; @@ -176,13 +176,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region, if(ns->got4 && ns->got6) ns->resolved = 1; } - return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame); + return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL); } int delegpt_add_addr(struct delegpt* dp, struct regional* region, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, - uint8_t lame) + uint8_t lame, char* tls_auth_name) { struct delegpt_addr* a; log_assert(!dp->dp_type_mlc); @@ -210,6 +210,13 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region, a->bogus = bogus; a->lame = lame; a->dnsseclame = 0; + if(tls_auth_name) { + a->tls_auth_name = regional_strdup(region, tls_auth_name); + if(!a->tls_auth_name) + return 0; + } else { + a->tls_auth_name = NULL; + } return 1; } @@ -276,11 +283,16 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp) (ns->done_pside6?" PSIDE_AAAA":"")); } for(a = dp->target_list; a; a = a->next_target) { + char s[128]; const char* str = " "; if(a->bogus && a->lame) str = " BOGUS ADDR_LAME "; else if(a->bogus) str = " BOGUS "; else if(a->lame) str = " ADDR_LAME "; - log_addr(VERB_ALGO, str, &a->addr, a->addrlen); + if(a->tls_auth_name) + snprintf(s, sizeof(s), "%s[%s]", str, + a->tls_auth_name); + else snprintf(s, sizeof(s), "%s", str); + log_addr(VERB_ALGO, s, &a->addr, a->addrlen); } } } @@ -539,6 +551,7 @@ void delegpt_free_mlc(struct delegpt* dp) a = dp->target_list; while(a) { na = a->next_target; + free(a->tls_auth_name); free(a); a = na; } @@ -585,7 +598,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame) } int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t bogus, uint8_t lame) + socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name) { struct delegpt_addr* a; log_assert(dp->dp_type_mlc); @@ -612,6 +625,15 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, a->bogus = bogus; a->lame = lame; a->dnsseclame = 0; + if(tls_auth_name) { + a->tls_auth_name = strdup(tls_auth_name); + if(!a->tls_auth_name) { + free(a); + return 0; + } + } else { + a->tls_auth_name = NULL; + } return 1; } @@ -632,7 +654,7 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, if(ns->got4 && ns->got6) ns->resolved = 1; } - return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame); + return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL); } size_t delegpt_get_mem(struct delegpt* dp) diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h index 24f057490..354bd6177 100644 --- a/iterator/iter_delegpt.h +++ b/iterator/iter_delegpt.h @@ -151,6 +151,8 @@ struct delegpt_addr { * option is useful to mark the address dnsseclame. * This value is not copied in addr-copy and dp-copy. */ uint8_t dnsseclame; + /** the TLS authentication name, (if not NULL) to use. */ + char* tls_auth_name; }; /** @@ -259,11 +261,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, * @param addrlen: the length of addr. * @param bogus: if address is bogus. * @param lame: if address is lame. + * @param tls_auth_name: TLS authentication name (or NULL). * @return false on error. */ int delegpt_add_addr(struct delegpt* dp, struct regional* regional, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t bogus, uint8_t lame); + uint8_t bogus, uint8_t lame, char* tls_auth_name); /** * Find NS record in name list of delegation point. @@ -394,10 +397,11 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame); * @param addrlen: the length of addr. * @param bogus: if address is bogus. * @param lame: if address is lame. + * @param tls_auth_name: TLS authentication name (or NULL). * @return false on error. */ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t bogus, uint8_t lame); + socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name); /** * Add target address to the delegation point. diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c index 0ba6c6ddf..a44f54386 100644 --- a/iterator/iter_fwd.c +++ b/iterator/iter_fwd.c @@ -231,14 +231,16 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp) struct config_strlist* p; struct sockaddr_storage addr; socklen_t addrlen; + char* tls_auth_name; for(p = s->addrs; p; p = p->next) { log_assert(p->str); - if(!extstrtoaddr(p->str, &addr, &addrlen)) { + if(!authextstrtoaddr(p->str, &addr, &addrlen, &tls_auth_name)) { log_err("cannot parse forward %s ip address: '%s'", s->name, p->str); return 0; } - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0, + tls_auth_name)) { log_err("out of memory"); return 0; } diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c index 1d4c228fa..e8d09338e 100644 --- a/iterator/iter_hints.c +++ b/iterator/iter_hints.c @@ -244,14 +244,16 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp) struct config_strlist* p; struct sockaddr_storage addr; socklen_t addrlen; + char* auth_name; for(p = s->addrs; p; p = p->next) { log_assert(p->str); - if(!extstrtoaddr(p->str, &addr, &addrlen)) { + if(!authextstrtoaddr(p->str, &addr, &addrlen, &auth_name)) { log_err("cannot parse stub %s ip address: '%s'", s->name, p->str); return 0; } - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0, + auth_name)) { log_err("out of memory"); return 0; } diff --git a/iterator/iterator.c b/iterator/iterator.c index 4e50457fd..65bb7199f 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1799,7 +1799,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, for(a = p->target_list; a; a=a->next_target) { (void)delegpt_add_addr(iq->dp, qstate->region, &a->addr, a->addrlen, a->bogus, - a->lame); + a->lame, a->tls_auth_name); } } iq->dp->has_parent_side_NS = 1; @@ -2387,7 +2387,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( ie, iq), &target->addr, target->addrlen, iq->dp->name, iq->dp->namelen, - (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate); + (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), + target->tls_auth_name, qstate); if(!outq) { log_addr(VERB_DETAIL, "error sending query to auth server", &target->addr, target->addrlen); diff --git a/libunbound/libworker.c b/libunbound/libworker.c index 155f987de..090fd276e 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -846,7 +846,8 @@ void libworker_alloc_cleanup(void* arg) struct outbound_entry* libworker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int ssl_upstream, struct module_qstate* q) + size_t zonelen, int ssl_upstream, char* tls_auth_name, + struct module_qstate* q) { struct libworker* w = (struct libworker*)q->env->worker; struct outbound_entry* e = (struct outbound_entry*)regional_alloc( @@ -856,8 +857,8 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo, e->qstate = q; e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec, want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream, - addr, addrlen, zone, zonelen, q, libworker_handle_service_reply, - e, w->back->udp_buff, q->env); + tls_auth_name, addr, addrlen, zone, zonelen, q, + libworker_handle_service_reply, e, w->back->udp_buff, q->env); if(!e->qsent) { return NULL; } @@ -977,7 +978,8 @@ struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), - int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q)) + int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), + struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; diff --git a/libunbound/worker.h b/libunbound/worker.h index 88e1cf799..7d2ede04e 100644 --- a/libunbound/worker.h +++ b/libunbound/worker.h @@ -63,6 +63,8 @@ struct query_info; * @param zone: delegation point name. * @param zonelen: length of zone name wireformat dname. * @param ssl_upstream: use SSL for upstream queries. + * @param tls_auth_name: if ssl_upstream, use this name with TLS + * authentication. * @param q: wich query state to reactivate upon return. * @return: false on failure (memory or socket related). no query was * sent. @@ -70,7 +72,8 @@ struct query_info; struct outbound_entry* libworker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int ssl_upstream, struct module_qstate* q); + size_t zonelen, int ssl_upstream, char* tls_auth_name, + struct module_qstate* q); /** process incoming replies from the network */ int libworker_handle_reply(struct comm_point* c, void* arg, int error, @@ -115,6 +118,8 @@ void worker_sighandler(int sig, void* arg); * @param zone: wireformat dname of the zone. * @param zonelen: length of zone name. * @param ssl_upstream: use SSL for upstream queries. + * @param tls_auth_name: if ssl_upstream, use this name with TLS + * authentication. * @param q: wich query state to reactivate upon return. * @return: false on failure (memory or socket related). no query was * sent. @@ -122,7 +127,8 @@ void worker_sighandler(int sig, void* arg); struct outbound_entry* worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int ssl_upstream, struct module_qstate* q); + size_t zonelen, int ssl_upstream, char* tls_auth_name, + struct module_qstate* q); /** * process control messages from the main thread. Frees the control diff --git a/pythonmod/interface.i b/pythonmod/interface.i index 748dec52d..72e6d99c7 100644 --- a/pythonmod/interface.i +++ b/pythonmod/interface.i @@ -574,7 +574,7 @@ struct module_env { struct outbound_entry* (*send_query)(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int ssl_upstream, + uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name, struct module_qstate* q); void (*detach_subs)(struct module_qstate* qstate); int (*attach_sub)(struct module_qstate* qstate, diff --git a/services/outside_network.c b/services/outside_network.c index 92212be02..63dfe4961 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -364,6 +364,20 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl); #endif pend->c->ssl_shake_state = comm_ssl_shake_write; +#ifdef HAVE_SSL_SET1_HOST + if(w->tls_auth_name) { + SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL); + /* setting the hostname makes openssl verify the + * host name in the x509 certificate in the + * SSL connection*/ + if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) { + log_err("SSL_set1_host failed"); + pend->c->fd = s; + comm_point_close(pend->c); + return 0; + } + } +#endif /* HAVE_SSL_SET1_HOST */ } w->pkt = NULL; w->next_waiting = (void*)pend; @@ -851,6 +865,7 @@ serviced_node_del(rbnode_type* node, void* ATTR_UNUSED(arg)) struct service_callback* p = sq->cblist, *np; free(sq->qbuf); free(sq->zone); + free(sq->tls_auth_name); edns_opt_list_free(sq->opt_list); while(p) { np = p->next; @@ -1284,6 +1299,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, w->cb = callback; w->cb_arg = callback_arg; w->ssl_upstream = sq->ssl_upstream; + w->tls_auth_name = sq->tls_auth_name; #ifndef S_SPLINT_S tv.tv_sec = timeout; tv.tv_usec = 0; @@ -1357,8 +1373,8 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec, static struct serviced_query* serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int qtype, struct edns_option* opt_list) + char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* zone, size_t zonelen, int qtype, struct edns_option* opt_list) { struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq)); #ifdef UNBOUND_DEBUG @@ -1386,12 +1402,24 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, sq->nocaps = nocaps; sq->tcp_upstream = tcp_upstream; sq->ssl_upstream = ssl_upstream; + if(tls_auth_name) { + sq->tls_auth_name = strdup(tls_auth_name); + if(!sq->tls_auth_name) { + free(sq->zone); + free(sq->qbuf); + free(sq); + return NULL; + } + } else { + sq->tls_auth_name = NULL; + } memcpy(&sq->addr, addr, addrlen); sq->addrlen = addrlen; sq->opt_list = NULL; if(opt_list) { sq->opt_list = edns_opt_copy_alloc(opt_list); if(!sq->opt_list) { + free(sq->tls_auth_name); free(sq->zone); free(sq->qbuf); free(sq); @@ -2055,7 +2083,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, struct serviced_query* outnet_serviced_query(struct outside_network* outnet, struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, int tcp_upstream, int ssl_upstream, + int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, struct module_qstate* qstate, comm_point_callback_type* callback, void* callback_arg, sldns_buffer* buff, @@ -2078,8 +2106,9 @@ outnet_serviced_query(struct outside_network* outnet, if(!sq) { /* make new serviced query entry */ sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps, - tcp_upstream, ssl_upstream, addr, addrlen, zone, - zonelen, (int)qinfo->qtype, qstate->edns_opts_back_out); + tcp_upstream, ssl_upstream, tls_auth_name, addr, + addrlen, zone, zonelen, (int)qinfo->qtype, + qstate->edns_opts_back_out); if(!sq) { free(cb); return NULL; diff --git a/services/outside_network.h b/services/outside_network.h index 09b2e6ced..0853f15e2 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -290,6 +290,8 @@ struct waiting_tcp { void* cb_arg; /** if it uses ssl upstream */ int ssl_upstream; + /** ref to the tls_auth_name from the serviced_query */ + char* tls_auth_name; }; /** @@ -332,6 +334,9 @@ struct serviced_query { int nocaps; /** tcp upstream used, use tcp, or ssl_upstream for SSL */ int tcp_upstream, ssl_upstream; + /** the name of the tls authentication name, eg. 'ns.example.com' + * or NULL */ + char* tls_auth_name; /** where to send it */ struct sockaddr_storage addr; /** length of addr field in use. */ @@ -501,7 +506,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p); */ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, int tcp_upstream, int ssl_upstream, + int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, struct module_qstate* qstate, comm_point_callback_type* callback, void* callback_arg, diff --git a/smallapp/worker_cb.c b/smallapp/worker_cb.c index e88e8c8d7..dda94cc67 100644 --- a/smallapp/worker_cb.c +++ b/smallapp/worker_cb.c @@ -105,7 +105,7 @@ struct outbound_entry* worker_send_query( int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream), - struct module_qstate* ATTR_UNUSED(q)) + char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; @@ -137,7 +137,7 @@ struct outbound_entry* libworker_send_query( int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream), - struct module_qstate* ATTR_UNUSED(q)) + char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 300a42c15..860e2e81e 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1161,10 +1161,11 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, struct query_info* qinfo, uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, struct module_qstate* qstate, - comm_point_callback_type* callback, void* callback_arg, - sldns_buffer* ATTR_UNUSED(buff), struct module_env* ATTR_UNUSED(env)) + char* ATTR_UNUSED(tls_auth_name), struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, + struct module_qstate* qstate, comm_point_callback_type* callback, + void* callback_arg, sldns_buffer* ATTR_UNUSED(buff), + struct module_env* ATTR_UNUSED(env)) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; struct fake_pending* pend = (struct fake_pending*)calloc(1, diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 400a15de2..302b6f784 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -311,7 +311,8 @@ int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q)) + uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name, + struct module_qstate* q)) { if(fptr == &worker_send_query) return 1; else if(fptr == &libworker_send_query) return 1; diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index 39e3f2d7f..03c2b92b4 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -212,7 +212,8 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr); int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q)); + uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name, + struct module_qstate* q)); /** * Check function pointer whitelist for module_env detach_subs callback values. diff --git a/util/module.h b/util/module.h index 73db994bd..c6e5164de 100644 --- a/util/module.h +++ b/util/module.h @@ -338,6 +338,8 @@ struct module_env { * @param zone: delegation point name. * @param zonelen: length of zone name. * @param ssl_upstream: use SSL for upstream queries. + * @param tls_auth_name: if ssl_upstream, use this name with TLS + * authentication. * @param q: wich query state to reactivate upon return. * @return: false on failure (memory or socket related). no query was * sent. Or returns an outbound entry with qsent and qstate set. @@ -348,7 +350,7 @@ struct module_env { uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream, - struct module_qstate* q); + char* tls_auth_name, struct module_qstate* q); /** * Detach-subqueries. diff --git a/util/net_help.c b/util/net_help.c index 89939bf97..439c60fab 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -270,6 +270,49 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, return 1; } +int authextstrtoaddr(char* str, struct sockaddr_storage* addr, + socklen_t* addrlen, char** auth_name) +{ + char* s; + int port = UNBOUND_DNS_PORT; + if((s=strchr(str, '@'))) { + char buf[MAX_ADDR_STRLEN]; + size_t len = s-str; + char* hash = strchr(s+1, '#'); + if(hash) { + *auth_name = hash+1; + } else { + *auth_name = NULL; + } + if(len >= MAX_ADDR_STRLEN) { + return 0; + } + (void)strlcpy(buf, str, sizeof(buf)); + buf[len] = 0; + port = atoi(s+1); + if(port == 0) { + if(!hash && strcmp(s+1,"0")!=0) + return 0; + if(hash && strncmp(s+1,"0#",2)!=0) + return 0; + } + return ipstrtoaddr(buf, port, addr, addrlen); + } + if((s=strchr(str, '#'))) { + char buf[MAX_ADDR_STRLEN]; + size_t len = s-str; + if(len >= MAX_ADDR_STRLEN) { + return 0; + } + (void)strlcpy(buf, str, sizeof(buf)); + buf[len] = 0; + *auth_name = s+1; + return ipstrtoaddr(buf, port, addr, addrlen); + } + *auth_name = NULL; + return ipstrtoaddr(str, port, addr, addrlen); +} + /** store port number into sockaddr structure */ void sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) diff --git a/util/net_help.h b/util/net_help.h index ba78c2486..5e0d3a629 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -201,6 +201,20 @@ int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, socklen_t* addrlen, int* net); +/** + * Convert address string, with "@port" appendix, to sockaddr. + * It can also have an "#tls-auth-name" appendix (after the port). + * The returned tls-auth-name string is a pointer into the input string. + * Uses DNS port by default. + * @param str: the string + * @param addr: where to store sockaddr. + * @param addrlen: length of stored sockaddr is returned. + * @param auth_name: returned pointer to tls_auth_name, or NULL if none. + * @return 0 on error. + */ +int authextstrtoaddr(char* str, struct sockaddr_storage* addr, + socklen_t* addrlen, char** auth_name); + /** * Store port number into sockaddr structure * @param addr: sockaddr structure, ip4 or ip6.