From cb6f3dc3c823f5e82d537fa40bc9d9514a446e59 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Wed, 7 Dec 2022 14:18:33 +0200 Subject: [PATCH] TLS: isc__nm_senddns() support This commit adds support for isc_nm_senddns() to the generic TLS code. --- lib/isc/netmgr/netmgr-int.h | 8 +++++ lib/isc/netmgr/netmgr.c | 3 ++ lib/isc/netmgr/tlsstream.c | 60 ++++++++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index a57222c367..f71d74fb5a 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -1444,6 +1444,14 @@ isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region, * Back-end implementation of isc_nm_send() for TLSDNS handles. */ +void +isc__nm_tls_senddns(isc_nmhandle_t *handle, const isc_region_t *region, + isc_nm_cb_t cb, void *cbarg); +/*%< + * The same as 'isc__nm_tls_send()', but with data length sent + * ahead of data (two bytes (16 bit) in big-endian format). + */ + void isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg); /*%< diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 80bcca310d..24caf453da 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1882,6 +1882,9 @@ isc__nm_senddns(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb, case isc_nm_tcpsocket: isc__nm_tcp_senddns(handle, region, cb, cbarg); break; + case isc_nm_tlssocket: + isc__nm_tls_senddns(handle, region, cb, cbarg); + break; default: UNREACHABLE(); } diff --git a/lib/isc/netmgr/tlsstream.c b/lib/isc/netmgr/tlsstream.c index 67298cf8eb..8a33711255 100644 --- a/lib/isc/netmgr/tlsstream.c +++ b/lib/isc/netmgr/tlsstream.c @@ -542,10 +542,41 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data, bool sent_shutdown = ((SSL_get_shutdown(sock->tlsstream.tls) & SSL_SENT_SHUTDOWN) != 0); - rv = SSL_write_ex(sock->tlsstream.tls, - send_data->uvbuf.base, - send_data->uvbuf.len, &len); - if (rv != 1 || len != send_data->uvbuf.len) { + bool write_failed = false; + if (*(uint16_t *)send_data->tcplen != 0) { + /* + * There is a DNS message length to write - do + * it. + */ + rv = SSL_write_ex( + sock->tlsstream.tls, send_data->tcplen, + sizeof(send_data->tcplen), &len); + if (rv != 1 || len != sizeof(send_data->tcplen)) + { + write_failed = true; + } else { + /* Write data */ + rv = SSL_write_ex(sock->tlsstream.tls, + send_data->uvbuf.base, + send_data->uvbuf.len, + &len); + if (rv != 1 || + len != send_data->uvbuf.len) + { + write_failed = true; + } + } + } else { + /* Write data only */ + rv = SSL_write_ex(sock->tlsstream.tls, + send_data->uvbuf.base, + send_data->uvbuf.len, &len); + if (rv != 1 || len != send_data->uvbuf.len) { + write_failed = true; + } + } + + if (write_failed) { result = received_shutdown || sent_shutdown ? ISC_R_CANCELED : ISC_R_TLSERROR; @@ -931,9 +962,9 @@ done: return; } -void -isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region, - isc_nm_cb_t cb, void *cbarg) { +static void +tls_send(isc_nmhandle_t *handle, const isc_region_t *region, isc_nm_cb_t cb, + void *cbarg, const bool dnsmsg) { isc__netievent_tlssend_t *ievent = NULL; isc__nm_uvreq_t *uvreq = NULL; isc_nmsocket_t *sock = NULL; @@ -951,6 +982,9 @@ isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region, uvreq->cbarg = cbarg; uvreq->uvbuf.base = (char *)region->base; uvreq->uvbuf.len = region->length; + if (dnsmsg) { + *(uint16_t *)uvreq->tcplen = htons(region->length); + } /* * We need to create an event and pass it using async channel @@ -959,6 +993,18 @@ isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region, isc__nm_enqueue_ievent(sock->worker, (isc__netievent_t *)ievent); } +void +isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region, + isc_nm_cb_t cb, void *cbarg) { + tls_send(handle, region, cb, cbarg, false); +} + +void +isc__nm_tls_senddns(isc_nmhandle_t *handle, const isc_region_t *region, + isc_nm_cb_t cb, void *cbarg) { + tls_send(handle, region, cb, cbarg, true); +} + void isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { isc_nmsocket_t *sock = NULL;