]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- xfr-tsig, tsig_sign_shared function.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 27 Jun 2025 06:52:32 +0000 (08:52 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 27 Jun 2025 06:52:32 +0000 (08:52 +0200)
util/tsig.c
util/tsig.h

index 6a1fc0ff17d08bd18421301d6897d0c0def032f3..fab8bd5bc1a818aa250d553e01488f5d09f997e1 100644 (file)
@@ -1727,3 +1727,78 @@ tsig_verify_shared(sldns_buffer* pkt, const uint8_t* name, const uint8_t* alg,
        }
        return 0;
 }
+
+/**
+ * Sign pkt with the name (domain name), algorithm and key in Base64.
+ * out 0 on success, -1 on failure.
+ * For a shared packet with contents.
+ */
+int
+tsig_sign_shared(sldns_buffer* pkt, const uint8_t* name, const uint8_t* alg,
+               const uint8_t* secret, size_t secret_len, uint64_t now)
+{
+       struct tsig_key key;
+       struct tsig_data tsig;
+       size_t aftername_pos;
+       uint8_t macbuf[1024];
+       uint8_t bufname[256];
+
+       memset(&key, 0, sizeof(key));
+       (void)dname_count_size_labels((uint8_t*)name, &key.name_len);
+       if(key.name_len == 0 || key.name_len > sizeof(bufname)) {
+               verbose(VERB_ALGO, "tsig_sign_shared: key name too long");
+               return -1;
+       }
+       memcpy(bufname, name, key.name_len);
+       query_dname_tolower(bufname);
+       key.name = bufname;
+       key.data = (uint8_t*)secret;
+       key.data_len = secret_len;
+       key.algo = tsig_algo_find_wire((uint8_t*)alg);
+       if(!key.algo) {
+               verbose(VERB_ALGO, "tsig_sign_shared: unknown algorithm");
+               return -1;
+       }
+       if(key.algo->max_digest_size > sizeof(macbuf)) {
+               verbose(VERB_ALGO, "tsig_sign_shared: mac size too large");
+               return -1;
+       }
+
+       memset(&tsig, 0, sizeof(tsig));
+       tsig.time_signed = now;
+       tsig.fudge = TSIG_FUDGE_TIME; /* seconds */
+       tsig.key_name = key.name;
+       tsig.key_name_len = key.name_len;
+       tsig.algo_name = NULL;
+       tsig.algo_name_len = key.algo->wireformat_name_len;
+       tsig.mac_size = key.algo->max_digest_size;
+       tsig.mac = macbuf;
+
+       if(sldns_buffer_remaining(pkt) < tsig_reserved_space(&tsig)) {
+               /* Not enough space in buffer for packet and TSIG. */
+               verbose(VERB_ALGO, "tsig_sign_shared: not enough buffer space");
+               return -1;
+       }
+       tsig.original_query_id = sldns_buffer_read_u16_at(pkt, 0);
+
+       /* That fits in the current buffer, since the reserved space for
+        * the TSIG record is larger. */
+       if(!tsig_vars_available(&tsig, pkt)) {
+               /* Buffer is too small */
+               verbose(VERB_ALGO, "tsig_sign_shared: not enough buffer space");
+               return -1;
+       }
+       tsig_write_vars(&tsig, pkt, &key, &aftername_pos);
+
+       /* Calculate the TSIG. */
+       if(!tsig_algo_calc(&key, pkt, &tsig)) {
+               /* Failure to calculate digest. */
+               verbose(VERB_ALGO, "tsig_sign_shared: failed to calculate digest");
+               return -1;
+       }
+
+       /* Append TSIG record. */
+       tsig_append_rr(&tsig, pkt, aftername_pos, key.algo->wireformat_name,
+               key.algo->wireformat_name_len, tsig.mac, tsig.mac_size);
+       return 0;
+}
index d96c3fd33e6946c23fd721c024ae4f370ecee37c..3b59b06ac45f738d287810376ca92b7af47535fb 100644 (file)
@@ -254,10 +254,21 @@ int tsig_verify(struct sldns_buffer* pkt, const uint8_t* name,
        const uint8_t* alg, const uint8_t* secret, size_t secret_len,
        uint64_t now);
 
+/**
+ * Sign pkt with the name (domain name), algorithm and key in Base64.
+ * out 0 on success, -1 on failure.
+ * For a shared packet with contents. This signs a reply packet without
+ * the prior hash, since there is no prior packet.
+ */
+int tsig_sign_shared(struct sldns_buffer* pkt, const uint8_t* name,
+       const uint8_t* alg, const uint8_t* secret, size_t secret_len,
+       uint64_t now);
+
 /**
  * Verify pkt with the name (domain name), algorithm and key in Base64.
  * out 0 on success, an error code otherwise.
- * For a shared packet with contents.
+ * For a shared packet with contents. This verifies a reply packet without
+ * the prior hash, since there is no prior packet.
  * out 0 on success, on failure:
  * -1 for malformed, no tsig RR, or too large for buffer.
  * >0 rcode with a TSIG error code otherwise.