Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6889fbf10 | ||
|
|
81340a9ee0 | ||
|
|
bc1b832603 | ||
|
|
16966e5174 | ||
|
|
ba72d6f015 | ||
|
|
37f81ca5fb | ||
|
|
fcb0b6a781 |
@@ -285,6 +285,7 @@ stages:
|
||||
"with-openssl=C:/OpenSSL"
|
||||
"with-libxml2=C:/libxml2"
|
||||
"with-libuv=C:/libuv"
|
||||
"with-nghttp2=C:/nghttp2"
|
||||
"without-python"
|
||||
"with-system-tests"
|
||||
x64'
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
5575. [func] Initial support for DNS-over-HTTP(S). BIND now
|
||||
includes DNS-over-HTTP(S) layer built on top of nghttp2.
|
||||
Both encrypted (via TLS) and unencrypted HTTP/2 connections
|
||||
are supported.
|
||||
|
||||
5574. [func] Incoming zone transfers can now use TLS.
|
||||
Addresses in a "primaries" list take an optional
|
||||
"tls" argument, specifying either a previously
|
||||
|
||||
@@ -367,3 +367,25 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
+39
-2
@@ -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,6 +352,8 @@ 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 {
|
||||
@@ -1412,8 +1418,39 @@ 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':
|
||||
FULLCHECK2("https", "https-get");
|
||||
switch (cmd[5]) {
|
||||
case '\0':
|
||||
FULLCHECK("https");
|
||||
lookup->https_mode = state;
|
||||
if (!lookup->tcp_mode_set) {
|
||||
lookup->tcp_mode = state;
|
||||
}
|
||||
if (value == NULL) {
|
||||
lookup->https_path = isc_mem_strdup(
|
||||
mctx, DEFAULT_HTTPS_PATH);
|
||||
break;
|
||||
}
|
||||
lookup->https_path = isc_mem_strdup(mctx,
|
||||
value);
|
||||
break;
|
||||
case '-':
|
||||
FULLCHECK("https-get");
|
||||
lookup->https_get = true;
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
switch (cmd[1]) {
|
||||
|
||||
+75
-92
@@ -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,11 @@ 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->sendcookie = lookold->sendcookie;
|
||||
looknew->seenbadcookie = lookold->seenbadcookie;
|
||||
looknew->badcookie = lookold->badcookie;
|
||||
@@ -1638,6 +1581,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 +2707,17 @@ 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) {
|
||||
port = 443;
|
||||
} else {
|
||||
port = 53;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "query->servname = %s\n", query->servname);
|
||||
|
||||
result = get_address(query->servname, port, &query->sockaddr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@@ -2835,7 +2792,27 @@ 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 portbuf[12];
|
||||
char uri[4096] = { 0 };
|
||||
snprintf(portbuf, sizeof(portbuf), "%u",
|
||||
(uint16_t)port);
|
||||
|
||||
strlcpy(uri, "https://", sizeof(uri));
|
||||
strlcat(uri, query->servname, sizeof(uri));
|
||||
strlcat(uri, ":", sizeof(uri));
|
||||
strlcat(uri, portbuf, sizeof(uri));
|
||||
strlcat(uri, query->lookup->https_path, sizeof(uri));
|
||||
|
||||
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, local_timeout, 0);
|
||||
check_result(result, "isc_nm_httpconnect");
|
||||
} else {
|
||||
result = isc_nm_tcpdnsconnect(
|
||||
netmgr, (isc_nmiface_t *)&localaddr,
|
||||
@@ -3183,7 +3160,12 @@ launch_next_query(dig_query_t *query) {
|
||||
isc_nmhandle_settimeout(query->handle, local_timeout);
|
||||
|
||||
query_attach(query, &readquery);
|
||||
isc_nm_read(query->handle, recv_done, readquery);
|
||||
if (query->lookup->https_mode) {
|
||||
isc_nm_httprequest(query->handle, &r, recv_done, readquery);
|
||||
goto cleanup;
|
||||
} else {
|
||||
isc_nm_read(query->handle, recv_done, readquery);
|
||||
}
|
||||
|
||||
if (!query->first_soa_rcvd) {
|
||||
dig_query_t *sendquery = NULL;
|
||||
@@ -3211,6 +3193,7 @@ launch_next_query(dig_query_t *query) {
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup:
|
||||
lookup_detach(&l);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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,11 @@ struct dig_lookup {
|
||||
int rrcomments;
|
||||
unsigned int eoferr;
|
||||
uint16_t qid;
|
||||
struct {
|
||||
bool https_mode;
|
||||
bool https_get;
|
||||
char *https_path;
|
||||
};
|
||||
};
|
||||
|
||||
/*% The dig_query structure */
|
||||
|
||||
@@ -94,6 +94,8 @@ options {\n\
|
||||
# pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\
|
||||
port 53;\n\
|
||||
tls-port 853;\n\
|
||||
http-port 80;\n\
|
||||
https-port 443;\n\
|
||||
prefetch 2 9;\n\
|
||||
recursing-file \"named.recursing\";\n\
|
||||
recursive-clients 1000;\n\
|
||||
|
||||
@@ -64,16 +64,18 @@ EXTERN isc_timermgr_t *named_g_timermgr INIT(NULL);
|
||||
EXTERN isc_socketmgr_t *named_g_socketmgr INIT(NULL);
|
||||
EXTERN isc_nm_t *named_g_nm INIT(NULL);
|
||||
EXTERN cfg_parser_t *named_g_parser INIT(NULL);
|
||||
EXTERN cfg_parser_t *named_g_addparser INIT(NULL);
|
||||
EXTERN const char *named_g_version INIT(PACKAGE_VERSION);
|
||||
EXTERN const char *named_g_product INIT(PACKAGE_NAME);
|
||||
EXTERN const char *named_g_description INIT(PACKAGE_DESCRIPTION);
|
||||
EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID);
|
||||
EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS);
|
||||
EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER);
|
||||
EXTERN in_port_t named_g_port INIT(0);
|
||||
EXTERN in_port_t named_g_tlsport INIT(0);
|
||||
EXTERN isc_dscp_t named_g_dscp INIT(-1);
|
||||
EXTERN cfg_parser_t *named_g_addparser INIT(NULL);
|
||||
EXTERN const char *named_g_version INIT(PACKAGE_VERSION);
|
||||
EXTERN const char *named_g_product INIT(PACKAGE_NAME);
|
||||
EXTERN const char *named_g_description INIT(PACKAGE_DESCRIPTION);
|
||||
EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID);
|
||||
EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS);
|
||||
EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER);
|
||||
EXTERN in_port_t named_g_port INIT(0);
|
||||
EXTERN in_port_t named_g_tlsport INIT(0);
|
||||
EXTERN in_port_t named_g_http_secure_port INIT(0);
|
||||
EXTERN in_port_t named_g_http_port INIT(0);
|
||||
EXTERN isc_dscp_t named_g_dscp INIT(-1);
|
||||
|
||||
EXTERN named_server_t *named_g_server INIT(NULL);
|
||||
|
||||
|
||||
+13
-1
@@ -705,7 +705,7 @@ parse_T_opt(char *option) {
|
||||
|
||||
static void
|
||||
parse_port(char *arg) {
|
||||
enum { DNSPORT, TLSPORT } ptype = DNSPORT;
|
||||
enum { DNSPORT, TLSPORT, HTTP_SECURE_PORT, HTTP_PORT } ptype = DNSPORT;
|
||||
char *value = arg;
|
||||
int port;
|
||||
|
||||
@@ -714,6 +714,12 @@ parse_port(char *arg) {
|
||||
} else if (strncmp(arg, "tls=", 4) == 0) {
|
||||
value = arg + 4;
|
||||
ptype = TLSPORT;
|
||||
} else if (strncmp(arg, "https=", 6) == 0) {
|
||||
value = arg + 6;
|
||||
ptype = HTTP_SECURE_PORT;
|
||||
} else if (strncmp(arg, "http=", 5) == 0) {
|
||||
value = arg + 6;
|
||||
ptype = HTTP_PORT;
|
||||
}
|
||||
|
||||
port = parse_int(value, "port");
|
||||
@@ -728,6 +734,12 @@ parse_port(char *arg) {
|
||||
case TLSPORT:
|
||||
named_g_tlsport = port;
|
||||
break;
|
||||
case HTTP_SECURE_PORT:
|
||||
named_g_http_secure_port = port;
|
||||
break;
|
||||
case HTTP_PORT:
|
||||
named_g_http_port = port;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
||||
@@ -86,6 +86,15 @@ DYNDB
|
||||
dyndb string quoted_string {
|
||||
unspecified-text };
|
||||
|
||||
HTTP
|
||||
^^^^
|
||||
|
||||
::
|
||||
|
||||
http string {
|
||||
endpoints { quoted_string; ... }; // experimental
|
||||
};
|
||||
|
||||
KEY
|
||||
^^^
|
||||
|
||||
@@ -264,6 +273,8 @@ OPTIONS
|
||||
glue-cache boolean;// deprecated
|
||||
heartbeat-interval integer;
|
||||
hostname ( quoted_string | none );
|
||||
http-port integer;
|
||||
https-port integer;
|
||||
inline-signing boolean;
|
||||
interface-interval duration;
|
||||
ipv4only-contact string;
|
||||
@@ -275,10 +286,12 @@ OPTIONS
|
||||
key-directory quoted_string;
|
||||
lame-ttl duration;
|
||||
listen-on [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
listen-on-v6 [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
lmdb-mapsize sizeval;
|
||||
lock-file ( quoted_string | none );
|
||||
|
||||
+5
-1
@@ -115,7 +115,11 @@ Options
|
||||
``portnum``; if not not specified, the default is port 53. If
|
||||
``value`` is of the form ``tls=<portnum>``, the server will
|
||||
listen for TLS queries on ``portnum``; the default is 853.
|
||||
|
||||
If ``value`` is of the form ``https=<portnum>``, the server will
|
||||
listen for HTTPS queries on ``portnum``; the default is 443.
|
||||
If ``value`` is of the form ``http=<portnum>``, the server will
|
||||
listen for HTTP queries on ``portnum``; the default is 80.
|
||||
|
||||
``-s``
|
||||
This option writes memory usage statistics to ``stdout`` on exit.
|
||||
|
||||
|
||||
+166
-41
@@ -101,8 +101,10 @@
|
||||
#include <dst/result.h>
|
||||
|
||||
#include <isccfg/grammar.h>
|
||||
#include <isccfg/httpconf.h>
|
||||
#include <isccfg/kaspconf.h>
|
||||
#include <isccfg/namedconf.h>
|
||||
#include <isccfg/tlsconf.h>
|
||||
|
||||
#include <ns/client.h>
|
||||
#include <ns/hooks.h>
|
||||
@@ -397,14 +399,24 @@ fatal(named_server_t *server, const char *msg, isc_result_t result);
|
||||
static void
|
||||
named_server_reload(isc_task_t *task, isc_event_t *event);
|
||||
|
||||
static isc_result_t
|
||||
ns_listenelt_from_http(isc_cfg_http_obj_t *http, isc_cfg_tls_obj_t *tls,
|
||||
in_port_t port, isc_mem_t *mctx,
|
||||
ns_listenelt_t **target);
|
||||
|
||||
static isc_result_t
|
||||
ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx,
|
||||
uint16_t family, ns_listenelt_t **target);
|
||||
uint16_t family, isc_cfg_http_storage_t *http_servers,
|
||||
isc_cfg_tls_data_storage_t *tls_storage,
|
||||
ns_listenelt_t **target);
|
||||
|
||||
static isc_result_t
|
||||
ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx,
|
||||
uint16_t family, ns_listenlist_t **target);
|
||||
uint16_t family, isc_cfg_http_storage_t *http_servers,
|
||||
isc_cfg_tls_data_storage_t *tls_storage,
|
||||
ns_listenlist_t **target);
|
||||
|
||||
static isc_result_t
|
||||
configure_forward(const cfg_obj_t *config, dns_view_t *view,
|
||||
@@ -8505,6 +8517,8 @@ load_configuration(const char *filename, named_server_t *server,
|
||||
unsigned int initial, idle, keepalive, advertised;
|
||||
dns_aclenv_t *env =
|
||||
ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
|
||||
isc_cfg_tls_data_storage_t tls_storage;
|
||||
isc_cfg_http_storage_t http_storage;
|
||||
|
||||
ISC_LIST_INIT(kasplist);
|
||||
ISC_LIST_INIT(viewlist);
|
||||
@@ -8512,6 +8526,9 @@ load_configuration(const char *filename, named_server_t *server,
|
||||
ISC_LIST_INIT(cachelist);
|
||||
ISC_LIST_INIT(altsecrets);
|
||||
|
||||
cfg_tls_storage_init(named_g_mctx, &tls_storage);
|
||||
cfg_http_storage_init(named_g_mctx, &http_storage);
|
||||
|
||||
/* Create the ACL configuration context */
|
||||
if (named_g_aclconfctx != NULL) {
|
||||
cfg_aclconfctx_detach(&named_g_aclconfctx);
|
||||
@@ -8573,6 +8590,19 @@ load_configuration(const char *filename, named_server_t *server,
|
||||
maps[i++] = named_g_defaults;
|
||||
maps[i] = NULL;
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "http-port", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
named_g_http_port = (in_port_t)cfg_obj_asuint32(obj);
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "https-port", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
named_g_http_secure_port = (in_port_t)cfg_obj_asuint32(obj);
|
||||
|
||||
CHECK(cfg_tls_storage_load(config, &tls_storage));
|
||||
CHECK(cfg_http_storage_load(config, &http_storage));
|
||||
|
||||
/*
|
||||
* If bind.keys exists, load it. If "dnssec-validation auto"
|
||||
* is turned on, the root key found there will be used as a
|
||||
@@ -8991,7 +9021,8 @@ load_configuration(const char *filename, named_server_t *server,
|
||||
/* check return code? */
|
||||
(void)ns_listenlist_fromconfig(
|
||||
clistenon, config, named_g_aclconfctx,
|
||||
named_g_mctx, AF_INET, &listenon);
|
||||
named_g_mctx, AF_INET, &http_storage,
|
||||
&tls_storage, &listenon);
|
||||
} else {
|
||||
/*
|
||||
* Not specified, use default.
|
||||
@@ -9019,7 +9050,8 @@ load_configuration(const char *filename, named_server_t *server,
|
||||
/* check return code? */
|
||||
(void)ns_listenlist_fromconfig(
|
||||
clistenon, config, named_g_aclconfctx,
|
||||
named_g_mctx, AF_INET6, &listenon);
|
||||
named_g_mctx, AF_INET6, &http_storage,
|
||||
&tls_storage, &listenon);
|
||||
} else {
|
||||
/*
|
||||
* Not specified, use default.
|
||||
@@ -9780,6 +9812,9 @@ cleanup:
|
||||
isc_task_endexclusive(server->task);
|
||||
}
|
||||
|
||||
cfg_http_storage_uninit(&http_storage);
|
||||
cfg_tls_storage_uninit(&tls_storage);
|
||||
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
|
||||
"load_configuration: %s", isc_result_totext(result));
|
||||
@@ -10987,7 +11022,9 @@ named_server_togglequerylog(named_server_t *server, isc_lex_t *lex) {
|
||||
static isc_result_t
|
||||
ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx,
|
||||
uint16_t family, ns_listenlist_t **target) {
|
||||
uint16_t family, isc_cfg_http_storage_t *http_servers,
|
||||
isc_cfg_tls_data_storage_t *tls_storage,
|
||||
ns_listenlist_t **target) {
|
||||
isc_result_t result;
|
||||
const cfg_listelt_t *element;
|
||||
ns_listenlist_t *dlist = NULL;
|
||||
@@ -11005,7 +11042,8 @@ ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
|
||||
ns_listenelt_t *delt = NULL;
|
||||
const cfg_obj_t *listener = cfg_listelt_value(element);
|
||||
result = ns_listenelt_fromconfig(listener, config, actx, mctx,
|
||||
family, &delt);
|
||||
family, http_servers,
|
||||
tls_storage, &delt);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -11026,14 +11064,18 @@ cleanup:
|
||||
static isc_result_t
|
||||
ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx,
|
||||
uint16_t family, ns_listenelt_t **target) {
|
||||
uint16_t family, isc_cfg_http_storage_t *http_servers,
|
||||
isc_cfg_tls_data_storage_t *tls_storage,
|
||||
ns_listenelt_t **target) {
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *tlsobj, *portobj, *dscpobj;
|
||||
in_port_t port;
|
||||
const cfg_obj_t *tlsobj, *portobj, *dscpobj, *httpobj;
|
||||
in_port_t port = 0;
|
||||
isc_dscp_t dscp = -1;
|
||||
const char *key = NULL, *cert = NULL;
|
||||
bool tls = false;
|
||||
bool tls = false, http = false;
|
||||
ns_listenelt_t *delt = NULL;
|
||||
isc_cfg_http_obj_t *http_server = NULL;
|
||||
isc_cfg_tls_obj_t *tls_cert = NULL;
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
/* XXXWPK TODO be more verbose on failures. */
|
||||
@@ -11042,43 +11084,60 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
||||
if (!strcmp(cfg_obj_asstring(tlsobj), "ephemeral")) {
|
||||
tls = true;
|
||||
} else {
|
||||
const cfg_obj_t *tlsconfigs = NULL;
|
||||
const cfg_listelt_t *element;
|
||||
(void)cfg_map_get(config, "tls", &tlsconfigs);
|
||||
for (element = cfg_list_first(tlsconfigs);
|
||||
element != NULL; element = cfg_list_next(element))
|
||||
{
|
||||
cfg_obj_t *tconfig = cfg_listelt_value(element);
|
||||
const cfg_obj_t *name =
|
||||
cfg_map_getname(tconfig);
|
||||
if (!strcmp(cfg_obj_asstring(name),
|
||||
cfg_obj_asstring(tlsobj))) {
|
||||
tls = true;
|
||||
const cfg_obj_t *keyo = NULL,
|
||||
*certo = NULL;
|
||||
(void)cfg_map_get(tconfig, "key-file",
|
||||
&keyo);
|
||||
if (keyo == NULL) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
(void)cfg_map_get(tconfig, "cert-file",
|
||||
&certo);
|
||||
if (certo == NULL) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
key = cfg_obj_asstring(keyo);
|
||||
cert = cfg_obj_asstring(certo);
|
||||
break;
|
||||
}
|
||||
tls_cert = cfg_tls_storage_find(
|
||||
cfg_obj_asstring(tlsobj), tls_storage);
|
||||
if (tls_cert != NULL) {
|
||||
tls = true;
|
||||
key = tls_cert->key_file;
|
||||
cert = tls_cert->cert_file;
|
||||
INSIST(key != NULL);
|
||||
INSIST(cert != NULL);
|
||||
}
|
||||
}
|
||||
if (!tls) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
httpobj = cfg_tuple_get(listener, "http");
|
||||
if (httpobj != NULL && cfg_obj_isstring(httpobj)) {
|
||||
if (tls && tls_cert == NULL) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
http = true;
|
||||
http_server = cfg_http_find(cfg_obj_asstring(httpobj),
|
||||
http_servers);
|
||||
if (http_server == NULL) {
|
||||
isc_log_write(
|
||||
named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"HTTP(S) server \"%s\" is nowhere to be found",
|
||||
cfg_obj_asstring(httpobj));
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
portobj = cfg_tuple_get(listener, "port");
|
||||
if (!cfg_obj_isuint32(portobj)) {
|
||||
if (tls) {
|
||||
if (http && tls) {
|
||||
if (named_g_http_secure_port != 0) {
|
||||
port = named_g_http_secure_port;
|
||||
} else {
|
||||
result = named_config_getport(
|
||||
config, "https-port", &port);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
} else if (http && !tls) {
|
||||
if (named_g_http_port != 0) {
|
||||
port = named_g_port;
|
||||
} else {
|
||||
result = named_config_getport(
|
||||
config, "http-port", &port);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
} else if (tls) {
|
||||
if (named_g_tlsport != 0) {
|
||||
port = named_g_tlsport;
|
||||
} else {
|
||||
@@ -11122,8 +11181,14 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
||||
dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
|
||||
}
|
||||
|
||||
result = ns_listenelt_create(mctx, port, dscp, NULL, tls, key, cert,
|
||||
&delt);
|
||||
if (http) {
|
||||
INSIST(http_server != NULL);
|
||||
result = ns_listenelt_from_http(http_server, tls_cert, port,
|
||||
mctx, &delt);
|
||||
} else {
|
||||
result = ns_listenelt_create(mctx, port, dscp, NULL, tls, key,
|
||||
cert, &delt);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
@@ -11139,6 +11204,66 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a listen list for HTTP/HTTPS
|
||||
*/
|
||||
static isc_result_t
|
||||
ns_listenelt_from_http(isc_cfg_http_obj_t *http, isc_cfg_tls_obj_t *tls,
|
||||
in_port_t port, isc_mem_t *mctx,
|
||||
ns_listenelt_t **target) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
ns_listenelt_t *delt = NULL;
|
||||
const char *key = NULL, *cert = NULL;
|
||||
char **http_endpoints = NULL;
|
||||
size_t http_endpoints_number;
|
||||
isc_cfg_http_endpoint_t *ep;
|
||||
size_t i = 0;
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
if (tls) {
|
||||
INSIST(tls->key_file != NULL);
|
||||
INSIST(tls->cert_file != NULL);
|
||||
key = tls->key_file;
|
||||
cert = tls->cert_file;
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
port = tls != NULL ? named_g_http_secure_port
|
||||
: named_g_http_port;
|
||||
}
|
||||
|
||||
for (ep = ISC_LIST_HEAD(http->endpoints), i = 0; ep != NULL;
|
||||
ep = ISC_LIST_NEXT(ep, link), i++)
|
||||
;
|
||||
|
||||
INSIST(i > 0);
|
||||
|
||||
http_endpoints_number = i;
|
||||
http_endpoints = isc_mem_allocate(mctx, sizeof(http_endpoints[0]) *
|
||||
http_endpoints_number);
|
||||
for (ep = ISC_LIST_HEAD(http->endpoints), i = 0; ep != NULL;
|
||||
ep = ISC_LIST_NEXT(ep, link), i++)
|
||||
{
|
||||
http_endpoints[i] = isc_mem_strdup(mctx, ep->path);
|
||||
}
|
||||
|
||||
INSIST(i == http_endpoints_number);
|
||||
|
||||
result = ns_listenelt_create_http(mctx, port, named_g_dscp, NULL, key,
|
||||
cert, http_endpoints,
|
||||
http_endpoints_number, &delt);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (delt != NULL) {
|
||||
ns_listenelt_destroy(delt);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
*target = delt;
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
named_server_dumpstats(named_server_t *server) {
|
||||
isc_result_t result;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
tls local-tls {
|
||||
key-file "key.pem";
|
||||
cert-file "cert.pem";
|
||||
};
|
||||
|
||||
http local-http-server {
|
||||
endpoints { "/dns-query"; };
|
||||
};
|
||||
|
||||
options {
|
||||
listen-on { 10.53.0.1; };
|
||||
http-port 80;
|
||||
https-port 443;
|
||||
listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
|
||||
listen-on port 8080 http local-http-server { 10.53.0.1; };
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
tls local-tls {
|
||||
key-file "key.pem";
|
||||
cert-file "cert.pem";
|
||||
};
|
||||
|
||||
options {
|
||||
listen-on port 853 tls local-tls { 10.53.0.1; };
|
||||
};
|
||||
@@ -668,6 +668,8 @@ 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}HTTPSPORT${atsign}/${HTTPSPORT}/g" \
|
||||
-e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
|
||||
-e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/g" \
|
||||
-e "s/${atsign}EXTRAPORT3${atsign}/${EXTRAPORT3}/g" \
|
||||
|
||||
@@ -82,6 +82,8 @@ done
|
||||
|
||||
echo "export PORT=$(get_port "$baseport")"
|
||||
echo "export TLSPORT=$(get_port)"
|
||||
echo "export HTTPPORT=$(get_port)"
|
||||
echo "export HTTPSPORT=$(get_port)"
|
||||
echo "export EXTRAPORT1=$(get_port)"
|
||||
echo "export EXTRAPORT2=$(get_port)"
|
||||
echo "export EXTRAPORT3=$(get_port)"
|
||||
|
||||
@@ -149,7 +149,7 @@ stop_servers() {
|
||||
echostart "S:$systest:$(date_with_args)"
|
||||
echoinfo "T:$systest:1:A"
|
||||
echoinfo "A:$systest:System test $systest"
|
||||
echoinfo "I:$systest:PORTS:${PORT},${TLSPORT},${EXTRAPORT1},${EXTRAPORT2},${EXTRAPORT3},${EXTRAPORT4},${EXTRAPORT5},${EXTRAPORT6},${EXTRAPORT7},${EXTRAPORT8},${CONTROLPORT}"
|
||||
echoinfo "I:$systest:PORTS:${PORT},${TLSPORT},${HTTPPORT},${HTTPSPORT},${EXTRAPORT1},${EXTRAPORT2},${EXTRAPORT3},${EXTRAPORT4},${EXTRAPORT5},${EXTRAPORT6},${EXTRAPORT7},${EXTRAPORT8},${CONTROLPORT}"
|
||||
|
||||
$PERL ${srcdir}/testsock.pl -p "$PORT" || {
|
||||
echowarn "I:$systest:Network interface aliases not set up. Skipping test."
|
||||
|
||||
@@ -138,7 +138,8 @@ const FileData installFiles[] =
|
||||
{"libdns.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"libirs.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"libeay32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"libuv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"nghttp2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"uv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
#ifdef HAVE_LIBXML2
|
||||
{"libxml2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
#endif
|
||||
|
||||
+10
-1
@@ -124,7 +124,7 @@ AS_IF([test "$enable_static" != "no" && test "$enable_developer" != "yes"],
|
||||
#
|
||||
# Set the default CFLAGS and CPPFLAGS
|
||||
#
|
||||
STD_CFLAGS="-Wall -Wextra -Wwrite-strings -Wcast-qual -Wpointer-arith -Wno-missing-field-initializers -Wformat -Wshadow"
|
||||
STD_CFLAGS="-Wall -Wextra -Wwrite-strings -Wpointer-arith -Wno-missing-field-initializers -Wformat -Wshadow"
|
||||
|
||||
# These should be always errors
|
||||
STD_CFLAGS="$STD_CFLAGS -Werror=implicit-function-declaration -Werror=missing-prototypes -Werror=format-security -Werror=parentheses -Werror=implicit -Werror=strict-prototypes"
|
||||
@@ -574,6 +574,15 @@ LIBS="$LIBS $LIBUV_LIBS"
|
||||
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data uv_import uv_udp_connect uv_translate_sys_error])
|
||||
AX_RESTORE_FLAGS([libuv])
|
||||
|
||||
# libnghttp2
|
||||
AC_MSG_CHECKING([for libnghttp2])
|
||||
PKG_CHECK_MODULES([LIBNGHTTP2], [libnghttp2 >= 1.6.0], [],
|
||||
[AC_MSG_ERROR([libnghttp2 not found])])
|
||||
AX_SAVE_FLAGS([libnghttp2])
|
||||
|
||||
CFLAGS="$CFLAGS $LIBNGHTTP2_CFLAGS"
|
||||
LIBS="$LIBS $LIBNGHTTP2_LIBS"
|
||||
|
||||
#
|
||||
# flockfile is usually provided by pthreads
|
||||
#
|
||||
|
||||
@@ -1078,6 +1078,14 @@ default is used.
|
||||
the default is the ``named`` working directory. See :ref:`acl`
|
||||
for details about ``geoip`` ACLs.
|
||||
|
||||
.. _https_endpoint:
|
||||
|
||||
``https-endpoint``
|
||||
This configures an DNS-over-HTTPS service endpoint. It takes a string
|
||||
which specifies the endpoint URL path, and an ``https-server``
|
||||
parameter specifying the server name of an HTTPS listener. (See
|
||||
:ref:`Link title <https_server>`.)
|
||||
|
||||
``key-directory``
|
||||
This is the directory where the public and private DNSSEC key files should be
|
||||
found when performing a dynamic update of secure zones, if different
|
||||
@@ -2436,6 +2444,8 @@ Interfaces
|
||||
|
||||
The interfaces and ports that the server answers queries from may be
|
||||
specified using the ``listen-on`` and ``listen-on-v6`` options.
|
||||
specified using the ``listen-on`` and ``listen-on-v6`` options, as
|
||||
well as the ``https-server`` option for HTTPS queries.
|
||||
|
||||
``listen-on`` takes an optional port, an optional TLS configuration
|
||||
identifier, and an ``address_match_list`` of IPv4 addresses. (IPv6
|
||||
@@ -2488,6 +2498,15 @@ To instruct the server not to listen on any IPv6 addresses, use:
|
||||
|
||||
listen-on-v6 { none; };
|
||||
|
||||
.. _https_server:
|
||||
|
||||
``https-server`` takes a server name, an optional port, a TLS
|
||||
configuration identifier, and an ``address_match_list`` of both IPv4 and
|
||||
IPv6 addresses. This sets up an HTTPS responder using the key and
|
||||
certificate specified in the referenced ``tls`` statement. The endpoint
|
||||
for incoming HTTPS queries must be specified using the ``https-endpoint``
|
||||
option (see :ref:`Link title <https_endpoint>`).
|
||||
|
||||
.. _query_address:
|
||||
|
||||
Query Address
|
||||
|
||||
@@ -115,6 +115,10 @@ for queries. If \fBvalue\fP is of the form \fB<portnum>\fP or
|
||||
\fBportnum\fP; if not not specified, the default is port 53. If
|
||||
\fBvalue\fP is of the form \fBtls=<portnum>\fP, the server will
|
||||
listen for TLS queries on \fBportnum\fP; the default is 853.
|
||||
If \fBvalue\fP is of the form \fBhttps=<portnum>\fP, the server will
|
||||
listen for HTTPS queries on \fBportnum\fP; the default is 443.
|
||||
If \fBvalue\fP is of the form \fBhttp=<portnum>\fP, the server will
|
||||
listen for HTTP queries on \fBportnum\fP; the default is 80.
|
||||
.TP
|
||||
.B \fB\-s\fP
|
||||
This option writes memory usage statistics to \fBstdout\fP on exit.
|
||||
|
||||
+19
-2
@@ -132,6 +132,19 @@ dyndb string quoted_string {
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS HTTP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
http string {
|
||||
endpoints { quoted_string; ... }; // experimental
|
||||
};
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS KEY
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
@@ -327,6 +340,8 @@ options {
|
||||
glue\-cache boolean;// deprecated
|
||||
heartbeat\-interval integer;
|
||||
hostname ( quoted_string | none );
|
||||
http\-port integer;
|
||||
https\-port integer;
|
||||
inline\-signing boolean;
|
||||
interface\-interval duration;
|
||||
ipv4only\-contact string;
|
||||
@@ -338,10 +353,12 @@ options {
|
||||
key\-directory quoted_string;
|
||||
lame\-ttl duration;
|
||||
listen\-on [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
listen\-on\-v6 [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
lmdb\-mapsize sizeval;
|
||||
lock\-file ( quoted_string | none );
|
||||
|
||||
+10
-2
@@ -42,6 +42,10 @@ dnssec-policy <string> {
|
||||
dyndb <string> <quoted_string> {
|
||||
<unspecified-text> }; // may occur multiple times
|
||||
|
||||
http <string> {
|
||||
endpoints { <quoted_string>; ... }; // experimental
|
||||
}; // may occur multiple times
|
||||
|
||||
key <string> {
|
||||
algorithm <string>;
|
||||
secret <string>;
|
||||
@@ -193,6 +197,8 @@ options {
|
||||
glue-cache <boolean>; // deprecated
|
||||
heartbeat-interval <integer>;
|
||||
hostname ( <quoted_string> | none );
|
||||
http-port <integer>;
|
||||
https-port <integer>;
|
||||
inline-signing <boolean>;
|
||||
interface-interval <duration>;
|
||||
ipv4only-contact <string>;
|
||||
@@ -204,10 +210,12 @@ options {
|
||||
key-directory <quoted_string>;
|
||||
lame-ttl <duration>;
|
||||
listen-on [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
listen-on-v6 [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
lmdb-mapsize <sizeval>;
|
||||
lock-file ( <quoted_string> | none );
|
||||
|
||||
+10
-2
@@ -41,6 +41,10 @@ dnssec-policy <string> {
|
||||
dyndb <string> <quoted_string> {
|
||||
<unspecified-text> }; // may occur multiple times
|
||||
|
||||
http <string> {
|
||||
endpoints { <quoted_string>; ... }; // experimental
|
||||
}; // may occur multiple times
|
||||
|
||||
key <string> {
|
||||
algorithm <string>;
|
||||
secret <string>;
|
||||
@@ -192,6 +196,8 @@ options {
|
||||
glue-cache <boolean>; // deprecated
|
||||
heartbeat-interval <integer>;
|
||||
hostname ( <quoted_string> | none );
|
||||
http-port <integer>;
|
||||
https-port <integer>;
|
||||
inline-signing <boolean>;
|
||||
interface-interval <duration>;
|
||||
ipv4only-contact <string>;
|
||||
@@ -203,10 +209,12 @@ options {
|
||||
key-directory <quoted_string>;
|
||||
lame-ttl <duration>;
|
||||
listen-on [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
listen-on-v6 [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
lmdb-mapsize <sizeval>;
|
||||
lock-file ( <quoted_string> | none );
|
||||
|
||||
@@ -119,6 +119,8 @@
|
||||
glue-cache <boolean>; // deprecated
|
||||
heartbeat-interval <integer>;
|
||||
hostname ( <quoted_string> | none );
|
||||
http-port <integer>;
|
||||
https-port <integer>;
|
||||
inline-signing <boolean>;
|
||||
interface-interval <duration>;
|
||||
ipv4only-contact <string>;
|
||||
@@ -130,10 +132,12 @@
|
||||
key-directory <quoted_string>;
|
||||
lame-ttl <duration>;
|
||||
listen-on [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... };
|
||||
listen-on-v6 [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... };
|
||||
lmdb-mapsize <sizeval>;
|
||||
lock-file ( <quoted_string> | none );
|
||||
|
||||
@@ -52,6 +52,13 @@ New Features
|
||||
an optional ``tls`` option which specifies either a previously configured
|
||||
``tls`` statement or ``ephemeral``. [GL #2392]
|
||||
|
||||
- ``named`` now has initial support for DNS-over-HTTP(S). Both
|
||||
encrypted (via TLS) and unencrypted HTTP/2 connections are supported.
|
||||
The latter are mostly there for debugging/troubleshooting
|
||||
purposes and for the means of encryption offloading to third-party
|
||||
software (as might be desirable in some environments to aid in TLS
|
||||
certificates management).
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ libisc_la_HEADERS = \
|
||||
include/isc/tls.h \
|
||||
include/isc/tm.h \
|
||||
include/isc/types.h \
|
||||
include/isc/url.h \
|
||||
include/isc/utf8.h \
|
||||
include/isc/util.h \
|
||||
pthreads/include/isc/condition.h\
|
||||
@@ -124,11 +125,13 @@ libisc_la_SOURCES = \
|
||||
$(libisc_la_HEADERS) \
|
||||
$(pk11_HEADERS) \
|
||||
$(pkcs11_HEADERS) \
|
||||
netmgr/http.c \
|
||||
netmgr/netmgr-int.h \
|
||||
netmgr/netmgr.c \
|
||||
netmgr/tcp.c \
|
||||
netmgr/tcpdns.c \
|
||||
netmgr/tlsdns.c \
|
||||
netmgr/tlsstream.c \
|
||||
netmgr/udp.c \
|
||||
netmgr/uv-compat.c \
|
||||
netmgr/uv-compat.h \
|
||||
@@ -149,6 +152,7 @@ libisc_la_SOURCES = \
|
||||
unix/stdtime.c \
|
||||
unix/syslog.c \
|
||||
unix/time.c \
|
||||
url.c \
|
||||
pk11.c \
|
||||
pk11_result.c \
|
||||
aes.c \
|
||||
|
||||
@@ -172,6 +172,8 @@ typedef struct isc_memmethods {
|
||||
void *(*memreallocate)(isc_mem_t *mctx, void *ptr,
|
||||
size_t size _ISC_MEM_FLARG);
|
||||
char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG);
|
||||
char *(*memstrndup)(isc_mem_t *mctx, const char *s,
|
||||
size_t size _ISC_MEM_FLARG);
|
||||
void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG);
|
||||
} isc_memmethods_t;
|
||||
|
||||
@@ -226,7 +228,9 @@ struct isc_mempool {
|
||||
#define isc_mem_reallocate(c, p, s) \
|
||||
ISCMEMFUNC(reallocate)((c), (p), (s)_ISC_MEM_FILELINE)
|
||||
#define isc_mem_strdup(c, p) ISCMEMFUNC(strdup)((c), (p)_ISC_MEM_FILELINE)
|
||||
#define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c)_ISC_MEM_FILELINE)
|
||||
#define isc_mem_strndup(c, p, l) \
|
||||
ISCMEMFUNC(strndup)((c), (p), (l)_ISC_MEM_FILELINE)
|
||||
#define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c)_ISC_MEM_FILELINE)
|
||||
|
||||
#define isc_mem_put(c, p, s) \
|
||||
do { \
|
||||
@@ -596,6 +600,7 @@ void *ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
|
||||
void *ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
|
||||
void ISCMEMFUNC(free)(isc_mem_t *, void *_ISC_MEM_FLARG);
|
||||
char *ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG);
|
||||
char *ISCMEMFUNC(strndup)(isc_mem_t *, const char *, size_t _ISC_MEM_FLARG);
|
||||
void *ISCMEMPOOLFUNC(get)(isc_mempool_t *_ISC_MEM_FLARG);
|
||||
void ISCMEMPOOLFUNC(put)(isc_mempool_t *, void *_ISC_MEM_FLARG);
|
||||
|
||||
|
||||
@@ -473,6 +473,17 @@ isc_nm_setstats(isc_nm_t *mgr, isc_stats_t *stats);
|
||||
* full range of socket-related stats counter numbers.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
|
||||
isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
|
||||
size_t extrahandlesize, int backlog, isc_quota_t *quota,
|
||||
isc_tlsctx_t *sslctx, isc_nmsocket_t **sockp);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
isc_nm_cb_t cb, void *cbarg, isc_tlsctx_t *ctx,
|
||||
unsigned int timeout, size_t extrahandlesize);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
isc_nm_cb_t cb, void *cbarg, unsigned int timeout,
|
||||
@@ -494,3 +505,46 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
* The connected socket can only be accessed via the handle passed to
|
||||
* '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,
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <isc/result.h>
|
||||
|
||||
/*
|
||||
* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
#define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ISC_UF_SCHEMA = 0,
|
||||
ISC_UF_HOST = 1,
|
||||
ISC_UF_PORT = 2,
|
||||
ISC_UF_PATH = 3,
|
||||
ISC_UF_QUERY = 4,
|
||||
ISC_UF_FRAGMENT = 5,
|
||||
ISC_UF_USERINFO = 6,
|
||||
ISC_UF_MAX = 7
|
||||
} isc_url_field_t;
|
||||
|
||||
/* Result structure for isc_url_parse().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[ISC_UF_MAX];
|
||||
} isc_url_parser_t;
|
||||
|
||||
isc_result_t
|
||||
isc_url_parse(const char *buf, size_t buflen, bool is_connect,
|
||||
isc_url_parser_t *up);
|
||||
/*%<
|
||||
* Parse a URL; return nonzero on failure
|
||||
*/
|
||||
+33
-1
@@ -244,13 +244,15 @@ static void *
|
||||
isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG);
|
||||
static char *
|
||||
isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG);
|
||||
static char *
|
||||
isc___mem_strndup(isc_mem_t *mctx, const char *s, size_t size FLARG);
|
||||
static void
|
||||
isc___mem_free(isc_mem_t *ctx, void *ptr FLARG);
|
||||
|
||||
static isc_memmethods_t memmethods = {
|
||||
isc___mem_get, isc___mem_put, isc___mem_putanddetach,
|
||||
isc___mem_allocate, isc___mem_reallocate, isc___mem_strdup,
|
||||
isc___mem_free,
|
||||
isc___mem_strndup, isc___mem_free,
|
||||
};
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
@@ -1439,6 +1441,29 @@ isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) {
|
||||
return (ns);
|
||||
}
|
||||
|
||||
char *
|
||||
isc___mem_strndup(isc_mem_t *mctx0, const char *s, size_t size FLARG) {
|
||||
REQUIRE(VALID_CONTEXT(mctx0));
|
||||
REQUIRE(s != NULL);
|
||||
|
||||
isc__mem_t *mctx = (isc__mem_t *)mctx0;
|
||||
size_t len;
|
||||
char *ns;
|
||||
|
||||
len = strlen(s) + 1;
|
||||
if (len > size) {
|
||||
len = size;
|
||||
}
|
||||
|
||||
ns = isc__mem_allocate((isc_mem_t *)mctx, len FLARG_PASS);
|
||||
|
||||
if (ns != NULL) {
|
||||
strlcpy(ns, s, len);
|
||||
}
|
||||
|
||||
return (ns);
|
||||
}
|
||||
|
||||
void
|
||||
isc_mem_setdestroycheck(isc_mem_t *ctx0, bool flag) {
|
||||
REQUIRE(VALID_CONTEXT(ctx0));
|
||||
@@ -2467,6 +2492,13 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
|
||||
return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
|
||||
}
|
||||
|
||||
char *
|
||||
isc__mem_strndup(isc_mem_t *mctx, const char *s, size_t size FLARG) {
|
||||
REQUIRE(ISCAPI_MCTX_VALID(mctx));
|
||||
|
||||
return (mctx->methods->memstrndup(mctx, s, size FLARG_PASS));
|
||||
}
|
||||
|
||||
void
|
||||
isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
|
||||
REQUIRE(ISCAPI_MCTX_VALID(mctx));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+237
-5
@@ -30,6 +30,7 @@
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/thread.h>
|
||||
@@ -155,6 +156,8 @@ 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.
|
||||
*/
|
||||
@@ -207,6 +210,8 @@ 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_sockaddr_t peer;
|
||||
isc_sockaddr_t local;
|
||||
isc_nm_opaquecb_t doreset; /* reset extra callback, external */
|
||||
@@ -252,6 +257,13 @@ typedef enum isc__netievent_type {
|
||||
netievent_tcpdnsclose,
|
||||
netievent_tcpdnsstop,
|
||||
|
||||
netievent_tlsclose,
|
||||
netievent_tlssend,
|
||||
netievent_tlsstartread,
|
||||
netievent_tlsconnect,
|
||||
netievent_tlsdobio,
|
||||
netievent_tlscancel,
|
||||
|
||||
netievent_tlsdnsaccept,
|
||||
netievent_tlsdnsconnect,
|
||||
netievent_tlsdnssend,
|
||||
@@ -262,6 +274,10 @@ typedef enum isc__netievent_type {
|
||||
netievent_tlsdnscycle,
|
||||
netievent_tlsdnsshutdown,
|
||||
|
||||
netievent_httpstop,
|
||||
netievent_httpsend,
|
||||
netievent_httpclose,
|
||||
|
||||
netievent_close,
|
||||
netievent_shutdown,
|
||||
netievent_stop,
|
||||
@@ -286,11 +302,22 @@ 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 {
|
||||
char *path;
|
||||
isc_nm_http_cb_t cb;
|
||||
void *cbarg;
|
||||
size_t extrahandlesize;
|
||||
LINK(isc_nm_http2_server_handler_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper around uv_req_t with 'our' fields in it. req->data should
|
||||
* always point to its parent. Note that we always allocate more than
|
||||
@@ -642,8 +669,12 @@ typedef enum isc_nmsocket_type {
|
||||
isc_nm_tcplistener,
|
||||
isc_nm_tcpdnslistener,
|
||||
isc_nm_tcpdnssocket,
|
||||
isc_nm_tlslistener,
|
||||
isc_nm_tlssocket,
|
||||
isc_nm_tlsdnslistener,
|
||||
isc_nm_tlsdnssocket
|
||||
isc_nm_tlsdnssocket,
|
||||
isc_nm_httplistener,
|
||||
isc_nm_httpstream
|
||||
} isc_nmsocket_type;
|
||||
|
||||
/*%
|
||||
@@ -670,12 +701,74 @@ enum {
|
||||
STATID_ACTIVE = 10
|
||||
};
|
||||
|
||||
typedef struct isc_nmsocket_tls_send_req {
|
||||
isc_nmsocket_t *tlssock;
|
||||
isc_region_t data;
|
||||
} isc_nmsocket_tls_send_req_t;
|
||||
|
||||
typedef enum isc_doh_request_type {
|
||||
ISC_HTTP_REQ_GET,
|
||||
ISC_HTTP_REQ_POST,
|
||||
ISC_HTTP_REQ_UNSUPPORTED
|
||||
} isc_http2_request_type_t;
|
||||
|
||||
typedef enum isc_http2_scheme_type {
|
||||
ISC_HTTP_SCHEME_HTTP,
|
||||
ISC_HTTP_SCHEME_HTTP_SECURE,
|
||||
ISC_HTTP_SCHEME_UNSUPPORTED
|
||||
} isc_http2_scheme_type_t;
|
||||
|
||||
typedef struct isc_nm_http_doh_cbarg {
|
||||
isc_nm_recv_cb_t cb;
|
||||
void *cbarg;
|
||||
LINK(struct isc_nm_http_doh_cbarg) link;
|
||||
} isc_nm_http_doh_cbarg_t;
|
||||
|
||||
typedef struct isc_nmsocket_h2 {
|
||||
isc_nmsocket_t *psock; /* owner of the structure */
|
||||
char *request_path;
|
||||
char *query_data;
|
||||
size_t query_data_len;
|
||||
bool query_too_large;
|
||||
isc_nm_http2_server_handler_t *handler;
|
||||
|
||||
uint8_t *buf;
|
||||
size_t bufsize;
|
||||
size_t bufpos;
|
||||
|
||||
int32_t stream_id;
|
||||
isc_nm_http2_session_t *session;
|
||||
|
||||
isc_nmsocket_t *httpserver;
|
||||
|
||||
isc_http2_request_type_t request_type;
|
||||
isc_http2_scheme_type_t request_scheme;
|
||||
size_t content_length;
|
||||
bool content_type_verified;
|
||||
bool accept_type_verified;
|
||||
|
||||
isc_nm_http_cb_t handler_cb;
|
||||
void *handler_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;
|
||||
|
||||
char response_content_length_str[128];
|
||||
|
||||
struct isc_nmsocket_h2_connect_data {
|
||||
char *uri;
|
||||
bool post;
|
||||
} connect;
|
||||
} isc_nmsocket_h2_t;
|
||||
struct isc_nmsocket {
|
||||
/*% Unlocked, RO */
|
||||
int magic;
|
||||
int tid;
|
||||
isc_nmsocket_type type;
|
||||
isc_nm_t *mgr;
|
||||
|
||||
/*% Parent socket for multithreaded listeners */
|
||||
isc_nmsocket_t *parent;
|
||||
/*% Listener socket this connection was accepted on */
|
||||
@@ -705,6 +798,28 @@ struct isc_nmsocket {
|
||||
isc__nm_uvreq_t *pending_req;
|
||||
} tls;
|
||||
|
||||
/*% TLS stuff */
|
||||
struct tlsstream {
|
||||
bool server;
|
||||
BIO *app_bio;
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
BIO *ssl_bio;
|
||||
isc_nmsocket_t *tlslistener;
|
||||
enum {
|
||||
TLS_INIT,
|
||||
TLS_HANDSHAKE,
|
||||
TLS_IO,
|
||||
TLS_ERROR,
|
||||
TLS_CLOSING,
|
||||
TLS_CLOSED
|
||||
} state;
|
||||
size_t nsending;
|
||||
/* List of active send requests. */
|
||||
ISC_LIST(isc__nm_uvreq_t) sends;
|
||||
} tlsstream;
|
||||
|
||||
isc_nmsocket_h2_t h2;
|
||||
/*%
|
||||
* quota is the TCP client, attached when a TCP connection
|
||||
* is established. pquota is a non-attached pointer to the
|
||||
@@ -906,6 +1021,7 @@ struct isc_nmsocket {
|
||||
void *accept_cbarg;
|
||||
|
||||
atomic_int_fast32_t active_child_connections;
|
||||
|
||||
#ifdef NETMGR_TRACE
|
||||
void *backtrace[TRACE_SIZE];
|
||||
int backtrace_size;
|
||||
@@ -1070,8 +1186,8 @@ isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg);
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
/*%<
|
||||
* Back-end implementation of isc_nm_send() for UDP handles.
|
||||
*/
|
||||
@@ -1132,8 +1248,8 @@ isc__nm_async_udpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg);
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
/*%<
|
||||
* Back-end implementation of isc_nm_send() for TCP handles.
|
||||
*/
|
||||
@@ -1220,6 +1336,28 @@ isc__nm_async_tcpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
* stoplisten, send, read, pause, close).
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_tlsstartread(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_tlsdobio(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_tlscancel(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
/*%<
|
||||
* Callback handlers for asynchronouse TLS events.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_async_tcpdnsaccept(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
void
|
||||
@@ -1291,6 +1429,14 @@ isc__nm_async_tlsdnslisten(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
void
|
||||
isc__nm_tlsdns_send(isc_nmhandle_t *handle, isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_tls_cancelread(isc_nmhandle_t *handle);
|
||||
|
||||
/*%<
|
||||
* Back-end implementation of isc_nm_send() for TLSDNS handles.
|
||||
*/
|
||||
@@ -1344,6 +1490,71 @@ isc__nm_tlsdns_cancelread(isc_nmhandle_t *handle);
|
||||
* Stop reading on a connected TLSDNS handle.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_tls_close(isc_nmsocket_t *sock);
|
||||
/*%<
|
||||
* Close a TLS socket.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tls_pauseread(isc_nmhandle_t *handle);
|
||||
/*%<
|
||||
* Pause reading on this handle, while still remembering the callback.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tls_resumeread(isc_nmhandle_t *handle);
|
||||
/*%<
|
||||
* Resume reading from the handle.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tls_cleanup_data(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_clear_handlers(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_clear_session(isc_nmsocket_t *sock);
|
||||
|
||||
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_close(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_async_httpsend(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
bool
|
||||
isc__nm_parse_doh_query_string(const char *query_string, const char **start,
|
||||
size_t *len);
|
||||
|
||||
char *
|
||||
isc__nm_base64url_to_base64(isc_mem_t *mem, const char *base64url,
|
||||
const size_t base64url_len, size_t *res_len);
|
||||
|
||||
char *
|
||||
isc__nm_base64_to_base64url(isc_mem_t *mem, const char *base64,
|
||||
const size_t base64_len, size_t *res_len);
|
||||
|
||||
#define isc__nm_uverr2result(x) \
|
||||
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
||||
isc_result_t
|
||||
@@ -1444,6 +1655,12 @@ NETIEVENT_SOCKET_TYPE(tcpclose);
|
||||
NETIEVENT_SOCKET_TYPE(tcplisten);
|
||||
NETIEVENT_SOCKET_TYPE(tcppauseread);
|
||||
NETIEVENT_SOCKET_TYPE(tcpstop);
|
||||
NETIEVENT_SOCKET_TYPE(tlsclose);
|
||||
/* NETIEVENT_SOCKET_TYPE(tlsconnect); */ /* unique type, defined independently
|
||||
*/
|
||||
NETIEVENT_SOCKET_TYPE(tlsdobio);
|
||||
NETIEVENT_SOCKET_TYPE(tlsstartread);
|
||||
NETIEVENT_SOCKET_HANDLE_TYPE(tlscancel);
|
||||
NETIEVENT_SOCKET_TYPE(udpclose);
|
||||
NETIEVENT_SOCKET_TYPE(udplisten);
|
||||
NETIEVENT_SOCKET_TYPE(udpread);
|
||||
@@ -1470,9 +1687,14 @@ NETIEVENT_SOCKET_HANDLE_TYPE(tlsdnscancel);
|
||||
NETIEVENT_SOCKET_QUOTA_TYPE(tlsdnsaccept);
|
||||
NETIEVENT_SOCKET_TYPE(tlsdnscycle);
|
||||
|
||||
NETIEVENT_SOCKET_TYPE(httpstop);
|
||||
NETIEVENT_SOCKET_REQ_TYPE(httpsend);
|
||||
NETIEVENT_SOCKET_TYPE(httpclose);
|
||||
|
||||
NETIEVENT_SOCKET_REQ_TYPE(tcpconnect);
|
||||
NETIEVENT_SOCKET_REQ_TYPE(tcpsend);
|
||||
NETIEVENT_SOCKET_TYPE(tcpstartread);
|
||||
NETIEVENT_SOCKET_REQ_TYPE(tlssend);
|
||||
NETIEVENT_SOCKET_REQ_TYPE(udpconnect);
|
||||
|
||||
NETIEVENT_SOCKET_REQ_RESULT_TYPE(connectcb);
|
||||
@@ -1498,6 +1720,11 @@ NETIEVENT_SOCKET_DECL(tcplisten);
|
||||
NETIEVENT_SOCKET_DECL(tcppauseread);
|
||||
NETIEVENT_SOCKET_DECL(tcpstartread);
|
||||
NETIEVENT_SOCKET_DECL(tcpstop);
|
||||
NETIEVENT_SOCKET_DECL(tlsclose);
|
||||
NETIEVENT_SOCKET_DECL(tlsconnect);
|
||||
NETIEVENT_SOCKET_DECL(tlsdobio);
|
||||
NETIEVENT_SOCKET_DECL(tlsstartread);
|
||||
NETIEVENT_SOCKET_HANDLE_DECL(tlscancel);
|
||||
NETIEVENT_SOCKET_DECL(udpclose);
|
||||
NETIEVENT_SOCKET_DECL(udplisten);
|
||||
NETIEVENT_SOCKET_DECL(udpread);
|
||||
@@ -1524,8 +1751,13 @@ NETIEVENT_SOCKET_HANDLE_DECL(tlsdnscancel);
|
||||
NETIEVENT_SOCKET_QUOTA_DECL(tlsdnsaccept);
|
||||
NETIEVENT_SOCKET_DECL(tlsdnscycle);
|
||||
|
||||
NETIEVENT_SOCKET_DECL(httpstop);
|
||||
NETIEVENT_SOCKET_REQ_DECL(httpsend);
|
||||
NETIEVENT_SOCKET_DECL(httpclose);
|
||||
|
||||
NETIEVENT_SOCKET_REQ_DECL(tcpconnect);
|
||||
NETIEVENT_SOCKET_REQ_DECL(tcpsend);
|
||||
NETIEVENT_SOCKET_REQ_DECL(tlssend);
|
||||
NETIEVENT_SOCKET_REQ_DECL(udpconnect);
|
||||
|
||||
NETIEVENT_SOCKET_REQ_RESULT_DECL(connectcb);
|
||||
|
||||
+123
-2
@@ -716,6 +716,13 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
|
||||
NETIEVENT_CASE(tcpdnsread);
|
||||
NETIEVENT_CASE(tcpdnsstop);
|
||||
|
||||
NETIEVENT_CASE(tlsstartread);
|
||||
NETIEVENT_CASE(tlssend);
|
||||
NETIEVENT_CASE(tlsclose);
|
||||
NETIEVENT_CASE(tlsconnect);
|
||||
NETIEVENT_CASE(tlsdobio);
|
||||
NETIEVENT_CASE(tlscancel);
|
||||
|
||||
NETIEVENT_CASE(tlsdnscycle);
|
||||
NETIEVENT_CASE(tlsdnsaccept);
|
||||
NETIEVENT_CASE(tlsdnslisten);
|
||||
@@ -727,6 +734,10 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
|
||||
NETIEVENT_CASE(tlsdnsstop);
|
||||
NETIEVENT_CASE(tlsdnsshutdown);
|
||||
|
||||
NETIEVENT_CASE(httpstop);
|
||||
NETIEVENT_CASE(httpsend);
|
||||
NETIEVENT_CASE(httpclose);
|
||||
|
||||
NETIEVENT_CASE(connectcb);
|
||||
NETIEVENT_CASE(readcb);
|
||||
NETIEVENT_CASE(sendcb);
|
||||
@@ -776,6 +787,11 @@ NETIEVENT_SOCKET_DEF(tcplisten);
|
||||
NETIEVENT_SOCKET_DEF(tcppauseread);
|
||||
NETIEVENT_SOCKET_DEF(tcpstartread);
|
||||
NETIEVENT_SOCKET_DEF(tcpstop);
|
||||
NETIEVENT_SOCKET_DEF(tlsclose);
|
||||
NETIEVENT_SOCKET_DEF(tlsconnect);
|
||||
NETIEVENT_SOCKET_DEF(tlsdobio);
|
||||
NETIEVENT_SOCKET_DEF(tlsstartread);
|
||||
NETIEVENT_SOCKET_HANDLE_DEF(tlscancel);
|
||||
NETIEVENT_SOCKET_DEF(udpclose);
|
||||
NETIEVENT_SOCKET_DEF(udplisten);
|
||||
NETIEVENT_SOCKET_DEF(udpread);
|
||||
@@ -802,8 +818,13 @@ NETIEVENT_SOCKET_QUOTA_DEF(tlsdnsaccept);
|
||||
NETIEVENT_SOCKET_DEF(tlsdnscycle);
|
||||
NETIEVENT_SOCKET_DEF(tlsdnsshutdown);
|
||||
|
||||
NETIEVENT_SOCKET_DEF(httpstop);
|
||||
NETIEVENT_SOCKET_REQ_DEF(httpsend);
|
||||
NETIEVENT_SOCKET_DEF(httpclose);
|
||||
|
||||
NETIEVENT_SOCKET_REQ_DEF(tcpconnect);
|
||||
NETIEVENT_SOCKET_REQ_DEF(tcpsend);
|
||||
NETIEVENT_SOCKET_REQ_DEF(tlssend);
|
||||
NETIEVENT_SOCKET_REQ_DEF(udpconnect);
|
||||
|
||||
NETIEVENT_SOCKET_REQ_RESULT_DEF(connectcb);
|
||||
@@ -986,6 +1007,34 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
|
||||
isc_mutex_destroy(&sock->lock);
|
||||
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);
|
||||
#ifdef NETMGR_TRACE
|
||||
LOCK(&sock->mgr->lock);
|
||||
ISC_LIST_UNLINK(sock->mgr->active_sockets, sock, active_link);
|
||||
@@ -1094,9 +1143,15 @@ isc___nmsocket_prep_destroy(isc_nmsocket_t *sock FLARG) {
|
||||
case isc_nm_tcpdnssocket:
|
||||
isc__nm_tcpdns_close(sock);
|
||||
return;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_close(sock);
|
||||
break;
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_close(sock);
|
||||
return;
|
||||
case isc_nm_httpstream:
|
||||
isc__nm_http_close(sock);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1139,7 +1194,9 @@ isc_nmsocket_close(isc_nmsocket_t **sockp) {
|
||||
REQUIRE((*sockp)->type == isc_nm_udplistener ||
|
||||
(*sockp)->type == isc_nm_tcplistener ||
|
||||
(*sockp)->type == isc_nm_tcpdnslistener ||
|
||||
(*sockp)->type == isc_nm_tlsdnslistener);
|
||||
(*sockp)->type == isc_nm_tlsdnslistener ||
|
||||
(*sockp)->type == isc_nm_tlslistener ||
|
||||
(*sockp)->type == isc_nm_httplistener);
|
||||
|
||||
isc__nmsocket_detach(sockp);
|
||||
}
|
||||
@@ -1202,6 +1259,8 @@ 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_httplistener:
|
||||
if (family == AF_INET) {
|
||||
sock->statsindex = tcp4statsindex;
|
||||
} else {
|
||||
@@ -1218,6 +1277,9 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
||||
isc_condition_init(&sock->scond);
|
||||
isc_refcount_init(&sock->references, 1);
|
||||
|
||||
memset(&sock->tlsstream, 0, sizeof(sock->tlsstream));
|
||||
ISC_LIST_INIT(sock->tlsstream.sends);
|
||||
|
||||
NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %lu\n", sock,
|
||||
isc_refcount_current(&sock->references));
|
||||
|
||||
@@ -1228,6 +1290,28 @@ 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;
|
||||
|
||||
sock->magic = NMSOCK_MAGIC;
|
||||
}
|
||||
|
||||
@@ -1353,7 +1437,7 @@ isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
|
||||
#endif
|
||||
UNLOCK(&sock->lock);
|
||||
|
||||
if (sock->type == isc_nm_tcpsocket ||
|
||||
if (sock->type == isc_nm_tcpsocket || sock->type == isc_nm_tlssocket ||
|
||||
(sock->type == isc_nm_udpsocket && atomic_load(&sock->client)) ||
|
||||
(sock->type == isc_nm_tcpdnssocket && atomic_load(&sock->client)) ||
|
||||
(sock->type == isc_nm_tlsdnssocket && atomic_load(&sock->client)))
|
||||
@@ -1369,6 +1453,10 @@ 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;
|
||||
}
|
||||
|
||||
return (handle);
|
||||
}
|
||||
|
||||
@@ -1390,6 +1478,7 @@ isc_nmhandle_is_stream(isc_nmhandle_t *handle) {
|
||||
|
||||
return (handle->sock->type == isc_nm_tcpsocket ||
|
||||
handle->sock->type == isc_nm_tcpdnssocket ||
|
||||
handle->sock->type == isc_nm_tlssocket ||
|
||||
handle->sock->type == isc_nm_tlsdnssocket);
|
||||
}
|
||||
|
||||
@@ -1667,9 +1756,15 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
case isc_nm_tcpdnssocket:
|
||||
isc__nm_tcpdns_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_httpstream:
|
||||
isc__nm_http_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@@ -1697,6 +1792,9 @@ isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
|
||||
case isc_nm_tcpdnssocket:
|
||||
isc__nm_tcpdns_read(handle, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_read(handle, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_read(handle, cb, cbarg);
|
||||
break;
|
||||
@@ -1723,6 +1821,9 @@ isc_nm_cancelread(isc_nmhandle_t *handle) {
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_cancelread(handle);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_cancelread(handle);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@@ -1739,6 +1840,9 @@ isc_nm_pauseread(isc_nmhandle_t *handle) {
|
||||
case isc_nm_tcpsocket:
|
||||
isc__nm_tcp_pauseread(handle);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_pauseread(handle);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@@ -1755,6 +1859,9 @@ isc_nm_resumeread(isc_nmhandle_t *handle) {
|
||||
case isc_nm_tcpsocket:
|
||||
isc__nm_tcp_resumeread(handle);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_resumeread(handle);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@@ -1775,9 +1882,15 @@ isc_nm_stoplistening(isc_nmsocket_t *sock) {
|
||||
case isc_nm_tcplistener:
|
||||
isc__nm_tcp_stoplistening(sock);
|
||||
break;
|
||||
case isc_nm_tlslistener:
|
||||
isc__nm_tls_stoplistening(sock);
|
||||
break;
|
||||
case isc_nm_tlsdnslistener:
|
||||
isc__nm_tlsdns_stoplistening(sock);
|
||||
break;
|
||||
case isc_nm_httplistener:
|
||||
isc__nm_http_stoplistening(sock);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@@ -2322,10 +2435,18 @@ nmsocket_type_totext(isc_nmsocket_type type) {
|
||||
return ("isc_nm_tcpdnslistener");
|
||||
case isc_nm_tcpdnssocket:
|
||||
return ("isc_nm_tcpdnssocket");
|
||||
case isc_nm_tlssocket:
|
||||
return ("isc_nm_tlssocket");
|
||||
case isc_nm_tlslistener:
|
||||
return ("isc_nm_tlslistener");
|
||||
case isc_nm_tlsdnslistener:
|
||||
return ("isc_nm_tlsdnslistener");
|
||||
case isc_nm_tlsdnssocket:
|
||||
return ("isc_nm_tlsdnssocket");
|
||||
case isc_nm_httplistener:
|
||||
return ("isc_nm_httplistener");
|
||||
case isc_nm_httpstream:
|
||||
return ("isc_nm_httpstream");
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
||||
+28
-21
@@ -167,6 +167,27 @@ 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);
|
||||
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
|
||||
atomic_store(&sock->connecting, true);
|
||||
@@ -210,7 +231,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);
|
||||
@@ -239,10 +260,13 @@ 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);
|
||||
isc__nm_tcp_close(sock);
|
||||
if (sock->fd != (uv_os_sock_t)(-1)) {
|
||||
isc__nm_tcp_close(sock);
|
||||
}
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
|
||||
@@ -309,36 +333,19 @@ 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);
|
||||
|
||||
result = isc__nm_socket_connectiontimeout(fd, timeout);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
req = isc__nm_uvreq_get(mgr, sock);
|
||||
req->cb.connect = cb;
|
||||
req->cbarg = cbarg;
|
||||
@@ -1155,8 +1162,8 @@ failure:
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg) {
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
|
||||
@@ -0,0 +1,936 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/once.h>
|
||||
#include <isc/quota.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/stdtime.h>
|
||||
#include <isc/thread.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "netmgr-int.h"
|
||||
#include "uv-compat.h"
|
||||
|
||||
#define TLS_BUF_SIZE 65536
|
||||
|
||||
static isc_result_t
|
||||
tls_error_to_result(int tls_err) {
|
||||
switch (tls_err) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
return (ISC_R_EOF);
|
||||
default:
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tls_do_bio(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
tls_close_direct(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
async_tls_do_bio(isc_nmsocket_t *sock);
|
||||
|
||||
/*
|
||||
* The socket is closing, outerhandle has been detached, listener is
|
||||
* inactive, or the netmgr is closing: any operation on it should abort
|
||||
* with ISC_R_CANCELED.
|
||||
*/
|
||||
static bool
|
||||
inactive(isc_nmsocket_t *sock) {
|
||||
return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
|
||||
sock->outerhandle == NULL ||
|
||||
(sock->listener != NULL &&
|
||||
!isc__nmsocket_active(sock->listener)) ||
|
||||
atomic_load(&sock->mgr->closing));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
UNLOCK(&sock->lock);
|
||||
if (sock->parent) {
|
||||
LOCK(&sock->parent->lock);
|
||||
sock->parent->result = result;
|
||||
UNLOCK(&sock->parent->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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));
|
||||
|
||||
/* XXXWPK TODO */
|
||||
UNUSED(eresult);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
||||
const isc_result_t result, const bool close) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
|
||||
if (!sock->tlsstream.server &&
|
||||
(sock->tlsstream.state == TLS_INIT ||
|
||||
sock->tlsstream.state == TLS_HANDSHAKE) &&
|
||||
sock->connect_cb != NULL)
|
||||
{
|
||||
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);
|
||||
isc_nmhandle_detach(&handle);
|
||||
} else if (sock->recv_cb != NULL) {
|
||||
isc__nm_uvreq_t *req = NULL;
|
||||
req = isc__nm_uvreq_get(sock->mgr, sock);
|
||||
req->cb.recv = sock->recv_cb;
|
||||
req->cbarg = sock->recv_cbarg;
|
||||
req->handle = NULL;
|
||||
if (handle) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
isc_nmhandle_attach(handle, &req->handle);
|
||||
} else {
|
||||
req->handle = isc__nmhandle_get(sock, NULL, NULL);
|
||||
}
|
||||
isc__nmsocket_clearcb(sock);
|
||||
isc__nm_readcb(sock, req, result);
|
||||
}
|
||||
sock->tlsstream.state = TLS_ERROR;
|
||||
|
||||
if (close) {
|
||||
isc__nmsocket_prep_destroy(sock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
async_tls_do_bio(isc_nmsocket_t *sock) {
|
||||
isc__netievent_tlsdobio_t *ievent =
|
||||
isc__nm_get_netievent_tlsdobio(sock->mgr, sock);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
|
||||
static void
|
||||
tls_do_bio(isc_nmsocket_t *sock) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
int pending, tls_err = 0;
|
||||
int rv;
|
||||
isc__nm_uvreq_t *req;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
/* We will resume read if TLS layer wants us to */
|
||||
if (sock->outerhandle != NULL) {
|
||||
REQUIRE(VALID_NMHANDLE(sock->outerhandle));
|
||||
isc_nm_pauseread(sock->outerhandle);
|
||||
}
|
||||
|
||||
if (sock->tlsstream.state == TLS_INIT) {
|
||||
(void)SSL_do_handshake(sock->tlsstream.ssl);
|
||||
sock->tlsstream.state = TLS_HANDSHAKE;
|
||||
} else if (sock->tlsstream.state == TLS_ERROR) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto low_level_error;
|
||||
} else if (sock->tlsstream.state == TLS_CLOSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
if (pending > TLS_BUF_SIZE) {
|
||||
pending = TLS_BUF_SIZE;
|
||||
}
|
||||
isc_region_t region = {
|
||||
isc_mem_get(sock->mgr->mctx, pending), pending
|
||||
};
|
||||
isc_region_t dregion;
|
||||
memset(region.base, 0, region.length);
|
||||
rv = SSL_read(sock->tlsstream.ssl, 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);
|
||||
isc_mem_put(sock->mgr->mctx, region.base,
|
||||
region.length);
|
||||
}
|
||||
}
|
||||
|
||||
/* Peek to move the session forward */
|
||||
(void)SSL_peek(sock->tlsstream.ssl, 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? */
|
||||
isc_nmsocket_tls_send_req_t *send_req = NULL;
|
||||
if (pending > TLS_BUF_SIZE) {
|
||||
pending = TLS_BUF_SIZE;
|
||||
}
|
||||
send_req = isc_mem_get(sock->mgr->mctx, sizeof(*send_req));
|
||||
send_req->data.base = isc_mem_get(sock->mgr->mctx, pending);
|
||||
send_req->data.length = pending;
|
||||
send_req->tlssock = NULL;
|
||||
isc__nmsocket_attach(sock, &send_req->tlssock);
|
||||
rv = BIO_read(sock->tlsstream.app_bio, send_req->data.base,
|
||||
pending);
|
||||
/* There's something pending, read must succeed */
|
||||
RUNTIME_CHECK(rv == pending);
|
||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||
isc_nm_send(sock->outerhandle, &send_req->data, tls_senddone,
|
||||
send_req);
|
||||
/* We'll continue in tls_senddone */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the potential error code */
|
||||
rv = SSL_peek(sock->tlsstream.ssl, buf, 1);
|
||||
|
||||
if (rv < 0) {
|
||||
tls_err = SSL_get_error(sock->tlsstream.ssl, 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)
|
||||
{
|
||||
isc_nmhandle_t *tlshandle = isc__nmhandle_get(sock, NULL, NULL);
|
||||
if (sock->tlsstream.server) {
|
||||
sock->listener->accept_cb(sock->statichandle,
|
||||
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);
|
||||
}
|
||||
isc_nmhandle_detach(&tlshandle);
|
||||
sock->tlsstream.state = TLS_IO;
|
||||
async_tls_do_bio(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (tls_err) {
|
||||
case 0:
|
||||
return;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
if (sock->tlsstream.nsending == 0) {
|
||||
/*
|
||||
* Launch tls_do_bio asynchronously. If we're sending
|
||||
* already the send callback will call it.
|
||||
*/
|
||||
async_tls_do_bio(sock);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||
isc_nm_resumeread(sock->outerhandle);
|
||||
break;
|
||||
default:
|
||||
result = tls_error_to_result(tls_err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((req = ISC_LIST_HEAD(sock->tlsstream.sends)) != NULL) {
|
||||
INSIST(VALID_UVREQ(req));
|
||||
rv = SSL_write(sock->tlsstream.ssl, req->uvbuf.base,
|
||||
req->uvbuf.len);
|
||||
if (rv < 0) {
|
||||
if (sock->tlsstream.nsending == 0) {
|
||||
async_tls_do_bio(sock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rv != (int)req->uvbuf.len) {
|
||||
if (!sock->tlsstream.server &&
|
||||
(sock->tlsstream.state == TLS_HANDSHAKE ||
|
||||
TLS_INIT))
|
||||
{
|
||||
isc_nmhandle_t *tlshandle =
|
||||
isc__nmhandle_get(sock, NULL, NULL);
|
||||
sock->connect_cb(tlshandle, result,
|
||||
sock->connect_cbarg);
|
||||
update_result(tlshandle->sock, result);
|
||||
isc_nmhandle_detach(&tlshandle);
|
||||
}
|
||||
sock->tlsstream.state = TLS_ERROR;
|
||||
async_tls_do_bio(sock);
|
||||
return;
|
||||
}
|
||||
ISC_LIST_UNLINK(sock->tlsstream.sends, req, link);
|
||||
req->cb.send(sock->statichandle, ISC_R_SUCCESS, req->cbarg);
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR,
|
||||
ISC_LOG_ERROR, "SSL error in BIO: %d %s", tls_err,
|
||||
isc_result_totext(result));
|
||||
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);
|
||||
}
|
||||
isc_nmhandle_detach(&tlshandle);
|
||||
} else if (sock->tlsstream.state == TLS_IO) {
|
||||
if (ISC_LIST_HEAD(sock->tlsstream.sends) != NULL) {
|
||||
while ((req = ISC_LIST_HEAD(sock->tlsstream.sends)) !=
|
||||
NULL) {
|
||||
req->cb.send(sock->statichandle, result,
|
||||
req->cbarg);
|
||||
ISC_LIST_UNLINK(sock->tlsstream.sends, req,
|
||||
link);
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
} else if (sock->recv_cb != NULL) {
|
||||
tls_failed_read_cb(sock, sock->statichandle, result,
|
||||
false);
|
||||
} else {
|
||||
tls_close_direct(sock);
|
||||
}
|
||||
}
|
||||
sock->tlsstream.state = TLS_ERROR;
|
||||
}
|
||||
|
||||
static void
|
||||
tls_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
|
||||
void *cbarg) {
|
||||
isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg;
|
||||
int rv;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(tlssock));
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(tlssock->tid == isc_nm_tid());
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
tls_failed_read_cb(tlssock, tlssock->statichandle, result,
|
||||
true);
|
||||
return;
|
||||
}
|
||||
rv = BIO_write(tlssock->tlsstream.app_bio, region->base,
|
||||
region->length);
|
||||
|
||||
if (rv != (int)region->length) {
|
||||
/* XXXWPK log it? */
|
||||
tlssock->tlsstream.state = TLS_ERROR;
|
||||
}
|
||||
tls_do_bio(tlssock);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
initialize_tls(isc_nmsocket_t *sock, bool server) {
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
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);
|
||||
return (ISC_R_TLSERROR);
|
||||
}
|
||||
|
||||
SSL_set_bio(sock->tlsstream.ssl, sock->tlsstream.ssl_bio,
|
||||
sock->tlsstream.ssl_bio);
|
||||
if (server) {
|
||||
SSL_set_accept_state(sock->tlsstream.ssl);
|
||||
} else {
|
||||
SSL_set_connect_state(sock->tlsstream.ssl);
|
||||
}
|
||||
sock->tlsstream.nsending = 0;
|
||||
isc_nm_read(sock->outerhandle, tls_readcb, sock);
|
||||
tls_do_bio(sock);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg;
|
||||
isc_nmsocket_t *tlssock = NULL;
|
||||
int r;
|
||||
|
||||
/* If accept() was unsuccessful we can't do anything */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
REQUIRE(VALID_NMSOCK(tlslistensock));
|
||||
REQUIRE(tlslistensock->type == isc_nm_tlslistener);
|
||||
|
||||
/*
|
||||
* We need to create a 'wrapper' tlssocket for this connection.
|
||||
*/
|
||||
tlssock = isc_mem_get(handle->sock->mgr->mctx, sizeof(*tlssock));
|
||||
isc__nmsocket_init(tlssock, handle->sock->mgr, isc_nm_tlssocket,
|
||||
handle->sock->iface);
|
||||
|
||||
/* 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);
|
||||
ISC_LIST_INIT(tlssock->tlsstream.sends);
|
||||
if (tlssock->tlsstream.ssl == NULL) {
|
||||
update_result(tlssock, ISC_R_TLSERROR);
|
||||
atomic_store(&tlssock->closed, true);
|
||||
isc__nmsocket_detach(&tlssock);
|
||||
return (ISC_R_TLSERROR);
|
||||
}
|
||||
|
||||
tlssock->extrahandlesize = tlslistensock->extrahandlesize;
|
||||
isc__nmsocket_attach(tlslistensock, &tlssock->listener);
|
||||
isc_nmhandle_attach(handle, &tlssock->outerhandle);
|
||||
tlssock->peer = handle->sock->peer;
|
||||
tlssock->read_timeout = atomic_load(&handle->sock->mgr->init);
|
||||
tlssock->tid = isc_nm_tid();
|
||||
tlssock->tlsstream.server = true;
|
||||
tlssock->tlsstream.state = TLS_INIT;
|
||||
|
||||
r = uv_timer_init(&tlssock->mgr->workers[isc_nm_tid()].loop,
|
||||
&tlssock->timer);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
|
||||
tlssock->timer.data = tlssock;
|
||||
tlssock->timer_initialized = true;
|
||||
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
||||
|
||||
result = initialize_tls(tlssock, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
/* TODO: catch failure code, detach tlssock, and log the error */
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
|
||||
isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
|
||||
size_t extrahandlesize, int backlog, isc_quota_t *quota,
|
||||
SSL_CTX *sslctx, isc_nmsocket_t **sockp) {
|
||||
isc_result_t result;
|
||||
isc_nmsocket_t *tlssock = isc_mem_get(mgr->mctx, sizeof(*tlssock));
|
||||
isc_nmsocket_t *tsock = NULL;
|
||||
|
||||
REQUIRE(VALID_NM(mgr));
|
||||
|
||||
isc__nmsocket_init(tlssock, mgr, isc_nm_tlslistener, iface);
|
||||
tlssock->result = ISC_R_DEFAULT;
|
||||
tlssock->accept_cb = accept_cb;
|
||||
tlssock->accept_cbarg = accept_cbarg;
|
||||
tlssock->extrahandlesize = extrahandlesize;
|
||||
tlssock->tlsstream.ctx = sslctx;
|
||||
tlssock->tlsstream.ssl = NULL;
|
||||
|
||||
/*
|
||||
* tlssock will be a TLS 'wrapper' around an unencrypted stream.
|
||||
* We set tlssock->outer to a socket listening for a TCP connection.
|
||||
*/
|
||||
result = isc_nm_listentcp(mgr, iface, tlslisten_acceptcb, tlssock,
|
||||
extrahandlesize, backlog, quota,
|
||||
&tlssock->outer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
atomic_store(&tlssock->closed, true);
|
||||
isc__nmsocket_detach(&tlssock);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* wait for listen result */
|
||||
isc__nmsocket_attach(tlssock->outer, &tsock);
|
||||
LOCK(&tlssock->outer->lock);
|
||||
while (tlssock->outer->rchildren != tlssock->outer->nchildren) {
|
||||
WAIT(&tlssock->outer->cond, &tlssock->outer->lock);
|
||||
}
|
||||
result = tlssock->outer->result;
|
||||
tlssock->result = result;
|
||||
atomic_store(&tlssock->active, true);
|
||||
INSIST(tlssock->outer->tlsstream.tlslistener == NULL);
|
||||
isc__nmsocket_attach(tlssock, &tlssock->outer->tlsstream.tlslistener);
|
||||
BROADCAST(&tlssock->outer->scond);
|
||||
UNLOCK(&tlssock->outer->lock);
|
||||
isc__nmsocket_detach(&tsock);
|
||||
INSIST(result != ISC_R_DEFAULT);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
atomic_store(&tlssock->listening, true);
|
||||
*sockp = tlssock;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
UNUSED(worker);
|
||||
|
||||
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);
|
||||
tls_do_bio(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = SSL_write(sock->tlsstream.ssl, req->uvbuf.base, req->uvbuf.len);
|
||||
if (rv < 0) {
|
||||
/*
|
||||
* We might need to read, we might need to write, or the
|
||||
* TLS socket might be dead - in any case, we need to
|
||||
* enqueue the uvreq and let the TLS BIO layer do the rest.
|
||||
*/
|
||||
ISC_LIST_APPEND(sock->tlsstream.sends, req, link);
|
||||
tls_do_bio(sock);
|
||||
return;
|
||||
}
|
||||
if (rv != (int)req->uvbuf.len) {
|
||||
sock->tlsstream.state = TLS_ERROR;
|
||||
async_tls_do_bio(sock);
|
||||
return;
|
||||
}
|
||||
req->cb.send(sock->statichandle, ISC_R_SUCCESS, req->cbarg);
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
tls_do_bio(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
isc__netievent_tlssend_t *ievent = NULL;
|
||||
isc__nm_uvreq_t *uvreq = NULL;
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
sock = handle->sock;
|
||||
|
||||
REQUIRE(sock->type == isc_nm_tlssocket);
|
||||
|
||||
if (inactive(sock)) {
|
||||
cb(handle, ISC_R_CANCELED, cbarg);
|
||||
return;
|
||||
}
|
||||
|
||||
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
|
||||
isc_nmhandle_attach(handle, &uvreq->handle);
|
||||
uvreq->cb.send = cb;
|
||||
uvreq->cbarg = cbarg;
|
||||
|
||||
uvreq->uvbuf.base = (char *)region->base;
|
||||
uvreq->uvbuf.len = region->length;
|
||||
|
||||
/*
|
||||
* We need to create an event and pass it using async channel
|
||||
*/
|
||||
ievent = isc__nm_get_netievent_tlssend(sock->mgr, sock, uvreq);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_tlsstartread(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent_tlsstartread_t *ievent =
|
||||
(isc__netievent_tlsstartread_t *)ev0;
|
||||
isc_nmsocket_t *sock = ievent->sock;
|
||||
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
UNUSED(worker);
|
||||
|
||||
tls_do_bio(sock);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (inactive(sock)) {
|
||||
cb(handle, ISC_R_NOTCONNECTED, NULL, cbarg);
|
||||
return;
|
||||
}
|
||||
|
||||
sock->recv_cb = cb;
|
||||
sock->recv_cbarg = cbarg;
|
||||
|
||||
ievent = isc__nm_get_netievent_tlsstartread(sock->mgr, sock);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
timer_close_cb(uv_handle_t *handle) {
|
||||
isc_nmsocket_t *sock = (isc_nmsocket_t *)uv_handle_get_data(handle);
|
||||
tls_close_direct(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
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) {
|
||||
uv_timer_stop(&sock->timer);
|
||||
sock->timer_running = false;
|
||||
}
|
||||
|
||||
/* We don't need atomics here, it's all in single network thread
|
||||
*/
|
||||
if (sock->timer_initialized) {
|
||||
/*
|
||||
* We need to fire the timer callback to clean it up,
|
||||
* it will then call us again (via detach) so that we
|
||||
* can finally close the socket.
|
||||
*/
|
||||
sock->timer_initialized = false;
|
||||
uv_timer_stop(&sock->timer);
|
||||
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
|
||||
} else {
|
||||
/*
|
||||
* At this point we're certain that there are no
|
||||
* external references, we can close everything.
|
||||
*/
|
||||
if (sock->outerhandle != NULL) {
|
||||
isc_nm_pauseread(sock->outerhandle);
|
||||
isc_nmhandle_detach(&sock->outerhandle);
|
||||
}
|
||||
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* */
|
||||
sock->tlsstream.ctx = NULL;
|
||||
sock->tlsstream.ssl_bio = NULL;
|
||||
}
|
||||
if (sock->tlsstream.app_bio != NULL) {
|
||||
BIO_free(sock->tlsstream.app_bio);
|
||||
sock->tlsstream.app_bio = NULL;
|
||||
}
|
||||
sock->tlsstream.state = TLS_CLOSED;
|
||||
atomic_store(&sock->closed, true);
|
||||
isc__nmsocket_detach(&sock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_close(isc_nmsocket_t *sock) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->type == isc_nm_tlssocket);
|
||||
|
||||
if (!atomic_compare_exchange_strong(&sock->closing, &(bool){ false },
|
||||
true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sock->tid == isc_nm_tid()) {
|
||||
tls_close_direct(sock);
|
||||
} else {
|
||||
isc__netievent_tlsclose_t *ievent =
|
||||
isc__nm_get_netievent_tlsclose(sock->mgr, sock);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->type == isc_nm_tlslistener);
|
||||
|
||||
atomic_store(&sock->listening, false);
|
||||
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;
|
||||
sock->tlsstream.ctx = NULL;
|
||||
}
|
||||
|
||||
if (sock->outer != NULL) {
|
||||
isc_nm_stoplistening(sock->outer);
|
||||
isc__nmsocket_detach(&sock->outer);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
isc_nm_cb_t cb, void *cbarg, SSL_CTX *ctx,
|
||||
unsigned int timeout, size_t extrahandlesize) {
|
||||
isc_nmsocket_t *nsock = NULL, *tsock = NULL;
|
||||
isc__netievent_tlsconnect_t *ievent = NULL;
|
||||
isc_result_t result = ISC_R_DEFAULT;
|
||||
|
||||
REQUIRE(VALID_NM(mgr));
|
||||
|
||||
nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
|
||||
isc__nmsocket_init(nsock, mgr, isc_nm_tlssocket, local);
|
||||
nsock->extrahandlesize = extrahandlesize;
|
||||
nsock->result = ISC_R_DEFAULT;
|
||||
nsock->connect_cb = cb;
|
||||
nsock->connect_cbarg = cbarg;
|
||||
nsock->connect_timeout = timeout;
|
||||
nsock->tlsstream.ctx = ctx;
|
||||
|
||||
ievent = isc__nm_get_netievent_tlsconnect(mgr, nsock);
|
||||
ievent->local = local->addr;
|
||||
ievent->peer = peer->addr;
|
||||
ievent->ctx = ctx;
|
||||
|
||||
isc__nmsocket_attach(nsock, &tsock);
|
||||
if (isc__nm_in_netthread()) {
|
||||
nsock->tid = isc_nm_tid();
|
||||
isc__nm_async_tlsconnect(&mgr->workers[nsock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
isc__nm_put_netievent_tlsconnect(mgr, ievent);
|
||||
} else {
|
||||
nsock->tid = isc_random_uniform(mgr->nworkers);
|
||||
isc__nm_enqueue_ievent(&mgr->workers[nsock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
|
||||
LOCK(&nsock->lock);
|
||||
result = nsock->result;
|
||||
while (result == ISC_R_DEFAULT) {
|
||||
WAIT(&nsock->cond, &nsock->lock);
|
||||
result = nsock->result;
|
||||
}
|
||||
atomic_store(&nsock->active, true);
|
||||
BROADCAST(&nsock->scond);
|
||||
UNLOCK(&nsock->lock);
|
||||
INSIST(VALID_NMSOCK(nsock));
|
||||
isc__nmsocket_detach(&tsock);
|
||||
|
||||
INSIST(result != ISC_R_DEFAULT);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
tls_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(tlssock));
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
tlssock->connect_cb(handle, result, tlssock->connect_cbarg);
|
||||
update_result(tlssock, result);
|
||||
tls_close_direct(tlssock);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent_tlsconnect_t *ievent =
|
||||
(isc__netievent_tlsconnect_t *)ev0;
|
||||
isc_nmsocket_t *tlssock = ievent->sock;
|
||||
isc_result_t result;
|
||||
int r;
|
||||
isc_nmhandle_t *tlshandle = NULL;
|
||||
|
||||
UNUSED(worker);
|
||||
|
||||
/*
|
||||
* We need to initialize SSL now to reference SSL_CTX properly.
|
||||
*/
|
||||
tlssock->tlsstream.ssl = SSL_new(tlssock->tlsstream.ctx);
|
||||
if (tlssock->tlsstream.ssl == NULL) {
|
||||
result = ISC_R_TLSERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
tlssock->tid = isc_nm_tid();
|
||||
r = uv_timer_init(&tlssock->mgr->workers[isc_nm_tid()].loop,
|
||||
&tlssock->timer);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
|
||||
tlssock->timer.data = tlssock;
|
||||
tlssock->timer_initialized = true;
|
||||
tlssock->tlsstream.state = TLS_INIT;
|
||||
|
||||
result = isc_nm_tcpconnect(worker->mgr, (isc_nmiface_t *)&ievent->local,
|
||||
(isc_nmiface_t *)&ievent->peer,
|
||||
tls_connect_cb, tlssock,
|
||||
tlssock->connect_timeout, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
error:
|
||||
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
|
||||
atomic_store(&tlssock->closed, true);
|
||||
tlssock->connect_cb(tlshandle, result, tlssock->connect_cbarg);
|
||||
isc_nmhandle_detach(&tlshandle);
|
||||
update_result(tlssock, result);
|
||||
tls_close_direct(tlssock);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_cancelread(isc_nmhandle_t *handle) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
isc__netievent_tlscancel_t *ievent = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
|
||||
sock = handle->sock;
|
||||
|
||||
REQUIRE(sock->type == isc_nm_tlssocket);
|
||||
|
||||
ievent = isc__nm_get_netievent_tlscancel(sock->mgr, sock, handle);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_tlscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent_tlscancel_t *ievent = (isc__netievent_tlscancel_t *)ev0;
|
||||
isc_nmsocket_t *sock = ievent->sock;
|
||||
isc_nmhandle_t *handle = ievent->handle;
|
||||
|
||||
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) {
|
||||
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;
|
||||
tls_do_bio(ievent->sock);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
|
||||
if (sock->tlsstream.tlslistener) {
|
||||
REQUIRE(VALID_NMSOCK(sock->tlsstream.tlslistener));
|
||||
isc__nmsocket_detach(&sock->tlsstream.tlslistener);
|
||||
}
|
||||
}
|
||||
@@ -478,8 +478,8 @@ free:
|
||||
* another thread.
|
||||
*/
|
||||
void
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg) {
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
isc_nmsocket_t *sock = handle->sock;
|
||||
isc_nmsocket_t *psock = NULL, *rsock = sock;
|
||||
isc_sockaddr_t *peer = &handle->peer;
|
||||
|
||||
@@ -20,6 +20,7 @@ TESTS = \
|
||||
buffer_test \
|
||||
counter_test \
|
||||
crc64_test \
|
||||
doh_test \
|
||||
errno_test \
|
||||
file_test \
|
||||
hash_test \
|
||||
@@ -44,17 +45,27 @@ TESTS = \
|
||||
symtab_test \
|
||||
task_test \
|
||||
taskpool_test \
|
||||
tcp_test \
|
||||
tcp_quota_test \
|
||||
tcp_test \
|
||||
tcpdns_test \
|
||||
tlsdns_test \
|
||||
time_test \
|
||||
timer_test \
|
||||
tlsdns_test \
|
||||
udp_test
|
||||
|
||||
check_PROGRAMS = \
|
||||
$(TESTS)
|
||||
|
||||
doh_test_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(OPENSSL_CFLAGS) \
|
||||
$(LIBUV_CFLAGS)
|
||||
|
||||
doh_test_LDADD = \
|
||||
$(LDADD) \
|
||||
$(OPENSSL_LIBS) \
|
||||
$(LIBUV_LIBS)
|
||||
|
||||
hmac_test_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(OPENSSL_CFLAGS)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -127,8 +127,10 @@ isc_tlsctx_createclient(isc_tlsctx_t **ctxp) {
|
||||
#if HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
||||
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
|
||||
#else
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
|
||||
SSL_CTX_set_options(
|
||||
ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
|
||||
SSL_OP_NO_TLSv1_1 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
#endif
|
||||
|
||||
*ctxp = ctx;
|
||||
|
||||
+667
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/url.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#ifndef BIT_AT
|
||||
#define BIT_AT(a, i) \
|
||||
(!!((unsigned int)(a)[(unsigned int)(i) >> 3] & \
|
||||
(1 << ((unsigned int)(i)&7))))
|
||||
#endif
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
#define T(v) 0
|
||||
#else
|
||||
#define T(v) v
|
||||
#endif
|
||||
|
||||
static const uint8_t normal_url_char[32] = {
|
||||
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
|
||||
0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
|
||||
/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
||||
0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
|
||||
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
|
||||
/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
|
||||
};
|
||||
|
||||
#undef T
|
||||
|
||||
typedef enum {
|
||||
s_dead = 1, /* important that this is > 0 */
|
||||
|
||||
s_start_req_or_res,
|
||||
s_res_or_resp_H,
|
||||
s_start_res,
|
||||
s_res_H,
|
||||
s_res_HT,
|
||||
s_res_HTT,
|
||||
s_res_HTTP,
|
||||
s_res_http_major,
|
||||
s_res_http_dot,
|
||||
s_res_http_minor,
|
||||
s_res_http_end,
|
||||
s_res_first_status_code,
|
||||
s_res_status_code,
|
||||
s_res_status_start,
|
||||
s_res_status,
|
||||
s_res_line_almost_done,
|
||||
|
||||
s_start_req,
|
||||
|
||||
s_req_method,
|
||||
s_req_spaces_before_url,
|
||||
s_req_schema,
|
||||
s_req_schema_slash,
|
||||
s_req_schema_slash_slash,
|
||||
s_req_server_start,
|
||||
s_req_server,
|
||||
s_req_server_with_at,
|
||||
s_req_path,
|
||||
s_req_query_string_start,
|
||||
s_req_query_string,
|
||||
s_req_fragment_start,
|
||||
s_req_fragment,
|
||||
s_req_http_start,
|
||||
s_req_http_H,
|
||||
s_req_http_HT,
|
||||
s_req_http_HTT,
|
||||
s_req_http_HTTP,
|
||||
s_req_http_I,
|
||||
s_req_http_IC,
|
||||
s_req_http_major,
|
||||
s_req_http_dot,
|
||||
s_req_http_minor,
|
||||
s_req_http_end,
|
||||
s_req_line_almost_done,
|
||||
|
||||
s_header_field_start,
|
||||
s_header_field,
|
||||
s_header_value_discard_ws,
|
||||
s_header_value_discard_ws_almost_done,
|
||||
s_header_value_discard_lws,
|
||||
s_header_value_start,
|
||||
s_header_value,
|
||||
s_header_value_lws,
|
||||
|
||||
s_header_almost_done,
|
||||
|
||||
s_chunk_size_start,
|
||||
s_chunk_size,
|
||||
s_chunk_parameters,
|
||||
s_chunk_size_almost_done,
|
||||
|
||||
s_headers_almost_done,
|
||||
s_headers_done,
|
||||
|
||||
/*
|
||||
* Important: 's_headers_done' must be the last 'header' state. All
|
||||
* states beyond this must be 'body' states. It is used for overflow
|
||||
* checking. See the PARSING_HEADER() macro.
|
||||
*/
|
||||
|
||||
s_chunk_data,
|
||||
s_chunk_data_almost_done,
|
||||
s_chunk_data_done,
|
||||
|
||||
s_body_identity,
|
||||
s_body_identity_eof,
|
||||
|
||||
s_message_done
|
||||
} state_t;
|
||||
|
||||
typedef enum {
|
||||
s_http_host_dead = 1,
|
||||
s_http_userinfo_start,
|
||||
s_http_userinfo,
|
||||
s_http_host_start,
|
||||
s_http_host_v6_start,
|
||||
s_http_host,
|
||||
s_http_host_v6,
|
||||
s_http_host_v6_end,
|
||||
s_http_host_v6_zone_start,
|
||||
s_http_host_v6_zone,
|
||||
s_http_host_port_start,
|
||||
s_http_host_port
|
||||
} host_state_t;
|
||||
|
||||
/* Macros for character classes; depends on strict-mode */
|
||||
#define IS_MARK(c) \
|
||||
((c) == '-' || (c) == '_' || (c) == '.' || (c) == '!' || (c) == '~' || \
|
||||
(c) == '*' || (c) == '\'' || (c) == '(' || (c) == ')')
|
||||
#define IS_USERINFO_CHAR(c) \
|
||||
(isalnum(c) || IS_MARK(c) || (c) == '%' || (c) == ';' || (c) == ':' || \
|
||||
(c) == '&' || (c) == '=' || (c) == '+' || (c) == '$' || (c) == ',')
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
|
||||
#define IS_HOST_CHAR(c) (isalnum(c) || (c) == '.' || (c) == '-')
|
||||
#else
|
||||
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c) || ((c)&0x80))
|
||||
#define IS_HOST_CHAR(c) (isalnum(c) || (c) == '.' || (c) == '-' || (c) == '_')
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Our URL parser.
|
||||
*
|
||||
* This is designed to be shared by http_parser_execute() for URL validation,
|
||||
* hence it has a state transition + byte-for-byte interface. In addition, it
|
||||
* is meant to be embedded in http_parser_parse_url(), which does the dirty
|
||||
* work of turning state transitions URL components for its API.
|
||||
*
|
||||
* This function should only be invoked with non-space characters. It is
|
||||
* assumed that the caller cares about (and can detect) the transition between
|
||||
* URL and non-URL states by looking for these.
|
||||
*/
|
||||
static state_t
|
||||
parse_url_char(state_t s, const char ch) {
|
||||
if (ch == ' ' || ch == '\r' || ch == '\n') {
|
||||
return (s_dead);
|
||||
}
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
if (ch == '\t' || ch == '\f') {
|
||||
return (s_dead);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (s) {
|
||||
case s_req_spaces_before_url:
|
||||
/* Proxied requests are followed by scheme of an absolute URI
|
||||
* (alpha). All methods except CONNECT are followed by '/' or
|
||||
* '*'.
|
||||
*/
|
||||
|
||||
if (ch == '/' || ch == '*') {
|
||||
return (s_req_path);
|
||||
}
|
||||
|
||||
if (isalpha(ch)) {
|
||||
return (s_req_schema);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema:
|
||||
if (isalpha(ch)) {
|
||||
return (s);
|
||||
}
|
||||
|
||||
if (ch == ':') {
|
||||
return (s_req_schema_slash);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema_slash:
|
||||
if (ch == '/') {
|
||||
return (s_req_schema_slash_slash);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema_slash_slash:
|
||||
if (ch == '/') {
|
||||
return (s_req_server_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_server_with_at:
|
||||
if (ch == '@') {
|
||||
return (s_dead);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_req_server_start:
|
||||
case s_req_server:
|
||||
if (ch == '/') {
|
||||
return (s_req_path);
|
||||
}
|
||||
|
||||
if (ch == '?') {
|
||||
return (s_req_query_string_start);
|
||||
}
|
||||
|
||||
if (ch == '@') {
|
||||
return (s_req_server_with_at);
|
||||
}
|
||||
|
||||
if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
|
||||
return (s_req_server);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_path:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
return (s_req_query_string_start);
|
||||
|
||||
case '#':
|
||||
return (s_req_fragment_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_query_string_start:
|
||||
case s_req_query_string:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s_req_query_string);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
/* allow extra '?' in query string */
|
||||
return (s_req_query_string);
|
||||
|
||||
case '#':
|
||||
return (s_req_fragment_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_fragment_start:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s_req_fragment);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
return (s_req_fragment);
|
||||
|
||||
case '#':
|
||||
return (s);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_fragment:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
case '#':
|
||||
return (s);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We should never fall out of the switch above unless there's an
|
||||
* error.
|
||||
*/
|
||||
return (s_dead);
|
||||
}
|
||||
|
||||
static host_state_t
|
||||
http_parse_host_char(host_state_t s, const char ch) {
|
||||
switch (s) {
|
||||
case s_http_userinfo:
|
||||
case s_http_userinfo_start:
|
||||
if (ch == '@') {
|
||||
return (s_http_host_start);
|
||||
}
|
||||
|
||||
if (IS_USERINFO_CHAR(ch)) {
|
||||
return (s_http_userinfo);
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_start:
|
||||
if (ch == '[') {
|
||||
return (s_http_host_v6_start);
|
||||
}
|
||||
|
||||
if (IS_HOST_CHAR(ch)) {
|
||||
return (s_http_host);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_http_host:
|
||||
if (IS_HOST_CHAR(ch)) {
|
||||
return (s_http_host);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_end:
|
||||
if (ch == ':') {
|
||||
return (s_http_host_port_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_http_host_v6:
|
||||
if (ch == ']') {
|
||||
return (s_http_host_v6_end);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_start:
|
||||
if (isxdigit(ch) || ch == ':' || ch == '.') {
|
||||
return (s_http_host_v6);
|
||||
}
|
||||
|
||||
if (s == s_http_host_v6 && ch == '%') {
|
||||
return (s_http_host_v6_zone_start);
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_v6_zone:
|
||||
if (ch == ']') {
|
||||
return (s_http_host_v6_end);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_zone_start:
|
||||
/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
|
||||
if (isalnum(ch) || ch == '%' || ch == '.' || ch == '-' ||
|
||||
ch == '_' || ch == '~')
|
||||
{
|
||||
return (s_http_host_v6_zone);
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_port:
|
||||
case s_http_host_port_start:
|
||||
if (isdigit(ch)) {
|
||||
return (s_http_host_port);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (s_http_host_dead);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
http_parse_host(const char *buf, isc_url_parser_t *up, int found_at) {
|
||||
host_state_t s;
|
||||
const char *p = NULL;
|
||||
size_t buflen = up->field_data[ISC_UF_HOST].off +
|
||||
up->field_data[ISC_UF_HOST].len;
|
||||
|
||||
REQUIRE((up->field_set & (1 << ISC_UF_HOST)) != 0);
|
||||
|
||||
up->field_data[ISC_UF_HOST].len = 0;
|
||||
|
||||
s = found_at ? s_http_userinfo_start : s_http_host_start;
|
||||
|
||||
for (p = buf + up->field_data[ISC_UF_HOST].off; p < buf + buflen; p++) {
|
||||
host_state_t new_s = http_parse_host_char(s, *p);
|
||||
|
||||
if (new_s == s_http_host_dead) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
switch (new_s) {
|
||||
case s_http_host:
|
||||
if (s != s_http_host) {
|
||||
up->field_data[ISC_UF_HOST].off =
|
||||
(uint16_t)(p - buf);
|
||||
}
|
||||
up->field_data[ISC_UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_v6:
|
||||
if (s != s_http_host_v6) {
|
||||
up->field_data[ISC_UF_HOST].off =
|
||||
(uint16_t)(p - buf);
|
||||
}
|
||||
up->field_data[ISC_UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_v6_zone_start:
|
||||
case s_http_host_v6_zone:
|
||||
up->field_data[ISC_UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_port:
|
||||
if (s != s_http_host_port) {
|
||||
up->field_data[ISC_UF_PORT].off =
|
||||
(uint16_t)(p - buf);
|
||||
up->field_data[ISC_UF_PORT].len = 0;
|
||||
up->field_set |= (1 << ISC_UF_PORT);
|
||||
}
|
||||
up->field_data[ISC_UF_PORT].len++;
|
||||
break;
|
||||
|
||||
case s_http_userinfo:
|
||||
if (s != s_http_userinfo) {
|
||||
up->field_data[ISC_UF_USERINFO].off =
|
||||
(uint16_t)(p - buf);
|
||||
up->field_data[ISC_UF_USERINFO].len = 0;
|
||||
up->field_set |= (1 << ISC_UF_USERINFO);
|
||||
}
|
||||
up->field_data[ISC_UF_USERINFO].len++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s = new_s;
|
||||
}
|
||||
|
||||
/* Make sure we don't end somewhere unexpected */
|
||||
switch (s) {
|
||||
case s_http_host_start:
|
||||
case s_http_host_v6_start:
|
||||
case s_http_host_v6:
|
||||
case s_http_host_v6_zone_start:
|
||||
case s_http_host_v6_zone:
|
||||
case s_http_host_port_start:
|
||||
case s_http_userinfo:
|
||||
case s_http_userinfo_start:
|
||||
return (ISC_R_FAILURE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_url_parse(const char *buf, size_t buflen, bool is_connect,
|
||||
isc_url_parser_t *up) {
|
||||
state_t s;
|
||||
isc_url_field_t uf, old_uf;
|
||||
int found_at = 0;
|
||||
const char *p = NULL;
|
||||
|
||||
if (buflen == 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
up->port = up->field_set = 0;
|
||||
s = is_connect ? s_req_server_start : s_req_spaces_before_url;
|
||||
old_uf = ISC_UF_MAX;
|
||||
|
||||
for (p = buf; p < buf + buflen; p++) {
|
||||
s = parse_url_char(s, *p);
|
||||
|
||||
/* Figure out the next field that we're operating on */
|
||||
switch (s) {
|
||||
case s_dead:
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
/* Skip delimiters */
|
||||
case s_req_schema_slash:
|
||||
case s_req_schema_slash_slash:
|
||||
case s_req_server_start:
|
||||
case s_req_query_string_start:
|
||||
case s_req_fragment_start:
|
||||
continue;
|
||||
|
||||
case s_req_schema:
|
||||
uf = ISC_UF_SCHEMA;
|
||||
break;
|
||||
|
||||
case s_req_server_with_at:
|
||||
found_at = 1;
|
||||
/* FALLTHROUGH */
|
||||
case s_req_server:
|
||||
uf = ISC_UF_HOST;
|
||||
break;
|
||||
|
||||
case s_req_path:
|
||||
uf = ISC_UF_PATH;
|
||||
break;
|
||||
|
||||
case s_req_query_string:
|
||||
uf = ISC_UF_QUERY;
|
||||
break;
|
||||
|
||||
case s_req_fragment:
|
||||
uf = ISC_UF_FRAGMENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
/* Nothing's changed; soldier on */
|
||||
if (uf == old_uf) {
|
||||
up->field_data[uf].len++;
|
||||
continue;
|
||||
}
|
||||
|
||||
up->field_data[uf].off = (uint16_t)(p - buf);
|
||||
up->field_data[uf].len = 1;
|
||||
|
||||
up->field_set |= (1 << uf);
|
||||
old_uf = uf;
|
||||
}
|
||||
|
||||
/* host must be present if there is a schema */
|
||||
/* parsing http:///toto will fail */
|
||||
if ((up->field_set & (1 << ISC_UF_SCHEMA)) &&
|
||||
(up->field_set & (1 << ISC_UF_HOST)) == 0)
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (up->field_set & (1 << ISC_UF_HOST)) {
|
||||
isc_result_t result;
|
||||
|
||||
result = http_parse_host(buf, up, found_at);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
/* CONNECT requests can only contain "hostname:port" */
|
||||
if (is_connect &&
|
||||
up->field_set != ((1 << ISC_UF_HOST) | (1 << ISC_UF_PORT))) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (up->field_set & (1 << ISC_UF_PORT)) {
|
||||
uint16_t off;
|
||||
uint16_t len;
|
||||
const char *pp = NULL;
|
||||
const char *end = NULL;
|
||||
unsigned long v;
|
||||
|
||||
off = up->field_data[ISC_UF_PORT].off;
|
||||
len = up->field_data[ISC_UF_PORT].len;
|
||||
end = buf + off + len;
|
||||
|
||||
/*
|
||||
* NOTE: The characters are already validated and are in the
|
||||
* [0-9] range
|
||||
*/
|
||||
INSIST(off + len <= buflen);
|
||||
|
||||
v = 0;
|
||||
for (pp = buf + off; pp < end; pp++) {
|
||||
v *= 10;
|
||||
v += *pp - '0';
|
||||
|
||||
/* Ports have a max value of 2^16 */
|
||||
if (v > 0xffff) {
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
}
|
||||
|
||||
up->port = (uint16_t)v;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -448,7 +448,14 @@ 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_httpconnect
|
||||
isc_nm_httprequest
|
||||
isc_nm_listenhttp
|
||||
isc_nm_listentcpdns
|
||||
isc_nm_listentls
|
||||
isc_nm_listentlsdns
|
||||
isc_nm_listentcp
|
||||
isc_nm_listenudp
|
||||
@@ -467,6 +474,7 @@ isc_nm_settimeouts
|
||||
isc_nm_tcpdns_keepalive
|
||||
isc_nm_tcpdns_sequential
|
||||
isc_nm_tid
|
||||
isc_nm_tlsconnect
|
||||
isc_nm_tlsdnsconnect
|
||||
isc_nm_udpconnect
|
||||
isc_nmsocket_close
|
||||
@@ -706,6 +714,7 @@ isc_tlsctx_createserver
|
||||
isc_tlsctx_free
|
||||
isc_tm_timegm
|
||||
isc_tm_strptime
|
||||
isc_url_parse
|
||||
isc_utf8_bom
|
||||
isc_utf8_valid
|
||||
isc_win32os_versioncheck
|
||||
|
||||
@@ -260,6 +260,9 @@
|
||||
<ClInclude Include="..\include\isc\types.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\url.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\utf8.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -608,12 +611,15 @@
|
||||
<ClCompile Include="..\timer.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tls.c">
|
||||
<ClCompile Include="..\tlsstream.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tm.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\url.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\utf8.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -62,11 +62,11 @@
|
||||
@IF PKCS11
|
||||
<PreprocessorDefinitions>BIND9;@PK11_LIB_LOCATION@WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@ELSE PKCS11
|
||||
<PreprocessorDefinitions>BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@END PKCS11
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
|
||||
@@ -80,7 +80,7 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@NGHTTP2_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile>
|
||||
<ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary>
|
||||
</Link>
|
||||
@@ -116,6 +116,9 @@ echo Copying the libxml DLL.
|
||||
copy @LIBXML2_DLL@ ..\Build\Debug\
|
||||
@END LIBXML2
|
||||
|
||||
echo Copying nghttp2 DLL.
|
||||
copy @NGHTTP2_DLL@ ..\Build\Debug\
|
||||
|
||||
@IF GSSAPI
|
||||
echo Copying the GSSAPI and KRB5 DLLs.
|
||||
|
||||
@@ -163,11 +166,11 @@ copy InstallFiles ..\Build\Debug\
|
||||
@IF PKCS11
|
||||
<PreprocessorDefinitions>BIND9;@PK11_LIB_LOCATION@WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@ELSE PKCS11
|
||||
<PreprocessorDefinitions>BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@END PKCS11
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
@@ -184,7 +187,7 @@ copy InstallFiles ..\Build\Debug\
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@NGHTTP2_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile>
|
||||
<ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
@@ -211,6 +214,9 @@ copy @OPENSSL_PATH@\LICENSE ..\Build\Release\OpenSSL-LICENSE
|
||||
echo Copying libuv DLL.
|
||||
copy @LIBUV_DLL@ ..\Build\Release\
|
||||
|
||||
echo Copying nghttp2 DLL.
|
||||
copy @NGHTTP2_DLL@ ..\Build\Release\
|
||||
|
||||
@IF LIBXML2
|
||||
echo Copying the libxml DLL.
|
||||
|
||||
@@ -337,6 +343,7 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClInclude Include="..\include\isc\tls.h" />
|
||||
<ClInclude Include="..\include\isc\tm.h" />
|
||||
<ClInclude Include="..\include\isc\types.h" />
|
||||
<ClInclude Include="..\include\isc\url.h" />
|
||||
<ClInclude Include="..\include\isc\utf8.h" />
|
||||
<ClInclude Include="..\include\isc\util.h" />
|
||||
@IF PKCS11
|
||||
@@ -408,13 +415,15 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClCompile Include="..\mem.c" />
|
||||
<ClCompile Include="..\mutexblock.c" />
|
||||
<ClCompile Include="..\netaddr.c" />
|
||||
<ClCompile Include="..\netmgr\http.c" />
|
||||
<ClCompile Include="..\netmgr\netmgr.c" />
|
||||
<ClCompile Include="..\netmgr\tcp.c" />
|
||||
<ClCompile Include="..\netmgr\udp.c" />
|
||||
<ClCompile Include="..\netmgr\uverr2result.c" />
|
||||
<ClCompile Include="..\netmgr\uv-compat.c" />
|
||||
<ClCompile Include="..\netmgr\tcpdns.c" />
|
||||
<ClCompile Include="..\netmgr\tlsstream.c" />
|
||||
<ClCompile Include="..\netmgr\udp.c" />
|
||||
<ClCompile Include="..\netmgr\tlsdns.c" />
|
||||
<ClCompile Include="..\netmgr\uv-compat.c" />
|
||||
<ClCompile Include="..\netmgr\uverr2result.c" />
|
||||
<ClCompile Include="..\netscope.c" />
|
||||
<ClCompile Include="..\nonce.c" />
|
||||
<ClCompile Include="..\openssl_shim.c" />
|
||||
@@ -442,6 +451,7 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClCompile Include="..\timer.c" />
|
||||
<ClCompile Include="..\tls.c" />
|
||||
<ClCompile Include="..\tm.c" />
|
||||
<ClCompile Include="..\url.c" />
|
||||
<ClCompile Include="..\utf8.c" />
|
||||
@IF PKCS11
|
||||
<ClCompile Include="..\pk11.c" />
|
||||
|
||||
@@ -7,17 +7,21 @@ libisccfg_la_HEADERS = \
|
||||
include/isccfg/aclconf.h \
|
||||
include/isccfg/cfg.h \
|
||||
include/isccfg/grammar.h \
|
||||
include/isccfg/httpconf.h \
|
||||
include/isccfg/kaspconf.h \
|
||||
include/isccfg/log.h \
|
||||
include/isccfg/namedconf.h
|
||||
include/isccfg/namedconf.h \
|
||||
include/isccfg/tlsconf.h
|
||||
|
||||
libisccfg_la_SOURCES = \
|
||||
$(libisccfg_la_HEADERS) \
|
||||
aclconf.c \
|
||||
httpconf.c \
|
||||
dnsconf.c \
|
||||
kaspconf.c \
|
||||
log.c \
|
||||
namedconf.c \
|
||||
tlsconf.c \
|
||||
parser.c
|
||||
|
||||
libisccfg_la_CPPFLAGS = \
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccfg/grammar.h>
|
||||
#include <isccfg/httpconf.h>
|
||||
|
||||
void
|
||||
cfg_http_storage_init(isc_mem_t *mctx, isc_cfg_http_storage_t *storage) {
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
memset(storage, 0, sizeof(*storage));
|
||||
isc_mem_attach(mctx, &storage->mctx);
|
||||
ISC_LIST_INIT(storage->list);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_http_storage_uninit(isc_cfg_http_storage_t *storage) {
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
cfg_http_storage_clear(storage);
|
||||
isc_mem_detach(&storage->mctx);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_http_storage_clear(isc_cfg_http_storage_t *storage) {
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
isc_mem_t *mctx = storage->mctx;
|
||||
|
||||
if (!ISC_LIST_EMPTY(storage->list)) {
|
||||
isc_cfg_http_obj_t *http = ISC_LIST_HEAD(storage->list);
|
||||
while (http != NULL) {
|
||||
isc_cfg_http_obj_t *next = ISC_LIST_NEXT(http, link);
|
||||
ISC_LIST_DEQUEUE(storage->list, http, link);
|
||||
storage->nservers--;
|
||||
|
||||
isc_mem_free(mctx, http->name);
|
||||
|
||||
if (!ISC_LIST_EMPTY(http->endpoints)) {
|
||||
isc_cfg_http_endpoint_t *ep =
|
||||
ISC_LIST_HEAD(http->endpoints);
|
||||
while (ep != NULL) {
|
||||
isc_cfg_http_endpoint_t *epnext =
|
||||
ISC_LIST_NEXT(ep, link);
|
||||
isc_mem_free(mctx, ep->path);
|
||||
isc_mem_put(mctx, ep, sizeof(*ep));
|
||||
ep = epnext;
|
||||
http->nendponts--;
|
||||
}
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, http, sizeof(*http));
|
||||
http = next;
|
||||
}
|
||||
}
|
||||
|
||||
INSIST(storage->nservers == 0);
|
||||
}
|
||||
|
||||
isc_cfg_http_obj_t *
|
||||
cfg_http_find(const char *name, isc_cfg_http_storage_t *storage) {
|
||||
isc_cfg_http_obj_t *http = NULL;
|
||||
REQUIRE(name != NULL && *name != '\0');
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
for (http = ISC_LIST_HEAD(storage->list); http != NULL;
|
||||
http = ISC_LIST_NEXT(http, link))
|
||||
{
|
||||
if (strcasecmp(name, http->name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (http);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
push_http_obj(const cfg_obj_t *map, isc_cfg_http_storage_t *storage) {
|
||||
isc_mem_t *mctx = storage->mctx;
|
||||
isc_cfg_http_obj_t *new;
|
||||
const cfg_obj_t *endpoints = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
|
||||
if (!cfg_obj_ismap(map) || map->value.map.id == NULL ||
|
||||
!cfg_obj_isstring(map->value.map.id))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_http_find(cfg_obj_asstring(map->value.map.id), storage) != NULL)
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_map_get(map, "endpoints", &endpoints) != ISC_R_SUCCESS ||
|
||||
!cfg_obj_islist(endpoints))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
INSIST(endpoints != NULL);
|
||||
|
||||
new = isc_mem_get(mctx, sizeof(*new));
|
||||
memset(new, 0, sizeof(*new));
|
||||
ISC_LIST_INIT(new->endpoints);
|
||||
new->name = isc_mem_strdup(mctx, cfg_obj_asstring(map->value.map.id));
|
||||
|
||||
for (elt = cfg_list_first(endpoints); elt != NULL;
|
||||
elt = cfg_list_next(elt)) {
|
||||
isc_cfg_http_endpoint_t *newep = NULL;
|
||||
const cfg_obj_t *endp = cfg_listelt_value(elt);
|
||||
newep = isc_mem_get(mctx, sizeof(*newep));
|
||||
ISC_LINK_INIT(newep, link);
|
||||
newep->path = isc_mem_strdup(mctx, cfg_obj_asstring(endp));
|
||||
|
||||
ISC_LIST_PREPEND(new->endpoints, newep, link);
|
||||
new->nendponts++;
|
||||
}
|
||||
|
||||
ISC_LINK_INIT(new, link);
|
||||
ISC_LIST_PREPEND(storage->list, new, link);
|
||||
storage->nservers++;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
cfg_http_storage_load(const cfg_obj_t *cfg_ctx,
|
||||
isc_cfg_http_storage_t *storage) {
|
||||
bool found = false;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *http = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
const cfg_obj_t *map = NULL;
|
||||
|
||||
REQUIRE(cfg_ctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
cfg_http_storage_clear(storage);
|
||||
result = cfg_map_get(cfg_ctx, "http", &http);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* No statements found, but it is fine. */
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
INSIST(http != NULL);
|
||||
|
||||
for (elt = cfg_list_first(http); elt != NULL; elt = cfg_list_next(elt))
|
||||
{
|
||||
map = cfg_listelt_value(elt);
|
||||
INSIST(map != NULL);
|
||||
found = true;
|
||||
result = push_http_obj(map, storage);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true && storage->nservers == 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ISCCFG_HTTPCONF_H
|
||||
#define ISCCFG_HTTPCONF_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
#include <isccfg/tlsconf.h>
|
||||
|
||||
typedef struct isc_cfg_http_endpoint {
|
||||
char *path;
|
||||
LINK(struct isc_cfg_http_endpoint) link;
|
||||
} isc_cfg_http_endpoint_t;
|
||||
|
||||
typedef struct isc_cfg_http_obj {
|
||||
char *name;
|
||||
LINK(struct isc_cfg_http_obj) link;
|
||||
ISC_LIST(isc_cfg_http_endpoint_t) endpoints;
|
||||
size_t nendponts;
|
||||
} isc_cfg_http_obj_t;
|
||||
|
||||
typedef struct isc_cfg_http_storage {
|
||||
isc_mem_t *mctx;
|
||||
ISC_LIST(isc_cfg_http_obj_t) list;
|
||||
size_t nservers;
|
||||
} isc_cfg_http_storage_t;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
cfg_http_storage_init(isc_mem_t *mctx, isc_cfg_http_storage_t *storage);
|
||||
|
||||
void
|
||||
cfg_http_storage_uninit(isc_cfg_http_storage_t *storage);
|
||||
|
||||
isc_result_t
|
||||
cfg_http_storage_load(const cfg_obj_t * cfg_ctx,
|
||||
isc_cfg_http_storage_t *storage);
|
||||
|
||||
isc_cfg_http_obj_t *
|
||||
cfg_http_find(const char *name, isc_cfg_http_storage_t *storage);
|
||||
|
||||
void
|
||||
cfg_http_storage_clear(isc_cfg_http_storage_t *storage);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISCCFG_HTTPCONF_H */
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ISCCFG_TLSCONF_H
|
||||
#define ISCCFG_TLSCONF_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
|
||||
typedef struct isc_cfg_tls_obj {
|
||||
char *name;
|
||||
char *key_file;
|
||||
char *cert_file;
|
||||
char *dh_param;
|
||||
char *protocols;
|
||||
char *ciphers;
|
||||
LINK(struct isc_cfg_tls_obj) link;
|
||||
} isc_cfg_tls_obj_t;
|
||||
|
||||
typedef struct isc_cfg_tls_data_storage {
|
||||
isc_mem_t *mctx;
|
||||
size_t count;
|
||||
ISC_LIST(isc_cfg_tls_obj_t) list;
|
||||
} isc_cfg_tls_data_storage_t;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
cfg_tls_storage_init(isc_mem_t *mctx, isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
void
|
||||
cfg_tls_storage_uninit(isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
isc_result_t
|
||||
cfg_tls_storage_load(const cfg_obj_t * cfg_ctx,
|
||||
isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
isc_cfg_tls_obj_t *
|
||||
cfg_tls_storage_find(const char *name, isc_cfg_tls_data_storage_t *storage);
|
||||
/*
|
||||
* Looks for TLS key/certificate pair.
|
||||
*/
|
||||
|
||||
void
|
||||
cfg_tls_storage_clear(isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISCCFG_TLSCONF_H */
|
||||
@@ -81,6 +81,7 @@ static cfg_type_t cfg_type_bracketed_dscpsockaddrlist;
|
||||
static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
|
||||
static cfg_type_t cfg_type_bracketed_netaddrlist;
|
||||
static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
|
||||
static cfg_type_t cfg_type_bracketed_qstring_list;
|
||||
static cfg_type_t cfg_type_controls;
|
||||
static cfg_type_t cfg_type_controls_sockaddr;
|
||||
static cfg_type_t cfg_type_destinationlist;
|
||||
@@ -91,6 +92,7 @@ static cfg_type_t cfg_type_dnstap;
|
||||
static cfg_type_t cfg_type_dnstapoutput;
|
||||
static cfg_type_t cfg_type_dyndb;
|
||||
static cfg_type_t cfg_type_plugin;
|
||||
static cfg_type_t cfg_type_http_description;
|
||||
static cfg_type_t cfg_type_ixfrdifftype;
|
||||
static cfg_type_t cfg_type_ixfrratio;
|
||||
static cfg_type_t cfg_type_key;
|
||||
@@ -108,6 +110,7 @@ static cfg_type_t cfg_type_optional_allow;
|
||||
static cfg_type_t cfg_type_optional_class;
|
||||
static cfg_type_t cfg_type_optional_dscp;
|
||||
static cfg_type_t cfg_type_optional_facility;
|
||||
static cfg_type_t cfg_type_optional_http;
|
||||
static cfg_type_t cfg_type_optional_keyref;
|
||||
static cfg_type_t cfg_type_optional_port;
|
||||
static cfg_type_t cfg_type_optional_uint32;
|
||||
@@ -151,6 +154,7 @@ static cfg_tuplefielddef_t listenon_fields[] = {
|
||||
{ "port", &cfg_type_optional_port, 0 },
|
||||
{ "dscp", &cfg_type_optional_dscp, 0 },
|
||||
{ "tls", &cfg_type_optional_tls, 0 },
|
||||
{ "http", &cfg_type_optional_http, 0 },
|
||||
{ "acl", &cfg_type_bracketed_aml, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
@@ -1088,6 +1092,7 @@ static cfg_clausedef_t namedconf_clauses[] = {
|
||||
{ "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "dnssec-policy", &cfg_type_dnssecpolicy, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "http", &cfg_type_http_description, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "logging", &cfg_type_logging, 0 },
|
||||
{ "lwres", NULL, CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_ANCIENT },
|
||||
{ "masters", &cfg_type_primaries, CFG_CLAUSEFLAG_MULTI },
|
||||
@@ -1221,6 +1226,8 @@ static cfg_clausedef_t options_clauses[] = {
|
||||
{ "pid-file", &cfg_type_qstringornone, 0 },
|
||||
{ "port", &cfg_type_uint32, 0 },
|
||||
{ "tls-port", &cfg_type_uint32, 0 },
|
||||
{ "http-port", &cfg_type_uint32, 0 },
|
||||
{ "https-port", &cfg_type_uint32, 0 },
|
||||
{ "querylog", &cfg_type_boolean, 0 },
|
||||
{ "random-device", &cfg_type_qstringornone, 0 },
|
||||
{ "recursing-file", &cfg_type_qstring, 0 },
|
||||
@@ -3853,3 +3860,33 @@ static cfg_type_t cfg_type_optional_tls = {
|
||||
"tlsoptional", parse_optional_keyvalue, print_keyvalue,
|
||||
doc_optional_keyvalue, &cfg_rep_string, &tls_kw
|
||||
};
|
||||
|
||||
/* http and https */
|
||||
|
||||
static cfg_type_t cfg_type_bracketed_qstring_list = { "bracketed_qstring_list",
|
||||
cfg_parse_bracketed_list,
|
||||
cfg_print_bracketed_list,
|
||||
cfg_doc_bracketed_list,
|
||||
&cfg_rep_list,
|
||||
&cfg_type_qstring };
|
||||
|
||||
static cfg_clausedef_t cfg_http_description_clauses[] = {
|
||||
{ "endpoints", &cfg_type_bracketed_qstring_list,
|
||||
CFG_CLAUSEFLAG_EXPERIMENTAL },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static cfg_clausedef_t *http_description_clausesets[] = {
|
||||
cfg_http_description_clauses, NULL
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_http_description = {
|
||||
"http_desc", cfg_parse_named_map, cfg_print_map,
|
||||
cfg_doc_map, &cfg_rep_map, http_description_clausesets
|
||||
};
|
||||
|
||||
static keyword_type_t http_kw = { "http", &cfg_type_astring };
|
||||
static cfg_type_t cfg_type_optional_http = {
|
||||
"http_optional", parse_optional_keyvalue, print_keyvalue,
|
||||
doc_optional_keyvalue, &cfg_rep_string, &http_kw
|
||||
};
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccfg/grammar.h>
|
||||
#include <isccfg/tlsconf.h>
|
||||
|
||||
void
|
||||
cfg_tls_storage_init(isc_mem_t *mctx, isc_cfg_tls_data_storage_t *storage) {
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
memset(storage, 0, sizeof(*storage));
|
||||
isc_mem_attach(mctx, &storage->mctx);
|
||||
ISC_LIST_INIT(storage->list);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_tls_storage_uninit(isc_cfg_tls_data_storage_t *storage) {
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
cfg_tls_storage_clear(storage);
|
||||
isc_mem_detach(&storage->mctx);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_tls_storage_clear(isc_cfg_tls_data_storage_t *storage) {
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
isc_mem_t *mctx = storage->mctx;
|
||||
|
||||
if (!ISC_LIST_EMPTY(storage->list)) {
|
||||
isc_cfg_tls_obj_t *tls_obj = ISC_LIST_HEAD(storage->list);
|
||||
while (tls_obj != NULL) {
|
||||
isc_cfg_tls_obj_t *next = ISC_LIST_NEXT(tls_obj, link);
|
||||
ISC_LIST_DEQUEUE(storage->list, tls_obj, link);
|
||||
storage->count--;
|
||||
|
||||
isc_mem_free(mctx, tls_obj->name);
|
||||
isc_mem_free(mctx, tls_obj->key_file);
|
||||
isc_mem_free(mctx, tls_obj->cert_file);
|
||||
|
||||
if (tls_obj->dh_param != NULL) {
|
||||
isc_mem_free(mctx, tls_obj->dh_param);
|
||||
}
|
||||
|
||||
if (tls_obj->protocols != NULL) {
|
||||
isc_mem_free(mctx, tls_obj->protocols);
|
||||
}
|
||||
|
||||
if (tls_obj->ciphers != NULL) {
|
||||
isc_mem_free(mctx, tls_obj->ciphers);
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, tls_obj, sizeof(*tls_obj));
|
||||
tls_obj = next;
|
||||
}
|
||||
}
|
||||
|
||||
INSIST(storage->count == 0);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
push_tls_obj(const cfg_obj_t *map, isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_mem_t *mctx = storage->mctx;
|
||||
isc_cfg_tls_obj_t *new;
|
||||
const cfg_obj_t *key_file = NULL, *cert_file = NULL, *dh_param = NULL,
|
||||
*protocols = NULL, *ciphers = NULL;
|
||||
|
||||
if (!cfg_obj_ismap(map) || map->value.map.id == NULL ||
|
||||
!cfg_obj_isstring(map->value.map.id))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_tls_storage_find(cfg_obj_asstring(map->value.map.id),
|
||||
storage) != NULL) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_map_get(map, "key-file", &key_file) != ISC_R_SUCCESS ||
|
||||
!cfg_obj_isstring(key_file))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_map_get(map, "cert-file", &cert_file) != ISC_R_SUCCESS) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
(void)cfg_map_get(map, "dh-param", &dh_param);
|
||||
(void)cfg_map_get(map, "protocols", &protocols);
|
||||
(void)cfg_map_get(map, "ciphers", &ciphers);
|
||||
|
||||
INSIST(key_file != NULL);
|
||||
INSIST(cert_file != NULL);
|
||||
|
||||
new = isc_mem_get(mctx, sizeof(*new));
|
||||
memset(new, 0, sizeof(*new));
|
||||
new->name = isc_mem_strdup(mctx, cfg_obj_asstring(map->value.map.id));
|
||||
new->key_file = isc_mem_strdup(mctx, cfg_obj_asstring(key_file));
|
||||
new->cert_file = isc_mem_strdup(mctx, cfg_obj_asstring(cert_file));
|
||||
|
||||
if (dh_param != NULL && cfg_obj_isstring(dh_param)) {
|
||||
new->dh_param = isc_mem_strdup(mctx,
|
||||
cfg_obj_asstring(dh_param));
|
||||
}
|
||||
|
||||
if (protocols != NULL && cfg_obj_isstring(protocols)) {
|
||||
new->protocols = isc_mem_strdup(mctx,
|
||||
cfg_obj_asstring(protocols));
|
||||
}
|
||||
|
||||
if (ciphers != NULL && cfg_obj_isstring(ciphers)) {
|
||||
new->ciphers = isc_mem_strdup(mctx, cfg_obj_asstring(ciphers));
|
||||
}
|
||||
|
||||
ISC_LINK_INIT(new, link);
|
||||
ISC_LIST_PREPEND(storage->list, new, link);
|
||||
storage->count++;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
cfg_tls_storage_load(const cfg_obj_t *cfg_ctx,
|
||||
isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool found = false;
|
||||
const cfg_obj_t *tls = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
const cfg_obj_t *map = NULL;
|
||||
|
||||
REQUIRE(cfg_ctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
result = cfg_map_get(cfg_ctx, "tls", &tls);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* No tls statements found, but it is fine. */
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
cfg_tls_storage_clear(storage);
|
||||
INSIST(tls != NULL);
|
||||
|
||||
for (elt = cfg_list_first(tls); elt != NULL; elt = cfg_list_next(elt)) {
|
||||
map = cfg_listelt_value(elt);
|
||||
INSIST(map != NULL);
|
||||
found = true;
|
||||
result = push_tls_obj(map, storage);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true && storage->count == 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_cfg_tls_obj_t *
|
||||
cfg_tls_storage_find(const char *name, isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_cfg_tls_obj_t *tls_obj = NULL;
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (tls_obj = ISC_LIST_HEAD(storage->list); tls_obj != NULL;
|
||||
tls_obj = ISC_LIST_NEXT(tls_obj, link))
|
||||
{
|
||||
if (strcasecmp(name, tls_obj->name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tls_obj;
|
||||
}
|
||||
@@ -23,6 +23,11 @@ cfg_doc_terminal
|
||||
cfg_doc_tuple
|
||||
cfg_doc_void
|
||||
cfg_gettoken
|
||||
cfg_http_storage_clear
|
||||
cfg_http_storage_init
|
||||
cfg_http_storage_uninit
|
||||
cfg_http_storage_load
|
||||
cfg_http_find
|
||||
cfg_is_enum
|
||||
cfg_kasp_fromconfig
|
||||
cfg_list_first
|
||||
@@ -65,6 +70,11 @@ cfg_obj_isuint64
|
||||
cfg_obj_isvoid
|
||||
cfg_obj_line
|
||||
cfg_obj_log
|
||||
cfg_tls_storage_clear
|
||||
cfg_tls_storage_init
|
||||
cfg_tls_storage_uninit
|
||||
cfg_tls_storage_load
|
||||
cfg_tls_storage_find
|
||||
cfg_parse_addressed_map
|
||||
cfg_parse_astring
|
||||
cfg_parse_boolean
|
||||
|
||||
@@ -27,12 +27,18 @@
|
||||
<ClCompile Include="..\dnsconf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\httpconf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\kaspconf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\log.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tlsconf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\namedconf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -50,12 +56,18 @@
|
||||
<ClInclude Include="..\include\isccfg\grammar.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isccfg\httpconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isccfg\kaspconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isccfg\log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isccfg\tlsconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isccfg\namedconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -120,9 +120,11 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\aclconf.c" />
|
||||
<ClCompile Include="..\dnsconf.c" />
|
||||
<ClCompile Include="..\httpconf.c" />
|
||||
<ClCompile Include="..\kaspconf.c" />
|
||||
<ClCompile Include="..\log.c" />
|
||||
<ClCompile Include="..\namedconf.c" />
|
||||
<ClCompile Include="..\tlsconf.c" />
|
||||
<ClCompile Include="..\parser.c" />
|
||||
<ClCompile Include="DLLMain.c" />
|
||||
</ItemGroup>
|
||||
@@ -130,9 +132,11 @@
|
||||
<ClInclude Include="..\include\isccfg\aclconf.h" />
|
||||
<ClInclude Include="..\include\isccfg\cfg.h" />
|
||||
<ClInclude Include="..\include\isccfg\grammar.h" />
|
||||
<ClInclude Include="..\include\isccfg\httpconf.h" />
|
||||
<ClInclude Include="..\include\isccfg\kaspconf.h" />
|
||||
<ClInclude Include="..\include\isccfg\log.h" />
|
||||
<ClInclude Include="..\include\isccfg\namedconf.h" />
|
||||
<ClInclude Include="..\include\isccfg\tlsconf.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\lib\isc\win32\libisc.vcxproj">
|
||||
|
||||
@@ -80,6 +80,8 @@ struct ns_interface {
|
||||
isc_socket_t * tcpsocket; /*%< TCP socket. */
|
||||
isc_nmsocket_t *udplistensocket;
|
||||
isc_nmsocket_t *tcplistensocket;
|
||||
isc_nmsocket_t *http_listensocket;
|
||||
isc_nmsocket_t *http_secure_listensocket;
|
||||
isc_dscp_t dscp; /*%< "listen-on" DSCP value */
|
||||
isc_refcount_t ntcpaccepting; /*%< Number of clients
|
||||
* ready to accept new
|
||||
|
||||
@@ -42,9 +42,12 @@ typedef struct ns_listenlist ns_listenlist_t;
|
||||
struct ns_listenelt {
|
||||
isc_mem_t * mctx;
|
||||
in_port_t port;
|
||||
bool is_http;
|
||||
isc_dscp_t dscp; /* -1 = not set, 0..63 */
|
||||
dns_acl_t * acl;
|
||||
isc_tlsctx_t *sslctx;
|
||||
char ** http_endpoints;
|
||||
size_t http_endpoints_number;
|
||||
ISC_LINK(ns_listenelt_t) link;
|
||||
};
|
||||
|
||||
@@ -66,6 +69,15 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
|
||||
* Create a listen-on list element.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
|
||||
dns_acl_t *acl, const char *key, const char *cert,
|
||||
char **endpoints, size_t nendpoints,
|
||||
ns_listenelt_t **target);
|
||||
/*%<
|
||||
* Create a listen-on list element for HTTP(S).
|
||||
*/
|
||||
|
||||
void
|
||||
ns_listenelt_destroy(ns_listenelt_t *elt);
|
||||
/*%<
|
||||
|
||||
@@ -437,6 +437,10 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ifp->tcplistensocket = NULL;
|
||||
ifp->http_listensocket = NULL;
|
||||
ifp->http_secure_listensocket = NULL;
|
||||
|
||||
*ifpret = ifp;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -539,6 +543,54 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
|
||||
size_t neps) {
|
||||
isc_result_t result;
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
result = isc_nm_listenhttp(ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr,
|
||||
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
|
||||
sslctx, &sock);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"creating %s socket: %s",
|
||||
sslctx ? "HTTPS" : "HTTP",
|
||||
isc_result_totext(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
if (sslctx) {
|
||||
ifp->http_secure_listensocket = sock;
|
||||
} else {
|
||||
ifp->http_listensocket = sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* We call this now to update the tcp-highwater statistic:
|
||||
* this is necessary because we are adding to the TCP quota just
|
||||
* by listening.
|
||||
*/
|
||||
result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"updating TCP stats: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
const char *name, ns_interface_t **ifpret, bool accept_tcp,
|
||||
@@ -555,6 +607,17 @@ ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
|
||||
ifp->dscp = elt->dscp;
|
||||
|
||||
if (elt->is_http) {
|
||||
result = ns_interface_listenhttp(ifp, elt->sslctx,
|
||||
elt->http_endpoints,
|
||||
elt->http_endpoints_number);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_interface;
|
||||
}
|
||||
*ifpret = ifp;
|
||||
return (result);
|
||||
}
|
||||
|
||||
if (elt->sslctx != NULL) {
|
||||
result = ns_interface_listentls(ifp, elt->sslctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@@ -611,6 +674,14 @@ ns_interface_shutdown(ns_interface_t *ifp) {
|
||||
isc_nm_stoplistening(ifp->tcplistensocket);
|
||||
isc_nmsocket_close(&ifp->tcplistensocket);
|
||||
}
|
||||
if (ifp->http_listensocket != NULL) {
|
||||
isc_nm_stoplistening(ifp->http_listensocket);
|
||||
isc_nmsocket_close(&ifp->http_listensocket);
|
||||
}
|
||||
if (ifp->http_secure_listensocket != NULL) {
|
||||
isc_nm_stoplistening(ifp->http_secure_listensocket);
|
||||
isc_nmsocket_close(&ifp->http_secure_listensocket);
|
||||
}
|
||||
if (ifp->clientmgr != NULL) {
|
||||
ns_clientmgr_destroy(&ifp->clientmgr);
|
||||
}
|
||||
|
||||
+48
-8
@@ -30,24 +30,56 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
|
||||
ns_listenelt_t **target) {
|
||||
ns_listenelt_t *elt = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_tlsctx_t *sslctx = NULL;
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
elt = isc_mem_get(mctx, sizeof(*elt));
|
||||
elt->mctx = mctx;
|
||||
ISC_LINK_INIT(elt, link);
|
||||
elt->port = port;
|
||||
elt->dscp = dscp;
|
||||
elt->acl = acl;
|
||||
elt->sslctx = NULL;
|
||||
if (tls) {
|
||||
result = isc_tlsctx_createserver(key, cert, &elt->sslctx);
|
||||
result = isc_tlsctx_createserver(key, cert, &sslctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
elt = isc_mem_get(mctx, sizeof(*elt));
|
||||
elt->mctx = mctx;
|
||||
ISC_LINK_INIT(elt, link);
|
||||
elt->port = port;
|
||||
elt->is_http = false;
|
||||
elt->dscp = dscp;
|
||||
elt->acl = acl;
|
||||
elt->sslctx = sslctx;
|
||||
elt->http_endpoints = NULL;
|
||||
elt->http_endpoints_number = 0;
|
||||
|
||||
*target = elt;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
|
||||
dns_acl_t *acl, const char *key, const char *cert,
|
||||
char **endpoints, size_t nendpoints,
|
||||
ns_listenelt_t **target) {
|
||||
isc_result_t result;
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
REQUIRE(endpoints != NULL && *endpoints != NULL);
|
||||
REQUIRE(nendpoints > 0);
|
||||
|
||||
result = ns_listenelt_create(mctx, http_port, dscp, acl, key != NULL,
|
||||
key, cert, target);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
(*target)->is_http = true;
|
||||
(*target)->http_endpoints = endpoints;
|
||||
(*target)->http_endpoints_number = nendpoints;
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < nendpoints; i++) {
|
||||
isc_mem_free(mctx, endpoints[i]);
|
||||
}
|
||||
isc_mem_free(mctx, endpoints);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
ns_listenelt_destroy(ns_listenelt_t *elt) {
|
||||
if (elt->acl != NULL) {
|
||||
@@ -56,6 +88,14 @@ ns_listenelt_destroy(ns_listenelt_t *elt) {
|
||||
if (elt->sslctx != NULL) {
|
||||
isc_tlsctx_free(&elt->sslctx);
|
||||
}
|
||||
if (elt->http_endpoints != NULL) {
|
||||
size_t i;
|
||||
INSIST(elt->http_endpoints_number > 0);
|
||||
for (i = 0; i < elt->http_endpoints_number; i++) {
|
||||
isc_mem_free(elt->mctx, elt->http_endpoints[i]);
|
||||
}
|
||||
isc_mem_free(elt->mctx, elt->http_endpoints);
|
||||
}
|
||||
isc_mem_put(elt->mctx, elt, sizeof(*elt));
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ ns_interfacemgr_shutdown
|
||||
ns_lib_init
|
||||
ns_lib_shutdown
|
||||
ns_listenelt_create
|
||||
ns_listenelt_create_http
|
||||
ns_listenelt_destroy
|
||||
ns_listenlist_attach
|
||||
ns_listenlist_create
|
||||
|
||||
@@ -1887,6 +1887,7 @@
|
||||
./lib/isc/include/isc/tls.h C 2021
|
||||
./lib/isc/include/isc/tm.h C 2014,2016,2018,2019,2020,2021
|
||||
./lib/isc/include/isc/types.h C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2012,2013,2014,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/include/isc/url.h C 2021
|
||||
./lib/isc/include/isc/utf8.h C 2020,2021
|
||||
./lib/isc/include/isc/util.h C 1998,1999,2000,2001,2004,2005,2006,2007,2010,2011,2012,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/include/pk11/constants.h C 2014,2016,2017,2018,2019,2020,2021
|
||||
@@ -1904,11 +1905,13 @@
|
||||
./lib/isc/mem_p.h C 2018,2019,2020,2021
|
||||
./lib/isc/mutexblock.c C 1999,2000,2001,2004,2005,2007,2011,2012,2016,2018,2019,2020,2021
|
||||
./lib/isc/netaddr.c C 1999,2000,2001,2002,2004,2005,2007,2010,2011,2012,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/netmgr/http.c C 2021
|
||||
./lib/isc/netmgr/netmgr-int.h C 2019,2020,2021
|
||||
./lib/isc/netmgr/netmgr.c C 2019,2020,2021
|
||||
./lib/isc/netmgr/tcp.c C 2019,2020,2021
|
||||
./lib/isc/netmgr/tcpdns.c C 2019,2020,2021
|
||||
./lib/isc/netmgr/tlsdns.c C 2020,2021
|
||||
./lib/isc/netmgr/tlsstream.c C 2019,2020,2021
|
||||
./lib/isc/netmgr/udp.c C 2019,2020,2021
|
||||
./lib/isc/netmgr/uv-compat.c C 2020,2021
|
||||
./lib/isc/netmgr/uv-compat.h C 2019,2020,2021
|
||||
@@ -1952,6 +1955,7 @@
|
||||
./lib/isc/tests/buffer_test.c C 2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/tests/counter_test.c C 2014,2016,2018,2019,2020,2021
|
||||
./lib/isc/tests/crc64_test.c C 2018,2019,2020,2021
|
||||
./lib/isc/tests/doh_test.c C 2020,2021
|
||||
./lib/isc/tests/errno_test.c C 2016,2018,2019,2020,2021
|
||||
./lib/isc/tests/file_test.c C 2014,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/tests/hash_test.c C 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
@@ -2018,6 +2022,7 @@
|
||||
./lib/isc/unix/stdtime.c C 1999,2000,2001,2004,2005,2007,2016,2018,2019,2020,2021
|
||||
./lib/isc/unix/syslog.c C 2001,2004,2005,2007,2016,2018,2019,2020,2021
|
||||
./lib/isc/unix/time.c C 1998,1999,2000,2001,2003,2004,2005,2006,2007,2008,2011,2012,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/url.c C 2021
|
||||
./lib/isc/utf8.c C 2020,2021
|
||||
./lib/isc/win32/DLLMain.c C 2001,2004,2007,2016,2018,2019,2020,2021
|
||||
./lib/isc/win32/condition.c C 1998,1999,2000,2001,2004,2006,2007,2016,2018,2019,2020,2021
|
||||
@@ -2100,18 +2105,22 @@
|
||||
./lib/isccc/win32/libisccc.vcxproj.user X 2013,2018,2019,2020,2021
|
||||
./lib/isccfg/aclconf.c C 1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isccfg/dnsconf.c C 2009,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/httpconf.c C 2021
|
||||
./lib/isccfg/include/isccfg/aclconf.h C 1999,2000,2001,2004,2005,2006,2007,2010,2011,2012,2013,2014,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/include/isccfg/cfg.h C 2000,2001,2002,2004,2005,2006,2007,2010,2013,2014,2015,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/include/isccfg/grammar.h C 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2013,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isccfg/include/isccfg/httpconf.h C 2021
|
||||
./lib/isccfg/include/isccfg/kaspconf.h C 2019,2020,2021
|
||||
./lib/isccfg/include/isccfg/log.h C 2001,2004,2005,2006,2007,2009,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/include/isccfg/namedconf.h C 2002,2004,2005,2006,2007,2009,2010,2014,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/include/isccfg/tlsconf.h C 2021
|
||||
./lib/isccfg/kaspconf.c C 2019,2020,2021
|
||||
./lib/isccfg/log.c C 2001,2004,2005,2006,2007,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/namedconf.c C 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isccfg/parser.c C 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isccfg/tests/duration_test.c C 2019,2020,2021
|
||||
./lib/isccfg/tests/parser_test.c C 2016,2018,2019,2020,2021
|
||||
./lib/isccfg/tlsconf.c C 2021
|
||||
./lib/isccfg/win32/DLLMain.c C 2001,2004,2007,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/win32/libisccfg.def X 2001,2002,2005,2009,2010,2011,2013,2014,2015,2016,2018,2019,2020,2021
|
||||
./lib/isccfg/win32/libisccfg.vcxproj.filters.in X 2013,2014,2015,2016,2018,2019,2020
|
||||
|
||||
@@ -221,6 +221,7 @@ my @substinc = ("GSSAPI_INC",
|
||||
"IDN_INC",
|
||||
"LIBXML2_INC",
|
||||
"LIBUV_INC",
|
||||
"NGHTTP2_INC",
|
||||
"OPENSSL_INC",
|
||||
"READLINE_INC",
|
||||
"ZLIB_INC");
|
||||
@@ -235,6 +236,7 @@ my @substlib = ("GSSAPI_LIB",
|
||||
"KRB5_LIB",
|
||||
"LIBXML2_LIB",
|
||||
"LIBUV_LIB",
|
||||
"NGHTTP2_LIB",
|
||||
"OPENSSL_LIBCRYPTO",
|
||||
"OPENSSL_LIBSSL",
|
||||
"READLINE_LIB",
|
||||
@@ -253,6 +255,7 @@ my @substdll = ("COMERR_DLL",
|
||||
"K5SPRT_DLL",
|
||||
"LIBXML2_DLL",
|
||||
"LIBUV_DLL",
|
||||
"NGHTTP2_DLL",
|
||||
"OPENSSL_DLLCRYPTO",
|
||||
"OPENSSL_DLLSSL",
|
||||
"WSHELP_DLL",
|
||||
@@ -341,6 +344,7 @@ my @withlist = ("aes",
|
||||
"idn",
|
||||
"openssl",
|
||||
"libxml2",
|
||||
"nghttp2",
|
||||
"pkcs11",
|
||||
"pssuspend",
|
||||
"python",
|
||||
@@ -389,6 +393,7 @@ my @help = (
|
||||
" with-samples build with sample programs\n",
|
||||
" with-openssl[=PATH] build with OpenSSL yes|path (mandatory)\n",
|
||||
" with-libuv[=PATH] build with libuv yes|path (mandatory)\n",
|
||||
" with-nghttp2[=PATH] build with nghttp2 yes|path (mandatory)\n",
|
||||
" with-pkcs11[=PATH] build with PKCS#11 support yes|no|provider-path\n",
|
||||
" with-gssapi[=PATH] build with MIT KfW GSSAPI yes|no|path\n",
|
||||
" with-libxml2[=PATH] build with libxml2 library yes|no|path\n",
|
||||
@@ -431,6 +436,8 @@ my $use_stests = "no";
|
||||
my $use_samples = "no";
|
||||
my $use_libuv = "auto";
|
||||
my $libuv_path = "../../";
|
||||
my $nghttp2_path = "../../";
|
||||
my $use_nghttp2 = "auto";
|
||||
my $use_openssl = "auto";
|
||||
my $openssl_path = "../../";
|
||||
my $use_pkcs11 = "no";
|
||||
@@ -758,6 +765,13 @@ sub mywith {
|
||||
$use_libuv = "yes";
|
||||
$libuv_path = $val;
|
||||
}
|
||||
} elsif ($key =~ /^nghttp2$/i) {
|
||||
if ($val =~ /^no$/i) {
|
||||
die "nghttp2 is required\n";
|
||||
} elsif ($val !~ /^yes$/i) {
|
||||
$use_nghttp2 = "yes";
|
||||
$nghttp2_path = $val;
|
||||
}
|
||||
} elsif ($key =~ /^pkcs11$/i) {
|
||||
if ($val =~ /^yes$/i) {
|
||||
$use_pkcs11 = "yes";
|
||||
@@ -949,6 +963,7 @@ if ($verbose) {
|
||||
print "querytrace: disabled\n";
|
||||
}
|
||||
print "libuv-path: $libuv_path\n";
|
||||
print "nghttp2-path: $nghttp2_path\n";
|
||||
print "openssl-path: $openssl_path\n";
|
||||
if ($use_tests eq "yes") {
|
||||
print "tests: enabled\n";
|
||||
@@ -1327,6 +1342,63 @@ if ($use_libuv eq "yes") {
|
||||
# $configdefh{"HAVE_UV_IMPORT"} = 1;
|
||||
}
|
||||
|
||||
# with-nghttp2
|
||||
if ($use_nghttp2 eq "auto") {
|
||||
if ($verbose) {
|
||||
print "checking for an nghttp2 built directory at sibling root\n";
|
||||
}
|
||||
opendir DIR, $nghttp2_path || die "No Directory: $!\n";
|
||||
my @dirlist = grep (/^nghttp2-[0-9]+\.[0-9]+\.[0-9]+$/i, readdir(DIR));
|
||||
closedir(DIR);
|
||||
|
||||
# Make sure we have something
|
||||
if (scalar(@dirlist) == 0) {
|
||||
die "can't find an nghttp2 at sibling root\n";
|
||||
}
|
||||
# Now see if we have a directory or just a file.
|
||||
# Make sure we are case insensitive
|
||||
my $file;
|
||||
foreach $file (sort {uc($b) cmp uc($a)} @dirlist) {
|
||||
if (-f File::Spec->catfile($nghttp2_path,
|
||||
$file,
|
||||
"include", "nghttp2", "nghttp2.h")) {
|
||||
$nghttp2_path = File::Spec->catdir($nghttp2_path, $file);
|
||||
$use_nghttp2 = "yes";
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# If we have one use it otherwise report the error
|
||||
if ($use_nghttp2 eq "auto") {
|
||||
die "can't find an nghttp2 built directory at sibling root\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($use_nghttp2 eq "yes") {
|
||||
$nghttp2_path = File::Spec->rel2abs($nghttp2_path);
|
||||
if ($verbose) {
|
||||
print "checking for nghttp2 directory at \"$nghttp2_path\"\n";
|
||||
}
|
||||
if (!-f File::Spec->catfile($nghttp2_path,
|
||||
"include", "nghttp2", "nghttp2.h")) {
|
||||
die "can't find nghttp2 nghttp2.h include\n";
|
||||
}
|
||||
my $nghttp2_inc = File::Spec->catdir($nghttp2_path, "include");
|
||||
my $nghttp2_bindir = File::Spec->catdir($nghttp2_path, "bin");
|
||||
my $nghttp2_libdir = File::Spec->catdir($nghttp2_path, "lib");
|
||||
my $nghttp2_dll = File::Spec->catfile($nghttp2_bindir, "nghttp2.dll");
|
||||
my $nghttp2_lib = File::Spec->catfile($nghttp2_libdir, "nghttp2.lib");
|
||||
if (!-f $nghttp2_lib) {
|
||||
die "can't find nghttp2.lib library\n";
|
||||
}
|
||||
if (!-f $nghttp2_dll) {
|
||||
die "can't find nghttp2.dll library\n";
|
||||
}
|
||||
$configinc{"NGHTTP2_INC"} = "$nghttp2_inc";
|
||||
$configlib{"NGHTTP2_LIB"} = "$nghttp2_lib";
|
||||
$configdll{"NGHTTP2_DLL"} = "$nghttp2_dll";
|
||||
}
|
||||
|
||||
# with-openssl
|
||||
if ($use_openssl eq "auto") {
|
||||
if ($verbose) {
|
||||
@@ -2433,6 +2505,7 @@ sub makeinstallfile {
|
||||
print LOUT "libdns.dll-BCFT\n";
|
||||
print LOUT "libirs.dll-BCFT\n";
|
||||
print LOUT "libns.dll-BCFT\n";
|
||||
print LOUT "nghttp2.dll-BCFT\n";
|
||||
print LOUT "uv.dll-BCFT\n";
|
||||
if ($use_openssl eq "yes") {
|
||||
my $v;
|
||||
|
||||
Reference in New Issue
Block a user