]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- xfr-tsig, tsig test.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Jun 2025 14:41:10 +0000 (16:41 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Jun 2025 14:41:10 +0000 (16:41 +0200)
testcode/unittsig.c
util/tsig.c
util/tsig.h

index 2156c22375ed2e213f4588cc96d0437b77a81737..197623175fe5d833442faecadc90d47ac361ed7c 100644 (file)
  */
 #include "config.h"
 #include "util/tsig.h"
+#include "util/config_file.h"
 #include "testcode/unitmain.h"
+#include "sldns/sbuffer.h"
+#include <ctype.h>
+
+#define xstr(s) str(s)
+#define str(s) #s
+#define SRCDIRSTR xstr(SRCDIR)
+
+/** verbosity for this file */
+static int vtest = 0;
+
+/**
+ * Content of the TSIG test files.
+ *
+ * The tsig test files have this syntax. It is made of lines, lines started
+ * with # are a comment. empty lines are ignored.
+ * file_algorithm <name>
+ *     The name is like md5, sha1, sha256 and if the algorithm is not
+ *     supported at the test run time, the file is skipped, silently.
+ * tsig-key:
+ *     the following lines define name:, algorithm: and secret:
+ *     and it adds a tsig-key that can be used.
+ * del-key <name>
+ *     The tsig key is deleted, from the in-memory key table.
+ *
+ */
+
+/** Clean up first keyword */
+static char*
+get_keyword(char* line)
+{
+       char* s = line;
+       while(isspace(*s))
+               s++;
+       if(strlen(s)>0 && s[strlen(s)-1] == '\n')
+               s[strlen(s)-1] = 0;
+       return s;
+}
+
+/** Get argument from line */
+static char*
+get_arg_on_line(char* line, char* keyword)
+{
+       char* s = line;
+       s += strlen(keyword);
+       while(isspace(*s))
+               s++;
+       return s;
+}
+
+/** See if algorithm is supported for tsig test */
+static int
+tsig_algo_test(char* algo)
+{
+       if(strcmp(algo, "md5") == 0)
+               return 1;
+       if(strcmp(algo, "sha1") == 0)
+               return 1;
+       if(strcmp(algo, "sha224") == 0) {
+               /* The EVP_sha256 test is also used for sha224. */
+#ifdef HAVE_EVP_SHA256
+               return 1;
+#else
+               return 0;
+#endif
+       }
+       if(strcmp(algo, "sha256") == 0) {
+#ifdef HAVE_EVP_SHA256
+               return 1;
+#else
+               return 0;
+#endif
+       }
+       if(strcmp(algo, "sha384") == 0) {
+               /* The EVP_sha512 test is also used for sha384. */
+#ifdef HAVE_EVP_SHA512
+               return 1;
+#else
+               return 0;
+#endif
+       }
+       if(strcmp(algo, "sha512") == 0) {
+#ifdef HAVE_EVP_SHA512
+               return 1;
+#else
+               return 0;
+#endif
+       }
+       if(vtest)
+               printf("Unknown tsig test algorithm %s\n", algo);
+       return 0;
+}
+
+/** Handle the file_algorithm */
+static void
+handle_file_algorithm(char* line, int* break_file)
+{
+       char* algo = get_arg_on_line(line, "file_algorithm");
+       if(!tsig_algo_test(algo)) {
+               if(vtest)
+                       printf("algorithm not supported\n");
+               *break_file = 1;
+               return;
+       }
+       if(vtest)
+               printf("algorithm supported\n");
+}
+
+/** Removes quotes if any */
+static char*
+quote_removal(char* line)
+{
+       if(line[0] == '"') {
+               char* s = line+1;
+               if(strlen(s)>0 && s[strlen(s)-1] == '"')
+                       s[strlen(s)-1] = 0;
+               return s;
+       }
+       return line;
+}
+
+/** Handle the tsig-key */
+static void
+handle_tsig_key(struct tsig_key_table* key_table, FILE* in, const char* fname)
+{
+       char line[1024];
+       char* s;
+       char* name = NULL, *algorithm = NULL, *secret = NULL;
+       struct config_tsig_key k;
+
+       while(fgets(line, sizeof(line), in)) {
+               line[sizeof(line)-1]=0;
+               s = get_keyword(line);
+               if(strncmp(s, "name:", 5) == 0) {
+                       name = strdup(quote_removal(
+                               get_arg_on_line(s, "name:")));
+                       if(!name)
+                               fatal_exit("out of memory");
+               } else if(strncmp(s, "algorithm:", 10) == 0) {
+                       algorithm = strdup(quote_removal(
+                               get_arg_on_line(s, "algorithm:")));
+                       if(!algorithm)
+                               fatal_exit("out of memory");
+               } else if(strncmp(s, "secret:", 7) == 0) {
+                       secret = strdup(quote_removal(
+                               get_arg_on_line(s, "secret:")));
+                       if(!secret)
+                               fatal_exit("out of memory");
+               } else {
+                       fatal_exit("unknown tsig-key element %s: %s",
+                               fname, s);
+               }
+
+               if(name && algorithm && secret)
+                       break;
+       }
+
+       k.next = NULL;
+       k.name = name;
+       k.algorithm = algorithm;
+       k.secret = secret;
+       if(!tsig_key_table_add_key(key_table, &k))
+               fatal_exit("could not tsig_key_table_add_key, out of memory");
+       if(vtest)
+               printf("add key %s %s\n", name, algorithm);
+
+       free(name);
+       free(algorithm);
+       explicit_bzero(secret, strlen(secret));
+       free(secret);
+}
+
+/** Handle the del_key */
+static void
+handle_del_key(char* line, struct tsig_key_table* key_table)
+{
+       char* name = get_arg_on_line(line, "del_key");
+       tsig_key_table_del_key_fromstr(key_table, name);
+       if(vtest)
+               printf("deleted key %s\n", name);
+}
+
+/** Handle one line from the TSIG test file */
+static void
+handle_line(char* line, struct tsig_key_table* key_table,
+       struct sldns_buffer* pkt, FILE* in, const char* fname,
+       int* break_file)
+{
+       char* s = get_keyword(line);
+       if(vtest)
+               printf("line: %s\n", s);
+       if(strncmp(s, "file_algorithm", 14) == 0) {
+               handle_file_algorithm(s, break_file);
+       } else if(strcmp(s, "tsig-key:") == 0) {
+               handle_tsig_key(key_table, in, fname);
+       } else if(strncmp(s, "delkey", 6) == 0) {
+               handle_del_key(s, key_table);
+       } else if(strncmp(s, "#", 1) == 0) {
+               /* skip comment */
+       } else if(strcmp(s, "") == 0) {
+               /* skip empty lines */
+       } else {
+               fatal_exit("Unknown tsig line %s: %s", fname, s);
+       }
+       (void)pkt;
+}
+
+/** test tsig */
+static void
+tsig_test_one(const char* fname)
+{
+       struct tsig_key_table* key_table;
+       sldns_buffer* pkt;
+       FILE* in;
+       char line[1024];
+       int break_file = 0;
+
+       unit_show_func("tsig", fname);
+       key_table = tsig_key_table_create();
+       if(!key_table)
+               fatal_exit("out of memory");
+       pkt = sldns_buffer_new(65536);
+       if(!pkt)
+               fatal_exit("out of memory");
+       sldns_buffer_flip(pkt); /* start with empty buffer */
+       in = fopen(fname, "r");
+       if(!in)
+               fatal_exit("could not open %s: %s", fname, strerror(errno));
+
+       while(fgets(line, sizeof(line), in)) {
+               line[sizeof(line)-1]=0;
+               handle_line(line, key_table, pkt, in, fname, &break_file);
+               if(break_file)
+                       break;
+       }
+       if(ferror(in))
+               fatal_exit("error read %s: %s", fname, strerror(errno));
+
+       tsig_key_table_delete(key_table);
+       sldns_buffer_free(pkt);
+       fclose(in);
+}
 
 /** test tsig code */
 void 
 tsig_test(void)
 {
        unit_show_feature("tsig");
+       tsig_test_one(SRCDIRSTR "/testdata/tsig_test.1");
 }
index 69094e088df1b8dc4564af739f1fdf7556bc053c..7a82848d372bc9824d2a777ded004ae45e75ba28 100644 (file)
@@ -174,8 +174,7 @@ tsig_key_create(const char* name, const char* algorithm, const char* secret)
        return key;
 }
 
-/** Add a key to the TSIG key table. */
-static int
+int
 tsig_key_table_add_key(struct tsig_key_table* key_table,
        struct config_tsig_key* s)
 {
@@ -198,6 +197,29 @@ tsig_key_table_add_key(struct tsig_key_table* key_table,
        return 1;
 }
 
+void
+tsig_key_table_del_key_fromstr(struct tsig_key_table* key_table,
+       char* name)
+{
+       uint8_t buf[LDNS_MAX_DOMAINLEN+1];
+       size_t len = sizeof(buf);
+       struct tsig_key k, *key;
+       rbnode_type* node;
+       if(!sldns_str2wire_dname_buf(name, buf, &len)) {
+               log_err("could not parse '%s'", name);
+               return;
+       }
+
+       k.node.key = &k;
+       k.name = buf;
+       k.name_len = len;
+       node = rbtree_delete(key_table->tree, &k);
+       if(!node)
+               return;
+       key = (struct tsig_key*)node->key;
+       tsig_key_delete(key);
+}
+
 int
 tsig_key_table_apply_cfg(struct tsig_key_table* key_table,
        struct config_file* cfg)
index b63ecd53072e5816648345b88fa5e4682feee7da..5c44d4f06891e4a1731d2eb342d599540185a9e5 100644 (file)
@@ -45,6 +45,7 @@
 #include "util/rbtree.h"
 struct sldns_buffer;
 struct config_file;
+struct config_tsig_key;
 struct regional;
 
 /**
@@ -181,6 +182,14 @@ struct tsig_key_table* tsig_key_table_create(void);
  */
 void tsig_key_table_delete(struct tsig_key_table* key_table);
 
+/** Add a key to the TSIG key table. */
+int tsig_key_table_add_key(struct tsig_key_table* key_table,
+       struct config_tsig_key* s);
+
+/** Delete a key from the TSIG key table. */
+void tsig_key_table_del_key_fromstr(struct tsig_key_table* key_table,
+       char* name);
+
 /**
  * Apply config to the tsig key table.
  * @param key_table: the tsig key table.