Compare commits

...
39 Commits
Author SHA1 Message Date
Evan Hunt 0c6fea8429 fail robustly if TLS is misconfigured
named could crash if run as a non-root user with a configuration
that used a privileged port for TLS. this has now been fixed.
2021-02-12 00:54:25 -08:00
Evan Hunt fc1ad28aa4 allow configuration of "default" http endpoint
specifying "http default" in a listen-on statement sets up
the default "/dns-query" endpoint. tests and documentation
have been added.
2021-02-12 00:38:19 -08:00
Evan Hunt d58edda725 add basic DoH system tests
- rename dot to doth, as it now covers both dot and doh.
- merge xot into doth as it's closely related.
- added long-lived key and cert files (expiring 2121).
- add tests with https-get, https-post, http-plain, alternate
  endpoints, and both static and ephemeral TLS configuration.
- incidentally fixed a memory leak in dig that occurred if +https
  was specified more than once.
2021-02-11 19:30:22 -08:00
Evan Hunt 42a4093423 send the specified hostname in the HTTP URI
dig was not working with a server with offloaded TLS;
this turned out to be because it was sending the URI as
"https://<address>/dns-query", not "https://<name>/dns-query".
using userarg instead of servname fixes the problem. (incidentally
also corrected logged output to use the hostname when available.)
2021-02-11 14:37:26 -08:00
Evan Hunt d18a4d47f6 prevent dig hang when nghttp2 callback fails
calling recv_done() with ISC_R_CANCELED prevents dig from cleaning
up fully from the query, because when that result code is used
it means some resources are already gone. changing the result
to ISC_R_UNEXPECTED prevents the hang.
2021-02-11 12:17:19 -08:00
Artem Boldariev f9ec55fd9a fixup! start refactoring isc_nm_httprequest() into read/send 2021-02-11 19:44:19 +02:00
Artem Boldariev 9d1ab27081 isc__nm_tls_settimeout() and isc__nm_http_settimeout() implementations 2021-02-11 18:37:51 +02:00
Artem Boldariev 70b1946896 fixup! HACK: make isc_nm_tlsconnect() work when being invoked from within the context of a network thread 2021-02-11 16:01:34 +02:00
Artem Boldariev b7e8994ad3 HACK: make isc_nm_tlsconnect() work when being invoked from within the context of a network thread 2021-02-11 15:03:44 +02:00
Artem Boldariev 9b3f3e96ea fix unit tests 2021-02-11 13:20:00 +02:00
Evan Hunt bdc49a0650 fix handling of tcp connection errors
- a bug that was already fixed in tcpdns.c and tlsdns.c had been
  left unfixed in tcp.c: we needed to check whether the socket() call
  succeeds before attempting any asynchronous connection code.
  this corrects a problem that occurred when uv__socket() failed
  with too many open files.
- also corrected the behavior of nm_connectcb().  previously, it was
  forcing synchronous execution when force_async was false. what we
  want is to force asynchronous execution if force_async is true. if
  force_async is false, we want it to decide based on whether we're in
  the network thread.
2021-02-10 20:16:33 -08:00
Evan Hunt 4a90d76163 rename isc_nm_httprequest()
isc_nm_httprequest() is retained for use by doh_test, but has
been renamed isc__nm_http_request() and is no longer part of
the main API.

eventually doh_test should be changed to use isc_nm_read() and
isc_nm_send(), and this function should be removed.
2021-02-10 15:07:41 -08:00
Evan Hunt 8c3f83dcea add support for dig +http-plain
this allows dig to connect over an unencrypted HTTP/2 channel.
2021-02-10 13:28:11 -08:00
Evan Hunt de7bbe277e fixup! fixup! fixup! fixup! fixup! call connect_cb from isc_nm_httpconnect() asynchronously 2021-02-10 12:34:10 -08:00
Evan Hunt c0f369a975 fixup! add preliminary DoH client support to dig 2021-02-10 12:33:45 -08:00
Artem Boldariev db2b8340e6 Fix keeping track of TLS context 2021-02-10 18:34:12 +02:00
Artem Boldariev a414d909c4 HTTP/2 session reference counting fixes 2021-02-10 16:38:44 +02:00
Artem Boldariev 27e184b32d fixup! clean up TLS and HTTP data correctly 2021-02-10 13:23:21 +02:00
Evan Hunt df1fd19182 fixup! fixup! fixup! fixup! call connect_cb from isc_nm_httpconnect() asynchronously 2021-02-09 22:35:50 -08:00
Evan Hunt 180899f186 fixup! reference-count http session objects 2021-02-09 18:39:55 -08:00
Evan Hunt 0828834a5e reference-count http session objects 2021-02-09 18:39:17 -08:00
Evan Hunt 14dad4c9b5 fixup! clean up TLS and HTTP data correctly 2021-02-09 18:36:28 -08:00
Evan Hunt e6d35ea0e8 clean up TLS and HTTP data correctly
we don't want to call isc__nm_http_cleanup_data() for TLS sockets
or isc__nm_tls_cleanup_data() for HTTP sockets, they can step on
each other and cause a crash or deadlock.
2021-02-09 12:57:26 -08:00
Artem Boldariev 662197d5c2 fixup! add preliminary DoH client support to dig 2021-02-09 20:47:41 +02:00
Artem Boldariev 266d8120f4 fixup! fixup! fixup! call connect_cb from isc_nm_httpconnect() asynchronously 2021-02-09 20:37:09 +02:00
Artem Boldariev 5356b36ebd fixup! fixup! call connect_cb from isc_nm_httpconnect() asynchronously 2021-02-09 18:29:27 +02:00
Artem Boldariev 96620f41dd fixup! update the socket result correctly 2021-02-09 14:37:40 +02:00
Artem Boldariev e01debbb1d fixup! call connect_cb from isc_nm_httpconnect() asynchronously 2021-02-09 14:37:33 +02:00
Evan Hunt 4fe216e6f7 call connect_cb from isc_nm_httpconnect() asynchronously
this isn't working yet, but it's a step in the right direction:
we need to call the connect callback from isc_nm_httpconnect()
asynchronously, after the connect has already returned. this
will enable dig to unlock the lookup before tcp_connected()
locks it, as it does when using tcpdns or tlsdns sockets.

this commit also removes the http_connect_t structure and stores
the connection data in a newly created http socket instead. (since
the socket structure was going to be needed to call isc__nm_connectcb()
anyway, it seemed like a good idea to make use of it to simplify
the connection code.)
2021-02-09 01:13:25 -08:00
Evan Hunt 8ea2cd7864 update the socket result correctly
in tls_call_connect_cb(), we want to update the result for
the TLS socket.  however, in some error conditions on connect,
the handle we're passing is for the TCP socket instead. this
was causing the wrong socket's result code to be updated, and
the thread that was waiting for the result to be updated never
woke up.

(note: while the fix in this commit causes doh_test to stop
deadlocking, I'm not sure whether I've actually fixed the bug.
in other places, we create a new 'tlshandle' to pass into
tls_call_connect_cb(). perhaps we should be doing that in
all cases?)

incidentally, I also renamed tls_connect_cb() to tcp_connected(),
because the handle passed in is for the TCP socket, and I kept
being confused by the name having "tls" in it.
2021-02-08 15:27:38 -08:00
Evan Hunt bf9796140e fixup! start refactoring isc_nm_httprequest() into read/send 2021-02-08 12:43:22 -08:00
Artem Boldariev 01fce69199 fixup! start refactoring isc_nm_httprequest() into read/send 2021-02-08 20:59:44 +02:00
Artem Boldariev 697192d5cd TLS (WIP): fix double free(), other fixes 2021-02-08 20:26:23 +02:00
Evan Hunt b690117276 still-broken checkpoint 2021-02-07 23:14:15 -08:00
Evan Hunt 6a3153950a start refactoring isc_nm_httprequest() into read/send
the goal here is to have the interface to http sockets be
the same as other types of netmgr socket, so that (for
example) dig can open an http connection and then just work
with no further code change, the same as it does with tcpdns
or tlsdns.

but the supporting code for https seems to be written with
the assumption that there will be a tight connection between
a request and a response, so the send and read functions have been
compressed into a single 'httprequest' function call. in an effort
to make the normal send and read semantics work correctly, we're
trying to set it up so that read sets us up to listen for a
response, send sets up the query we're sending, and whichever one
comes second triggers the transaction.

currently this is working in doh_test, but dig is failing due to a
deadlock; isc_http_connect() needs to return so launch_next_query()
can unlock the lookup before tcp_connected() runs.
2021-02-07 22:43:29 -08:00
Evan Hunt d7090060be more cleanup 2021-02-07 22:43:29 -08:00
Evan Hunt 32de043c7d add setter functions for HTTP/2 ALPN
instead of setting up ALPN in isc_tlsctx_createclient(), we now
have a function isc_tlsctx_enable_http2client_alpn() that can be
run from isc_nm_httpconnect().  isc_tlsctx_enable_http2server_alpn()
can similarly be run from isc_nm_httpconnect().
2021-02-07 10:31:41 -08:00
Evan Hunt 9b133ad447 netmgr http refactoring
- style, cleanup, and removal of unnecessary code
- combine isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
  into one function, renamed isc_http_endpoint()
- move isc_nm_http_connect_send_request() into doh_test.c as a helper
  function; remove it from the public API
- renamed isc_http2 and isc_nm_http2 entities to just isc_http and
  isc_nm_http, for consistency with other existing names
- shortened a number of long names
- the caller is now responsible for determining the peer address
  in isc_nm_httpconnect(); this eliminates the need to parse the URI
  and the dependency on an external resolver. the caller is also now
  responsible for creating the SSL client context, for consistency with
  isc_nm_tlsdnsconnect().
2021-02-07 10:31:41 -08:00
Ondřej SurýandEvan Hunt 505d8d6ca4 add preliminary DoH client support to dig 2021-02-07 10:30:24 -08:00
33 changed files with 1637 additions and 1383 deletions
+71 -3
View File
@@ -228,6 +228,10 @@ help(void) {
"SERVFAIL)\n"
" +[no]header-only (Send query without a "
"question section)\n"
" +[no]https[=###] (DNS over HTTPS mode) "
"[/]\n"
" +[no]https-get (Use GET instead of "
"default POST method\n"
" +[no]identify (ID responders in short "
"answers)\n"
#ifdef HAVE_LIBIDN2
@@ -348,12 +352,14 @@ received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
}
if (query->lookup->tls_mode) {
proto = "TLS";
} else if (query->lookup->https_mode) {
proto = "HTTPS";
} else if (query->lookup->tcp_mode) {
proto = "TCP";
} else {
proto = "UDP";
}
printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->servname,
printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->userarg,
proto);
time(&tnow);
(void)localtime_r(&tnow, &tmnow);
@@ -1066,6 +1072,15 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
goto invalid_option; \
} while (0)
#define FULLCHECK4(A, B, C, D) \
do { \
size_t _l = strlen(cmd); \
if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0) && \
(_l >= sizeof(C) || strncasecmp(cmd, C, _l) != 0) && \
(_l >= sizeof(D) || strncasecmp(cmd, D, _l) != 0)) \
goto invalid_option; \
} while (0)
switch (cmd[0]) {
case 'a':
@@ -1412,8 +1427,61 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
lookup->servfail_stops = state;
break;
case 'h':
FULLCHECK("header-only");
lookup->header_only = state;
switch (cmd[1]) {
case 'e': /* header-only */
FULLCHECK("header-only");
lookup->header_only = state;
break;
case 't':
FULLCHECK4("https", "https-get", "https-post",
"http-plain");
if (lookup->https_path != NULL) {
isc_mem_free(mctx, lookup->https_path);
lookup->https_path = NULL;
}
if (!state) {
lookup->https_mode = false;
break;
}
if (cmd[4] == '-') {
FULLCHECK("http-plain");
lookup->https_mode = true;
lookup->http_plain = true;
} else {
switch (cmd[5]) {
case '\0':
FULLCHECK("https");
break;
case '-':
switch (cmd[6]) {
case 'p':
FULLCHECK("https-post");
break;
case 'g':
FULLCHECK("https-get");
lookup->https_get = true;
break;
}
break;
default:
goto invalid_option;
}
lookup->https_mode = true;
}
if (!lookup->tcp_mode_set) {
lookup->tcp_mode = state;
}
if (value == NULL) {
lookup->https_path = isc_mem_strdup(
mctx, DEFAULT_HTTPS_PATH);
} else {
lookup->https_path = isc_mem_strdup(
mctx, value);
}
break;
default:
goto invalid_option;
}
break;
case 'i':
switch (cmd[1]) {
+72 -92
View File
@@ -608,97 +608,35 @@ make_empty_lookup(void) {
INSIST(!free_now);
looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
looknew->pending = true;
looknew->textname[0] = 0;
looknew->cmdline[0] = 0;
looknew->rdtype = dns_rdatatype_a;
looknew->qrdtype = dns_rdatatype_a;
looknew->rdclass = dns_rdataclass_in;
looknew->rdtypeset = false;
looknew->rdclassset = false;
looknew->sendspace = NULL;
looknew->sendmsg = NULL;
looknew->name = NULL;
looknew->oname = NULL;
looknew->xfr_q = NULL;
looknew->current_query = NULL;
looknew->doing_xfr = false;
looknew->ixfr_serial = 0;
looknew->trace = false;
looknew->trace_root = false;
looknew->identify = false;
looknew->identify_previous_line = false;
looknew->ignore = false;
looknew->servfail_stops = true;
looknew->besteffort = true;
looknew->dns64prefix = false;
looknew->dnssec = false;
looknew->ednsflags = 0;
looknew->opcode = dns_opcode_query;
looknew->expire = false;
looknew->nsid = false;
looknew->tcp_keepalive = false;
looknew->padding = 0;
looknew->header_only = false;
looknew->sendcookie = false;
looknew->seenbadcookie = false;
looknew->badcookie = true;
looknew->multiline = false;
looknew->nottl = false;
looknew->noclass = false;
looknew->onesoa = false;
looknew->use_usec = false;
looknew->nocrypto = false;
looknew->ttlunits = false;
looknew->expandaaaa = false;
looknew->qr = false;
looknew = isc_mem_allocate(mctx, sizeof(*looknew));
*looknew = (dig_lookup_t){
.pending = true,
.rdtype = dns_rdatatype_a,
.qrdtype = dns_rdatatype_a,
.rdclass = dns_rdataclass_in,
.servfail_stops = true,
.besteffort = true,
.opcode = dns_opcode_query,
.badcookie = true,
#ifdef HAVE_LIBIDN2
looknew->idnin = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
looknew->idnout = looknew->idnin;
#else /* ifdef HAVE_LIBIDN2 */
looknew->idnin = false;
looknew->idnout = false;
.idnin = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false,
.idnout = looknew->idnin,
#endif /* HAVE_LIBIDN2 */
looknew->udpsize = -1;
looknew->edns = -1;
looknew->recurse = true;
looknew->aaonly = false;
looknew->adflag = false;
looknew->cdflag = false;
looknew->raflag = false;
looknew->tcflag = false;
looknew->print_unknown_format = false;
looknew->zflag = false;
looknew->setqid = false;
looknew->qid = 0;
looknew->ns_search_only = false;
looknew->origin = NULL;
looknew->tsigctx = NULL;
looknew->querysig = NULL;
looknew->retries = tries;
looknew->nsfound = 0;
looknew->tcp_mode = false;
looknew->tcp_mode_set = false;
looknew->tls_mode = false;
looknew->comments = true;
looknew->stats = true;
looknew->section_question = true;
looknew->section_answer = true;
looknew->section_authority = true;
looknew->section_additional = true;
looknew->new_search = false;
looknew->done_as_is = false;
looknew->need_search = false;
looknew->ecs_addr = NULL;
looknew->cookie = NULL;
looknew->ednsopts = NULL;
looknew->ednsoptscnt = 0;
looknew->ednsneg = true;
looknew->mapped = true;
looknew->dscp = -1;
looknew->rrcomments = 0;
looknew->eoferr = 0;
.udpsize = -1,
.edns = -1,
.recurse = true,
.retries = tries,
.comments = true,
.stats = true,
.section_question = true,
.section_answer = true,
.section_authority = true,
.section_additional = true,
.ednsneg = true,
.mapped = true,
.dscp = -1,
};
dns_fixedname_init(&looknew->fdomain);
ISC_LINK_INIT(looknew, link);
ISC_LIST_INIT(looknew->q);
@@ -787,6 +725,12 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
looknew->nsid = lookold->nsid;
looknew->tcp_keepalive = lookold->tcp_keepalive;
looknew->header_only = lookold->header_only;
looknew->https_mode = lookold->https_mode;
if (lookold->https_path != NULL) {
looknew->https_path = isc_mem_strdup(mctx, lookold->https_path);
}
looknew->https_get = lookold->https_get;
looknew->http_plain = lookold->http_plain;
looknew->sendcookie = lookold->sendcookie;
looknew->seenbadcookie = lookold->seenbadcookie;
looknew->badcookie = lookold->badcookie;
@@ -1638,6 +1582,10 @@ _destroy_lookup(dig_lookup_t *lookup) {
isc_mem_free(mctx, lookup->ednsopts);
}
if (lookup->https_path) {
isc_mem_free(mctx, lookup->https_path);
}
isc_mem_free(mctx, lookup);
}
@@ -2760,7 +2708,20 @@ start_tcp(dig_query_t *query) {
* For TLS connections, we want to override the default
* port number.
*/
port = port_set ? port : (query->lookup->tls_mode ? 853 : 53);
if (!port_set) {
if (query->lookup->tls_mode) {
port = 853;
} else if (query->lookup->https_mode &&
!query->lookup->http_plain) {
port = 443;
} else if (query->lookup->https_mode) {
port = 80;
} else {
port = 53;
}
}
debug("query->servname = %s\n", query->servname);
result = get_address(query->servname, port, &query->sockaddr);
if (result != ISC_R_SUCCESS) {
@@ -2835,7 +2796,25 @@ start_tcp(dig_query_t *query) {
(isc_nmiface_t *)&query->sockaddr,
tcp_connected, query, local_timeout, 0,
query->tlsctx);
check_result(result, "isc_nm_tcpdnsconnect");
check_result(result, "isc_nm_tlsdnsconnect");
} else if (query->lookup->https_mode) {
char uri[4096] = { 0 };
snprintf(uri, sizeof(uri), "https://%s:%u%s",
query->userarg, (uint16_t)port,
query->lookup->https_path);
if (!query->lookup->http_plain) {
result = isc_tlsctx_createclient(
&query->tlsctx);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
result = isc_nm_httpconnect(
netmgr, (isc_nmiface_t *)&localaddr,
(isc_nmiface_t *)&query->sockaddr, uri,
!query->lookup->https_get, tcp_connected, query,
query->tlsctx, false, local_timeout, 0);
check_result(result, "isc_nm_httpconnect");
} else {
result = isc_nm_tcpdnsconnect(
netmgr, (isc_nmiface_t *)&localaddr,
@@ -3211,6 +3190,7 @@ launch_next_query(dig_query_t *query) {
}
}
}
lookup_detach(&l);
return;
}
@@ -3583,7 +3563,7 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
REQUIRE(DIG_VALID_QUERY(query));
INSIST(query->readhandle != NULL);
INSIST(handle == query->readhandle);
/* INSIST(handle == query->readhandle); */
INSIST(!free_now);
debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult),
+9
View File
@@ -76,6 +76,9 @@
#define DEFAULT_EDNS_VERSION 0
#define DEFAULT_EDNS_BUFSIZE 1232
#define DEFAULT_HTTPS_PATH "/dns-query"
#define DEFAULT_HTTPS_QUERY "?dns="
/*%
* Lookup_limit is just a limiter, keeping too many lookups from being
* created. It's job is mainly to prevent the program from running away
@@ -168,6 +171,12 @@ struct dig_lookup {
int rrcomments;
unsigned int eoferr;
uint16_t qid;
struct {
bool http_plain;
bool https_mode;
bool https_get;
char *https_path;
};
};
/*% The dig_query structure */
+31 -17
View File
@@ -9004,10 +9004,9 @@ load_configuration(const char *filename, named_server_t *server,
(void)cfg_map_get(options, "listen-on", &clistenon);
}
if (clistenon != NULL) {
/* check return code? */
(void)listenlist_fromconfig(
CHECK(listenlist_fromconfig(
clistenon, config, named_g_aclconfctx,
named_g_mctx, AF_INET, &listenon);
named_g_mctx, AF_INET, &listenon));
} else {
/*
* Not specified, use default.
@@ -9032,10 +9031,9 @@ load_configuration(const char *filename, named_server_t *server,
(void)cfg_map_get(options, "listen-on-v6", &clistenon);
}
if (clistenon != NULL) {
/* check return code? */
(void)listenlist_fromconfig(
CHECK(listenlist_fromconfig(
clistenon, config, named_g_aclconfctx,
named_g_mctx, AF_INET6, &listenon);
named_g_mctx, AF_INET6, &listenon));
} else {
/*
* Not specified, use default.
@@ -11092,6 +11090,10 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
tlsmap = find_maplist(config, "tls", tlsname);
if (tlsmap == NULL) {
cfg_obj_log(tlsobj, named_g_lctx,
ISC_LOG_ERROR,
"tls '%s' is not defined",
cfg_obj_asstring(tlsobj));
return (ISC_R_FAILURE);
}
@@ -11110,8 +11112,10 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
const char *httpname = cfg_obj_asstring(httpobj);
http_server = find_maplist(config, "http", httpname);
if (http_server == NULL) {
cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR,
if (http_server == NULL &&
strcasecmp(httpname, "default") != 0) {
cfg_obj_log(httpobj, named_g_lctx,
ISC_LOG_ERROR,
"http '%s' is not defined",
cfg_obj_asstring(httpobj));
return (ISC_R_FAILURE);
@@ -11188,7 +11192,6 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
}
if (http) {
INSIST(http_server != NULL);
CHECK(listenelt_http(http_server, do_tls, key, cert, port, mctx,
&delt));
} else {
@@ -11218,7 +11221,7 @@ listenelt_http(const cfg_obj_t *http, bool tls, const char *key,
char **endpoints = NULL;
const cfg_obj_t *eplist = NULL;
const cfg_listelt_t *elt = NULL;
size_t len, i = 0;
size_t len = 1, i = 0;
REQUIRE(target != NULL && *target == NULL);
REQUIRE((key == NULL) == (cert == NULL));
@@ -11227,15 +11230,26 @@ listenelt_http(const cfg_obj_t *http, bool tls, const char *key,
port = tls ? named_g_httpsport : named_g_httpport;
}
CHECK(cfg_map_get(http, "endpoints", &eplist));
len = cfg_list_length(eplist, false);
/*
* If "default" was used, we set up the default endpoint
* of "/dns-query".
*/
if (http != NULL) {
CHECK(cfg_map_get(http, "endpoints", &eplist));
len = cfg_list_length(eplist, false);
}
endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len);
for (elt = cfg_list_first(eplist); elt != NULL;
elt = cfg_list_next(elt)) {
const cfg_obj_t *ep = cfg_listelt_value(elt);
const char *path = cfg_obj_asstring(ep);
endpoints[i++] = isc_mem_strdup(mctx, path);
if (http != NULL) {
for (elt = cfg_list_first(eplist); elt != NULL;
elt = cfg_list_next(elt)) {
const cfg_obj_t *ep = cfg_listelt_value(elt);
const char *path = cfg_obj_asstring(ep);
endpoints[i++] = isc_mem_strdup(mctx, path);
}
} else {
endpoints[i++] = isc_mem_strdup(mctx, "/dns-query");
}
INSIST(i == len);
+1 -2
View File
@@ -151,7 +151,6 @@ TESTS += \
views \
wildcard \
xferquota \
xot \
zonechecks
# eddsa test is broken
@@ -177,7 +176,7 @@ TESTS += \
nsupdate \
resolver \
statistics \
dot \
doth \
upforwd \
zero
+1 -1
View File
@@ -668,7 +668,7 @@ copy_setports() {
atsign="@"
sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \
-e "s/${atsign}TLSPORT${atsign}/${TLSPORT}/g" \
-e "s/${atsign}HTTPPORT${atsign}/${HTTPSPORT}/g" \
-e "s/${atsign}HTTPPORT${atsign}/${HTTPPORT}/g" \
-e "s/${atsign}HTTPSPORT${atsign}/${HTTPSPORT}/g" \
-e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
-e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/g" \
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
rm -f */named.memstats
rm -f */named.run
rm -f */named.conf
rm -f */named.stats*
rm -f dig.out*
rm -f rndc.out*
rm -f ns*/named.lock
rm -f ns*/managed-keys.bind*
-28
View File
@@ -1,28 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
options {
port @PORT@;
tls-port @TLSPORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
listen-on tls ephemeral { 10.53.0.1; };
recursion no;
notify no;
statistics-file "named.stats";
};
zone "." {
type primary;
file "root.db";
allow-transfer { any; };
};
-16
View File
@@ -1,16 +0,0 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. ../conf.sh
$SHELL clean.sh
copy_setports ns1/named.conf.in ns1/named.conf
-41
View File
@@ -1,41 +0,0 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
set -e
# shellcheck source=../conf.sh
. ../conf.sh
dig_dot_with_opts() {
"${DIG}" -p "${TLSPORT}" +tls "$@"
}
status=0
n=0
n=$((n + 1))
echo_i "checking DoT query response ($n)"
ret=0
dig_dot_with_opts @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoT XFR ($n)"
ret=0
dig_dot_with_opts +comment @10.53.0.1 . AXFR > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
@@ -18,4 +18,4 @@ rm -f ./*/named.memstats
rm -f ./*/named.run
rm -f ./*/named.run.prev
rm -f ./dig.out.*
rm -f ./*/*.db
rm -f ./*/example.db
@@ -15,13 +15,21 @@ controls {
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
http local {
endpoints { "/dns-query"; "/alter"; };
};
options {
port @PORT@;
tls-port @TLSPORT@;
https-port @HTTPSPORT@;
http-port @HTTPPORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on tls ephemeral { 10.53.0.1; }; // DoT
listen-on tls ephemeral http local { 10.53.0.1; }; // DoH
listen-on http local { 10.53.0.1; }; // unencrypted DoH
listen-on-v6 { none; };
listen-on tls ephemeral { 10.53.0.1; };
recursion no;
notify explicit;
also-notify { 10.53.0.2 port @PORT@; };
@@ -30,8 +38,9 @@ options {
};
zone "." {
type hint;
file "../../common/root.hint";
type primary;
file "root.db";
allow-transfer { any; };
};
zone "example" {
+14
View File
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICHTCCAcOgAwIBAgIUATq1E48Hj7vAQBwn8H/1oQvqvJ0wCgYIKoZIzj0EAwIw
YzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENp
dHkxDDAKBgNVBAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2Fs
aG9zdDAgFw0yMTAyMTIwMzIxMzFaGA8yMTIxMDExOTAzMjEzMVowYzELMAkGA1UE
BhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDDAKBgNV
BAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMG
ByqGSM49AgEGCCqGSM49AwEHA0IABC1uCviud7QFTJ8DfdrLwjkBolYHJJR9c9HP
bshvKDXahhRU9+HCbWBNLlqFR6aMs8wyE32cXHLZ70XaILkH88SjUzBRMB0GA1Ud
DgQWBBRPpE9aC2MO0TAlCp18vR9vqe4R2TAfBgNVHSMEGDAWgBRPpE9aC2MO0TAl
Cp18vR9vqe4R2TAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIE3L
zx4iRVqjnOACc+/G0Shru+AIk/MEglfrvP5wxZaVAiEArcmut+hYb+cG0UW5ct/U
Q183Kk25XYJkTj39GSBiiiA=
-----END CERTIFICATE-----
+8
View File
@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFBLYPWvhrGBMyfi04oC53LOl00LZRZbVOVnC0K30XOCoAoGCCqGSM49
AwEHoUQDQgAELW4K+K53tAVMnwN92svCOQGiVgcklH1z0c9uyG8oNdqGFFT34cJt
YE0uWoVHpoyzzDITfZxcctnvRdoguQfzxA==
-----END EC PRIVATE KEY-----
@@ -15,17 +15,25 @@ controls {
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
tls local {
key-file "key.pem";
cert-file "cert.pem";
};
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port @PORT@;
tls-port @TLSPORT@;
https-port @HTTPSPORT@;
http-port @HTTPPORT@;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on tls ephemeral { 10.53.0.2; };
listen-on tls local { 10.53.0.2; }; // DoT
listen-on tls local http default { 10.53.0.2; }; // DoH
listen-on http default { 10.53.0.2; }; // unencrypted DoH
listen-on-v6 { none; };
listen-on tls ephemeral { 10.53.0.2; };
recursion no;
notify no;
ixfr-from-differences yes;
+178
View File
@@ -0,0 +1,178 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. ../conf.sh
dig_with_tls_opts() {
"$DIG" +tls +noadd +nosea +nostat +noquest +nocmd -p "${TLSPORT}" "$@"
}
dig_with_https_opts() {
"$DIG" +https +noadd +nosea +nostat +noquest +nocmd -p "${HTTPSPORT}" "$@"
}
dig_with_http_opts() {
"$DIG" +http-plain +noadd +nosea +nostat +noquest +nocmd -p "${HTTPPORT}" "$@"
}
wait_for_tls_xfer() (
dig_with_tls_opts -b 10.53.0.3 @10.53.0.2 example. AXFR > "dig.out.ns2.test$n" || return 1
grep "^;" "dig.out.ns2.test$n" > /dev/null && return 1
return 0
)
status=0
n=0
n=$((n+1))
echo_i "testing XoT server functionality (using dig) ($n)"
ret=0
dig_with_tls_opts example. -b 10.53.0.3 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
grep "^;" dig.out.ns1.test$n | cat_i
digcomp dig1.good dig.out.ns1.test$n || ret=1
if test $ret != 0 ; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "testing incoming XoT functionality (from secondary) ($n)"
ret=0
if retry_quiet 10 wait_for_tls_xfer; then
grep "^;" "dig.out.ns2.test$n" | cat_i
digcomp dig1.good "dig.out.ns2.test$n" || ret=1
else
echo_i "timed out waiting for zone transfer"
ret=1
fi
if test $ret != 0 ; then echo_i "failed"; fi
status=$((status+ret))
n=$((n + 1))
echo_i "checking DoT query (ephemeral key) ($n)"
ret=0
dig_with_tls_opts @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoT query (static key) ($n)"
ret=0
dig_with_tls_opts @10.53.0.2 example SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoT XFR ($n)"
ret=0
dig_with_tls_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (POST) ($n)"
ret=0
dig_with_https_opts @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (POST, static key) ($n)"
ret=0
dig_with_https_opts @10.53.0.2 example SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (POST, nonstandard endpoint) ($n)"
ret=0
dig_with_https_opts +https=/alter @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (POST, undefined endpoint, failure expected) ($n)"
ret=0
dig_with_https_opts +tries=1 +time=1 +https=/fake @10.53.0.1 . SOA > dig.out.test$n
grep "connection timed out" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH XFR (POST) (failure expected) ($n)"
ret=0
dig_with_https_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (GET) ($n)"
ret=0
dig_with_https_opts +https-get @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (GET, static key) ($n)"
ret=0
dig_with_https_opts +https-get @10.53.0.2 example SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (GET, nonstandard endpoint) ($n)"
ret=0
dig_with_https_opts +https-get=/alter @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (GET, undefined endpoint, failure expected) ($n)"
ret=0
dig_with_https_opts +tries=1 +time=1 +https-get=/fake @10.53.0.1 . SOA > dig.out.test$n
grep "connection timed out" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH XFR (GET) (failure expected) ($n)"
ret=0
dig_with_https_opts +https-get +comm @10.53.0.1 . AXFR > dig.out.test$n
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking unencrypted DoH query ($n)"
ret=0
dig_with_http_opts @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking unencrypted DoH XFR (failure expected) ($n)"
ret=0
dig_with_http_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
-50
View File
@@ -1,50 +0,0 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. ../conf.sh
dig_with_opts() {
"$DIG" +tls +noadd +nosea +nostat +noquest +nocomm +nocmd -p "${TLSPORT}" "$@"
}
wait_for_xfer() (
dig_with_opts -b 10.53.0.3 @10.53.0.2 example. AXFR > "dig.out.ns2.test$n" || return 1
grep "^;" "dig.out.ns2.test$n" > /dev/null && return 1
return 0
)
status=0
n=0
n=$((n+1))
echo_i "testing XoT server functionality (using dig) ($n)"
ret=0
dig_with_opts example. -b 10.53.0.3 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
grep "^;" dig.out.ns1.test$n | cat_i
digcomp dig1.good dig.out.ns1.test$n || ret=1
if test $ret != 0 ; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "testing basic incoming XoT functionality (from secondary) ($n)"
ret=0
if retry_quiet 10 wait_for_xfer; then
grep "^;" "dig.out.ns2.test$n" | cat_i
digcomp dig1.good "dig.out.ns2.test$n" || ret=1
else
echo_i "timed out waiting for zone transfer"
ret=1
fi
if test $ret != 0 ; then echo_i "failed"; fi
status=$((status+ret))
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
+19 -13
View File
@@ -2468,16 +2468,22 @@ DNS queries on port 53 of all IPv6 interfaces.
If a TLS configuration is specified, ``named`` will listen for DNS-over-TLS
(DoT) connections, using the key and certificate specified in the
referenced ``tls`` statement.
referenced ``tls`` statement. If the name ``ephemeral`` is used,
an ephemeral key and certificate created for the currently running
``named`` process will be used.
If an HTTP configuration is specified, ``named`` will listen for
DNS-over-HTTPS (DoH) connections using the HTTP endpoint specified in the
referenced ``http`` statement. Normally, ``http`` and ``tls``
configurations will be used together, but ``tls`` may be omitted if
encryption is being handled by external software.
referenced ``http`` statement. If the name ``default`` is used, then
``named`` will listen on the default endpoing, ``/dns-query``.
Normally, ``http`` and ``tls`` configurations will be used together, but
``tls`` may be omitted if encryption is being handled by external software.
If a port number is not specified, the default is 53 for standard DNS, 853
for DNS-over-TLS, and 443 for DNS-over-HTTPS.
for DNS-over-TLS, 443 for DNS-over-HTTPS, and 80 for unencrypted HTTP.
These defaults may be overridden using the ``port``, ``tls-port``,
``https-port`` and ``http-port`` options.
Multiple ``listen-on`` statements are allowed. For example:
@@ -2492,11 +2498,10 @@ The first two lines instruct the name server to listen for standard DNS
queries on port 53 of the IP address 5.6.7.8 and on port 1234 of an address
on the machine in net 1.2 that is not 1.2.3.4. The third line instructs the
server to listen for DNS-over-TLS connections on port 8853 of the IP
address 4.3.2.1 using an ephemeral TLS key and certificate created for the
currently running ``named`` process. The fourth line enables DNS-over-HTTPS
connections on port 8453 of address 8.7.6.5, using the same ephemeral
key and certificate, and the HTTP endpoint or endpoints configured in
an ``http`` statement with the name ``myserver``.
address 4.3.2.1 using the ephemeral key and certifcate. The fourth line
enables DNS-over-HTTPS connections on port 8453 of address 8.7.6.5, using
the ephemeral key and certificate, and the HTTP endpoint or endpoints
configured in an ``http`` statement with the name ``myserver``.
Multiple ``listen-on-v6`` options can be used. For example:
@@ -2505,7 +2510,7 @@ Multiple ``listen-on-v6`` options can be used. For example:
listen-on-v6 { any; };
listen-on-v6 port 1234 { !2001:db8::/32; any; };
listen-on port 8853 tls example-tls { 2001:db8::100; };
listen-on port 8453 tls example-tls http myserver { 2001:db8::100; };
listen-on port 8453 tls example-tls http default { 2001:db8::100; };
listen-on port 8000 http myserver { 2001:db8::100; };
The first two lines instruct the name server to listen for standard DNS
@@ -2515,9 +2520,10 @@ instructs the server to listen for for DNS-over-TLS connections on port
8853 of the address 2001:db8::100, using a TLS key and certificate specified
in the a ``tls`` statement with the name ``example-tls``. The fourth
instructs the server to listen for DNS-over-HTTPS connections, again using
``example-tls``, on the HTTP endpoint specified in ``http myserver``. The
``example-tls``, on the default HTTP endpoint. The
fifth line, in which the ``tls`` parameter is omitted, instructs the server
to listen for *unencrypted* DNS queries over HTTP.
to listen for *unencrypted* DNS queries over HTTP, on the endpoint
specified in ``myserver``.
To instruct the server not to listen on any IPv6 addresses, use:
+3 -31
View File
@@ -506,45 +506,17 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
* 'cb'.
*/
typedef void (*isc_nm_http_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *data, void *cbarg);
/*%<
* Callback function to be used when receiving an HTTP request.
*
* 'handle' the handle that can be used to send back the answer.
* 'eresult' the result of the event.
* 'data' contains the received data, if any. It will be freed
* after return by caller.
* 'cbarg' the callback argument passed to listen function.
*/
isc_result_t
isc_nm_http_connect_send_request(isc_nm_t *mgr, const char *uri, bool POST,
isc_region_t *message, isc_nm_recv_cb_t cb,
void *cbarg, isc_tlsctx_t *ctx,
unsigned int timeout);
isc_result_t
isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg,
isc_tlsctx_t *ctx, unsigned int timeout,
isc_tlsctx_t *ctx, bool free_ctx, unsigned int timeout,
size_t extrahandlesize);
isc_result_t
isc_nm_httprequest(isc_nmhandle_t *handle, isc_region_t *region,
isc_nm_recv_cb_t reply_cb, void *cbarg);
isc_result_t
isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog,
isc_quota_t *quota, isc_tlsctx_t *ctx,
isc_nmsocket_t **sockp);
isc_result_t
isc_nm_http_add_endpoint(isc_nmsocket_t *sock, const char *uri,
isc_nm_http_cb_t cb, void *cbarg,
size_t extrahandlesize);
isc_result_t
isc_nm_http_add_doh_endpoint(isc_nmsocket_t *sock, const char *uri,
isc_nm_recv_cb_t cb, void *cbarg,
size_t extrahandlesize);
isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
void *cbarg, size_t extrahandlesize);
+50 -11
View File
@@ -14,41 +14,80 @@
#include <isc/mem.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/tls.h>
#include <isc/types.h>
typedef struct ssl_ctx_st isc_tlsctx_t;
typedef struct ssl_st isc_tls_t;
void
isc_tls_initialize(void);
void
isc_tls_destroy(void);
/*%<
* Set up/tear down the crypto system for TLS.
*/
void
isc_tlsctx_free(isc_tlsctx_t **ctpx);
/*%
* Free the TLS client/server context.
/*%<
* Free a TLS client or server context.
*
* Require:
* Requires:
*\li 'ctxp' != NULL and '*ctxp' != NULL.
*/
isc_result_t
isc_tlsctx_createserver(const char *keyfile, const char *certfile,
isc_tlsctx_t **ctxp);
/*%
* Set up TLS server context.
/*%<
* Set up a TLS server context, using the key and certificate specified in
* 'keyfile' and 'certfile', or a self-generated ephemeral key and
* certificdate if both 'keyfile' and 'certfile' are NULL.
*
* Require:
* Requires:
*\li 'ctxp' != NULL and '*ctxp' == NULL.
*\li 'keyfile' and 'certfile' are either both NULL or both non-NULL.
*/
isc_result_t
isc_tlsctx_createclient(isc_tlsctx_t **ctxp);
/*%
* Set up TLS client context.
/*%<
* Set up a TLS client context.
*
* Require:
* Requires:
*\li 'ctxp' != NULL and '*ctxp' == NULL.
*/
isc_tls_t *
isc_tls_create(isc_tlsctx_t *ctx);
/*%<
* Set up the structure to hold data for a new TLS connection.
*
* Requires:
*\li 'ctx' != NULL.
*/
void
isc_tls_free(isc_tls_t **tlsp);
/*%<
* Free a TLS structure.
*
* Requires:
*\li 'tlsp' != NULL and '*tlsp' != NULL.
*/
void
isc_tlsctx_enable_http2client_alpn(isc_tlsctx_t *ctx);
void
isc_tlsctx_enable_http2server_alpn(isc_tlsctx_t *ctx);
/*%<
*
* Enable HTTP/2 Application Layer Protocol Negotation for 'ctx'.
*
* Requires:
*\li 'ctx' is not NULL.
*/
void
isc_tls_get_http2_alpn(isc_tls_t *tls, const unsigned char **alpn,
unsigned int *alpnlen);
+628 -687
View File
File diff suppressed because it is too large Load Diff
+73 -35
View File
@@ -34,6 +34,7 @@
#include <isc/sockaddr.h>
#include <isc/stats.h>
#include <isc/thread.h>
#include <isc/tls.h>
#include <isc/util.h>
#include "uv-compat.h"
@@ -156,8 +157,6 @@ isc__nm_dump_active(isc_nm_t *nm);
#define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock)
#endif
typedef struct isc_nm_http2_session isc_nm_http2_session_t;
/*
* Single network event loop worker.
*/
@@ -195,6 +194,7 @@ typedef struct isc__networker {
atomic_load(&(t)->references) > 0)
typedef void (*isc__nm_closecb)(isc_nmhandle_t *);
typedef struct isc_nm_http_session isc_nm_http_session_t;
struct isc_nmhandle {
int magic;
@@ -210,7 +210,7 @@ struct isc_nmhandle {
isc_nmsocket_t *sock;
size_t ah_pos; /* Position in the socket's 'active handles' array */
isc_nm_http2_session_t *httpsession;
isc_nm_http_session_t *httpsession;
isc_sockaddr_t peer;
isc_sockaddr_t local;
@@ -302,20 +302,18 @@ typedef enum isc__netievent_type {
typedef union {
isc_nm_recv_cb_t recv;
isc_nm_http_cb_t http;
isc_nm_cb_t send;
isc_nm_cb_t connect;
isc_nm_accept_cb_t accept;
} isc__nm_cb_t;
typedef struct isc_nm_http2_server_handler isc_nm_http2_server_handler_t;
struct isc_nm_http2_server_handler {
typedef struct isc_nm_httphandler isc_nm_httphandler_t;
struct isc_nm_httphandler {
char *path;
isc_nm_http_cb_t cb;
isc_nm_recv_cb_t cb;
void *cbarg;
size_t extrahandlesize;
LINK(isc_nm_http2_server_handler_t) link;
LINK(isc_nm_httphandler_t) link;
};
/*
@@ -674,7 +672,7 @@ typedef enum isc_nmsocket_type {
isc_nm_tlsdnslistener,
isc_nm_tlsdnssocket,
isc_nm_httplistener,
isc_nm_httpstream
isc_nm_httpsocket
} isc_nmsocket_type;
/*%
@@ -710,19 +708,19 @@ typedef enum isc_doh_request_type {
ISC_HTTP_REQ_GET,
ISC_HTTP_REQ_POST,
ISC_HTTP_REQ_UNSUPPORTED
} isc_http2_request_type_t;
} isc_http_request_type_t;
typedef enum isc_http2_scheme_type {
typedef enum isc_http_scheme_type {
ISC_HTTP_SCHEME_HTTP,
ISC_HTTP_SCHEME_HTTP_SECURE,
ISC_HTTP_SCHEME_UNSUPPORTED
} isc_http2_scheme_type_t;
} isc_http_scheme_type_t;
typedef struct isc_nm_http_doh_cbarg {
typedef struct isc_nm_httpcbarg {
isc_nm_recv_cb_t cb;
void *cbarg;
LINK(struct isc_nm_http_doh_cbarg) link;
} isc_nm_http_doh_cbarg_t;
LINK(struct isc_nm_httpcbarg) link;
} isc_nm_httpcbarg_t;
typedef struct isc_nmsocket_h2 {
isc_nmsocket_t *psock; /* owner of the structure */
@@ -730,38 +728,43 @@ typedef struct isc_nmsocket_h2 {
char *query_data;
size_t query_data_len;
bool query_too_large;
isc_nm_http2_server_handler_t *handler;
isc_nm_httphandler_t *handler;
uint8_t *buf;
size_t bufsize;
size_t bufpos;
int32_t stream_id;
isc_nm_http2_session_t *session;
isc_nm_http_session_t *session;
isc_nmsocket_t *httpserver;
isc_http2_request_type_t request_type;
isc_http2_scheme_type_t request_scheme;
isc_http_request_type_t request_type;
isc_http_scheme_type_t request_scheme;
size_t content_length;
char clenbuf[128];
bool content_type_verified;
bool accept_type_verified;
isc_nm_http_cb_t handler_cb;
void *handler_cbarg;
isc_nm_recv_cb_t cb;
void *cbarg;
LINK(struct isc_nmsocket_h2) link;
ISC_LIST(isc_nm_http2_server_handler_t) handlers;
ISC_LIST(isc_nm_http_doh_cbarg_t) handlers_cbargs;
isc_rwlock_t handlers_lock;
ISC_LIST(isc_nm_httphandler_t) handlers;
ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs;
isc_rwlock_t lock;
char response_content_length_str[128];
struct isc_nmsocket_h2_connect_data {
struct {
char *uri;
bool post;
bool free_tlsctx;
isc_tlsctx_t *tlsctx;
void *cstream;
} connect;
} isc_nmsocket_h2_t;
struct isc_nmsocket {
/*% Unlocked, RO */
int magic;
@@ -778,8 +781,8 @@ struct isc_nmsocket {
/*% TLS stuff */
struct tls {
SSL *ssl;
SSL_CTX *ctx;
isc_tls_t *tls;
isc_tlsctx_t *ctx;
BIO *app_rbio;
BIO *app_wbio;
BIO *ssl_rbio;
@@ -802,10 +805,12 @@ struct isc_nmsocket {
struct tlsstream {
bool server;
BIO *app_bio;
SSL *ssl;
SSL_CTX *ctx;
isc_tls_t *tls;
isc_tlsctx_t *ctx;
BIO *ssl_bio;
isc_nmsocket_t *tlslistener;
bool connect_from_networker;
atomic_bool result_updated;
enum {
TLS_INIT,
TLS_HANDSHAKE,
@@ -1149,11 +1154,15 @@ isc__nmsocket_clearcb(isc_nmsocket_t *sock);
void
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
isc_result_t eresult);
void
isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
isc_result_t eresult);
void
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0);
/*%<
* Issue a connect callback on the socket, used to call the callback
*/
void
@@ -1518,19 +1527,42 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock);
void
isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
void
isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
/*%<
* Set the read timeout and reset the timer for the socket
* associated with 'handle', and the TCP socket it wraps
* around.
*/
void
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
void
isc__nm_http_clear_handlers(isc_nmsocket_t *sock);
isc__nm_http_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
/*%<
* Set the read timeout and reset the timer for the socket
* associated with 'handle', and the TLS/TCP socket it wraps
* around.
*/
void
isc__nm_http_clear_session(isc_nmsocket_t *sock);
isc__nm_http_initsocket(isc_nmsocket_t *sock);
void
isc__nm_http_cleanup_data(isc_nmsocket_t *sock);
isc_result_t
isc__nm_http_request(isc_nmhandle_t *handle, isc_region_t *region,
isc_nm_recv_cb_t reply_cb, void *cbarg);
void
isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region,
isc_nm_cb_t cb, void *cbarg);
void
isc__nm_http_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
void
isc__nm_http_close(isc_nmsocket_t *sock);
@@ -1555,6 +1587,12 @@ char *
isc__nm_base64_to_base64url(isc_mem_t *mem, const char *base64,
const size_t base64_len, size_t *res_len);
void
isc__nm_httpsession_attach(isc_nm_http_session_t *source,
isc_nm_http_session_t **targetp);
void
isc__nm_httpsession_detach(isc_nm_http_session_t **sessionp);
#define isc__nm_uverr2result(x) \
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
isc_result_t
+46 -67
View File
@@ -1008,33 +1008,7 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
isc_condition_destroy(&sock->cond);
isc_condition_destroy(&sock->scond);
isc__nm_tls_cleanup_data(sock);
if (sock->type == isc_nm_httplistener) {
isc__nm_http_clear_handlers(sock);
isc_rwlock_destroy(&sock->h2.handlers_lock);
}
if (sock->h2.request_path != NULL) {
isc_mem_free(sock->mgr->mctx, sock->h2.request_path);
sock->h2.request_path = NULL;
}
if (sock->h2.query_data != NULL) {
isc_mem_free(sock->mgr->mctx, sock->h2.query_data);
sock->h2.query_data = NULL;
}
if (sock->h2.connect.uri != NULL) {
isc_mem_free(sock->mgr->mctx, sock->h2.connect.uri);
sock->h2.query_data = NULL;
}
if (sock->h2.buf != NULL) {
isc_mem_free(sock->mgr->mctx, sock->h2.buf);
sock->h2.buf = NULL;
}
isc__nm_http_clear_session(sock);
isc__nm_http_cleanup_data(sock);
#ifdef NETMGR_TRACE
LOCK(&sock->mgr->lock);
ISC_LIST_UNLINK(sock->mgr->active_sockets, sock, active_link);
@@ -1149,7 +1123,7 @@ isc___nmsocket_prep_destroy(isc_nmsocket_t *sock FLARG) {
case isc_nm_tlsdnssocket:
isc__nm_tlsdns_close(sock);
return;
case isc_nm_httpstream:
case isc_nm_httpsocket:
isc__nm_http_close(sock);
return;
default:
@@ -1259,7 +1233,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
case isc_nm_tcpdnslistener:
case isc_nm_tlsdnssocket:
case isc_nm_tlsdnslistener:
case isc_nm_httpstream:
case isc_nm_httpsocket:
case isc_nm_httplistener:
if (family == AF_INET) {
sock->statsindex = tcp4statsindex;
@@ -1290,27 +1264,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
atomic_store(&sock->active_child_connections, 0);
if (type == isc_nm_httplistener) {
ISC_LIST_INIT(sock->h2.handlers);
ISC_LIST_INIT(sock->h2.handlers_cbargs);
isc_rwlock_init(&sock->h2.handlers_lock, 0, 1);
}
sock->h2.session = NULL;
sock->h2.httpserver = NULL;
sock->h2.query_data = NULL;
sock->h2.query_data_len = 0;
sock->h2.query_too_large = false;
sock->h2.request_path = NULL;
sock->h2.request_type = ISC_HTTP_REQ_UNSUPPORTED;
sock->h2.request_scheme = ISC_HTTP_SCHEME_UNSUPPORTED;
sock->h2.content_length = 0;
sock->h2.content_type_verified = false;
sock->h2.accept_type_verified = false;
sock->h2.handler_cb = NULL;
sock->h2.handler_cbarg = NULL;
sock->h2.connect.uri = NULL;
sock->h2.buf = NULL;
isc__nm_http_initsocket(sock);
sock->magic = NMSOCK_MAGIC;
}
@@ -1453,8 +1407,9 @@ isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
sock->statichandle = handle;
}
if (sock->type == isc_nm_httpstream) {
handle->httpsession = sock->h2.session;
if (sock->type == isc_nm_httpsocket && sock->h2.session) {
isc__nm_httpsession_attach(sock->h2.session,
&handle->httpsession);
}
return (handle);
@@ -1609,6 +1564,10 @@ nmhandle_detach_cb(isc_nmhandle_t **handlep FLARG) {
sock->statichandle = NULL;
}
if (sock->type == isc_nm_httpsocket && handle->httpsession != NULL) {
isc__nm_httpsession_detach(&handle->httpsession);
}
isc___nmsocket_detach(&sock FLARG_PASS);
}
@@ -1646,6 +1605,12 @@ isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
case isc_nm_tlsdnssocket:
isc__nm_tlsdns_settimeout(handle, timeout);
break;
case isc_nm_tlssocket:
isc__nm_tls_settimeout(handle, timeout);
break;
case isc_nm_httpsocket:
isc__nm_http_settimeout(handle, timeout);
break;
default:
INSIST(0);
ISC_UNREACHABLE();
@@ -1762,7 +1727,7 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
case isc_nm_tlsdnssocket:
isc__nm_tlsdns_send(handle, region, cb, cbarg);
break;
case isc_nm_httpstream:
case isc_nm_httpsocket:
isc__nm_http_send(handle, region, cb, cbarg);
break;
default:
@@ -1798,6 +1763,9 @@ isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
case isc_nm_tlsdnssocket:
isc__nm_tlsdns_read(handle, cb, cbarg);
break;
case isc_nm_httpsocket:
isc__nm_http_read(handle, cb, cbarg);
break;
default:
INSIST(0);
ISC_UNREACHABLE();
@@ -1897,27 +1865,38 @@ isc_nm_stoplistening(isc_nmsocket_t *sock) {
}
}
void
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
isc_result_t eresult) {
static void
nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq, isc_result_t eresult,
bool force_async) {
isc__netievent_connectcb_t *ievent = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(VALID_UVREQ(uvreq));
REQUIRE(VALID_NMHANDLE(uvreq->handle));
if (eresult == ISC_R_SUCCESS) {
isc__netievent_connectcb_t ievent = { .sock = sock,
.req = uvreq,
.result = eresult };
isc__nm_async_connectcb(NULL, (isc__netievent_t *)&ievent);
} else {
isc__netievent_connectcb_t *ievent =
isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
eresult);
ievent = isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
eresult);
if (force_async) {
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
} else {
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
}
void
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
isc_result_t eresult) {
nm_connectcb(sock, uvreq, eresult, false);
}
void
isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
isc_result_t eresult) {
nm_connectcb(sock, uvreq, eresult, true);
}
void
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_connectcb_t *ievent = (isc__netievent_connectcb_t *)ev0;
@@ -2445,8 +2424,8 @@ nmsocket_type_totext(isc_nmsocket_type type) {
return ("isc_nm_tlsdnssocket");
case isc_nm_httplistener:
return ("isc_nm_httplistener");
case isc_nm_httpstream:
return ("isc_nm_httpstream");
case isc_nm_httpsocket:
return ("isc_nm_httpsocket");
default:
INSIST(0);
ISC_UNREACHABLE();
+15 -19
View File
@@ -167,23 +167,6 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
REQUIRE(isc__nm_in_netthread());
REQUIRE(sock->tid == isc_nm_tid());
result = isc__nm_socket(req->peer.type.sa.sa_family, SOCK_STREAM, 0,
&sock->fd);
/*
* The socket() call can fail spuriously on FreeBSD 12, so we need to
* handle the failure early and gracefully.
*/
if (result != ISC_R_SUCCESS) {
atomic_store(&sock->closed, true);
isc__nm_uvreq_t *cbreq = NULL;
cbreq = isc__nm_uvreq_get(sock->mgr, sock);
cbreq->cb.connect = req->cb.connect;
cbreq->cbarg = req->cbarg;
isc_nmhandle_attach(req->handle, &cbreq->handle);
isc__nmsocket_clearcb(sock);
isc__nm_connectcb(sock, cbreq, result);
goto error;
}
result = isc__nm_socket_connectiontimeout(sock->fd,
sock->connect_timeout);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@@ -231,7 +214,7 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
done:
result = isc__nm_uverr2result(r);
error:
LOCK(&sock->lock);
sock->result = result;
SIGNAL(&sock->cond);
@@ -260,7 +243,6 @@ isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(sock->parent == NULL);
REQUIRE(sock->tid == isc_nm_tid());
sock->fd = (uv_os_sock_t)(-1);
result = tcp_connect_direct(sock, req);
if (result != ISC_R_SUCCESS) {
atomic_store(&sock->active, false);
@@ -333,17 +315,31 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
isc_nmsocket_t *sock = NULL;
isc__netievent_tcpconnect_t *ievent = NULL;
isc__nm_uvreq_t *req = NULL;
sa_family_t sa_family;
uv_os_sock_t fd;
REQUIRE(VALID_NM(mgr));
REQUIRE(local != NULL);
REQUIRE(peer != NULL);
sa_family = peer->addr.type.sa.sa_family;
/*
* The socket() call can fail spuriously on FreeBSD 12, so we need to
* handle the failure early and gracefully.
*/
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &fd);
if (result != ISC_R_SUCCESS) {
return (result);
}
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
isc__nmsocket_init(sock, mgr, isc_nm_tcpsocket, local);
sock->extrahandlesize = extrahandlesize;
sock->connect_timeout = timeout;
sock->result = ISC_R_DEFAULT;
sock->fd = fd;
atomic_init(&sock->client, true);
req = isc__nm_uvreq_get(mgr, sock);
+30 -31
View File
@@ -338,8 +338,8 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
}
sock->tls.state = TLS_STATE_NONE;
sock->tls.ssl = SSL_new(sock->tls.ctx);
RUNTIME_CHECK(sock->tls.ssl != NULL);
sock->tls.tls = isc_tls_create(sock->tls.ctx);
RUNTIME_CHECK(sock->tls.tls != NULL);
/*
*
@@ -359,13 +359,13 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
* may be necessary to increment the number of references available
* using BIO_up_ref(3) before calling the set0 functions.
*/
SSL_set0_rbio(sock->tls.ssl, sock->tls.ssl_rbio);
SSL_set0_wbio(sock->tls.ssl, sock->tls.ssl_wbio);
SSL_set0_rbio(sock->tls.tls, sock->tls.ssl_rbio);
SSL_set0_wbio(sock->tls.tls, sock->tls.ssl_wbio);
#else
SSL_set_bio(sock->tls.ssl, sock->tls.ssl_rbio, sock->tls.ssl_wbio);
SSL_set_bio(sock->tls.tls, sock->tls.ssl_rbio, sock->tls.ssl_wbio);
#endif
SSL_set_connect_state(sock->tls.ssl);
SSL_set_connect_state(sock->tls.tls);
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@@ -781,7 +781,7 @@ isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
return;
}
rv = SSL_shutdown(sock->tls.ssl);
rv = SSL_shutdown(sock->tls.tls);
if (rv == 1) {
sock->tls.state = TLS_STATE_NONE;
@@ -801,7 +801,7 @@ isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
return;
}
err = SSL_get_error(sock->tls.ssl, rv);
err = SSL_get_error(sock->tls.tls, rv);
switch (err) {
case SSL_ERROR_WANT_READ:
@@ -1166,9 +1166,9 @@ tls_cycle_input(isc_nmsocket_t *sock) {
size_t len;
for (;;) {
(void)SSL_peek(sock->tls.ssl, &(char){ '\0' }, 0);
(void)SSL_peek(sock->tls.tls, &(char){ '\0' }, 0);
int pending = SSL_pending(sock->tls.ssl);
int pending = SSL_pending(sock->tls.tls);
if (pending > TLS_BUF_SIZE) {
pending = TLS_BUF_SIZE;
}
@@ -1178,7 +1178,7 @@ tls_cycle_input(isc_nmsocket_t *sock) {
}
len = 0;
rv = SSL_read_ex(sock->tls.ssl,
rv = SSL_read_ex(sock->tls.tls,
sock->buf + sock->buf_len,
sock->buf_size - sock->buf_len, &len);
if (rv != 1) {
@@ -1195,11 +1195,11 @@ tls_cycle_input(isc_nmsocket_t *sock) {
process_sock_buffer(sock);
}
} else if (!SSL_is_init_finished(sock->tls.ssl)) {
if (SSL_is_server(sock->tls.ssl)) {
rv = SSL_accept(sock->tls.ssl);
} else if (!SSL_is_init_finished(sock->tls.tls)) {
if (SSL_is_server(sock->tls.tls)) {
rv = SSL_accept(sock->tls.tls);
} else {
rv = SSL_connect(sock->tls.ssl);
rv = SSL_connect(sock->tls.tls);
}
} else {
@@ -1207,13 +1207,13 @@ tls_cycle_input(isc_nmsocket_t *sock) {
}
if (rv <= 0) {
err = SSL_get_error(sock->tls.ssl, rv);
err = SSL_get_error(sock->tls.tls, rv);
}
switch (err) {
case SSL_ERROR_WANT_READ:
if (sock->tls.state == TLS_STATE_NONE &&
!SSL_is_init_finished(sock->tls.ssl)) {
!SSL_is_init_finished(sock->tls.tls)) {
sock->tls.state = TLS_STATE_HANDSHAKE;
start_reading(sock);
}
@@ -1236,11 +1236,11 @@ tls_cycle_input(isc_nmsocket_t *sock) {
/* Stop state after handshake */
if (sock->tls.state == TLS_STATE_HANDSHAKE &&
SSL_is_init_finished(sock->tls.ssl))
SSL_is_init_finished(sock->tls.tls))
{
sock->tls.state = TLS_STATE_IO;
if (SSL_is_server(sock->tls.ssl)) {
if (SSL_is_server(sock->tls.tls)) {
REQUIRE(sock->recv_handle != NULL);
result = sock->accept_cb(sock->recv_handle,
ISC_R_SUCCESS,
@@ -1655,8 +1655,8 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
csock->tls.state = TLS_STATE_NONE;
csock->tls.ssl = SSL_new(ssock->tls.ctx);
RUNTIME_CHECK(csock->tls.ssl != NULL);
csock->tls.tls = isc_tls_create(ssock->tls.ctx);
RUNTIME_CHECK(csock->tls.tls != NULL);
r = BIO_new_bio_pair(&csock->tls.ssl_wbio, TLS_BUF_SIZE,
&csock->tls.app_rbio, TLS_BUF_SIZE);
@@ -1673,13 +1673,13 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
* may be necessary to increment the number of references available
* using BIO_up_ref(3) before calling the set0 functions.
*/
SSL_set0_rbio(csock->tls.ssl, csock->tls.ssl_rbio);
SSL_set0_wbio(csock->tls.ssl, csock->tls.ssl_wbio);
SSL_set0_rbio(csock->tls.tls, csock->tls.ssl_rbio);
SSL_set0_wbio(csock->tls.tls, csock->tls.ssl_wbio);
#else
SSL_set_bio(csock->tls.ssl, csock->tls.ssl_rbio, csock->tls.ssl_wbio);
SSL_set_bio(csock->tls.tls, csock->tls.ssl_rbio, csock->tls.ssl_wbio);
#endif
SSL_set_accept_state(csock->tls.ssl);
SSL_set_accept_state(csock->tls.tls);
/* FIXME: Set SSL_MODE_RELEASE_BUFFERS */
@@ -1812,7 +1812,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
}
/* Writes won't succeed until handshake end */
if (!SSL_is_init_finished(sock->tls.ssl)) {
if (!SSL_is_init_finished(sock->tls.tls)) {
goto requeue;
}
@@ -1826,7 +1826,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
memmove(worker->sendbuf + sizeof(uint16_t), req->uvbuf.base,
req->uvbuf.len);
rv = SSL_write_ex(sock->tls.ssl, worker->sendbuf, sendlen, &bytes);
rv = SSL_write_ex(sock->tls.tls, worker->sendbuf, sendlen, &bytes);
if (rv > 0) {
/* SSL_write_ex() doesn't do partial writes */
INSIST(sendlen == bytes);
@@ -1837,7 +1837,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
}
/* Nothing was written, maybe enqueue? */
err = SSL_get_error(sock->tls.ssl, rv);
err = SSL_get_error(sock->tls.tls, rv);
switch (err) {
case SSL_ERROR_WANT_WRITE:
@@ -1910,9 +1910,8 @@ tlsdns_close_cb(uv_handle_t *handle) {
atomic_store(&sock->connected, false);
if (sock->tls.ssl) {
SSL_free(sock->tls.ssl);
sock->tls.ssl = NULL;
if (sock->tls.tls != NULL) {
isc_tls_free(&sock->tls.tls);
}
BIO_free_all(sock->tls.app_rbio);
+135 -96
View File
@@ -74,17 +74,34 @@ inactive(isc_nmsocket_t *sock) {
static void
update_result(isc_nmsocket_t *sock, const isc_result_t result) {
LOCK(&sock->lock);
sock->result = result;
SIGNAL(&sock->cond);
if (!atomic_load(&sock->active)) {
WAIT(&sock->scond, &sock->lock);
if (!atomic_load(&sock->tlsstream.result_updated)) {
atomic_store(&sock->tlsstream.result_updated, true);
if (!sock->tlsstream.server) {
LOCK(&sock->lock);
sock->result = result;
SIGNAL(&sock->cond);
while (!atomic_load(&sock->active)) {
WAIT(&sock->scond, &sock->lock);
}
UNLOCK(&sock->lock);
} else {
LOCK(&sock->lock);
sock->result = result;
UNLOCK(&sock->lock);
}
}
UNLOCK(&sock->lock);
if (sock->parent) {
LOCK(&sock->parent->lock);
sock->parent->result = result;
UNLOCK(&sock->parent->lock);
}
static void
tls_call_connect_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
const isc_result_t result) {
if (sock->connect_cb == NULL) {
return;
}
sock->connect_cb(handle, result, sock->connect_cbarg);
update_result(sock, result);
if (result != ISC_R_SUCCESS) {
isc__nmsocket_clearcb(handle->sock);
}
}
@@ -93,6 +110,7 @@ tls_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
isc_nmsocket_tls_send_req_t *send_req =
(isc_nmsocket_tls_send_req_t *)cbarg;
isc_nmsocket_t *sock = send_req->tlssock;
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
REQUIRE(VALID_NMSOCK(sock));
@@ -103,9 +121,10 @@ tls_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
isc_mem_put(handle->sock->mgr->mctx, send_req->data.base,
send_req->data.length);
isc_mem_put(handle->sock->mgr->mctx, send_req, sizeof(*send_req));
sock->tlsstream.nsending--;
async_tls_do_bio(sock);
isc__nmsocket_detach(&sock);
}
@@ -121,9 +140,7 @@ tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
{
INSIST(handle == NULL);
handle = isc__nmhandle_get(sock, NULL, NULL);
sock->connect_cb(handle, result, sock->connect_cbarg);
update_result(sock, result);
isc__nmsocket_clearcb(sock);
tls_call_connect_cb(sock, handle, result);
isc_nmhandle_detach(&handle);
} else if (sock->recv_cb != NULL) {
isc__nm_uvreq_t *req = NULL;
@@ -131,7 +148,7 @@ tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
req->cb.recv = sock->recv_cb;
req->cbarg = sock->recv_cbarg;
req->handle = NULL;
if (handle) {
if (handle != NULL) {
REQUIRE(VALID_NMHANDLE(handle));
isc_nmhandle_attach(handle, &req->handle);
} else {
@@ -158,9 +175,10 @@ async_tls_do_bio(isc_nmsocket_t *sock) {
static void
tls_do_bio(isc_nmsocket_t *sock) {
isc_result_t result = ISC_R_SUCCESS;
isc__nm_uvreq_t *req = NULL;
int pending, tls_err = 0;
int rv;
isc__nm_uvreq_t *req;
char buf[1];
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
@@ -172,7 +190,7 @@ tls_do_bio(isc_nmsocket_t *sock) {
}
if (sock->tlsstream.state == TLS_INIT) {
(void)SSL_do_handshake(sock->tlsstream.ssl);
(void)SSL_do_handshake(sock->tlsstream.tls);
sock->tlsstream.state = TLS_HANDSHAKE;
} else if (sock->tlsstream.state == TLS_ERROR) {
result = ISC_R_FAILURE;
@@ -182,24 +200,27 @@ tls_do_bio(isc_nmsocket_t *sock) {
}
/* Data from TLS to client */
char buf[1];
if (sock->tlsstream.state == TLS_IO && sock->recv_cb != NULL &&
!atomic_load(&sock->readpaused))
{
(void)SSL_peek(sock->tlsstream.ssl, buf, 1);
while ((pending = SSL_pending(sock->tlsstream.ssl)) > 0) {
(void)SSL_peek(sock->tlsstream.tls, buf, 1);
while ((pending = SSL_pending(sock->tlsstream.tls)) > 0) {
isc_region_t region, dregion;
if (pending > TLS_BUF_SIZE) {
pending = TLS_BUF_SIZE;
}
isc_region_t region = {
isc_mem_get(sock->mgr->mctx, pending), pending
region = (isc_region_t){
.base = isc_mem_get(sock->mgr->mctx, pending),
.length = pending
};
isc_region_t dregion;
memset(region.base, 0, region.length);
rv = SSL_read(sock->tlsstream.ssl, region.base,
rv = SSL_read(sock->tlsstream.tls, region.base,
region.length);
/* Pending succeded, so should read */
RUNTIME_CHECK(rv == pending);
dregion = (isc_region_t){ region.base, rv };
sock->recv_cb(sock->statichandle, ISC_R_SUCCESS,
&dregion, sock->recv_cbarg);
@@ -209,12 +230,12 @@ tls_do_bio(isc_nmsocket_t *sock) {
}
/* Peek to move the session forward */
(void)SSL_peek(sock->tlsstream.ssl, buf, 1);
(void)SSL_peek(sock->tlsstream.tls, buf, 1);
/* Data from TLS to network */
pending = BIO_pending(sock->tlsstream.app_bio);
if (pending > 0) {
/*TODO Should we keep the track of these requests in a list? */
/* TODO Should we keep track of these requests in a list? */
isc_nmsocket_tls_send_req_t *send_req = NULL;
if (pending > TLS_BUF_SIZE) {
pending = TLS_BUF_SIZE;
@@ -236,15 +257,14 @@ tls_do_bio(isc_nmsocket_t *sock) {
}
/* Get the potential error code */
rv = SSL_peek(sock->tlsstream.ssl, buf, 1);
rv = SSL_peek(sock->tlsstream.tls, buf, 1);
if (rv < 0) {
tls_err = SSL_get_error(sock->tlsstream.ssl, rv);
tls_err = SSL_get_error(sock->tlsstream.tls, rv);
}
/* Only after doing the IO we can check if SSL handshake is done */
if (sock->tlsstream.state == TLS_HANDSHAKE &&
SSL_is_init_finished(sock->tlsstream.ssl) == 1)
SSL_is_init_finished(sock->tlsstream.tls) == 1)
{
isc_nmhandle_t *tlshandle = isc__nmhandle_get(sock, NULL, NULL);
if (sock->tlsstream.server) {
@@ -252,9 +272,7 @@ tls_do_bio(isc_nmsocket_t *sock) {
ISC_R_SUCCESS,
sock->listener->accept_cbarg);
} else {
sock->connect_cb(tlshandle, ISC_R_SUCCESS,
sock->connect_cbarg);
update_result(tlshandle->sock, ISC_R_SUCCESS);
tls_call_connect_cb(sock, tlshandle, ISC_R_SUCCESS);
}
isc_nmhandle_detach(&tlshandle);
sock->tlsstream.state = TLS_IO;
@@ -287,7 +305,7 @@ tls_do_bio(isc_nmsocket_t *sock) {
while ((req = ISC_LIST_HEAD(sock->tlsstream.sends)) != NULL) {
INSIST(VALID_UVREQ(req));
rv = SSL_write(sock->tlsstream.ssl, req->uvbuf.base,
rv = SSL_write(sock->tlsstream.tls, req->uvbuf.base,
req->uvbuf.len);
if (rv < 0) {
if (sock->tlsstream.nsending == 0) {
@@ -302,9 +320,7 @@ tls_do_bio(isc_nmsocket_t *sock) {
{
isc_nmhandle_t *tlshandle =
isc__nmhandle_get(sock, NULL, NULL);
sock->connect_cb(tlshandle, result,
sock->connect_cbarg);
update_result(tlshandle->sock, result);
tls_call_connect_cb(sock, tlshandle, result);
isc_nmhandle_detach(&tlshandle);
}
sock->tlsstream.state = TLS_ERROR;
@@ -326,9 +342,7 @@ low_level_error:
if (sock->tlsstream.state == TLS_HANDSHAKE) {
isc_nmhandle_t *tlshandle = isc__nmhandle_get(sock, NULL, NULL);
if (!sock->tlsstream.server) {
sock->connect_cb(tlshandle, result,
sock->connect_cbarg);
update_result(tlshandle->sock, result);
tls_call_connect_cb(sock, tlshandle, result);
}
isc_nmhandle_detach(&tlshandle);
} else if (sock->tlsstream.state == TLS_IO) {
@@ -367,7 +381,6 @@ tls_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
}
rv = BIO_write(tlssock->tlsstream.app_bio, region->base,
region->length);
if (rv != (int)region->length) {
/* XXXWPK log it? */
tlssock->tlsstream.state = TLS_ERROR;
@@ -382,16 +395,16 @@ initialize_tls(isc_nmsocket_t *sock, bool server) {
if (BIO_new_bio_pair(&(sock->tlsstream.ssl_bio), TLS_BUF_SIZE,
&(sock->tlsstream.app_bio), TLS_BUF_SIZE) != 1)
{
SSL_free(sock->tlsstream.ssl);
isc_tls_free(&sock->tlsstream.tls);
return (ISC_R_TLSERROR);
}
SSL_set_bio(sock->tlsstream.ssl, sock->tlsstream.ssl_bio,
SSL_set_bio(sock->tlsstream.tls, sock->tlsstream.ssl_bio,
sock->tlsstream.ssl_bio);
if (server) {
SSL_set_accept_state(sock->tlsstream.ssl);
SSL_set_accept_state(sock->tlsstream.tls);
} else {
SSL_set_connect_state(sock->tlsstream.ssl);
SSL_set_connect_state(sock->tlsstream.tls);
}
sock->tlsstream.nsending = 0;
isc_nm_read(sock->outerhandle, tls_readcb, sock);
@@ -424,9 +437,9 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
/* We need to initialize SSL now to reference SSL_CTX properly */
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
tlssock->tlsstream.ssl = SSL_new(tlssock->tlsstream.ctx);
tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx);
ISC_LIST_INIT(tlssock->tlsstream.sends);
if (tlssock->tlsstream.ssl == NULL) {
if (tlssock->tlsstream.tls == NULL) {
update_result(tlssock, ISC_R_TLSERROR);
atomic_store(&tlssock->closed, true);
isc__nmsocket_detach(&tlssock);
@@ -474,7 +487,7 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
tlssock->accept_cbarg = accept_cbarg;
tlssock->extrahandlesize = extrahandlesize;
tlssock->tlsstream.ctx = sslctx;
tlssock->tlsstream.ssl = NULL;
tlssock->tlsstream.tls = NULL;
/*
* tlssock will be a TLS 'wrapper' around an unencrypted stream.
@@ -515,20 +528,24 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
void
isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0) {
int rv;
isc__netievent_tlssend_t *ievent = (isc__netievent_tlssend_t *)ev0;
isc_nmsocket_t *sock = ievent->sock;
isc__nm_uvreq_t *req = ievent->req;
ievent->req = NULL;
int rv;
REQUIRE(VALID_UVREQ(req));
REQUIRE(sock->tid == isc_nm_tid());
UNUSED(worker);
ievent->req = NULL;
if (inactive(sock)) {
req->cb.send(req->handle, ISC_R_CANCELED, req->cbarg);
isc__nm_uvreq_put(&req, sock);
return;
}
if (!ISC_LIST_EMPTY(sock->tlsstream.sends)) {
/* We're not the first */
ISC_LIST_APPEND(sock->tlsstream.sends, req, link);
@@ -536,7 +553,7 @@ isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0) {
return;
}
rv = SSL_write(sock->tlsstream.ssl, req->uvbuf.base, req->uvbuf.len);
rv = SSL_write(sock->tlsstream.tls, req->uvbuf.base, req->uvbuf.len);
if (rv < 0) {
/*
* We might need to read, we might need to write, or the
@@ -600,6 +617,7 @@ isc__nm_async_tlsstartread(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_nmsocket_t *sock = ievent->sock;
REQUIRE(sock->tid == isc_nm_tid());
UNUSED(worker);
tls_do_bio(sock);
@@ -607,13 +625,16 @@ isc__nm_async_tlsstartread(isc__networker_t *worker, isc__netievent_t *ev0) {
void
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
REQUIRE(handle->sock->statichandle == handle);
REQUIRE(handle->sock->tid == isc_nm_tid());
isc__netievent_tlsstartread_t *ievent = NULL;
isc_nmsocket_t *sock = handle->sock;
isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
sock = handle->sock;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->statichandle == handle);
REQUIRE(sock->tid == isc_nm_tid());
if (inactive(sock)) {
cb(handle, ISC_R_NOTCONNECTED, NULL, cbarg);
@@ -632,19 +653,17 @@ void
isc__nm_tls_pauseread(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
isc_nmsocket_t *sock = handle->sock;
atomic_store(&sock->readpaused, true);
atomic_store(&handle->sock->readpaused, true);
}
void
isc__nm_tls_resumeread(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
isc_nmsocket_t *sock = handle->sock;
atomic_store(&sock->readpaused, false);
async_tls_do_bio(sock);
atomic_store(&handle->sock->readpaused, false);
async_tls_do_bio(handle->sock);
}
static void
@@ -658,11 +677,6 @@ tls_close_direct(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
/* if (!sock->tlsstream.server) { */
/* INSIST(sock->tlsstream.state != TLS_HANDSHAKE && */
/* sock->tlsstream.state != TLS_INIT); */
/* } */
sock->tlsstream.state = TLS_CLOSING;
if (sock->timer_running) {
@@ -670,7 +684,8 @@ tls_close_direct(isc_nmsocket_t *sock) {
sock->timer_running = false;
}
/* We don't need atomics here, it's all in single network thread
/*
* We don't need atomics here, it's all in single network thread
*/
if (sock->timer_initialized) {
/*
@@ -693,10 +708,9 @@ tls_close_direct(isc_nmsocket_t *sock) {
if (sock->listener != NULL) {
isc__nmsocket_detach(&sock->listener);
}
if (sock->tlsstream.ssl != NULL) {
SSL_free(sock->tlsstream.ssl);
sock->tlsstream.ssl = NULL;
/* These are destroyed when we free SSL* */
if (sock->tlsstream.tls != NULL) {
isc_tls_free(&sock->tlsstream.tls);
/* These are destroyed when we free SSL */
sock->tlsstream.ctx = NULL;
sock->tlsstream.ssl_bio = NULL;
}
@@ -735,6 +749,7 @@ isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_tlsclose_t *ievent = (isc__netievent_tlsclose_t *)ev0;
REQUIRE(ievent->sock->tid == isc_nm_tid());
UNUSED(worker);
tls_close_direct(ievent->sock);
@@ -749,9 +764,8 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
atomic_store(&sock->closed, true);
sock->recv_cb = NULL;
sock->recv_cbarg = NULL;
if (sock->tlsstream.ssl != NULL) {
SSL_free(sock->tlsstream.ssl);
sock->tlsstream.ssl = NULL;
if (sock->tlsstream.tls != NULL) {
isc_tls_free(&sock->tlsstream.tls);
sock->tlsstream.ctx = NULL;
}
@@ -768,6 +782,10 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
isc_nmsocket_t *nsock = NULL, *tsock = NULL;
isc__netievent_tlsconnect_t *ievent = NULL;
isc_result_t result = ISC_R_DEFAULT;
#if defined(NETMGR_TRACE) && defined(NETMGR_TRACE_VERBOSE)
fprintf(stderr, "TLS: isc_nm_tlsconnect(): in net thread: %s\n",
isc__nm_in_netthread() ? "yes" : "no");
#endif /* NETMGR_TRACE */
REQUIRE(VALID_NM(mgr));
@@ -779,6 +797,7 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
nsock->connect_cbarg = cbarg;
nsock->connect_timeout = timeout;
nsock->tlsstream.ctx = ctx;
nsock->tlsstream.connect_from_networker = isc__nm_in_netthread();
ievent = isc__nm_get_netievent_tlsconnect(mgr, nsock);
ievent->local = local->addr;
@@ -815,29 +834,30 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
}
static void
tls_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg;
isc_nmhandle_t *tlshandle = NULL;
REQUIRE(VALID_NMSOCK(tlssock));
REQUIRE(VALID_NMHANDLE(handle));
if (result != ISC_R_SUCCESS) {
tlssock->connect_cb(handle, result, tlssock->connect_cbarg);
update_result(tlssock, result);
tls_close_direct(tlssock);
return;
goto error;
}
INSIST(VALID_NMHANDLE(handle));
tlssock->peer = isc_nmhandle_peeraddr(handle);
isc_nmhandle_attach(handle, &tlssock->outerhandle);
result = initialize_tls(tlssock, false);
if (result != ISC_R_SUCCESS) {
tlssock->connect_cb(handle, result, tlssock->connect_cbarg);
update_result(tlssock, result);
tls_close_direct(tlssock);
return;
goto error;
}
return;
error:
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
atomic_store(&tlssock->closed, true);
tls_call_connect_cb(tlssock, tlshandle, result);
isc_nmhandle_detach(&tlshandle);
tls_close_direct(tlssock);
}
void
@@ -854,8 +874,8 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
/*
* We need to initialize SSL now to reference SSL_CTX properly.
*/
tlssock->tlsstream.ssl = SSL_new(tlssock->tlsstream.ctx);
if (tlssock->tlsstream.ssl == NULL) {
tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx);
if (tlssock->tlsstream.tls == NULL) {
result = ISC_R_TLSERROR;
goto error;
}
@@ -871,18 +891,18 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
result = isc_nm_tcpconnect(worker->mgr, (isc_nmiface_t *)&ievent->local,
(isc_nmiface_t *)&ievent->peer,
tls_connect_cb, tlssock,
tcp_connected, tlssock,
tlssock->connect_timeout, 0);
if (result != ISC_R_SUCCESS) {
goto error;
if (tlssock->tlsstream.connect_from_networker) {
update_result(tlssock, result);
}
return;
error:
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
atomic_store(&tlssock->closed, true);
tlssock->connect_cb(tlshandle, result, tlssock->connect_cbarg);
tls_call_connect_cb(tlssock, tlshandle, result);
isc_nmhandle_detach(&tlshandle);
update_result(tlssock, result);
tls_close_direct(tlssock);
}
@@ -911,26 +931,45 @@ isc__nm_async_tlscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(worker->id == sock->tid);
REQUIRE(sock->tid == isc_nm_tid());
UNUSED(worker);
tls_failed_read_cb(sock, handle, ISC_R_EOF, false);
if (sock->outerhandle) {
if (sock->outerhandle != NULL) {
isc__nm_tcp_cancelread(sock->outerhandle);
}
}
void
isc__nm_async_tlsdobio(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(worker);
isc__netievent_tlsdobio_t *ievent = (isc__netievent_tlsdobio_t *)ev0;
UNUSED(worker);
tls_do_bio(ievent->sock);
}
void
isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
if (sock->tlsstream.tlslistener) {
if (sock->type == isc_nm_tcplistener &&
sock->tlsstream.tlslistener != NULL) {
REQUIRE(VALID_NMSOCK(sock->tlsstream.tlslistener));
isc__nmsocket_detach(&sock->tlsstream.tlslistener);
}
}
void
isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
REQUIRE(handle->sock->type == isc_nm_tlssocket);
sock = handle->sock;
if (sock->outerhandle != NULL) {
INSIST(VALID_NMHANDLE(sock->outerhandle));
isc_nmhandle_settimeout(sock->outerhandle, timeout);
}
}
+109 -102
View File
@@ -72,7 +72,7 @@ static bool reuse_supported = true;
static atomic_bool POST = ATOMIC_VAR_INIT(true);
static atomic_bool use_TLS = ATOMIC_VAR_INIT(false);
static SSL_CTX *server_ssl_ctx = NULL;
static SSL_CTX *server_tlsctx = NULL;
#define NSENDS 100
#define NWRITES 10
@@ -101,6 +101,63 @@ static SSL_CTX *server_ssl_ctx = NULL;
#define X(v)
#endif
typedef struct csdata {
isc_nm_recv_cb_t reply_cb;
void *cb_arg;
isc_region_t region;
} csdata_t;
static void
connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
csdata_t data;
REQUIRE(VALID_NMHANDLE(handle));
memmove(&data, arg, sizeof(data));
isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data));
if (result != ISC_R_SUCCESS) {
goto error;
}
result = isc__nm_http_request(handle, &data.region, data.reply_cb,
data.cb_arg);
if (result != ISC_R_SUCCESS) {
goto error;
}
isc_mem_put(handle->sock->mgr->mctx, data.region.base,
data.region.length);
return;
error:
data.reply_cb(handle, result, NULL, data.cb_arg);
isc_mem_put(handle->sock->mgr->mctx, data.region.base,
data.region.length);
}
static isc_result_t
connect_send_request(isc_nm_t *mgr, const char *uri, bool post,
isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg,
bool tls, unsigned int timeout) {
isc_result_t result;
isc_region_t copy;
csdata_t *data = NULL;
SSL_CTX *ctx = NULL;
copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length),
.length = region->length };
memmove(copy.base, region->base, region->length);
data = isc_mem_get(mgr->mctx, sizeof(*data));
*data = (csdata_t){ .reply_cb = cb, .cb_arg = cbarg, .region = copy };
if (tls) {
isc_tlsctx_createclient(&ctx);
}
result = isc_nm_httpconnect(
mgr, NULL, (isc_nmiface_t *)&tcp_listen_addr, uri, post,
connect_send_cb, data, ctx, true, timeout, 0);
return (result);
}
static int
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
isc_result_t result;
@@ -243,8 +300,8 @@ nm_setup(void **state) {
assert_non_null(nm[i]);
}
server_ssl_ctx = NULL;
isc_tlsctx_createserver(NULL, NULL, &server_ssl_ctx);
server_tlsctx = NULL;
isc_tlsctx_createserver(NULL, NULL, &server_tlsctx);
*state = nm;
@@ -261,8 +318,8 @@ nm_teardown(void **state) {
}
isc_mem_put(test_mctx, nm, MAX_NM * sizeof(nm[0]));
if (server_ssl_ctx) {
isc_tlsctx_free(&server_ssl_ctx);
if (server_tlsctx != NULL) {
isc_tlsctx_free(&server_tlsctx);
}
return (0);
@@ -276,6 +333,7 @@ sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf,
uint16_t port;
char saddr[INET6_ADDRSTRLEN] = { 0 };
int family;
if (sa == NULL || outbuf == NULL || outbuf_len == 0) {
return;
}
@@ -322,7 +380,7 @@ doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
}
atomic_store(&was_error, true);
/* Send failed, we need to stop reading too */
isc_nm_cancelread(handle);
/* isc_nm_cancelread(handle); */
}
}
@@ -382,10 +440,6 @@ mock_doh_uv_tcp_bind(void **state) {
isc_nm_t *listen_nm = nm[0];
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *listen_sock = NULL;
isc_sockaddr_t tcp_connect_addr;
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE);
@@ -404,17 +458,13 @@ doh_noop(void **state) {
isc_nm_t *connect_nm = nm[1];
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *listen_sock = NULL;
isc_sockaddr_t tcp_connect_addr;
char req_url[256];
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr,
0, NULL, NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
noop_read_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
0);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
@@ -422,11 +472,11 @@ doh_noop(void **state) {
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
DOH_PATH);
(void)isc_nm_http_connect_send_request(
(void)connect_send_request(
connect_nm, req_url, atomic_load(&POST),
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
.length = send_msg.len },
noop_read_cb, NULL, NULL, 30000);
noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
isc_nm_closedown(connect_nm);
@@ -455,27 +505,23 @@ doh_noresponse(void **state) {
isc_nm_t *connect_nm = nm[1];
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *listen_sock = NULL;
isc_sockaddr_t tcp_connect_addr;
char req_url[256];
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr,
0, NULL, NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
noop_read_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
0);
assert_int_equal(result, ISC_R_SUCCESS);
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
DOH_PATH);
(void)isc_nm_http_connect_send_request(
(void)connect_send_request(
connect_nm, req_url, atomic_load(&POST),
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
.length = send_msg.len },
noop_read_cb, NULL, NULL, 30000);
noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
@@ -509,7 +555,7 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
size_t i;
atomic_fetch_sub(&nsends, 1);
for (i = 0; i < NWRITES / 2; i++) {
eresult = isc_nm_httprequest(
eresult = isc__nm_http_request(
handle,
&(isc_region_t){
.base = (uint8_t *)send_msg.base,
@@ -535,20 +581,18 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
static isc_threadresult_t
doh_connect_thread(isc_threadarg_t arg) {
isc_nm_t *connect_nm = (isc_nm_t *)arg;
isc_sockaddr_t tcp_connect_addr;
char req_url[256];
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
sizeof(req_url), DOH_PATH);
while (atomic_load(&nsends) > 0) {
(void)isc_nm_http_connect_send_request(
(void)connect_send_request(
connect_nm, req_url, atomic_load(&POST),
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
.length = send_msg.len },
doh_receive_send_reply_cb, NULL, NULL, 5000);
doh_receive_send_reply_cb, NULL, atomic_load(&use_TLS),
30000);
}
return ((isc_threadresult_t)0);
@@ -561,33 +605,26 @@ doh_recv_one(void **state) {
isc_nm_t *connect_nm = nm[1];
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *listen_sock = NULL;
isc_sockaddr_t tcp_connect_addr;
char req_url[256];
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
atomic_store(&nsends, 1);
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
sizeof(req_url), DOH_PATH);
result = isc_nm_http_connect_send_request(
result = connect_send_request(
connect_nm, req_url, atomic_load(&POST),
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
.length = send_msg.len },
doh_receive_reply_cb, NULL, NULL, 5000);
doh_receive_reply_cb, NULL, atomic_load(&use_TLS), 30000);
assert_int_equal(result, ISC_R_SUCCESS);
@@ -657,7 +694,7 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
goto error;
}
result = isc_nm_httprequest(
result = isc__nm_http_request(
handle,
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
.length = send_msg.len },
@@ -666,7 +703,7 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
goto error;
}
result = isc_nm_httprequest(
result = isc__nm_http_request(
handle,
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
.length = send_msg.len },
@@ -674,8 +711,6 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
if (result != ISC_R_SUCCESS) {
goto error;
}
isc_nm_resumeread(handle);
return;
error:
atomic_store(&was_error, true);
@@ -688,31 +723,31 @@ doh_recv_two(void **state) {
isc_nm_t *connect_nm = nm[1];
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *listen_sock = NULL;
isc_sockaddr_t tcp_connect_addr;
char req_url[256];
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
SSL_CTX *ctx = NULL;
atomic_store(&nsends, 2);
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
sizeof(req_url), DOH_PATH);
if (atomic_load(&use_TLS)) {
isc_tlsctx_createclient(&ctx);
}
result = isc_nm_httpconnect(
connect_nm, NULL, NULL, req_url, atomic_load(&POST),
doh_connect_send_two_requests_cb, NULL, NULL, 5000, 0);
connect_nm, NULL, (isc_nmiface_t *)&tcp_listen_addr, req_url,
atomic_load(&POST), doh_connect_send_two_requests_cb, NULL, ctx,
true, 5000, 0);
assert_int_equal(result, ISC_R_SUCCESS);
@@ -783,21 +818,14 @@ doh_recv_send(void **state) {
isc_nmsocket_t *listen_sock = NULL;
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
isc_thread_t threads[32] = { 0 };
isc_sockaddr_t tcp_connect_addr;
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) {
@@ -859,21 +887,14 @@ doh_recv_half_send(void **state) {
isc_nmsocket_t *listen_sock = NULL;
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
isc_thread_t threads[32] = { 0 };
isc_sockaddr_t tcp_connect_addr;
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) {
@@ -940,21 +961,14 @@ doh_half_recv_send(void **state) {
isc_nmsocket_t *listen_sock = NULL;
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
isc_thread_t threads[32] = { 0 };
isc_sockaddr_t tcp_connect_addr;
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) {
@@ -1021,21 +1035,14 @@ doh_half_recv_half_send(void **state) {
isc_nmsocket_t *listen_sock = NULL;
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
isc_thread_t threads[32] = { 0 };
isc_sockaddr_t tcp_connect_addr;
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
result = isc_nm_listenhttp(
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) {
@@ -1625,12 +1632,12 @@ doh_cloudflare(void **state) {
isc_nm_t **nm = (isc_nm_t **)*state;
isc_result_t result = ISC_R_SUCCESS;
result = isc_nm_http_connect_send_request(
result = connect_send_request(
nm[0], "https://cloudflare-dns.com/dns-query",
atomic_load(&POST),
&(isc_region_t){ .base = (uint8_t *)wikipedia_org_A,
.length = sizeof(wikipedia_org_A) },
doh_print_reply_cb, NULL, NULL, 5000);
doh_print_reply_cb, NULL, atomic_load(&use_TLS), 30000);
assert_int_equal(result, ISC_R_SUCCESS);
+112 -8
View File
@@ -9,6 +9,9 @@
* information regarding copyright ownership.
*/
#include <inttypes.h>
#include <nghttp2/nghttp2.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
@@ -162,14 +165,7 @@ isc_tlsctx_createserver(const char *keyfile, const char *certfile,
const SSL_METHOD *method = NULL;
REQUIRE(ctxp != NULL && *ctxp == NULL);
if (ephemeral) {
INSIST(keyfile == NULL);
INSIST(certfile == NULL);
} else {
INSIST(keyfile != NULL);
INSIST(certfile != NULL);
}
REQUIRE((keyfile == NULL) == (certfile == NULL));
method = TLS_server_method();
if (method == NULL) {
@@ -296,3 +292,111 @@ ssl_error:
return (ISC_R_TLSERROR);
}
isc_tls_t *
isc_tls_create(isc_tlsctx_t *ctx) {
REQUIRE(ctx != NULL);
return (SSL_new(ctx));
}
void
isc_tls_free(isc_tls_t **tlsp) {
REQUIRE(tlsp != NULL && *tlsp != NULL);
SSL_free(*tlsp);
*tlsp = NULL;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* NPN TLS extension client callback.
*/
static int
select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg) {
UNUSED(ssl);
UNUSED(arg);
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
return (SSL_TLSEXT_ERR_NOACK);
}
return (SSL_TLSEXT_ERR_OK);
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
void
isc_tlsctx_enable_http2client_alpn(isc_tlsctx_t *ctx) {
REQUIRE(ctx != NULL);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ctx, select_next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)NGHTTP2_PROTO_ALPN,
NGHTTP2_PROTO_ALPN_LEN);
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
}
#ifndef OPENSSL_NO_NEXTPROTONEG
static int
next_proto_cb(isc_tls_t *ssl, const unsigned char **data, unsigned int *len,
void *arg) {
UNUSED(ssl);
UNUSED(arg);
*data = (const unsigned char *)NGHTTP2_PROTO_ALPN;
*len = (unsigned int)NGHTTP2_PROTO_ALPN_LEN;
return (SSL_TLSEXT_ERR_OK);
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
static int
alpn_select_proto_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg) {
int ret;
UNUSED(ssl);
UNUSED(arg);
ret = nghttp2_select_next_protocol((unsigned char **)(uintptr_t)out,
outlen, in, inlen);
if (ret != 1) {
return (SSL_TLSEXT_ERR_NOACK);
}
return (SSL_TLSEXT_ERR_OK);
}
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
void
isc_tlsctx_enable_http2server_alpn(isc_tlsctx_t *tls) {
REQUIRE(tls != NULL);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(tls, next_proto_cb, NULL);
#endif // OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_select_cb(tls, alpn_select_proto_cb, NULL);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
}
void
isc_tls_get_http2_alpn(isc_tls_t *tls, const unsigned char **alpn,
unsigned int *alpnlen) {
REQUIRE(tls != NULL);
REQUIRE(alpn != NULL);
REQUIRE(alpnlen != NULL);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(tls, alpn, alpnlen);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (*alpn == NULL) {
SSL_get0_alpn_selected(tls, alpn, alpnlen);
}
#endif
}
+6 -4
View File
@@ -448,11 +448,8 @@ isc_nm_cancelread
isc_nm_closedown
isc_nm_destroy
isc_nm_detach
isc_nm_http_add_doh_endpoint
isc_nm_http_add_endpoint
isc_nm_http_connect_send_request
isc_nm_http_endpoint
isc_nm_httpconnect
isc_nm_httprequest
isc_nm_listenhttp
isc_nm_listentcpdns
isc_nm_listentls
@@ -706,11 +703,16 @@ isc_timermgr_create
isc_timermgr_createinctx
isc_timermgr_destroy
isc_timermgr_poke
isc_tls_get_http2_alpn
isc_tls_initialize
isc_tls_create
isc_tls_destroy
isc_tls_free
isc_tlsctx_createclient
isc_tlsctx_createserver
isc_tlsctx_free
isc_tlsctx_enable_http2client_alpn
isc_tlsctx_enable_http2server_alpn
isc_tm_timegm
isc_tm_strptime
isc_url_parse
+3 -4
View File
@@ -524,7 +524,6 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"creating TLS socket: %s",
isc_result_totext(result));
isc_tlsctx_free(&sslctx);
return (result);
}
@@ -556,9 +555,9 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
if (result == ISC_R_SUCCESS) {
for (i = 0; i < neps; i++) {
result = isc_nm_http_add_doh_endpoint(
sock, eps[i], ns__client_request, ifp,
sizeof(ns_client_t));
result = isc_nm_http_endpoint(sock, eps[i],
ns__client_request, ifp,
sizeof(ns_client_t));
}
}