packetProcessing.c revision 309008
1243791Sdim#include "config.h" 2243791Sdim 3353358Sdim#include "sntptest.h" 4353358Sdim#include "networking.h" 5353358Sdim#include "ntp_stdlib.h" 6243791Sdim#include "unity.h" 7243791Sdim 8243791Sdim 9243791Sdimconst char * Version = "stub unit test Version string"; 10243791Sdim 11243791Sdim/* Hacks into the key database. */ 12243791Sdimextern struct key* key_ptr; 13243791Sdimextern int key_cnt; 14243791Sdim 15243791Sdim 16243791Sdimvoid PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq); 17243791Sdimvoid PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq); 18243791Sdimvoid setUp(void); 19243791Sdimvoid tearDown(void); 20243791Sdimvoid test_TooShortLength(void); 21243791Sdimvoid test_LengthNotMultipleOfFour(void); 22243791Sdimvoid test_TooShortExtensionFieldLength(void); 23243791Sdimvoid test_UnauthenticatedPacketReject(void); 24243791Sdimvoid test_CryptoNAKPacketReject(void); 25243791Sdimvoid test_AuthenticatedPacketInvalid(void); 26243791Sdimvoid test_AuthenticatedPacketUnknownKey(void); 27243791Sdimvoid test_ServerVersionTooOld(void); 28327952Sdimvoid test_ServerVersionTooNew(void); 29243791Sdimvoid test_NonWantedMode(void); 30243791Sdimvoid test_KoDRate(void); 31243791Sdimvoid test_KoDDeny(void); 32243791Sdimvoid test_RejectUnsyncedServer(void); 33243791Sdimvoid test_RejectWrongResponseServerMode(void); 34243791Sdimvoid test_AcceptNoSentPacketBroadcastMode(void); 35243791Sdimvoid test_CorrectUnauthenticatedPacket(void); 36243791Sdimvoid test_CorrectAuthenticatedPacketMD5(void); 37243791Sdimvoid test_CorrectAuthenticatedPacketSHA1(void); 38243791Sdim 39243791Sdim/* [Bug 2998] There are some issues whith the definition of 'struct pkt' 40249423Sdim * when AUTOKEY is undefined -- the formal struct is too small to hold 41249423Sdim * all the extension fields that are going to be tested. We have to make 42353358Sdim * sure we have the extra bytes, or the test yield undefined results due 43243791Sdim * to buffer overrun. 44243791Sdim */ 45243791Sdim#ifndef AUTOKEY 46243791Sdim# define EXTRA_BUFSIZE 256 47243791Sdim#else 48243791Sdim# define EXTRA_BUFSIZE 0 49243791Sdim#endif 50243791Sdim 51243791Sdimunion tpkt { 52243791Sdim struct pkt p; 53243791Sdim u_char b[sizeof(struct pkt) + EXTRA_BUFSIZE]; 54243791Sdim}; 55327952Sdim 56327952Sdimstatic union tpkt testpkt; 57327952Sdimstatic union tpkt testspkt; 58327952Sdimstatic sockaddr_u testsock; 59280031Sdimbool restoreKeyDb; 60327952Sdim 61327952Sdim 62327952Sdimvoid 63327952SdimPrepareAuthenticationTest( 64280031Sdim int key_id, 65327952Sdim int key_len, 66327952Sdim const char * type, 67327952Sdim const void * key_seq 68327952Sdim ) 69280031Sdim{ 70327952Sdim char str[25]; 71327952Sdim snprintf(str, 25, "%d", key_id); 72327952Sdim ActivateOption("-a", str); 73327952Sdim 74280031Sdim key_cnt = 1; 75327952Sdim key_ptr = emalloc(sizeof(struct key)); 76327952Sdim key_ptr->next = NULL; 77327952Sdim key_ptr->key_id = key_id; 78327952Sdim key_ptr->key_len = key_len; 79327952Sdim memcpy(key_ptr->type, "MD5", 3); 80327952Sdim 81327952Sdim TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq)); 82280031Sdim 83327952Sdim memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len); 84296417Sdim restoreKeyDb = true; 85296417Sdim} 86243791Sdim 87276479Sdim 88327952Sdimvoid 89327952SdimPrepareAuthenticationTestMD5( 90276479Sdim int key_id, 91243791Sdim int key_len, 92296417Sdim const void * key_seq 93327952Sdim ) 94243791Sdim{ 95280031Sdim PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq); 96280031Sdim} 97280031Sdim 98327952Sdim 99280031Sdimvoid 100280031SdimsetUp(void) 101280031Sdim{ 102280031Sdim 103327952Sdim sntptest(); 104280031Sdim restoreKeyDb = false; 105327952Sdim 106327952Sdim /* Initialize the test packet and socket, 107288943Sdim * so they contain at least some valid data. 108276479Sdim */ 109321369Sdim testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION, 110321369Sdim MODE_SERVER); 111321369Sdim testpkt.p.stratum = STRATUM_REFCLOCK; 112327952Sdim memcpy(&testpkt.p.refid, "GPS\0", 4); 113327952Sdim 114327952Sdim /* Set the origin timestamp of the received packet to the 115327952Sdim * same value as the transmit timestamp of the sent packet. 116327952Sdim */ 117327952Sdim l_fp tmp; 118327952Sdim tmp.l_ui = 1000UL; 119327952Sdim tmp.l_uf = 0UL; 120327952Sdim 121327952Sdim HTONL_FP(&tmp, &testpkt.p.org); 122327952Sdim HTONL_FP(&tmp, &testspkt.p.xmt); 123309124Sdim} 124309124Sdim 125243791Sdim 126296417Sdimvoid 127296417SdimtearDown(void) 128327952Sdim{ 129243791Sdim if (restoreKeyDb) { 130243791Sdim key_cnt = 0; 131280031Sdim free(key_ptr); 132280031Sdim key_ptr = NULL; 133243791Sdim } 134280031Sdim 135280031Sdim sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */ 136243791Sdim} 137296417Sdim 138296417Sdim 139296417Sdimvoid 140296417Sdimtest_TooShortLength(void) 141296417Sdim{ 142296417Sdim TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 143243791Sdim process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1, 144280031Sdim MODE_SERVER, &testspkt.p, "UnitTest")); 145360784Sdim TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 146280031Sdim process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1, 147327952Sdim MODE_BROADCAST, &testspkt.p, "UnitTest")); 148327952Sdim} 149327952Sdim 150327952Sdim 151280031Sdimvoid 152327952Sdimtest_LengthNotMultipleOfFour(void) 153280031Sdim{ 154327952Sdim TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 155243791Sdim process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6, 156327952Sdim MODE_SERVER, &testspkt.p, "UnitTest")); 157327952Sdim TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 158327952Sdim process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3, 159327952Sdim MODE_BROADCAST, &testspkt.p, "UnitTest")); 160327952Sdim} 161327952Sdim 162327952Sdim 163327952Sdimvoid 164327952Sdimtest_TooShortExtensionFieldLength(void) 165327952Sdim{ 166327952Sdim /* [Bug 2998] We have to get around the formal specification of 167327952Sdim * the extension field if AUTOKEY is undefined. (At least CLANG 168327952Sdim * issues a warning in this case. It's just a warning, but 169327952Sdim * still... 170327952Sdim */ 171327952Sdim uint32_t * pe = testpkt.p.exten + 7; 172327952Sdim 173327952Sdim /* The lower 16-bits are the length of the extension field. 174327952Sdim * This lengths must be multiples of 4 bytes, which gives 175327952Sdim * a minimum of 4 byte extension field length. 176327952Sdim */ 177327952Sdim *pe = htonl(3); /* 3 bytes is too short. */ 178 179 /* We send in a pkt_len of header size + 4 byte extension 180 * header + 24 byte MAC, this prevents the length error to 181 * be caught at an earlier stage 182 */ 183 int pkt_len = LEN_PKT_NOMAC + 4 + 24; 184 185 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 186 process_pkt(&testpkt.p, &testsock, pkt_len, 187 MODE_SERVER, &testspkt.p, "UnitTest")); 188} 189 190 191void 192test_UnauthenticatedPacketReject(void) 193{ 194 /* Activate authentication option */ 195 ActivateOption("-a", "123"); 196 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 197 198 int pkt_len = LEN_PKT_NOMAC; 199 200 /* We demand authentication, but no MAC header is present. */ 201 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 202 process_pkt(&testpkt.p, &testsock, pkt_len, 203 MODE_SERVER, &testspkt.p, "UnitTest")); 204} 205 206 207void 208test_CryptoNAKPacketReject(void) 209{ 210 /* Activate authentication option */ 211 ActivateOption("-a", "123"); 212 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 213 214 int pkt_len = LEN_PKT_NOMAC + 4; /* + 4 byte MAC = Crypto-NAK */ 215 216 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 217 process_pkt(&testpkt.p, &testsock, pkt_len, 218 MODE_SERVER, &testspkt.p, "UnitTest")); 219} 220 221 222void 223test_AuthenticatedPacketInvalid(void) 224{ 225 /* Activate authentication option */ 226 PrepareAuthenticationTestMD5(50, 9, "123456789"); 227 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 228 229 /* Prepare the packet. */ 230 int pkt_len = LEN_PKT_NOMAC; 231 232 testpkt.p.exten[0] = htonl(50); 233 int mac_len = make_mac(&testpkt.p, pkt_len, 234 MAX_MD5_LEN, key_ptr, 235 &testpkt.p.exten[1]); 236 237 pkt_len += 4 + mac_len; 238 239 /* Now, alter the MAC so it becomes invalid. */ 240 testpkt.p.exten[1] += 1; 241 242 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 243 process_pkt(&testpkt.p, &testsock, pkt_len, 244 MODE_SERVER, &testspkt.p, "UnitTest")); 245} 246 247 248void 249test_AuthenticatedPacketUnknownKey(void) 250{ 251 /* Activate authentication option */ 252 PrepareAuthenticationTestMD5(30, 9, "123456789"); 253 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 254 255 /* Prepare the packet. Note that the Key-ID expected is 30, but 256 * the packet has a key id of 50. 257 */ 258 int pkt_len = LEN_PKT_NOMAC; 259 260 testpkt.p.exten[0] = htonl(50); 261 int mac_len = make_mac(&testpkt.p, pkt_len, 262 MAX_MD5_LEN, key_ptr, 263 &testpkt.p.exten[1]); 264 pkt_len += 4 + mac_len; 265 266 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 267 process_pkt(&testpkt.p, &testsock, pkt_len, 268 MODE_SERVER, &testspkt.p, "UnitTest")); 269} 270 271 272void 273test_ServerVersionTooOld(void) 274{ 275 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 276 277 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 278 NTP_OLDVERSION - 1, 279 MODE_CLIENT); 280 TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) < NTP_OLDVERSION); 281 282 int pkt_len = LEN_PKT_NOMAC; 283 284 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 285 process_pkt(&testpkt.p, &testsock, pkt_len, 286 MODE_SERVER, &testspkt.p, "UnitTest")); 287} 288 289 290void 291test_ServerVersionTooNew(void) 292{ 293 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 294 295 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 296 NTP_VERSION + 1, 297 MODE_CLIENT); 298 TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) > NTP_VERSION); 299 300 int pkt_len = LEN_PKT_NOMAC; 301 302 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 303 process_pkt(&testpkt.p, &testsock, pkt_len, 304 MODE_SERVER, &testspkt.p, "UnitTest")); 305} 306 307 308void 309test_NonWantedMode(void) 310{ 311 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 312 313 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 314 NTP_VERSION, 315 MODE_CLIENT); 316 317 /* The packet has a mode of MODE_CLIENT, but process_pkt expects 318 * MODE_SERVER 319 */ 320 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 321 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 322 MODE_SERVER, &testspkt.p, "UnitTest")); 323} 324 325 326/* Tests bug 1597 */ 327void 328test_KoDRate(void) 329{ 330 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 331 332 testpkt.p.stratum = STRATUM_PKT_UNSPEC; 333 memcpy(&testpkt.p.refid, "RATE", 4); 334 335 TEST_ASSERT_EQUAL(KOD_RATE, 336 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 337 MODE_SERVER, &testspkt.p, "UnitTest")); 338} 339 340 341void 342test_KoDDeny(void) 343{ 344 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 345 346 testpkt.p.stratum = STRATUM_PKT_UNSPEC; 347 memcpy(&testpkt.p.refid, "DENY", 4); 348 349 TEST_ASSERT_EQUAL(KOD_DEMOBILIZE, 350 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 351 MODE_SERVER, &testspkt.p, "UnitTest")); 352} 353 354 355void 356test_RejectUnsyncedServer(void) 357{ 358 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 359 360 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, 361 NTP_VERSION, 362 MODE_SERVER); 363 364 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 365 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 366 MODE_SERVER, &testspkt.p, "UnitTest")); 367} 368 369 370void 371test_RejectWrongResponseServerMode(void) 372{ 373 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 374 375 l_fp tmp; 376 tmp.l_ui = 1000UL; 377 tmp.l_uf = 0UL; 378 HTONL_FP(&tmp, &testpkt.p.org); 379 380 tmp.l_ui = 2000UL; 381 tmp.l_uf = 0UL; 382 HTONL_FP(&tmp, &testspkt.p.xmt); 383 384 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 385 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 386 MODE_SERVER, &testspkt.p, "UnitTest")); 387} 388 389 390void 391test_AcceptNoSentPacketBroadcastMode(void) 392{ 393 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 394 395 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 396 NTP_VERSION, 397 MODE_BROADCAST); 398 399 TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, 400 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 401 MODE_BROADCAST, NULL, "UnitTest")); 402} 403 404 405void 406test_CorrectUnauthenticatedPacket(void) 407{ 408 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 409 410 TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, 411 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 412 MODE_SERVER, &testspkt.p, "UnitTest")); 413} 414 415 416void 417test_CorrectAuthenticatedPacketMD5(void) 418{ 419 PrepareAuthenticationTestMD5(10, 15, "123456789abcdef"); 420 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 421 422 int pkt_len = LEN_PKT_NOMAC; 423 424 /* Prepare the packet. */ 425 testpkt.p.exten[0] = htonl(10); 426 int mac_len = make_mac(&testpkt.p, pkt_len, 427 MAX_MD5_LEN, key_ptr, 428 &testpkt.p.exten[1]); 429 430 pkt_len += 4 + mac_len; 431 432 TEST_ASSERT_EQUAL(pkt_len, 433 process_pkt(&testpkt.p, &testsock, pkt_len, 434 MODE_SERVER, &testspkt.p, "UnitTest")); 435} 436 437 438void 439test_CorrectAuthenticatedPacketSHA1(void) 440{ 441 PrepareAuthenticationTest(20, 15, "SHA1", "abcdefghijklmno"); 442 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 443 444 int pkt_len = LEN_PKT_NOMAC; 445 446 /* Prepare the packet. */ 447 testpkt.p.exten[0] = htonl(20); 448 int mac_len = make_mac(&testpkt.p, pkt_len, 449 MAX_MAC_LEN, key_ptr, 450 &testpkt.p.exten[1]); 451 452 pkt_len += 4 + mac_len; 453 454 TEST_ASSERT_EQUAL(pkt_len, 455 process_pkt(&testpkt.p, &testsock, pkt_len, 456 MODE_SERVER, &testspkt.p, "UnitTest")); 457} 458