Fixes #546.
/** parse args into delegpt */
static struct delegpt*
-parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
+parse_delegpt(RES* ssl, char* args, uint8_t* nm)
{
/* parse args and add in */
char* p = args;
}
/* parse address */
if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) {
- if(allow_names) {
- uint8_t* n = NULL;
- size_t ln;
- int lb;
- if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) {
- (void)ssl_printf(ssl, "error cannot "
- "parse IP address or name "
- "'%s'\n", todo);
- delegpt_free_mlc(dp);
- return NULL;
- }
- if(!delegpt_add_ns_mlc(dp, n, 0)) {
- (void)ssl_printf(ssl, "error out of memory\n");
- free(n);
- delegpt_free_mlc(dp);
- return NULL;
- }
- free(n);
-
- } else {
+ uint8_t* dname= NULL;
+ int port;
+ dname = authextstrtodname(todo, &port, &auth_name);
+ if(!dname) {
(void)ssl_printf(ssl, "error cannot parse"
- " IP address '%s'\n", todo);
+ " '%s'\n", todo);
+ delegpt_free_mlc(dp);
+ return NULL;
+ }
+#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ if(auth_name)
+ log_err("no name verification functionality in "
+ "ssl library, ignored name for %s", todo);
+#endif
+ if(!delegpt_add_ns_mlc(dp, dname, 0, auth_name, port)) {
+ (void)ssl_printf(ssl, "error out of memory\n");
+ free(dname);
delegpt_free_mlc(dp);
return NULL;
}
} else {
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(auth_name)
- log_err("no name verification functionality in "
+ log_err("no name verification functionality in "
"ssl library, ignored name for %s", todo);
#endif
/* add address */
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
- auth_name)) {
+ auth_name, -1)) {
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
return NULL;
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
} else {
struct delegpt* dp;
- if(!(dp = parse_delegpt(ssl, args, root, 0)))
+ if(!(dp = parse_delegpt(ssl, args, root)))
return;
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
(void)ssl_printf(ssl, "error out of memory\n");
/* parse dp */
if(dp) {
- if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) {
+ if(!(*dp = parse_delegpt(ssl, args, *nm))) {
free(*nm);
return 0;
}
.TP
.B stub\-host: \fI<domain name>
Name of stub zone nameserver. Is itself resolved before it is used.
+To use a nondefault port for DNS communication append '@' with the port number.
+If tls is enabled, then you can append a '#' and a name, then it'll check the
+tls authentication certificates with that name. If you combine the '@' and
+'#', the '@' comes first. If only '#' is used the default port is the
+configured tls\-port.
.TP
.B stub\-addr: \fI<IP address>
IP address of stub zone nameserver. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
-If tls is enabled, then you can append a '#' and a name, then it'll check
-the tls authentication certificates with that name. If you combine
-the '@' and '#', the '@' comes first.
+If tls is enabled, then you can append a '#' and a name, then it'll check the
+tls authentication certificates with that name. If you combine the '@' and
+'#', the '@' comes first. If only '#' is used the default port is the
+configured tls\-port.
.TP
.B stub\-prime: \fI<yes or no>
This option is by default no. If enabled it performs NS set priming,
.TP
.B forward\-host: \fI<domain name>
Name of server to forward to. Is itself resolved before it is used.
+To use a nondefault port for DNS communication append '@' with the port number.
+If tls is enabled, then you can append a '#' and a name, then it'll check the
+tls authentication certificates with that name. If you combine the '@' and
+'#', the '@' comes first. If only '#' is used the default port is the
+configured tls\-port.
.TP
.B forward\-addr: \fI<IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
-If tls is enabled, then you can append a '#' and a name, then it'll check
-the tls authentication certificates with that name. If you combine
-the '@' and '#', the '@' comes first.
+If tls is enabled, then you can append a '#' and a name, then it'll check the
+tls authentication certificates with that name. If you combine the '@' and
+'#', the '@' comes first. If only '#' is used the default port is the
+configured tls\-port.
.IP
At high verbosity it logs the TLS certificate, with TLS enabled.
If you leave out the '#' and auth name from the forward\-addr, any
copy->ssl_upstream = dp->ssl_upstream;
copy->tcp_upstream = dp->tcp_upstream;
for(ns = dp->nslist; ns; ns = ns->next) {
- if(!delegpt_add_ns(copy, region, ns->name, ns->lame))
+ if(!delegpt_add_ns(copy, region, ns->name, ns->lame,
+ ns->tls_auth_name, ns->port))
return NULL;
copy->nslist->resolved = ns->resolved;
copy->nslist->got4 = ns->got4;
copy->nslist->done_pside6 = ns->done_pside6;
}
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->tls_auth_name, NULL))
+ if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
+ a->bogus, a->lame, a->tls_auth_name, -1, NULL))
return NULL;
}
return copy;
int
delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
- uint8_t lame)
+ uint8_t lame, char* tls_auth_name, int port)
{
struct delegpt_ns* ns;
size_t len;
ns->lame = lame;
ns->done_pside4 = 0;
ns->done_pside6 = 0;
+ ns->port = port;
+ if(tls_auth_name) {
+ ns->tls_auth_name = regional_strdup(region, tls_auth_name);
+ if(!ns->tls_auth_name)
+ return 0;
+ } else {
+ ns->tls_auth_name = NULL;
+ }
return ns->name != 0;
}
return NULL;
}
-int
-delegpt_add_target(struct delegpt* dp, struct regional* region,
- uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
+int
+delegpt_add_target(struct delegpt* dp, struct regional* region,
+ uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions)
{
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
- return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL,
- additions);
+ log_assert(ns->port>0);
+ return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame,
+ ns->tls_auth_name, ns->port, additions);
}
-int
-delegpt_add_addr(struct delegpt* dp, struct regional* region,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
- uint8_t lame, char* tls_auth_name, int* additions)
+int
+delegpt_add_addr(struct delegpt* dp, struct regional* region,
+ struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
+ uint8_t lame, char* tls_auth_name, int port, int* additions)
{
struct delegpt_addr* a;
log_assert(!dp->dp_type_mlc);
+ if(port != -1) {
+ log_assert(port>0);
+ sockaddr_store_port(addr, addrlen, port);
+ }
/* check for duplicates */
if((a = delegpt_find_addr(dp, addr, addrlen))) {
if(bogus)
(size_t)sldns_read_uint16(nsdata->rr_data[i]))
continue; /* bad format */
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
- if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame))
+ if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame,
+ NULL, UNBOUND_DNS_PORT))
return 0;
}
return 1;
log_assert(!dp->dp_type_mlc);
memset(&sa, 0, len);
sa.sin_family = AF_INET;
- sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
for(i=0; i<d->count; i++) {
if(d->rr_len[i] != 2 + INET_SIZE)
continue;
log_assert(!dp->dp_type_mlc);
memset(&sa, 0, len);
sa.sin6_family = AF_INET6;
- sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
for(i=0; i<d->count; i++) {
if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */
continue;
while(n) {
nn = n->next;
free(n->name);
+ free(n->tls_auth_name);
free(n);
n = nn;
}
return (dp->name != NULL);
}
-int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
+int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
+ char* tls_auth_name, int port)
{
struct delegpt_ns* ns;
size_t len;
ns->lame = (uint8_t)lame;
ns->done_pside4 = 0;
ns->done_pside6 = 0;
+ ns->port = port;
+ if(tls_auth_name) {
+ ns->tls_auth_name = strdup(tls_auth_name);
+ if(!ns->tls_auth_name) {
+ free(ns->name);
+ free(ns);
+ return 0;
+ }
+ } else {
+ ns->tls_auth_name = NULL;
+ }
return 1;
}
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
+ socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name,
+ int port)
{
struct delegpt_addr* a;
log_assert(dp->dp_type_mlc);
+ if(port != -1) {
+ log_assert(port>0);
+ sockaddr_store_port(addr, addrlen, port);
+ }
/* check for duplicates */
if((a = delegpt_find_addr(dp, addr, addrlen))) {
if(bogus)
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
- return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
+ log_assert(ns->port>0);
+ return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame,
+ ns->tls_auth_name, ns->port);
}
size_t delegpt_get_mem(struct delegpt* dp)
* Also enabled if a parent-side cache entry exists, or a parent-side
* negative-cache entry exists. */
uint8_t done_pside6;
+ /** the TLS authentication name, (if not NULL) to use. */
+ char* tls_auth_name;
+ /** the port to use; it should mosty be the default 53 but configured
+ * upstreams can provide nondefault ports. */
+ int port;
};
/**
* @param regional: where to allocate the info.
* @param name: domain name in wire format.
* @param lame: name is lame, disprefer it.
+ * @param tls_auth_name: TLS authentication name (or NULL).
+ * @param port: port to use for resolved addresses.
* @return false on error.
*/
-int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
- uint8_t* name, uint8_t lame);
+int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
+ uint8_t* name, uint8_t lame, char* tls_auth_name, int port);
/**
* Add NS rrset; calls add_ns repeatedly.
* @param bogus: if address is bogus.
* @param lame: if address is lame.
* @param tls_auth_name: TLS authentication name (or NULL).
+ * @param port: the port to use; if -1 the port is taken from addr.
* @param additions: will be set to 1 if a new address is added
* @return false on error.
*/
-int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
+int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t bogus, uint8_t lame, char* tls_auth_name, int* additions);
+ uint8_t bogus, uint8_t lame, char* tls_auth_name, int port,
+ int* additions);
/**
* Find NS record in name list of delegation point.
* @param dp: must have been created with delegpt_create_mlc.
* @param name: the name to add.
* @param lame: the name is lame, disprefer.
+ * @param tls_auth_name: TLS authentication name (or NULL).
+ * @param port: port to use for resolved addresses.
* @return false on error.
*/
-int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
+int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
+ char* tls_auth_name, int port);
/**
* add an address to a malloced delegation point.
- * @param dp: must have been created with delegpt_create_mlc.
+ * @param dp: must have been created with delegpt_create_mlc.
* @param addr: the address.
* @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).
+ * @param port: the port to use; if -1 the port is taken from addr.
* @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, char* tls_auth_name);
+ socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name,
+ int port);
/**
* Add target address to the delegation point.
}
/** set fwd host names */
-static int
+static int
read_fwds_host(struct config_stub* s, struct delegpt* dp)
{
struct config_strlist* p;
uint8_t* dname;
- size_t dname_len;
+ char* tls_auth_name;
+ int port;
for(p = s->hosts; p; p = p->next) {
log_assert(p->str);
- dname = sldns_str2wire_dname(p->str, &dname_len);
+ dname = authextstrtodname(p->str, &port, &tls_auth_name);
if(!dname) {
log_err("cannot parse forward %s server name: '%s'",
s->name, p->str);
return 0;
}
- if(!delegpt_add_ns_mlc(dp, dname, 0)) {
+#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ if(tls_auth_name)
+ log_err("no name verification functionality in "
+ "ssl library, ignored name for %s", p->str);
+#endif
+ if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) {
free(dname);
log_err("out of memory");
return 0;
"ssl library, ignored name for %s", p->str);
#endif
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
- tls_auth_name)) {
+ tls_auth_name, -1)) {
log_err("out of memory");
return 0;
}
log_err("could not parse %s", sv);
return 0;
}
- if(!delegpt_add_ns_mlc(dp, dname, 0) ||
+ if(!delegpt_add_ns_mlc(dp, dname, 0, NULL, UNBOUND_DNS_PORT) ||
!extstrtoaddr(ip, &addr, &addrlen) ||
!delegpt_add_target_mlc(dp, dname, dname_len,
&addr, addrlen, 0, 0)) {
}
/** set stub host names */
-static int
+static int
read_stubs_host(struct config_stub* s, struct delegpt* dp)
{
struct config_strlist* p;
- size_t dname_len;
uint8_t* dname;
+ char* tls_auth_name;
+ int port;
for(p = s->hosts; p; p = p->next) {
log_assert(p->str);
- dname = sldns_str2wire_dname(p->str, &dname_len);
+ dname = authextstrtodname(p->str, &port, &tls_auth_name);
if(!dname) {
log_err("cannot parse stub %s nameserver name: '%s'",
s->name, p->str);
return 0;
}
- if(!delegpt_add_ns_mlc(dp, dname, 0)) {
+#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ if(tls_auth_name)
+ log_err("no name verification functionality in "
+ "ssl library, ignored name for %s", p->str);
+#endif
+ if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) {
free(dname);
log_err("out of memory");
return 0;
"ssl library, ignored name for %s", p->str);
#endif
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
- auth_name)) {
+ auth_name, -1)) {
log_err("out of memory");
return 0;
}
if(sldns_wirerr_get_type(rr, rr_len, dname_len)
== LDNS_RR_TYPE_NS) {
if(!delegpt_add_ns_mlc(dp, sldns_wirerr_get_rdata(rr,
- rr_len, dname_len), 0)) {
+ rr_len, dname_len), 0, NULL, UNBOUND_DNS_PORT)) {
log_err("out of memory reading root hints");
goto stop_read;
}
iq->chase_flags &= ~BIT_RD; /* go to authorities */
for(ns = p->nslist; ns; ns=ns->next) {
(void)delegpt_add_ns(iq->dp, qstate->region,
- ns->name, ns->lame);
+ ns->name, ns->lame, ns->tls_auth_name,
+ ns->port);
}
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->tls_auth_name, NULL);
+ a->lame, a->tls_auth_name, -1, NULL);
}
}
iq->dp->has_parent_side_NS = 1;
log_err("out of memory adding pside glue");
}
- /* This response is relevant to the current query, so we
- * add (attempt to add, anyway) this target(s) and reactivate
- * the original event.
- * NOTE: we could only look for the AnswerRRset if the
+ /* This response is relevant to the current query, so we
+ * add (attempt to add, anyway) this target(s) and reactivate
+ * the original event.
+ * NOTE: we could only look for the AnswerRRset if the
* response type was ANSWER. */
rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep);
if(rrset) {
int additions = 0;
/* if CNAMEs have been followed - add new NS to delegpt. */
/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */
- if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
+ if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
rrset->rk.dname_len)) {
/* if dpns->lame then set newcname ns lame too */
- if(!delegpt_add_ns(foriq->dp, forq->region,
- rrset->rk.dname, dpns->lame))
+ if(!delegpt_add_ns(foriq->dp, forq->region,
+ rrset->rk.dname, dpns->lame, dpns->tls_auth_name,
+ dpns->port))
log_err("out of memory adding cnamed-ns");
}
/* if dpns->lame then set the address(es) lame too */
#include "util/config_file.h"
#include "sldns/parseutil.h"
#include "sldns/wire2str.h"
+#include "sldns/str2wire.h"
#include <fcntl.h>
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
return ipstrtoaddr(str, port, addr, addrlen);
}
+uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
+{
+ char* s;
+ uint8_t* dname;
+ size_t dname_len;
+ *port = UNBOUND_DNS_PORT;
+ *auth_name = NULL;
+ if((s=strchr(str, '@'))) {
+ char* hash = strchr(s+1, '#');
+ if(hash) {
+ *auth_name = hash+1;
+ } else {
+ *auth_name = NULL;
+ }
+ *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;
+ }
+ *s = 0;
+ dname = sldns_str2wire_dname(str, &dname_len);
+ *s = '@';
+ } else if((s=strchr(str, '#'))) {
+ *port = UNBOUND_DNS_OVER_TLS_PORT;
+ *auth_name = s+1;
+ *s = 0;
+ dname = sldns_str2wire_dname(str, &dname_len);
+ *s = '#';
+ } else {
+ dname = sldns_str2wire_dname(str, &dname_len);
+ }
+ return dname;
+}
+
/** store port number into sockaddr structure */
void
sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
/**
* 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.
+ * The returned auth_name string is a pointer into the input string.
+ * Uses DNS port by default; TLS port when a '#tls-auth-name' is configured.
* @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,
+int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
socklen_t* addrlen, char** auth_name);
+/**
+ * Convert domain string, with "@port" appendix, to dname.
+ * It can also have an "#tls-auth-name" appendix (after the port).
+ * The return port is the parsed port.
+ * Uses DNS port by default; TLS port when a '#tls-auth-name' is configured.
+ * The returned auth_name string is a pointer into the input string.
+ * @param str: the string
+ * @param port: pointer to be assigned the parsed port value.
+ * @param auth_name: returned pointer to tls_auth_name, or NULL if none.
+ * @return pointer to the dname.
+ */
+uint8_t* authextstrtodname(char* str, int* port, char** auth_name);
+
/**
* Store port number into sockaddr structure
* @param addr: sockaddr structure, ip4 or ip6.