1 /* $NetBSD: authkeys.c,v 1.3 2020/05/25 20:47:36 christos Exp $ */
2
3 /* This file contains test for both libntp/authkeys.c and libntp/authusekey.c */
4
5 #include "config.h"
6
7 #include "ntp.h"
8 #include "ntp_stdlib.h"
9 #include "ntp_calendar.h"
10
11 #include "unity.h"
12
13 #ifdef OPENSSL
14 # include "openssl/err.h"
15 # include "openssl/rand.h"
16 # include "openssl/evp.h"
17 #endif
18 #include <limits.h>
19
20 u_long current_time = 4;
21 int counter = 0;
22
23 void setUp(void);
24 void tearDown(void);
25 void AddTrustedKey(keyid_t keyno);
26 void AddUntrustedKey(keyid_t keyno);
27
28
29 void
setUp(void)30 setUp(void)
31 {
32 if (counter == 0) {
33 counter++;
34 init_auth(); // causes segfault if called more than once
35 }
36 /*
37 * init_auth() is called by tests_main.cpp earlier. It
38 * does not initialize global variables like
39 * authnumkeys, so let's reset them to zero here.
40 */
41 authnumkeys = 0;
42
43 /*
44 * Especially, empty the key cache!
45 */
46 cache_keyid = 0;
47 cache_type = 0;
48 cache_flags = 0;
49 cache_secret = NULL;
50 cache_secretsize = 0;
51 }
52
53 void
tearDown(void)54 tearDown(void)
55 {
56 /*NOP*/
57 }
58
59
60 static const int KEYTYPE = KEY_TYPE_MD5;
61 static char msgbuf[128];
62
63 void
AddTrustedKey(keyid_t keyno)64 AddTrustedKey(keyid_t keyno)
65 {
66 /*
67 * We need to add a MD5-key in addition to setting the
68 * trust, because authhavekey() requires type != 0.
69 */
70 MD5auth_setkey(keyno, KEYTYPE, NULL, 0, NULL);
71
72 authtrust(keyno, TRUE);
73 }
74
75 void
AddUntrustedKey(keyid_t keyno)76 AddUntrustedKey(keyid_t keyno)
77 {
78 authtrust(keyno, FALSE);
79 }
80
81 void test_AddTrustedKeys(void);
test_AddTrustedKeys(void)82 void test_AddTrustedKeys(void)
83 {
84 const keyid_t KEYNO1 = 5;
85 const keyid_t KEYNO2 = 8;
86
87 AddTrustedKey(KEYNO1);
88 AddTrustedKey(KEYNO2);
89
90 TEST_ASSERT_TRUE(authistrusted(KEYNO1));
91 TEST_ASSERT_TRUE(authistrusted(KEYNO2));
92 }
93
94 void test_AddUntrustedKey(void);
test_AddUntrustedKey(void)95 void test_AddUntrustedKey(void)
96 {
97 const keyid_t KEYNO = 3;
98
99 AddUntrustedKey(KEYNO);
100
101 TEST_ASSERT_FALSE(authistrusted(KEYNO));
102 }
103
104 void test_HaveKeyCorrect(void);
test_HaveKeyCorrect(void)105 void test_HaveKeyCorrect(void)
106 {
107 const keyid_t KEYNO = 3;
108
109 AddTrustedKey(KEYNO);
110
111 TEST_ASSERT_TRUE(auth_havekey(KEYNO));
112 TEST_ASSERT_TRUE(authhavekey(KEYNO));
113 }
114
115 void test_HaveKeyIncorrect(void);
test_HaveKeyIncorrect(void)116 void test_HaveKeyIncorrect(void)
117 {
118 const keyid_t KEYNO = 2;
119
120 TEST_ASSERT_FALSE(auth_havekey(KEYNO));
121 TEST_ASSERT_FALSE(authhavekey(KEYNO));
122 }
123
124 void test_AddWithAuthUseKey(void);
test_AddWithAuthUseKey(void)125 void test_AddWithAuthUseKey(void)
126 {
127 const keyid_t KEYNO = 5;
128 const char* KEY = "52a";
129
130 TEST_ASSERT_TRUE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY));
131 }
132
133 void test_EmptyKey(void);
test_EmptyKey(void)134 void test_EmptyKey(void)
135 {
136 const keyid_t KEYNO = 3;
137 const char* KEY = "";
138
139 TEST_ASSERT_FALSE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY));
140 }
141
142 /* test the implementation of 'auth_log2' -- use a local copy of the code */
143
144 static u_short
auth_log2(size_t x)145 auth_log2(
146 size_t x)
147 {
148 int s;
149 int r = 0;
150 size_t m = ~(size_t)0;
151
152 for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
153 m <<= s;
154 if (x & m)
155 r += s;
156 else
157 x <<= s;
158 }
159 return (u_short)r;
160 }
161
162 void test_auth_log2(void);
test_auth_log2(void)163 void test_auth_log2(void)
164 {
165 int l2;
166 size_t tv;
167
168 TEST_ASSERT_EQUAL_INT(0, auth_log2(0));
169 TEST_ASSERT_EQUAL_INT(0, auth_log2(1));
170 for (l2 = 1; l2 < sizeof(size_t)*CHAR_BIT; ++l2) {
171 tv = (size_t)1 << l2;
172 TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv ));
173 TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv + 1 ));
174 TEST_ASSERT_EQUAL_INT(l2, auth_log2(2*tv - 1));
175 }
176 }
177
178 /* Converting a string to a host address. Here we use 'getaddrinfo()' in
179 * an independent implementation to avoid cross-reactions with the
180 * object under test. 'inet_pton' is too dangerous to handle it
181 * properly, and ultimate performance is *not* the goal here.
182 */
183 static int/*BOOL*/
getaddr(int af,const char * astr,sockaddr_u * addr)184 getaddr(
185 int af,
186 const char *astr,
187 sockaddr_u * addr)
188 {
189 struct addrinfo hint;
190 struct addrinfo *ares;
191
192 memset(&hint, 0, sizeof(hint));
193 hint.ai_flags = AI_NUMERICHOST;
194 hint.ai_family = af;
195 if (getaddrinfo(astr, NULL, &hint, &ares))
196 return FALSE;
197 if (ares->ai_addrlen > sizeof(*addr))
198 memcpy(addr, ares->ai_addr, sizeof(*addr));
199 else
200 memcpy(addr, ares->ai_addr, ares->ai_addrlen);
201 freeaddrinfo(ares);
202 return TRUE;
203 }
204
205 void test_AddrMatch_anull(void);
test_AddrMatch_anull(void)206 void test_AddrMatch_anull(void)
207 {
208 /* Check the not-an-address logic with a prefix/check length of
209 * zero bits. Any compare with a NULL or AF_UNSPEC address
210 * returns inequality (aka FALSE).
211 */
212 sockaddr_u ip4, ip6, ipn;
213
214 memset(&ipn, 0, sizeof(ipn));
215 AF(&ipn) = AF_UNSPEC;
216
217 TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4));
218 TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6));
219
220 TEST_ASSERT_FALSE(keyacc_amatch(NULL, NULL, 0));
221 TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ipn, 0));
222 TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip4, 0));
223 TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip6, 0));
224
225 TEST_ASSERT_FALSE(keyacc_amatch(&ipn, NULL, 0));
226 TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ipn, 0));
227 TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip4, 0));
228 TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip6, 0));
229
230 TEST_ASSERT_FALSE(keyacc_amatch(&ip4, NULL, 0));
231 TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ipn, 0));
232 TEST_ASSERT_FALSE(keyacc_amatch(&ip6, NULL, 0));
233 TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ipn, 0));
234 }
235
236 void test_AddrMatch_self4(void);
test_AddrMatch_self4(void)237 void test_AddrMatch_self4(void)
238 {
239 sockaddr_u ip4;
240 unsigned int bits;
241
242 TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.1.1", &ip4));
243 for (bits = 0; bits < 40; ++bits)
244 TEST_ASSERT_TRUE(keyacc_amatch(&ip4, &ip4, bits));
245 }
246
247 void test_AddrMatch_self6(void);
test_AddrMatch_self6(void)248 void test_AddrMatch_self6(void)
249 {
250 sockaddr_u ip6;
251 unsigned int bits;
252
253 TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6));
254 for (bits = 0; bits < 136; ++bits)
255 TEST_ASSERT_TRUE(keyacc_amatch(&ip6, &ip6, bits));
256 }
257
258 void test_AddrMatch_afmix(void);
test_AddrMatch_afmix(void)259 void test_AddrMatch_afmix(void)
260 {
261 sockaddr_u ip6, ip4;
262
263 TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4));
264 TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6));
265
266 TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ip6, 0));
267 TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ip4, 0));
268 }
269
270 void test_AddrMatch_ipv4(void);
test_AddrMatch_ipv4(void)271 void test_AddrMatch_ipv4(void)
272 {
273 sockaddr_u a1, a2;
274 unsigned int bits;
275 int want;
276
277 TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.1", &a1));
278 TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.3.1", &a2));
279
280 /* the first 23 bits are equal, so any prefix <= 23 should match */
281 for (bits = 0; bits < 40; ++bits) {
282 snprintf(msgbuf, sizeof(msgbuf),
283 "keyacc_amatch(*,*,%u) wrong", bits);
284 want = (bits <= 23);
285 TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
286 }
287
288 TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.127", &a1));
289 TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.128", &a2));
290
291 /* the first 24 bits are equal, so any prefix <= 24 should match */
292 for (bits = 0; bits < 40; ++bits) {
293 snprintf(msgbuf, sizeof(msgbuf),
294 "keyacc_amatch(*,*,%u) wrong", bits);
295 want = (bits <= 24);
296 TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
297 }
298 }
299
300 void test_AddrMatch_ipv6(void);
test_AddrMatch_ipv6(void)301 void test_AddrMatch_ipv6(void)
302 {
303 sockaddr_u a1, a2;
304 unsigned int bits;
305 int want;
306
307 TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:FFFF", &a1));
308 TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::3:FFFF", &a2));
309
310 /* the first 111 bits are equal, so any prefix <= 111 should match */
311 for (bits = 0; bits < 136; ++bits) {
312 snprintf(msgbuf, sizeof(msgbuf),
313 "keyacc_amatch(*,*,%u) wrong", bits);
314 want = (bits <= 111);
315 TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
316 }
317
318 TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:7FFF", &a1));
319 TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:8000", &a2));
320
321 /* the first 112 bits are equal, so any prefix <= 112 should match */
322 for (bits = 0; bits < 136; ++bits) {
323 snprintf(msgbuf, sizeof(msgbuf),
324 "keyacc_amatch(*,*,%u) wrong", bits);
325 want = (bits <= 112);
326 TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
327 }
328 }
329