1 #include "config.h" 2 3 #include "sntptest.h" 4 #include "networking.h" 5 #include "ntp_stdlib.h" 6 #include "unity.h" 7 8 9 const char * Version = "stub unit test Version string"; 10 11 /* Hacks into the key database. */ 12 extern struct key* key_ptr; 13 extern int key_cnt; 14 15 16 void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq); 17 void PrepareAuthenticationTestMD5(int key_id,int key_len,const void* key_seq); 18 void setUp(void); 19 void tearDown(void); 20 void test_TooShortLength(void); 21 void test_LengthNotMultipleOfFour(void); 22 void test_TooShortExtensionFieldLength(void); 23 void test_UnauthenticatedPacketReject(void); 24 void test_CryptoNAKPacketReject(void); 25 void test_AuthenticatedPacketInvalid(void); 26 void test_AuthenticatedPacketUnknownKey(void); 27 void test_ServerVersionTooOld(void); 28 void test_ServerVersionTooNew(void); 29 void test_NonWantedMode(void); 30 void test_KoDRate(void); 31 void test_KoDDeny(void); 32 void test_RejectUnsyncedServer(void); 33 void test_RejectWrongResponseServerMode(void); 34 void test_AcceptNoSentPacketBroadcastMode(void); 35 void test_CorrectUnauthenticatedPacket(void); 36 void test_CorrectAuthenticatedPacketMD5(void); 37 void test_CorrectAuthenticatedPacketSHA1(void); 38 39 /* [Bug 2998] There are some issues whith the definition of 'struct pkt' 40 * when AUTOKEY is undefined -- the formal struct is too small to hold 41 * all the extension fields that are going to be tested. We have to make 42 * sure we have the extra bytes, or the test yield undefined results due 43 * to buffer overrun. 44 */ 45 #ifndef AUTOKEY 46 # define EXTRA_BUFSIZE 256 47 #else 48 # define EXTRA_BUFSIZE 0 49 #endif 50 51 union tpkt { 52 struct pkt p; 53 u_char b[sizeof(struct pkt) + EXTRA_BUFSIZE]; 54 }; 55 56 static union tpkt testpkt; 57 static union tpkt testspkt; 58 static sockaddr_u testsock; 59 bool restoreKeyDb; 60 61 62 void 63 PrepareAuthenticationTest( 64 int key_id, 65 int key_len, 66 const char * type, 67 const void * key_seq 68 ) 69 { 70 char str[25]; 71 snprintf(str, 25, "%d", key_id); 72 ActivateOption("-a", str); 73 74 key_cnt = 1; 75 key_ptr = emalloc(sizeof(struct key)); 76 key_ptr->next = NULL; 77 key_ptr->key_id = key_id; 78 key_ptr->key_len = key_len; 79 memcpy(key_ptr->type, "MD5", 3); 80 81 TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq)); 82 83 memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len); 84 restoreKeyDb = true; 85 } 86 87 88 void 89 PrepareAuthenticationTestMD5( 90 int key_id, 91 int key_len, 92 const void * key_seq 93 ) 94 { 95 PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq); 96 } 97 98 99 void 100 setUp(void) 101 { 102 103 sntptest(); 104 restoreKeyDb = false; 105 106 /* Initialize the test packet and socket, 107 * so they contain at least some valid data. 108 */ 109 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION, 110 MODE_SERVER); 111 testpkt.p.stratum = STRATUM_REFCLOCK; 112 memcpy(&testpkt.p.refid, "GPS\0", 4); 113 114 /* Set the origin timestamp of the received packet to the 115 * same value as the transmit timestamp of the sent packet. 116 */ 117 l_fp tmp; 118 tmp.l_ui = 1000UL; 119 tmp.l_uf = 0UL; 120 121 HTONL_FP(&tmp, &testpkt.p.org); 122 HTONL_FP(&tmp, &testspkt.p.xmt); 123 } 124 125 126 void 127 tearDown(void) 128 { 129 if (restoreKeyDb) { 130 key_cnt = 0; 131 free(key_ptr); 132 key_ptr = NULL; 133 } 134 135 sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */ 136 } 137 138 139 void 140 test_TooShortLength(void) 141 { 142 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 143 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1, 144 MODE_SERVER, &testspkt.p, "UnitTest")); 145 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 146 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1, 147 MODE_BROADCAST, &testspkt.p, "UnitTest")); 148 } 149 150 151 void 152 test_LengthNotMultipleOfFour(void) 153 { 154 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 155 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6, 156 MODE_SERVER, &testspkt.p, "UnitTest")); 157 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 158 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3, 159 MODE_BROADCAST, &testspkt.p, "UnitTest")); 160 } 161 162 163 void 164 test_TooShortExtensionFieldLength(void) 165 { 166 /* [Bug 2998] We have to get around the formal specification of 167 * the extension field if AUTOKEY is undefined. (At least CLANG 168 * issues a warning in this case. It's just a warning, but 169 * still... 170 */ 171 uint32_t * pe = testpkt.p.exten + 7; 172 173 /* The lower 16-bits are the length of the extension field. 174 * This lengths must be multiples of 4 bytes, which gives 175 * a minimum of 4 byte extension field length. 176 */ 177 *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 191 void 192 test_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 207 void 208 test_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 222 void 223 test_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 248 void 249 test_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 272 void 273 test_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 290 void 291 test_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 308 void 309 test_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 */ 327 void 328 test_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 341 void 342 test_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 355 void 356 test_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 370 void 371 test_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 390 void 391 test_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 405 void 406 test_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 416 void 417 test_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 438 void 439 test_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