echo_i "checking DoH XFR (POST) (failure expected) ($n)"
ret=0
dig_with_https_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
-grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+grep "; Transfer failed." dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "checking DoH XFR (GET) (failure expected) ($n)"
ret=0
dig_with_https_opts +https-get +comm @10.53.0.1 . AXFR > dig.out.test$n
-grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+grep "; Transfer failed." dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "checking unencrypted DoH XFR (failure expected) ($n)"
ret=0
dig_with_http_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
-grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+grep "; Transfer failed." dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
void *cbarg, size_t extrahandlesize);
+bool
+isc_nm_is_http_handle(isc_nmhandle_t *handle);
+
void
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
/*%<
nghttp2_data_provider data_prd;
int rv;
+ if (socket->h2.response_submitted) {
+ /* NGHTTP2 will gladly accept new response (write request)
+ * from us even though we cannot send more than one over the
+ * same HTTP/2 stream. Thus, we need to handle this case
+ * manually. We will return failure code so that it will be
+ * passed to the write callback. */
+ return (ISC_R_FAILURE);
+ }
+
data_prd.source.ptr = socket;
data_prd.read_callback = server_read_callback;
if (rv != 0) {
return (ISC_R_FAILURE);
}
+
+ socket->h2.response_submitted = true;
return (ISC_R_SUCCESS);
}
}
}
+bool
+isc_nm_is_http_handle(isc_nmhandle_t *handle) {
+ REQUIRE(VALID_NMHANDLE(handle));
+ REQUIRE(VALID_NMSOCK(handle->sock));
+
+ return (handle->sock->type == isc_nm_httpsocket);
+}
+
static const bool base64url_validation_table[256] = {
false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false,
ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs;
isc_rwlock_t lock;
+ bool response_submitted;
struct {
char *uri;
bool post;
break; /* Let the query logic handle it. */
case dns_rdatatype_ixfr:
case dns_rdatatype_axfr:
- ns_xfr_start(client, rdataset->type);
+ if (isc_nm_is_http_handle(handle)) {
+ /* We cannot use DoH for zone transfers.
+ * According to RFC8484 a DoH request contains
+ * exactly one DNS message (see Section 6:
+ * Definition of the "application/dns-message"
+ * Media Type,
+ * https://datatracker.ietf.org/doc/html/rfc8484#section-6).
+ * This makes DoH unsuitable for zone transfers
+ * as often (and usually!) these need more than
+ * one DNS message, especially for larger zones.
+ * As zone transfers over DoH are not (yet)
+ * standardised, nor discussed in the RFC8484,
+ * the best thing we can do is to return "not
+ * implemented". */
+ query_error(client, DNS_R_NOTIMP, __LINE__);
+ } else {
+ ns_xfr_start(client, rdataset->type);
+ }
return;
case dns_rdatatype_maila:
case dns_rdatatype_mailb: