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