From 4bbb74da398ed3295b571a551f57b4f1119510b6 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 18 Jun 2025 16:41:10 +0200 Subject: [PATCH] - xfr-tsig, tsig test. --- testcode/unittsig.c | 243 ++++++++++++++++++++++++++++++++++++++++++++ util/tsig.c | 26 ++++- util/tsig.h | 9 ++ 3 files changed, 276 insertions(+), 2 deletions(-) diff --git a/testcode/unittsig.c b/testcode/unittsig.c index 2156c2237..197623175 100644 --- a/testcode/unittsig.c +++ b/testcode/unittsig.c @@ -39,11 +39,254 @@ */ #include "config.h" #include "util/tsig.h" +#include "util/config_file.h" #include "testcode/unitmain.h" +#include "sldns/sbuffer.h" +#include + +#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 + * 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 + * 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"); } diff --git a/util/tsig.c b/util/tsig.c index 69094e088..7a82848d3 100644 --- a/util/tsig.c +++ b/util/tsig.c @@ -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) diff --git a/util/tsig.h b/util/tsig.h index b63ecd530..5c44d4f06 100644 --- a/util/tsig.h +++ b/util/tsig.h @@ -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. -- 2.47.2