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
20u_long current_time = 4;
21int counter = 0;
22
23void setUp(void);
24void tearDown(void);
25void AddTrustedKey(keyid_t keyno);
26void AddUntrustedKey(keyid_t keyno);
27
28
29void
30setUp(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
53void
54tearDown(void)
55{
56	/*NOP*/
57}
58
59
60static const int KEYTYPE = KEY_TYPE_MD5;
61static char      msgbuf[128];
62
63void
64AddTrustedKey(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
75void
76AddUntrustedKey(keyid_t keyno)
77{
78	authtrust(keyno, FALSE);
79}
80
81void test_AddTrustedKeys(void);
82void 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
94void test_AddUntrustedKey(void);
95void test_AddUntrustedKey(void)
96{
97	const keyid_t KEYNO = 3;
98
99	AddUntrustedKey(KEYNO);
100
101	TEST_ASSERT_FALSE(authistrusted(KEYNO));
102}
103
104void test_HaveKeyCorrect(void);
105void 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
115void test_HaveKeyIncorrect(void);
116void 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
124void test_AddWithAuthUseKey(void);
125void 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
133void test_EmptyKey(void);
134void 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
144static u_short
145auth_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
162void test_auth_log2(void);
163void 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 */
183static int/*BOOL*/
184getaddr(
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
205void test_AddrMatch_anull(void);
206void 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
236void test_AddrMatch_self4(void);
237void 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
247void test_AddrMatch_self6(void);
248void 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
258void test_AddrMatch_afmix(void);
259void 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
270void test_AddrMatch_ipv4(void);
271void 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
300void test_AddrMatch_ipv6(void);
301void 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