- xfr-tsig, unit test for tsig_sign_query.

This commit is contained in:
W.C.A. Wijngaards
2025-06-20 12:13:51 +02:00
parent aa22fd936e
commit f2c609b9a5
3 changed files with 256 additions and 7 deletions
+1 -1
View File
@@ -1333,7 +1333,6 @@ main(int argc, char* argv[])
if(NSS_NoDB_Init(".") != SECSuccess)
fatal_exit("could not init NSS");
#endif /* HAVE_SSL or HAVE_NSS*/
tsig_test();
authzone_test();
neg_test();
rnd_test();
@@ -1363,6 +1362,7 @@ main(int argc, char* argv[])
#ifdef HAVE_NGTCP2
doq_test();
#endif /* HAVE_NGTCP2 */
tsig_test();
if(log_get_lock()) {
lock_basic_destroy((lock_basic_type*)log_get_lock());
}
+249 -4
View File
@@ -40,15 +40,18 @@
#include "config.h"
#include "util/tsig.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "testcode/unitmain.h"
#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include <ctype.h>
#define xstr(s) str(s)
#define str(s) #s
#define SRCDIRSTR xstr(SRCDIR)
/** verbosity for this file */
/** verbosity for this file, 0 no, 1 print some, 2 print packet dumps */
static int vtest = 0;
/**
@@ -56,15 +59,28 @@ static int vtest = 0;
*
* 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>
* 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.
*
* packet
* A packet in hex dump, on the following lines. Until 'endpacket'.
* It can be used to sign or verify.
* check-packet
* A packet in hex dump, on the following lines. Until 'endpacket'.
* It is compared to the packet buffer, and the test fails if not equal.
*
* tsig-sign-query <key> <time> <expected result>
* It TSIG signs with key name, at timestamp in secs, and the
* result of the call is compared with the expected result, and
* the test fails if not equal. The result is in the packet buffer.
*
*/
/** Clean up first keyword */
@@ -137,7 +153,7 @@ tsig_algo_test(char* algo)
static void
handle_file_algorithm(char* line, int* break_file)
{
char* algo = get_arg_on_line(line, "file_algorithm");
char* algo = get_arg_on_line(line, "file-algorithm");
if(!tsig_algo_test(algo)) {
if(vtest)
printf("algorithm not supported\n");
@@ -222,6 +238,229 @@ handle_del_key(char* line, struct tsig_key_table* key_table)
printf("deleted key %s\n", name);
}
/** skip whitespace */
static void
skip_whites(const char** p)
{
while(1) {
while(isspace((unsigned char)**p))
(*p)++;
if(**p == ';' || **p == '#') {
/* comment, skip until newline */
while(**p && **p != '\n')
(*p)++;
if(**p == '\n')
(*p)++;
} else return;
}
}
/** Read hex part into buffer */
static int
read_hex_segment(char* s, struct sldns_buffer* buf)
{
uint8_t val;
const char* p = s;
while(*p) {
skip_whites(&p);
if(!*p) break;
if(sldns_buffer_position(buf) == sldns_buffer_limit(buf)) {
printf("read hex: buffer too small\n");
return 0;
}
if(sldns_hexdigit_to_int(*p) == -1) {
printf("read hex: not hex: '%c'\n", *p);
return 0;
}
val = sldns_hexdigit_to_int(*p++) << 4;
skip_whites(&p);
if(!*p) {
printf("read hex: expected another, second, hex digit\n");
return 0;
}
if(sldns_hexdigit_to_int(*p) == -1) {
printf("read hex: not hex: '%c'\n", *p);
return 0;
}
val |= sldns_hexdigit_to_int(*p++);
sldns_buffer_write_u8(buf, (uint8_t)val);
skip_whites(&p);
}
return 1;
}
/** Read hex packet until 'endpacket' */
static int
read_packet_hex(char* line, struct sldns_buffer* buf, FILE* in,
const char* fname)
{
char l[1024];
char* s;
sldns_buffer_clear(buf);
if(!read_hex_segment(line, buf)) {
printf("Could not read hex %s: %s\n", fname, line);
return 0;
}
while(fgets(l, sizeof(l), in)) {
line[sizeof(l)-1]=0;
s = get_keyword(l);
if(strcmp(s, "endpacket") == 0)
break;
if(!read_hex_segment(s, buf)) {
printf("Could not read hex %s: %s\n", fname, s);
return 0;
}
}
sldns_buffer_flip(buf);
return 1;
}
/** Handle the packet */
static void
handle_packet(char* line, struct sldns_buffer* pkt, FILE* in,
const char* fname)
{
char* arg = get_arg_on_line(line, "packet");
if(!read_packet_hex(arg, pkt, in, fname))
fatal_exit("Could not read packet");
if(vtest >= 2) {
char* str = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
sldns_buffer_limit(pkt));
if(str)
printf("packet: %s\n", str);
else
printf("could not wire2str_pkt\n");
free(str);
}
}
/** Handle the check-packet */
static void
handle_check_packet(char* line, struct sldns_buffer* pkt, FILE* in,
const char* fname)
{
char* arg = get_arg_on_line(line, "check-packet");
uint8_t data[65536];
sldns_buffer check;
sldns_buffer_init_frm_data(&check, data, sizeof(data));
if(!read_packet_hex(arg, &check, in, fname))
fatal_exit("Could not read check-packet");
if(vtest >= 2) {
char* str = sldns_wire2str_pkt(sldns_buffer_begin(&check),
sldns_buffer_limit(&check));
if(str)
printf("check-packet: %s\n", str);
else
printf("could not wire2str_pkt\n");
free(str);
}
/* Compare the packet */
if(vtest && (sldns_buffer_limit(pkt) != sldns_buffer_limit(&check) ||
memcmp(sldns_buffer_begin(pkt), sldns_buffer_begin(&check),
sldns_buffer_limit(pkt)) != 0)) {
printf("The packet and check-packet are different\n");
if(sldns_buffer_limit(pkt) != sldns_buffer_limit(&check))
printf("Lengths are different %d, %d (check)\n",
(int)sldns_buffer_limit(pkt),
(int)sldns_buffer_limit(&check));
else printf("Lengths are the same %d\n",
(int)sldns_buffer_limit(pkt));
if(vtest >= 2) {
char pkthex[64*1024*2+10], checkhex[64*1024*2+10];
char *pktstr, *checkstr;
hex_ntop(sldns_buffer_begin(pkt), sldns_buffer_limit(pkt),
pkthex, sizeof(pkthex));
hex_ntop(sldns_buffer_begin(&check), sldns_buffer_limit(&check),
checkhex, sizeof(checkhex));
printf(" packet: %s\n", pkthex);
printf("check-packet: %s\n", checkhex);
pktstr = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
sldns_buffer_limit(pkt));
checkstr = sldns_wire2str_pkt(
sldns_buffer_begin(&check),
sldns_buffer_limit(&check));
if(pktstr)
printf(" packet: %s\n", pktstr);
else
printf(" packet: could not wire2str\n");
if(checkstr)
printf("check-packet: %s\n", checkstr);
else
printf("check-packet: could not wire2str\n");
free(pktstr);
free(checkstr);
}
}
unit_assert(sldns_buffer_limit(pkt) == sldns_buffer_limit(&check) &&
memcmp(sldns_buffer_begin(pkt), sldns_buffer_begin(&check),
sldns_buffer_limit(pkt)) == 0);
if(vtest)
printf("check-packet is equal\n");
}
/** Handle the tsig-sign-query */
static void
handle_tsig_sign_query(char* line, struct tsig_key_table* key_table,
struct sldns_buffer* pkt)
{
char* arg = get_arg_on_line(line, "tsig-sign-query");
char* keyname, *s, *timestr, *expectedstr;
int expected_result, ret;
uint64_t timepoint;
struct tsig_data* tsig;
size_t pos;
keyname = arg;
s = arg;
s = strchr(s, ' ');
if(!s || !*s)
fatal_exit("expected arguments for %s", arg);
*s++ = 0;
while(*s && *s == ' ')
s++;
timestr = s;
s = strchr(s, ' ');
if(!s || !*s)
fatal_exit("expected arguments for %s", arg);
*s++ = 0;
while(*s && *s == ' ')
s++;
expectedstr = s;
timepoint = (uint64_t)atoll(timestr);
if(timepoint == 0 && strcmp(timestr, "0") != 0)
fatal_exit("expected time argument for %s", timestr);
expected_result = atoi(expectedstr);
if(expected_result == 0 && strcmp(expectedstr, "0") != 0)
fatal_exit("expected int argument for %s", expectedstr);
if(vtest)
printf("tsig-sign-query with %s %d %d\n", keyname,
(int)timepoint, expected_result);
tsig = tsig_create_fromstr(key_table, keyname);
if(!tsig)
fatal_exit("alloc fail or key not found %s", keyname);
/* Put position at the end of the packet to sign it. */
pos = sldns_buffer_limit(pkt);
sldns_buffer_clear(pkt);
sldns_buffer_set_position(pkt, pos);
ret = tsig_sign_query(tsig, pkt, key_table, timepoint);
sldns_buffer_flip(pkt);
if(vtest) {
if(ret == expected_result)
printf("function ok, %s\n", (ret?"success":"fail"));
else
printf("function returned %d, expected result %d\n",
ret, expected_result);
}
unit_assert(ret == expected_result);
}
/** Handle one line from the TSIG test file */
static void
handle_line(char* line, struct tsig_key_table* key_table,
@@ -231,12 +470,18 @@ handle_line(char* line, struct tsig_key_table* key_table,
char* s = get_keyword(line);
if(vtest)
printf("line: %s\n", s);
if(strncmp(s, "file_algorithm", 14) == 0) {
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, "packet", 6) == 0) {
handle_packet(s, pkt, in, fname);
} else if(strncmp(s, "check-packet", 12) == 0) {
handle_check_packet(s, pkt, in, fname);
} else if(strncmp(s, "tsig-sign-query", 15) == 0) {
handle_tsig_sign_query(s, key_table, pkt);
} else if(strncmp(s, "#", 1) == 0) {
/* skip comment */
} else if(strcmp(s, "") == 0) {