]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Implement asynchronous message signature verification
authorAram Sargsyan <aram@isc.org>
Wed, 6 Mar 2024 11:06:27 +0000 (11:06 +0000)
committerNicki Křížek <nicki@isc.org>
Mon, 10 Jun 2024 15:33:10 +0000 (17:33 +0200)
Add support for using the offload threadpool to perform message
signature verifications. This should allow check SIG(0)-signed
messages without affecting the worker threads.

lib/dns/include/dns/message.h
lib/dns/message.c

index ed135979d5ff21fbdb60c54d9e66b0c1ce3f27d1..81c641dd848eafb518e13455a597f074e06dd15a 100644 (file)
@@ -352,6 +352,8 @@ struct dns_ednsopt {
        unsigned char *value;
 };
 
+typedef void (*dns_message_cb_t)(void *arg, isc_result_t result);
+
 /***
  *** Functions
  ***/
@@ -1327,6 +1329,26 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view);
  *\li  #DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
  */
 
+isc_result_t
+dns_message_checksig_async(dns_message_t *msg, dns_view_t *view,
+                          isc_loop_t *loop, dns_message_cb_t cb, void *cbarg);
+/*%<
+ * Run dns_message_checksig() in an offloaded thread and return its result
+ * using the 'cb' callback function, running on the 'loop'.
+ *
+ * Requires:
+ *
+ *\li  msg is a valid parsed message.
+ *\li  view is a valid view or NULL.
+ *\li  loop is a valid loop.
+ *\li  cb is a valid callback function.
+ *
+ * Returns:
+ *
+ *\li  #DNS_R_WAIT
+ *
+ */
+
 void
 dns_message_resetsig(dns_message_t *msg);
 /*%<
index e99fd5edc9ae673958a6889de96ecd881762f1c8..bba68efe5428cad05c6ba6e44475bac1a3704149 100644 (file)
@@ -29,6 +29,7 @@
 #include <isc/string.h>
 #include <isc/utf8.h>
 #include <isc/util.h>
+#include <isc/work.h>
 
 #include <dns/dnssec.h>
 #include <dns/keyvalues.h>
@@ -180,6 +181,18 @@ msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
 #define msgblock_get(block, type) \
        ((type *)msgblock_internalget(block, sizeof(type)))
 
+/*
+ * A context type to pass information when checking a message signature
+ * asynchronously.
+ */
+typedef struct checksig_ctx {
+       dns_message_t *msg;
+       dns_view_t *view;
+       dns_message_cb_t cb;
+       void *cbarg;
+       isc_result_t result;
+} checksig_ctx_t;
+
 /*
  * This function differs from public dns_message_puttemprdataset() that it
  * requires the *rdatasetp to be associated, and it will disassociate and
@@ -3205,6 +3218,47 @@ dns_message_dumpsig(dns_message_t *msg, char *txt1) {
 }
 #endif /* ifdef SKAN_MSG_DEBUG */
 
+static void
+checksig_run(void *arg) {
+       checksig_ctx_t *chsigctx = arg;
+
+       chsigctx->result = dns_message_checksig(chsigctx->msg, chsigctx->view);
+}
+
+static void
+checksig_cb(void *arg) {
+       checksig_ctx_t *chsigctx = arg;
+       dns_message_t *msg = chsigctx->msg;
+
+       chsigctx->cb(chsigctx->cbarg, chsigctx->result);
+
+       dns_view_detach(&chsigctx->view);
+       isc_mem_put(msg->mctx, chsigctx, sizeof(*chsigctx));
+       dns_message_detach(&msg);
+}
+
+isc_result_t
+dns_message_checksig_async(dns_message_t *msg, dns_view_t *view,
+                          isc_loop_t *loop, dns_message_cb_t cb, void *cbarg) {
+       REQUIRE(DNS_MESSAGE_VALID(msg));
+       REQUIRE(view != NULL);
+       REQUIRE(loop != NULL);
+       REQUIRE(cb != NULL);
+
+       checksig_ctx_t *chsigctx = isc_mem_get(msg->mctx, sizeof(*chsigctx));
+       *chsigctx = (checksig_ctx_t){
+               .cb = cb,
+               .cbarg = cbarg,
+               .result = ISC_R_UNSET,
+       };
+       dns_message_attach(msg, &chsigctx->msg);
+       dns_view_attach(view, &chsigctx->view);
+
+       isc_work_enqueue(loop, checksig_run, checksig_cb, chsigctx);
+
+       return (DNS_R_WAIT);
+}
+
 isc_result_t
 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
        isc_buffer_t b, msgb;