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
PrepareAuthenticationTest(int key_id,int key_len,const char * type,const void * key_seq)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
setUp(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
tearDown(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
test_TooShortLength(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
test_LengthNotMultipleOfFour(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
test_TooShortExtensionFieldLength(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
test_UnauthenticatedPacketReject(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
test_CryptoNAKPacketReject(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
test_AuthenticatedPacketInvalid(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
test_AuthenticatedPacketUnknownKey(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
test_ServerVersionTooOld(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
test_ServerVersionTooNew(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
test_NonWantedMode(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
test_KoDRate(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
test_KoDDeny(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
test_RejectUnsyncedServer(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
test_RejectWrongResponseServerMode(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
test_AcceptNoSentPacketBroadcastMode(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
test_CorrectUnauthenticatedPacket(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
test_CorrectAuthenticatedPacketMD5(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
test_CorrectAuthenticatedPacketSHAKE128(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
test_CorrectAuthenticatedPacketSHA1(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
test_CorrectAuthenticatedPacketCMAC(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