1 /* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <https://www.gnu.org/licenses/>.
15 */
16
17 #include <tap/basic.h>
18 #include <assert.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include "libknot/errcode.h"
24 #include "libknot/tsig.h"
25
key_is_eq(const knot_tsig_key_t * a,const knot_tsig_key_t * b)26 static bool key_is_eq(const knot_tsig_key_t *a, const knot_tsig_key_t *b)
27 {
28 if (a == NULL && b == NULL) {
29 return true;
30 }
31
32 if (a == NULL || b == NULL) {
33 return false;
34 }
35
36 return a->algorithm == b->algorithm &&
37 knot_dname_is_equal(a->name, b->name) &&
38 dnssec_binary_cmp(&a->secret, &b->secret) == 0;
39 }
40
41 #define test_function(function, msg, expected, ...) \
42 knot_tsig_key_t key = { 0 }; \
43 int r = function(&key, __VA_ARGS__); \
44 ok((r != KNOT_EOK && expected == NULL) || \
45 (r == KNOT_EOK && key_is_eq(&key, expected)), \
46 "%s: %s", #function, msg); \
47 knot_tsig_key_deinit(&key);
48
test_init(const char * msg,const knot_tsig_key_t * expected,const char * algo,const char * name,const char * secret)49 static void test_init(const char *msg, const knot_tsig_key_t *expected,
50 const char *algo, const char *name, const char *secret)
51 {
52 test_function(knot_tsig_key_init, msg, expected, algo, name, secret);
53 }
54
test_init_str(const char * msg,const knot_tsig_key_t * expected,const char * params)55 static void test_init_str(const char *msg, const knot_tsig_key_t *expected,
56 const char *params)
57 {
58 test_function(knot_tsig_key_init_str, msg, expected, params);
59 }
60
test_init_file(const char * msg,const knot_tsig_key_t * expected,const char * filename)61 static void test_init_file(const char *msg, const knot_tsig_key_t *expected,
62 const char *filename)
63 {
64 test_function(knot_tsig_key_init_file, msg, expected, filename);
65 }
66
test_init_file_content(const char * msg,const knot_tsig_key_t * expected,const char * content)67 static void test_init_file_content(const char *msg,
68 const knot_tsig_key_t *expected,
69 const char *content)
70 {
71 char filename[] = "testkey.XXXXXX";
72
73 int fd = mkstemp(filename);
74 if (fd == -1) {
75 bail("failed to create temporary file");
76 return;
77 }
78
79 ok(write(fd, content, strlen(content)) != -1, "file write");
80 close(fd);
81
82 test_init_file(msg, expected, filename);
83
84 unlink(filename);
85 }
86
main(int argc,char * argv[])87 int main(int argc, char *argv[])
88 {
89 plan_lazy();
90
91 // initialization from parameters
92
93 test_init("missing name", NULL, "hmac-md5", NULL, "Wg==");
94 test_init("missing secret", NULL, "hmac-md5", "name", NULL);
95 test_init("invalid HMAC", NULL, "hmac-sha11", "name", "Wg==");
96 {
97 static const knot_tsig_key_t key = {
98 .algorithm = DNSSEC_TSIG_HMAC_SHA256,
99 .name = (uint8_t *)"\x3""key""\x4""name",
100 .secret.size = 1,
101 .secret.data = (uint8_t *)"\x5a"
102 };
103 test_init("default algorithm", &key, NULL, "key.name", "Wg==");
104 }
105 {
106 static const knot_tsig_key_t key = {
107 .algorithm = DNSSEC_TSIG_HMAC_SHA1,
108 .name = (uint8_t *)"\x4""knot""\x3""dns",
109 .secret.size = 6,
110 .secret.data = (uint8_t *)"secret"
111 };
112 test_init("sha1", &key, "hmac-sha1", "knot.dns.", "c2VjcmV0");
113 }
114
115 // initialization from string
116
117 test_init_str("missing value", NULL, NULL);
118 test_init_str("malformed", NULL, "this is malformed");
119 test_init_str("invalid HMAC", NULL, "hmac-sha51299:key:Wg==");
120 {
121 static const knot_tsig_key_t key = {
122 .algorithm = DNSSEC_TSIG_HMAC_SHA256,
123 .name = (uint8_t *)"\x4""tsig""\x3""key",
124 .secret.size = 9,
125 .secret.data = (uint8_t *)"bananakey"
126 };
127 test_init_str("default algorithm", &key, "tsig.key:YmFuYW5ha2V5");
128 }
129 {
130 static const knot_tsig_key_t key = {
131 .algorithm = DNSSEC_TSIG_HMAC_SHA384,
132 .name = (uint8_t *)"\x6""strong""\x3""key",
133 .secret.size = 8,
134 .secret.data = (uint8_t *)"applekey"
135 };
136 test_init_str("sha384", &key, "hmac-sha384:strong.KEY:YXBwbGVrZXk=");
137 }
138
139 // initialization from a file
140
141 test_init_file("no filename", NULL, NULL);
142 test_init_file("not-existing", NULL, "/this-really-should-not-exist");
143 test_init_file_content("malformed content", NULL, "malformed\n");
144 {
145 static const knot_tsig_key_t key = {
146 .algorithm = DNSSEC_TSIG_HMAC_SHA512,
147 .name = (uint8_t *)"\x6""django""\x3""one",
148 .secret.size = 40,
149 .secret.data = (uint8_t *)"Who's that stumbling around in the dark?"
150 };
151 test_init_file_content("sha512", &key,
152 "hmac-sha512:django.one:V2hvJ3MgdGhhdCB"
153 "zdHVtYmxpbmcgYXJvdW5kIGluIHRoZSBkYXJrP"
154 "w==\n\n\n");
155 }
156 {
157 static const knot_tsig_key_t key = {
158 .algorithm = DNSSEC_TSIG_HMAC_SHA512,
159 .name = (uint8_t *)"\x6""django""\x3""two",
160 .secret.size = 22,
161 .secret.data = (uint8_t *)"Prepare to get winged!"
162 };
163 test_init_file_content("sha512 without newline", &key,
164 "hmac-sha512:django.two:UHJlcGFyZSB0byB"
165 "nZXQgd2luZ2VkIQ==");
166 }
167 {
168 static const knot_tsig_key_t key = {
169 .algorithm = DNSSEC_TSIG_HMAC_SHA1,
170 .name = (uint8_t *)"\x4""test",
171 .secret.size = 1,
172 .secret.data = (uint8_t *)"\x5a"
173 };
174 test_init_file_content("leading and trailing white spaces", &key,
175 "\thmac-sha1:test:Wg== \n");
176 }
177
178 // tsig key duplication
179
180 {
181 static const knot_tsig_key_t key = {
182 .algorithm = DNSSEC_TSIG_HMAC_SHA1,
183 .name = (uint8_t *)"\x4""copy""\x2""me",
184 .secret.size = 6,
185 .secret.data = (uint8_t *)"orange"
186 };
187
188 knot_tsig_key_t copy = { 0 };
189 int r;
190
191 r = knot_tsig_key_copy(NULL, &key);
192 ok(r != KNOT_EOK, "knot_tsig_key_copy: no destination");
193 r = knot_tsig_key_copy(©, NULL);
194 ok(r != KNOT_EOK, "knot_tsig_key_copy: no source");
195 r = knot_tsig_key_copy(©, &key);
196 ok(r == KNOT_EOK && key_is_eq(©, &key) &&
197 copy.secret.data != key.secret.data && copy.name != key.name,
198 "knot_tsig_key_copy: simple copy");
199
200 knot_tsig_key_deinit(©);
201 }
202
203 return 0;
204 }
205