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