packetProcessing.c revision 330141
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 12const char * Version = "stub unit test Version string"; 13 14/* Hacks into the key database. */ 15extern struct key* key_ptr; 16extern int key_cnt; 17 18 19void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq); 20void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq); 21void setUp(void); 22void tearDown(void); 23void test_TooShortLength(void); 24void test_LengthNotMultipleOfFour(void); 25void test_TooShortExtensionFieldLength(void); 26void test_UnauthenticatedPacketReject(void); 27void test_CryptoNAKPacketReject(void); 28void test_AuthenticatedPacketInvalid(void); 29void test_AuthenticatedPacketUnknownKey(void); 30void test_ServerVersionTooOld(void); 31void test_ServerVersionTooNew(void); 32void test_NonWantedMode(void); 33void test_KoDRate(void); 34void test_KoDDeny(void); 35void test_RejectUnsyncedServer(void); 36void test_RejectWrongResponseServerMode(void); 37void test_AcceptNoSentPacketBroadcastMode(void); 38void test_CorrectUnauthenticatedPacket(void); 39void test_CorrectAuthenticatedPacketMD5(void); 40void test_CorrectAuthenticatedPacketSHA1(void); 41void 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 55union tpkt { 56 struct pkt p; 57 u_char b[sizeof(struct pkt) + EXTRA_BUFSIZE]; 58}; 59 60static union tpkt testpkt; 61static union tpkt testspkt; 62static sockaddr_u testsock; 63bool restoreKeyDb; 64 65 66void 67PrepareAuthenticationTest( 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 92void 93PrepareAuthenticationTestMD5( 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 103void 104setUp(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 130void 131tearDown(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 143void 144test_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 155void 156test_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 167void 168test_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 195void 196test_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 211void 212test_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 226void 227test_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 252void 253test_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 276void 277test_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 294void 295test_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 312void 313test_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 */ 331void 332test_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 345void 346test_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 359void 360test_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 374void 375test_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 394void 395test_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 409void 410test_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 420void 421test_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 442void 443test_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 464void 465test_CorrectAuthenticatedPacketCMAC(void) 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 485