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