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