2021-01-14 12:51:25 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
*
|
2021-06-03 08:37:05 +02:00
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*
|
2021-01-14 12:51:25 +01:00
|
|
|
* 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 <inttypes.h>
|
|
|
|
|
|
|
|
#include <isc/list.h>
|
|
|
|
#include <isc/mem.h>
|
|
|
|
#include <isc/refcount.h>
|
|
|
|
#include <isc/result.h>
|
|
|
|
#include <isc/rwlock.h>
|
|
|
|
#include <isc/util.h>
|
|
|
|
|
|
|
|
#include <dns/name.h>
|
|
|
|
#include <dns/rbt.h>
|
|
|
|
#include <dns/transport.h>
|
|
|
|
|
|
|
|
#define TRANSPORT_MAGIC ISC_MAGIC('T', 'r', 'n', 's')
|
|
|
|
#define VALID_TRANSPORT(ptr) ISC_MAGIC_VALID(ptr, TRANSPORT_MAGIC)
|
|
|
|
|
|
|
|
#define TRANSPORT_LIST_MAGIC ISC_MAGIC('T', 'r', 'L', 's')
|
|
|
|
#define VALID_TRANSPORT_LIST(ptr) ISC_MAGIC_VALID(ptr, TRANSPORT_LIST_MAGIC)
|
|
|
|
|
|
|
|
struct dns_transport_list {
|
|
|
|
unsigned int magic;
|
|
|
|
isc_refcount_t references;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_rwlock_t lock;
|
|
|
|
dns_rbt_t *transports[DNS_TRANSPORT_COUNT];
|
|
|
|
};
|
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
typedef enum ternary { ter_none = 0, ter_true = 1, ter_false = 2 } ternary_t;
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
struct dns_transport {
|
|
|
|
unsigned int magic;
|
|
|
|
isc_refcount_t references;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
dns_transport_type_t type;
|
|
|
|
struct {
|
2021-12-23 16:08:41 +02:00
|
|
|
char *tlsname;
|
2021-01-14 12:51:25 +01:00
|
|
|
char *certfile;
|
|
|
|
char *keyfile;
|
|
|
|
char *cafile;
|
2022-05-03 16:51:33 +03:00
|
|
|
char *remote_hostname;
|
2021-11-29 23:09:51 +02:00
|
|
|
char *ciphers;
|
|
|
|
uint32_t protocol_versions;
|
|
|
|
ternary_t prefer_server_ciphers;
|
2021-01-14 12:51:25 +01:00
|
|
|
} tls;
|
|
|
|
struct {
|
|
|
|
char *endpoint;
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
dns_http_mode_t mode;
|
2021-01-14 12:51:25 +01:00
|
|
|
} doh;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_dns_transport(void *node, void *arg) {
|
|
|
|
dns_transport_t *transport = node;
|
|
|
|
|
|
|
|
REQUIRE(node != NULL);
|
|
|
|
|
|
|
|
UNUSED(arg);
|
|
|
|
|
|
|
|
dns_transport_detach(&transport);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
list_add(dns_transport_list_t *list, const dns_name_t *name,
|
|
|
|
const dns_transport_type_t type, dns_transport_t *transport) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rbt_t *rbt = NULL;
|
|
|
|
|
|
|
|
RWLOCK(&list->lock, isc_rwlocktype_write);
|
|
|
|
rbt = list->transports[type];
|
|
|
|
INSIST(rbt != NULL);
|
|
|
|
|
|
|
|
result = dns_rbt_addname(rbt, name, transport);
|
|
|
|
|
|
|
|
RWUNLOCK(&list->lock, isc_rwlocktype_write);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_transport_type_t
|
|
|
|
dns_transport_get_type(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->type);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
dns_transport_get_certfile(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->tls.certfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
dns_transport_get_keyfile(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->tls.keyfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
dns_transport_get_cafile(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->tls.cafile);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2022-05-03 16:51:33 +03:00
|
|
|
dns_transport_get_remote_hostname(dns_transport_t *transport) {
|
2021-01-14 12:51:25 +01:00
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
2022-05-03 16:51:33 +03:00
|
|
|
return (transport->tls.remote_hostname);
|
2021-01-14 12:51:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
dns_transport_get_endpoint(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->doh.endpoint);
|
|
|
|
}
|
|
|
|
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
dns_http_mode_t
|
2021-01-14 12:51:25 +01:00
|
|
|
dns_transport_get_mode(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->doh.mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_transport_t *
|
|
|
|
dns_transport_new(const dns_name_t *name, dns_transport_type_t type,
|
|
|
|
dns_transport_list_t *list) {
|
|
|
|
dns_transport_t *transport = isc_mem_get(list->mctx,
|
|
|
|
sizeof(*transport));
|
|
|
|
*transport = (dns_transport_t){ .type = type };
|
|
|
|
isc_refcount_init(&transport->references, 1);
|
|
|
|
isc_mem_attach(list->mctx, &transport->mctx);
|
|
|
|
transport->magic = TRANSPORT_MAGIC;
|
|
|
|
|
|
|
|
list_add(list, name, type, transport);
|
|
|
|
|
|
|
|
return (transport);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_set_certfile(dns_transport_t *transport, const char *certfile) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
2021-01-14 12:51:25 +01:00
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
if (transport->tls.certfile != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.certfile);
|
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
if (certfile != NULL) {
|
|
|
|
transport->tls.certfile = isc_mem_strdup(transport->mctx,
|
|
|
|
certfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_set_keyfile(dns_transport_t *transport, const char *keyfile) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
2021-01-14 12:51:25 +01:00
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
if (transport->tls.keyfile != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.keyfile);
|
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
if (keyfile != NULL) {
|
|
|
|
transport->tls.keyfile = isc_mem_strdup(transport->mctx,
|
|
|
|
keyfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_set_cafile(dns_transport_t *transport, const char *cafile) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
2021-01-14 12:51:25 +01:00
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
if (transport->tls.cafile != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.cafile);
|
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
if (cafile != NULL) {
|
|
|
|
transport->tls.cafile = isc_mem_strdup(transport->mctx, cafile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-05-03 16:51:33 +03:00
|
|
|
dns_transport_set_remote_hostname(dns_transport_t *transport,
|
|
|
|
const char *hostname) {
|
2021-01-14 12:51:25 +01:00
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
2021-01-14 12:51:25 +01:00
|
|
|
|
2022-05-03 16:51:33 +03:00
|
|
|
if (transport->tls.remote_hostname != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.remote_hostname);
|
2021-11-29 23:09:51 +02:00
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
if (hostname != NULL) {
|
2022-05-03 16:51:33 +03:00
|
|
|
transport->tls.remote_hostname = isc_mem_strdup(transport->mctx,
|
|
|
|
hostname);
|
2021-01-14 12:51:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
2021-01-14 12:51:25 +01:00
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
if (transport->doh.endpoint != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->doh.endpoint);
|
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
if (endpoint != NULL) {
|
|
|
|
transport->doh.endpoint = isc_mem_strdup(transport->mctx,
|
|
|
|
endpoint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
dns_transport_set_mode(dns_transport_t *transport, dns_http_mode_t mode) {
|
2021-01-14 12:51:25 +01:00
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
2021-01-14 12:51:25 +01:00
|
|
|
|
|
|
|
transport->doh.mode = mode;
|
|
|
|
}
|
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
void
|
|
|
|
dns_transport_set_tls_versions(dns_transport_t *transport,
|
|
|
|
const uint32_t tls_versions) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_HTTP ||
|
|
|
|
transport->type == DNS_TRANSPORT_TLS);
|
|
|
|
|
|
|
|
transport->tls.protocol_versions = tls_versions;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
dns_transport_get_tls_versions(const dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->tls.protocol_versions);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_set_ciphers(dns_transport_t *transport, const char *ciphers) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
|
|
|
|
|
|
|
if (transport->tls.ciphers != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.ciphers);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ciphers != NULL) {
|
|
|
|
transport->tls.ciphers = isc_mem_strdup(transport->mctx,
|
|
|
|
ciphers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-23 16:08:41 +02:00
|
|
|
void
|
|
|
|
dns_transport_set_tlsname(dns_transport_t *transport, const char *tlsname) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
|
|
|
|
|
|
|
if (transport->tls.tlsname != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.tlsname);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsname != NULL) {
|
|
|
|
transport->tls.tlsname = isc_mem_strdup(transport->mctx,
|
|
|
|
tlsname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
char *
|
|
|
|
dns_transport_get_ciphers(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->tls.ciphers);
|
|
|
|
}
|
|
|
|
|
2021-12-23 16:08:41 +02:00
|
|
|
char *
|
|
|
|
dns_transport_get_tlsname(dns_transport_t *transport) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
|
|
|
|
return (transport->tls.tlsname);
|
|
|
|
}
|
|
|
|
|
2021-11-29 23:09:51 +02:00
|
|
|
void
|
|
|
|
dns_transport_set_prefer_server_ciphers(dns_transport_t *transport,
|
|
|
|
const bool prefer) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
|
|
|
transport->type == DNS_TRANSPORT_HTTP);
|
|
|
|
|
|
|
|
transport->tls.prefer_server_ciphers = prefer ? ter_true : ter_false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
dns_transport_get_prefer_server_ciphers(const dns_transport_t *transport,
|
|
|
|
bool *preferp) {
|
|
|
|
REQUIRE(VALID_TRANSPORT(transport));
|
|
|
|
REQUIRE(preferp != NULL);
|
|
|
|
if (transport->tls.prefer_server_ciphers == ter_none) {
|
|
|
|
return (false);
|
|
|
|
} else if (transport->tls.prefer_server_ciphers == ter_true) {
|
|
|
|
*preferp = true;
|
|
|
|
return (true);
|
|
|
|
} else if (transport->tls.prefer_server_ciphers == ter_false) {
|
|
|
|
*preferp = false;
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
2021-10-11 12:50:17 +02:00
|
|
|
UNREACHABLE();
|
2021-11-29 23:09:51 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
static void
|
|
|
|
transport_destroy(dns_transport_t *transport) {
|
|
|
|
isc_refcount_destroy(&transport->references);
|
|
|
|
transport->magic = 0;
|
|
|
|
|
|
|
|
if (transport->doh.endpoint != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->doh.endpoint);
|
|
|
|
}
|
2022-05-03 16:51:33 +03:00
|
|
|
if (transport->tls.remote_hostname != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.remote_hostname);
|
2021-01-14 12:51:25 +01:00
|
|
|
}
|
|
|
|
if (transport->tls.cafile != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.cafile);
|
|
|
|
}
|
|
|
|
if (transport->tls.keyfile != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.keyfile);
|
|
|
|
}
|
|
|
|
if (transport->tls.certfile != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.certfile);
|
|
|
|
}
|
2021-11-29 23:09:51 +02:00
|
|
|
if (transport->tls.ciphers != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.ciphers);
|
|
|
|
}
|
2021-01-14 12:51:25 +01:00
|
|
|
|
2021-12-23 16:08:41 +02:00
|
|
|
if (transport->tls.tlsname != NULL) {
|
|
|
|
isc_mem_free(transport->mctx, transport->tls.tlsname);
|
|
|
|
}
|
|
|
|
|
2021-01-14 12:51:25 +01:00
|
|
|
isc_mem_putanddetach(&transport->mctx, transport, sizeof(*transport));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_attach(dns_transport_t *source, dns_transport_t **targetp) {
|
|
|
|
REQUIRE(source != NULL);
|
|
|
|
REQUIRE(targetp != NULL && *targetp == NULL);
|
|
|
|
|
|
|
|
isc_refcount_increment(&source->references);
|
|
|
|
|
|
|
|
*targetp = source;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_detach(dns_transport_t **transportp) {
|
|
|
|
dns_transport_t *transport = NULL;
|
|
|
|
|
|
|
|
REQUIRE(transportp != NULL);
|
|
|
|
REQUIRE(VALID_TRANSPORT(*transportp));
|
|
|
|
|
|
|
|
transport = *transportp;
|
|
|
|
*transportp = NULL;
|
|
|
|
|
|
|
|
if (isc_refcount_decrement(&transport->references) == 1) {
|
|
|
|
transport_destroy(transport);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_transport_t *
|
|
|
|
dns_transport_find(const dns_transport_type_t type, const dns_name_t *name,
|
|
|
|
dns_transport_list_t *list) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_transport_t *transport = NULL;
|
|
|
|
dns_rbt_t *rbt = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_TRANSPORT_LIST(list));
|
|
|
|
REQUIRE(list->transports[type] != NULL);
|
|
|
|
|
|
|
|
rbt = list->transports[type];
|
|
|
|
|
|
|
|
RWLOCK(&list->lock, isc_rwlocktype_read);
|
|
|
|
result = dns_rbt_findname(rbt, name, 0, NULL, (void *)&transport);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
isc_refcount_increment(&transport->references);
|
|
|
|
}
|
|
|
|
RWUNLOCK(&list->lock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
return (transport);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_transport_list_t *
|
|
|
|
dns_transport_list_new(isc_mem_t *mctx) {
|
|
|
|
dns_transport_list_t *list = isc_mem_get(mctx, sizeof(*list));
|
|
|
|
|
|
|
|
*list = (dns_transport_list_t){ 0 };
|
|
|
|
|
|
|
|
isc_rwlock_init(&list->lock, 0, 0);
|
|
|
|
|
|
|
|
isc_mem_attach(mctx, &list->mctx);
|
|
|
|
isc_refcount_init(&list->references, 1);
|
|
|
|
|
|
|
|
list->magic = TRANSPORT_LIST_MAGIC;
|
|
|
|
|
|
|
|
for (size_t type = 0; type < DNS_TRANSPORT_COUNT; type++) {
|
|
|
|
isc_result_t result;
|
|
|
|
result = dns_rbt_create(list->mctx, free_dns_transport, NULL,
|
|
|
|
&list->transports[type]);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_list_attach(dns_transport_list_t *source,
|
|
|
|
dns_transport_list_t **targetp) {
|
|
|
|
REQUIRE(VALID_TRANSPORT_LIST(source));
|
|
|
|
REQUIRE(targetp != NULL && *targetp == NULL);
|
|
|
|
|
|
|
|
isc_refcount_increment(&source->references);
|
|
|
|
|
|
|
|
*targetp = source;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
transport_list_destroy(dns_transport_list_t *list) {
|
|
|
|
isc_refcount_destroy(&list->references);
|
|
|
|
list->magic = 0;
|
|
|
|
|
|
|
|
for (size_t type = 0; type < DNS_TRANSPORT_COUNT; type++) {
|
|
|
|
if (list->transports[type] != NULL) {
|
|
|
|
dns_rbt_destroy(&list->transports[type]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
isc_rwlock_destroy(&list->lock);
|
|
|
|
isc_mem_putanddetach(&list->mctx, list, sizeof(*list));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_transport_list_detach(dns_transport_list_t **listp) {
|
|
|
|
dns_transport_list_t *list = NULL;
|
|
|
|
|
|
|
|
REQUIRE(listp != NULL);
|
|
|
|
REQUIRE(VALID_TRANSPORT_LIST(*listp));
|
|
|
|
|
|
|
|
list = *listp;
|
|
|
|
*listp = NULL;
|
|
|
|
|
|
|
|
if (isc_refcount_decrement(&list->references) == 1) {
|
|
|
|
transport_list_destroy(list);
|
|
|
|
}
|
|
|
|
}
|