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