]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- xfr-tsig, tsig_create and tsig_delete.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Jun 2025 14:54:52 +0000 (16:54 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Jun 2025 14:54:52 +0000 (16:54 +0200)
util/tsig.c
util/tsig.h

index 79438adc02c161f594b581a1fbbd5d4eb163a887..984e3ba5bdc75ee7094107812496078d67f2a404 100644 (file)
@@ -43,6 +43,7 @@
 #include "util/tsig.h"
 #include "util/config_file.h"
 #include "util/log.h"
+#include "util/net_help.h"
 #include "sldns/parseutil.h"
 #include "sldns/pkthdr.h"
 #include "sldns/rrdef.h"
@@ -206,6 +207,20 @@ tsig_key_table_apply_cfg(struct tsig_key_table* key_table,
        return 1;
 }
 
+struct tsig_key*
+tsig_key_table_search(struct tsig_key_table* key_table, uint8_t* name,
+       size_t namelen)
+{
+       rbnode_type* node;
+       struct tsig_key k;
+       k.node.key = &k;
+       k.name = name;
+       k.name_len = namelen;
+       node = rbtree_search(key_table->tree, &k);
+       if(!node) return NULL;
+       return (struct tsig_key*)node->key;
+}
+
 void tsig_key_delete(struct tsig_key* key)
 {
        if(!key)
@@ -560,3 +575,64 @@ tsig_verify(sldns_buffer* pkt, const uint8_t* name, const uint8_t* alg,
        sldns_buffer_set_position(pkt, end_of_message);
        return LDNS_TSIG_ERROR_BADSIG;
 }
+
+struct tsig_data*
+tsig_create(struct tsig_key_table* key_table, uint8_t* name, size_t namelen)
+{
+       struct tsig_key* key;
+       struct tsig_data* tsig;
+       lock_rw_rdlock(&key_table->lock);
+       key = tsig_key_table_search(key_table, name, namelen);
+       if(!key) {
+               lock_rw_unlock(&key_table->lock);
+               return NULL;
+       }
+       /* the key table lock is also on the returned key */
+
+       tsig = calloc(1, sizeof(*tsig));
+       if(!tsig) {
+               lock_rw_unlock(&key_table->lock);
+               log_err("out of memory");
+               return NULL;
+       }
+       tsig->key_name_len = key->name_len;
+       tsig->key_name = memdup(key->name, key->name_len);
+       if(!tsig->key_name) {
+               lock_rw_unlock(&key_table->lock);
+               tsig_delete(tsig);
+               log_err("out of memory");
+               return NULL;
+       }
+       tsig->algorithm_name_len = key->algo->wireformat_name_len;
+       tsig->mac_size = key->algo->max_digest_size;
+       tsig->mac = calloc(1, tsig->mac_size);
+       if(!tsig->mac) {
+               lock_rw_unlock(&key_table->lock);
+               tsig_delete(tsig);
+               log_err("out of memory");
+               return NULL;
+       }
+       lock_rw_unlock(&key_table->lock);
+       return tsig;
+}
+
+struct tsig_data*
+tsig_create_fromstr(struct tsig_key_table* key_table, char* name)
+{
+       uint8_t buf[LDNS_MAX_DOMAINLEN+1];
+       size_t len = sizeof(buf);
+       if(!sldns_str2wire_dname_buf(name, buf, &len)) {
+               log_err("could not parse '%s'", name);
+               return NULL;
+       }
+       return tsig_create(key_table, buf, len);
+}
+
+void
+tsig_delete(struct tsig_data* tsig)
+{
+       if(!tsig) return;
+       free(tsig->key_name);
+       free(tsig->mac);
+       free(tsig);
+}
index d0d4226ca850a5d24b7c0eb5be70d75607cefc6f..68b71c23dda694e51972c9780dd5b3b0fb5c49fc 100644 (file)
@@ -79,6 +79,23 @@ struct tsig_record {
        uint8_t* other_data;
 };
 
+/**
+ * TSIG data. This keeps track of the information between packets,
+ * for the TSIG signature, and state, errors, key.
+ */
+struct tsig_data {
+       /** The key name, in wireformat */
+       uint8_t* key_name;
+       /** length of the key name */
+       size_t key_name_len;
+       /** length of the algorithm name */
+       size_t algorithm_name_len;
+       /** mac size */
+       size_t mac_size;
+       /** digest buffer */
+       uint8_t* mac;
+};
+
 /**
  * TSIG algorithm. This is the HMAC algorithm used for the TSIG mac.
  */
@@ -156,6 +173,17 @@ void tsig_key_table_delete(struct tsig_key_table* key_table);
 int tsig_key_table_apply_cfg(struct tsig_key_table* key_table,
        struct config_file* cfg);
 
+/**
+ * Find key in key table. Caller must hold lock on the table.
+ * @param key_table: the tsig key table.
+ * @param name: name to look for in wireformat.
+ * @param namelen: length of name.
+ * @return the found key or NULL if not found. The item is locked
+ * by the key_table lock.
+ */
+struct tsig_key* tsig_key_table_search(struct tsig_key_table* key_table,
+       uint8_t* name, size_t namelen);
+
 /**
  * Delete TSIG key.
  * @param key: to delete
@@ -189,4 +217,29 @@ int tsig_verify(struct sldns_buffer* pkt, const uint8_t* name,
 /** Compare function for the key table keys. */
 int tsig_key_compare(const void* v1, const void* v2);
 
+/**
+ * Find tsig key and create new tsig data.
+ * @param key_table: the tsig key table.
+ * @param name: key name in wireformat.
+ * @param namelen: length of name.
+ * @return NULL if not found, or alloc failure.
+ */
+struct tsig_data* tsig_create(struct tsig_key_table* key_table,
+       uint8_t* name, size_t namelen);
+
+/**
+ * Find tsig key and create new tsig data.
+ * @param key_table: the tsig key table.
+ * @param name: key name string.
+ * @return NULL if not found, or alloc failure, or could not parse string.
+ */
+struct tsig_data* tsig_create_fromstr(struct tsig_key_table* key_table,
+       char* name);
+
+/**
+ * Delete tsig data.
+ * @param tsig: the tsig data to delete.
+ */
+void tsig_delete(struct tsig_data* tsig);
+
 #endif /* UTIL_TSIG_H */