2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 23:25:38 +00:00

Merge branch 'artem/doh-ignore-accept-header' into 'main'

DoH: Improve compatiblity by ignoring an "Accept" HTTP header value

See merge request isc-projects/bind9!5246
This commit is contained in:
Artem Boldariev
2021-07-09 14:00:32 +00:00
6 changed files with 78 additions and 23 deletions

View File

@@ -1,3 +1,6 @@
5675. [bug] Improve BIND's compatibility with DoH clients by
ignoring an "Accept" HTTP header value. [GL !5246]
5674. [bug] Fix BIND hanging when HTTP/2 streams are aborted 5674. [bug] Fix BIND hanging when HTTP/2 streams are aborted
prematurely by web browsers. [GL !5245] prematurely by web browsers. [GL !5245]

View File

@@ -509,6 +509,18 @@ isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
bool bool
isc_nm_is_http_handle(isc_nmhandle_t *handle); isc_nm_is_http_handle(isc_nmhandle_t *handle);
void
isc_nm_bad_request(isc_nmhandle_t *handle);
/*%<
* Perform a transport protocol specific action on the handle in case of a
* bad/malformed incoming DNS message.
*
* NOTE: The function currently is no-op for any protocol except HTTP/2.
*
* Requires:
* \li 'handle' is a valid netmgr handle object.
*/
void void
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid); isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
/*%< /*%<

View File

@@ -1805,23 +1805,6 @@ server_handle_content_type_header(isc_nmsocket_t *socket, const uint8_t *value,
return (resp); return (resp);
} }
static isc_http_error_responses_t
server_handle_accept_header(isc_nmsocket_t *socket, const uint8_t *value,
const size_t valuelen) {
const char type_accept_all[] = "*/*";
const char type_dns_message[] = DNS_MEDIA_TYPE;
isc_http_error_responses_t resp = ISC_HTTP_ERROR_SUCCESS;
UNUSED(socket);
if (!(HEADER_MATCH(type_dns_message, value, valuelen) ||
HEADER_MATCH(type_accept_all, value, valuelen)))
{
resp = ISC_HTTP_ERROR_UNSUPPORTED_MEDIA_TYPE;
}
return (resp);
}
static isc_http_error_responses_t static isc_http_error_responses_t
server_handle_header(isc_nmsocket_t *socket, const uint8_t *name, server_handle_header(isc_nmsocket_t *socket, const uint8_t *name,
size_t namelen, const uint8_t *value, size_t namelen, const uint8_t *value,
@@ -1831,7 +1814,6 @@ server_handle_header(isc_nmsocket_t *socket, const uint8_t *name,
const char path[] = ":path"; const char path[] = ":path";
const char method[] = ":method"; const char method[] = ":method";
const char scheme[] = ":scheme"; const char scheme[] = ":scheme";
const char accept[] = "accept";
const char content_length[] = "Content-Length"; const char content_length[] = "Content-Length";
const char content_type[] = "Content-Type"; const char content_type[] = "Content-Type";
@@ -1852,9 +1834,6 @@ server_handle_header(isc_nmsocket_t *socket, const uint8_t *name,
} else if (!was_error && HEADER_MATCH(content_type, name, namelen)) { } else if (!was_error && HEADER_MATCH(content_type, name, namelen)) {
code = server_handle_content_type_header(socket, value, code = server_handle_content_type_header(socket, value,
valuelen); valuelen);
} else if (!was_error &&
HEADER_MATCH(accept, (const char *)name, namelen)) {
code = server_handle_accept_header(socket, value, valuelen);
} }
return (code); return (code);
@@ -2022,6 +2001,21 @@ server_call_cb(isc_nmsocket_t *socket, isc_nm_http_session_t *session,
isc_nmhandle_detach(&handle); isc_nmhandle_detach(&handle);
} }
void
isc__nm_http_bad_request(isc_nmhandle_t *handle) {
isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
sock = handle->sock;
REQUIRE(sock->type == isc_nm_httpsocket);
REQUIRE(!atomic_load(&sock->client));
REQUIRE(VALID_HTTP2_SESSION(sock->h2.session));
(void)server_send_error_response(ISC_HTTP_ERROR_BAD_REQUEST,
sock->h2.session->ngsession, sock);
}
static int static int
server_on_request_recv(nghttp2_session *ngsession, server_on_request_recv(nghttp2_session *ngsession,
isc_nm_http_session_t *session, isc_nmsocket_t *socket) { isc_nm_http_session_t *session, isc_nmsocket_t *socket) {
@@ -2057,7 +2051,7 @@ server_on_request_recv(nghttp2_session *ngsession,
if (isc_base64_decodestring(socket->h2.query_data, if (isc_base64_decodestring(socket->h2.query_data,
&decoded_buf) != ISC_R_SUCCESS) &decoded_buf) != ISC_R_SUCCESS)
{ {
code = ISC_HTTP_ERROR_GENERIC; code = ISC_HTTP_ERROR_BAD_REQUEST;
goto error; goto error;
} }
isc__buffer_usedregion(&decoded_buf, &data); isc__buffer_usedregion(&decoded_buf, &data);
@@ -2076,7 +2070,7 @@ server_on_request_recv(nghttp2_session *ngsession,
error: error:
result = server_send_error_response(code, ngsession, socket); result = server_send_error_response(code, ngsession, socket);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return (NGHTTP2_ERR_CALLBACK_FAILURE); return (NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE);
} }
return (0); return (0);
} }

View File

@@ -1654,6 +1654,16 @@ isc__nm_http_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
void void
isc__nm_http_close(isc_nmsocket_t *sock); isc__nm_http_close(isc_nmsocket_t *sock);
void
isc__nm_http_bad_request(isc_nmhandle_t *handle);
/*%<
* Respond to the request with 400 "Bad Request" status.
*
* Requires:
* \li 'handle' is a valid HTTP netmgr handle object, referencing a server-side
* socket
*/
void void
isc__nm_async_httpsend(isc__networker_t *worker, isc__netievent_t *ev0); isc__nm_async_httpsend(isc__networker_t *worker, isc__netievent_t *ev0);

View File

@@ -3301,6 +3301,38 @@ isc_nm_sequential(isc_nmhandle_t *handle) {
atomic_store(&sock->sequential, true); atomic_store(&sock->sequential, true);
} }
void
isc_nm_bad_request(isc_nmhandle_t *handle) {
isc_nmsocket_t *sock;
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
sock = handle->sock;
switch (sock->type) {
#if HAVE_LIBNGHTTP2
case isc_nm_httpsocket:
isc__nm_http_bad_request(handle);
break;
#endif /* HAVE_LIBNGHTTP2 */
case isc_nm_udpsocket:
case isc_nm_tcpdnssocket:
case isc_nm_tlsdnssocket:
return;
break;
case isc_nm_tcpsocket:
#if HAVE_LIBNGHTTP2
case isc_nm_tlssocket:
#endif /* HAVE_LIBNGHTTP2 */
default:
INSIST(0);
ISC_UNREACHABLE();
break;
}
}
#ifdef NETMGR_TRACE #ifdef NETMGR_TRACE
/* /*
* Dump all active sockets in netmgr. We output to stderr * Dump all active sockets in netmgr. We output to stderr

View File

@@ -1724,6 +1724,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
ns_client_log(client, DNS_LOGCATEGORY_SECURITY, ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"dropped request: suspicious port"); "dropped request: suspicious port");
isc_nm_bad_request(handle);
return; return;
} }
#endif /* if NS_CLIENT_DROPPORT */ #endif /* if NS_CLIENT_DROPPORT */
@@ -1737,6 +1738,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
ns_client_log(client, DNS_LOGCATEGORY_SECURITY, ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"dropped request: blackholed peer"); "dropped request: blackholed peer");
isc_nm_bad_request(handle);
return; return;
} }
@@ -1750,6 +1752,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
* There isn't enough header to determine whether * There isn't enough header to determine whether
* this was a request or a response. Drop it. * this was a request or a response. Drop it.
*/ */
isc_nm_bad_request(handle);
return; return;
} }
@@ -1766,6 +1769,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
*/ */
if ((flags & DNS_MESSAGEFLAG_QR) != 0) { if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
CTRACE("unexpected response"); CTRACE("unexpected response");
isc_nm_bad_request(handle);
return; return;
} }