xref: /netbsd-src/external/bsd/ntp/dist/sntp/tests/packetProcessing.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: packetProcessing.c,v 1.4 2020/05/25 20:47:35 christos Exp $	*/
2 
3 #include "config.h"
4 
5 #include "sntptest.h"
6 #include "networking.h"
7 #include "ntp_stdlib.h"
8 #include "unity.h"
9 
10 #define CMAC		"AES128CMAC"
11 #define CMAC_LENGTH	16
12 
13 
14 const char * Version = "stub unit test Version string";
15 
16 /* Hacks into the key database. */
17 extern struct key* key_ptr;
18 extern int key_cnt;
19 
20 
21 void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq);
22 void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq);
23 void setUp(void);
24 void tearDown(void);
25 void test_TooShortLength(void);
26 void test_LengthNotMultipleOfFour(void);
27 void test_TooShortExtensionFieldLength(void);
28 void test_UnauthenticatedPacketReject(void);
29 void test_CryptoNAKPacketReject(void);
30 void test_AuthenticatedPacketInvalid(void);
31 void test_AuthenticatedPacketUnknownKey(void);
32 void test_ServerVersionTooOld(void);
33 void test_ServerVersionTooNew(void);
34 void test_NonWantedMode(void);
35 void test_KoDRate(void);
36 void test_KoDDeny(void);
37 void test_RejectUnsyncedServer(void);
38 void test_RejectWrongResponseServerMode(void);
39 void test_AcceptNoSentPacketBroadcastMode(void);
40 void test_CorrectUnauthenticatedPacket(void);
41 void test_CorrectAuthenticatedPacketMD5(void);
42 void test_CorrectAuthenticatedPacketSHA1(void);
43 void test_CorrectAuthenticatedPacketCMAC(void);
44 
45 /* [Bug 2998] There are some issues whith the definition of 'struct pkt'
46  * when AUTOKEY is undefined -- the formal struct is too small to hold
47  * all the extension fields that are going to be tested. We have to make
48  * sure we have the extra bytes, or the test yield undefined results due
49  * to buffer overrun.
50  */
51 #ifndef AUTOKEY
52 # define EXTRA_BUFSIZE 256
53 #else
54 # define EXTRA_BUFSIZE 0
55 #endif
56 
57 union tpkt {
58 	struct pkt p;
59 	u_char     b[sizeof(struct pkt) + EXTRA_BUFSIZE];
60 };
61 
62 static union tpkt testpkt;
63 static union tpkt testspkt;
64 static sockaddr_u testsock;
65 bool restoreKeyDb;
66 
67 
68 void
69 PrepareAuthenticationTest(
70 	int		key_id,
71 	int		key_len,
72 	const char *	type,
73 	const void *	key_seq
74 	)
75 {
76 	char str[25];
77 	snprintf(str, 25, "%d", key_id);
78 	ActivateOption("-a", str);
79 
80 	key_cnt = 1;
81 	key_ptr = emalloc(sizeof(struct key));
82 	key_ptr->next = NULL;
83 	key_ptr->key_id = key_id;
84 	key_ptr->key_len = key_len;
85 	memcpy(key_ptr->typen, type, strlen(type) + 1);
86 
87 	TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq));
88 
89 	memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len);
90 	restoreKeyDb = true;
91 }
92 
93 
94 void
95 PrepareAuthenticationTestMD5(
96 	int 		key_id,
97 	int 		key_len,
98 	const void *	key_seq
99 	)
100 {
101 	PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq);
102 }
103 
104 
105 void
106 setUp(void)
107 {
108 
109 	sntptest();
110 	restoreKeyDb = false;
111 
112 	/* Initialize the test packet and socket,
113 	 * so they contain at least some valid data.
114 	 */
115 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
116 										MODE_SERVER);
117 	testpkt.p.stratum = STRATUM_REFCLOCK;
118 	memcpy(&testpkt.p.refid, "GPS\0", 4);
119 
120 	/* Set the origin timestamp of the received packet to the
121 	 * same value as the transmit timestamp of the sent packet.
122 	 */
123 	l_fp tmp;
124 	tmp.l_ui = 1000UL;
125 	tmp.l_uf = 0UL;
126 
127 	HTONL_FP(&tmp, &testpkt.p.org);
128 	HTONL_FP(&tmp, &testspkt.p.xmt);
129 }
130 
131 
132 void
133 tearDown(void)
134 {
135 	if (restoreKeyDb) {
136 		key_cnt = 0;
137 		free(key_ptr);
138 		key_ptr = NULL;
139 	}
140 
141 	sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */
142 }
143 
144 
145 void
146 test_TooShortLength(void)
147 {
148 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
149 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
150 				      MODE_SERVER, &testspkt.p, "UnitTest"));
151 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
152 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1,
153 				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
154 }
155 
156 
157 void
158 test_LengthNotMultipleOfFour(void)
159 {
160 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
161 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6,
162 				      MODE_SERVER, &testspkt.p, "UnitTest"));
163 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
164 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3,
165 				      MODE_BROADCAST, &testspkt.p, "UnitTest"));
166 }
167 
168 
169 void
170 test_TooShortExtensionFieldLength(void)
171 {
172 	/* [Bug 2998] We have to get around the formal specification of
173 	 * the extension field if AUTOKEY is undefined. (At least CLANG
174 	 * issues a warning in this case. It's just a warning, but
175 	 * still...
176 	 */
177 	uint32_t * pe = testpkt.p.exten + 7;
178 
179 	/* The lower 16-bits are the length of the extension field.
180 	 * This lengths must be multiples of 4 bytes, which gives
181 	 * a minimum of 4 byte extension field length.
182 	 */
183 	*pe = htonl(3); /* 3 bytes is too short. */
184 
185 	/* We send in a pkt_len of header size + 4 byte extension
186 	 * header + 24 byte MAC, this prevents the length error to
187 	 * be caught at an earlier stage
188 	 */
189 	int pkt_len = LEN_PKT_NOMAC + 4 + 24;
190 
191 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
192 			  process_pkt(&testpkt.p, &testsock, pkt_len,
193 				      MODE_SERVER, &testspkt.p, "UnitTest"));
194 }
195 
196 
197 void
198 test_UnauthenticatedPacketReject(void)
199 {
200 	/* Activate authentication option */
201 	ActivateOption("-a", "123");
202 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
203 
204 	int pkt_len = LEN_PKT_NOMAC;
205 
206 	/* We demand authentication, but no MAC header is present. */
207 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
208 			  process_pkt(&testpkt.p, &testsock, pkt_len,
209 				      MODE_SERVER, &testspkt.p, "UnitTest"));
210 }
211 
212 
213 void
214 test_CryptoNAKPacketReject(void)
215 {
216 	/* Activate authentication option */
217 	ActivateOption("-a", "123");
218 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
219 
220 	int pkt_len = LEN_PKT_NOMAC + 4; /* + 4 byte MAC = Crypto-NAK */
221 
222 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
223 			  process_pkt(&testpkt.p, &testsock, pkt_len,
224 				      MODE_SERVER, &testspkt.p, "UnitTest"));
225 }
226 
227 
228 void
229 test_AuthenticatedPacketInvalid(void)
230 {
231 	/* Activate authentication option */
232 	PrepareAuthenticationTestMD5(50, 9, "123456789");
233 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
234 
235 	/* Prepare the packet. */
236 	int pkt_len = LEN_PKT_NOMAC;
237 
238 	testpkt.p.exten[0] = htonl(50);
239 	int mac_len = make_mac(&testpkt.p, pkt_len,
240 			       MAX_MD5_LEN - KEY_MAC_LEN, key_ptr,
241 			       &testpkt.p.exten[1]);
242 
243 	pkt_len += 4 + mac_len;
244 
245 	/* Now, alter the MAC so it becomes invalid. */
246 	testpkt.p.exten[1] += 1;
247 
248 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
249 			  process_pkt(&testpkt.p, &testsock, pkt_len,
250 				      MODE_SERVER, &testspkt.p, "UnitTest"));
251 }
252 
253 
254 void
255 test_AuthenticatedPacketUnknownKey(void)
256 {
257 	/* Activate authentication option */
258 	PrepareAuthenticationTestMD5(30, 9, "123456789");
259 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
260 
261 	/* Prepare the packet. Note that the Key-ID expected is 30, but
262 	 * the packet has a key id of 50.
263 	 */
264 	int pkt_len = LEN_PKT_NOMAC;
265 
266 	testpkt.p.exten[0] = htonl(50);
267 	int mac_len = make_mac(&testpkt.p, pkt_len,
268 			       MAX_MD5_LEN - KEY_MAC_LEN, key_ptr,
269 			       &testpkt.p.exten[1]);
270 	pkt_len += KEY_MAC_LEN + mac_len;
271 
272 	TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL,
273 			  process_pkt(&testpkt.p, &testsock, pkt_len,
274 				      MODE_SERVER, &testspkt.p, "UnitTest"));
275 }
276 
277 
278 void
279 test_ServerVersionTooOld(void)
280 {
281 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
282 
283 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
284 					      NTP_OLDVERSION - 1,
285 					      MODE_CLIENT);
286 	TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) < NTP_OLDVERSION);
287 
288 	int pkt_len = LEN_PKT_NOMAC;
289 
290 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
291 			  process_pkt(&testpkt.p, &testsock, pkt_len,
292 				      MODE_SERVER, &testspkt.p, "UnitTest"));
293 }
294 
295 
296 void
297 test_ServerVersionTooNew(void)
298 {
299 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
300 
301 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
302 					      NTP_VERSION + 1,
303 					      MODE_CLIENT);
304 	TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) > NTP_VERSION);
305 
306 	int pkt_len = LEN_PKT_NOMAC;
307 
308 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
309 			  process_pkt(&testpkt.p, &testsock, pkt_len,
310 				      MODE_SERVER, &testspkt.p, "UnitTest"));
311 }
312 
313 
314 void
315 test_NonWantedMode(void)
316 {
317 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
318 
319 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
320 					      NTP_VERSION,
321 					      MODE_CLIENT);
322 
323 	/* The packet has a mode of MODE_CLIENT, but process_pkt expects
324 	 * MODE_SERVER
325 	 */
326 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
327 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
328 				      MODE_SERVER, &testspkt.p, "UnitTest"));
329 }
330 
331 
332 /* Tests bug 1597 */
333 void
334 test_KoDRate(void)
335 {
336 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
337 
338 	testpkt.p.stratum = STRATUM_PKT_UNSPEC;
339 	memcpy(&testpkt.p.refid, "RATE", 4);
340 
341 	TEST_ASSERT_EQUAL(KOD_RATE,
342 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
343 				      MODE_SERVER, &testspkt.p, "UnitTest"));
344 }
345 
346 
347 void
348 test_KoDDeny(void)
349 {
350 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
351 
352 	testpkt.p.stratum = STRATUM_PKT_UNSPEC;
353 	memcpy(&testpkt.p.refid, "DENY", 4);
354 
355 	TEST_ASSERT_EQUAL(KOD_DEMOBILIZE,
356 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
357 				      MODE_SERVER, &testspkt.p, "UnitTest"));
358 }
359 
360 
361 void
362 test_RejectUnsyncedServer(void)
363 {
364 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
365 
366 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
367 					      NTP_VERSION,
368 					      MODE_SERVER);
369 
370 	TEST_ASSERT_EQUAL(SERVER_UNUSEABLE,
371 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
372 				      MODE_SERVER, &testspkt.p, "UnitTest"));
373 }
374 
375 
376 void
377 test_RejectWrongResponseServerMode(void)
378 {
379 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
380 
381 	l_fp tmp;
382 	tmp.l_ui = 1000UL;
383 	tmp.l_uf = 0UL;
384 	HTONL_FP(&tmp, &testpkt.p.org);
385 
386 	tmp.l_ui = 2000UL;
387 	tmp.l_uf = 0UL;
388 	HTONL_FP(&tmp, &testspkt.p.xmt);
389 
390 	TEST_ASSERT_EQUAL(PACKET_UNUSEABLE,
391 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
392 				      MODE_SERVER, &testspkt.p, "UnitTest"));
393 }
394 
395 
396 void
397 test_AcceptNoSentPacketBroadcastMode(void)
398 {
399 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
400 
401 	testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
402 					      NTP_VERSION,
403 					      MODE_BROADCAST);
404 
405 	TEST_ASSERT_EQUAL(LEN_PKT_NOMAC,
406 		  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
407 			      MODE_BROADCAST, NULL, "UnitTest"));
408 }
409 
410 
411 void
412 test_CorrectUnauthenticatedPacket(void)
413 {
414 	TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION));
415 
416 	TEST_ASSERT_EQUAL(LEN_PKT_NOMAC,
417 			  process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC,
418 				      MODE_SERVER, &testspkt.p, "UnitTest"));
419 }
420 
421 
422 void
423 test_CorrectAuthenticatedPacketMD5(void)
424 {
425 	PrepareAuthenticationTestMD5(10, 15, "123456789abcdef");
426 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
427 
428 	int pkt_len = LEN_PKT_NOMAC;
429 
430 	/* Prepare the packet. */
431 	testpkt.p.exten[0] = htonl(10);
432 	int mac_len = make_mac(&testpkt.p, pkt_len,
433 			       MAX_MD5_LEN - KEY_MAC_LEN, key_ptr,
434 			       &testpkt.p.exten[1]);
435 
436 	pkt_len += KEY_MAC_LEN + mac_len;
437 
438 	TEST_ASSERT_EQUAL(pkt_len,
439 			  process_pkt(&testpkt.p, &testsock, pkt_len,
440 				      MODE_SERVER, &testspkt.p, "UnitTest"));
441 }
442 
443 
444 void
445 test_CorrectAuthenticatedPacketSHA1(void)
446 {
447 	PrepareAuthenticationTest(20, 15, "SHA1", "abcdefghijklmno");
448 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
449 
450 	int pkt_len = LEN_PKT_NOMAC;
451 
452 	/* Prepare the packet. */
453 	testpkt.p.exten[0] = htonl(20);
454 	int mac_len = make_mac(&testpkt.p, pkt_len,
455 			       MAX_MDG_LEN, key_ptr,
456 			       &testpkt.p.exten[1]);
457 
458 	pkt_len += KEY_MAC_LEN + mac_len;
459 
460 	TEST_ASSERT_EQUAL(pkt_len,
461 			  process_pkt(&testpkt.p, &testsock, pkt_len,
462 				      MODE_SERVER, &testspkt.p, "UnitTest"));
463 }
464 
465 
466 void
467 test_CorrectAuthenticatedPacketCMAC(void)
468 {
469 #if defined(OPENSSL) && defined(ENABLE_CMAC)
470 
471 	PrepareAuthenticationTest(30, CMAC_LENGTH, CMAC, "abcdefghijklmnop");
472 	TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION));
473 
474 	int pkt_len = LEN_PKT_NOMAC;
475 
476 	/* Prepare the packet. */
477 	testpkt.p.exten[0] = htonl(30);
478 	int mac_len = make_mac(&testpkt.p, pkt_len,
479 			       MAX_MAC_LEN, key_ptr,
480 			       &testpkt.p.exten[1]);
481 
482 	pkt_len += 4 + mac_len;
483 
484 	TEST_ASSERT_EQUAL(pkt_len,
485 			  process_pkt(&testpkt.p, &testsock, pkt_len,
486 				      MODE_SERVER, &testspkt.p, "UnitTest"));
487 
488 #else
489 
490 	TEST_IGNORE_MESSAGE("OpenSSL CMAC not used, skipping...");
491 
492 #endif	/* OPENSSL */
493 }
494 
495