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;
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;
}
} 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;
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(
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;
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;
+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.
}
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;
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);
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;
}
(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);
}
}
}
a = dp->target_list;
while(a) {
na = a->next_target;
+ free(a->tls_auth_name);
free(a);
a = na;
}
}
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);
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;
}
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)
* 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;
};
/**
* @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.
* @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.
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;
}
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;
}
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;
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);
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(
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;
}
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;
* @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.
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,
* @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.
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
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,
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;
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;
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;
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
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);
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,
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;
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;
};
/**
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. */
*/
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,
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;
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;
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,
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;
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.
* @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.
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.
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)
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.