diff options
Diffstat (limited to 'sntp/tests/g_packetProcessing.cpp')
-rw-r--r-- | sntp/tests/g_packetProcessing.cpp | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/sntp/tests/g_packetProcessing.cpp b/sntp/tests/g_packetProcessing.cpp new file mode 100644 index 000000000000..85659a43dda5 --- /dev/null +++ b/sntp/tests/g_packetProcessing.cpp @@ -0,0 +1,334 @@ +#include "g_sntptest.h" + +extern "C" { +#include "networking.h" +#include "ntp_stdlib.h" +}; + +#include <sstream> +#include <string> + +// Hacks into the key database. +extern key* key_ptr; +extern int key_cnt; + +class packetProcessingTest : public sntptest { +protected: + pkt testpkt; + pkt testspkt; + sockaddr_u testsock; + bool restoreKeyDb; + + void PrepareAuthenticationTest(int key_id, + int key_len, + const char* type, + const void* key_seq) { + std::stringstream ss; + ss << key_id; + + ActivateOption("-a", ss.str().c_str()); + + key_cnt = 1; + key_ptr = new key; + key_ptr->next = NULL; + key_ptr->key_id = key_id; + key_ptr->key_len = key_len; + memcpy(key_ptr->type, "MD5", 3); + + ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq)); + + memcpy(key_ptr->key_seq, key_seq, key_ptr->key_len); + restoreKeyDb = true; + } + + void PrepareAuthenticationTest(int key_id, + int key_len, + const void* key_seq) { + PrepareAuthenticationTest(key_id, key_len, "MD5", key_seq); + } + + virtual void SetUp() { + restoreKeyDb = false; + + /* Initialize the test packet and socket, + * so they contain at least some valid data. */ + testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION, + MODE_SERVER); + testpkt.stratum = STRATUM_REFCLOCK; + memcpy(&testpkt.refid, "GPS\0", 4); + + /* Set the origin timestamp of the received packet to the + * same value as the transmit timestamp of the sent packet. */ + l_fp tmp; + tmp.l_ui = 1000UL; + tmp.l_uf = 0UL; + + HTONL_FP(&tmp, &testpkt.org); + HTONL_FP(&tmp, &testspkt.xmt); + } + + virtual void TearDown() { + if (restoreKeyDb) { + key_cnt = 0; + delete key_ptr; + key_ptr = NULL; + } + } +}; + +TEST_F(packetProcessingTest, TooShortLength) { + EXPECT_EQ(PACKET_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC - 1, + MODE_SERVER, &testspkt, "UnitTest")); + EXPECT_EQ(PACKET_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC - 1, + MODE_BROADCAST, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, LengthNotMultipleOfFour) { + EXPECT_EQ(PACKET_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC + 6, + MODE_SERVER, &testspkt, "UnitTest")); + EXPECT_EQ(PACKET_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC + 3, + MODE_BROADCAST, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, TooShortExtensionFieldLength) { + /* The lower 16-bits are the length of the extension field. + * This lengths must be multiples of 4 bytes, which gives + * a minimum of 4 byte extension field length. */ + testpkt.exten[7] = htonl(3); // 3 bytes is too short. + + /* We send in a pkt_len of header size + 4 byte extension + * header + 24 byte MAC, this prevents the length error to + * be caught at an earlier stage */ + int pkt_len = LEN_PKT_NOMAC + 4 + 24; + + EXPECT_EQ(PACKET_UNUSEABLE, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, UnauthenticatedPacketReject) { + // Activate authentication option + ActivateOption("-a", "123"); + ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); + + int pkt_len = LEN_PKT_NOMAC; + + // We demand authentication, but no MAC header is present. + EXPECT_EQ(SERVER_AUTH_FAIL, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, CryptoNAKPacketReject) { + // Activate authentication option + ActivateOption("-a", "123"); + ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); + + int pkt_len = LEN_PKT_NOMAC + 4; // + 4 byte MAC = Crypto-NAK + + EXPECT_EQ(SERVER_AUTH_FAIL, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, AuthenticatedPacketInvalid) { + // Activate authentication option + PrepareAuthenticationTest(50, 9, "123456789"); + ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); + + // Prepare the packet. + int pkt_len = LEN_PKT_NOMAC; + + testpkt.exten[0] = htonl(50); + int mac_len = make_mac((char*)&testpkt, pkt_len, + MAX_MD5_LEN, key_ptr, + (char*)&testpkt.exten[1]); + + pkt_len += 4 + mac_len; + + // Now, alter the MAC so it becomes invalid. + testpkt.exten[1] += 1; + + EXPECT_EQ(SERVER_AUTH_FAIL, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, AuthenticatedPacketUnknownKey) { + // Activate authentication option + PrepareAuthenticationTest(30, 9, "123456789"); + ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); + + // Prepare the packet. Observe that the Key-ID expected is 30, + // but the packet has a key id of 50. + int pkt_len = LEN_PKT_NOMAC; + + testpkt.exten[0] = htonl(50); + int mac_len = make_mac((char*)&testpkt, pkt_len, + MAX_MD5_LEN, key_ptr, + (char*)&testpkt.exten[1]); + pkt_len += 4 + mac_len; + + EXPECT_EQ(SERVER_AUTH_FAIL, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, ServerVersionTooOld) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, + NTP_OLDVERSION - 1, + MODE_CLIENT); + ASSERT_LT(PKT_VERSION(testpkt.li_vn_mode), NTP_OLDVERSION); + + int pkt_len = LEN_PKT_NOMAC; + + EXPECT_EQ(SERVER_UNUSEABLE, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, ServerVersionTooNew) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, + NTP_VERSION + 1, + MODE_CLIENT); + ASSERT_GT(PKT_VERSION(testpkt.li_vn_mode), NTP_VERSION); + + int pkt_len = LEN_PKT_NOMAC; + + EXPECT_EQ(SERVER_UNUSEABLE, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, NonWantedMode) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, + NTP_VERSION, + MODE_CLIENT); + + // The packet has a mode of MODE_CLIENT, but process_pkt expects MODE_SERVER + + EXPECT_EQ(SERVER_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_SERVER, &testspkt, "UnitTest")); +} + +/* Tests bug 1597 */ +TEST_F(packetProcessingTest, KoDRate) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.stratum = STRATUM_PKT_UNSPEC; + memcpy(&testpkt.refid, "RATE", 4); + + EXPECT_EQ(KOD_RATE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, KoDDeny) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.stratum = STRATUM_PKT_UNSPEC; + memcpy(&testpkt.refid, "DENY", 4); + + EXPECT_EQ(KOD_DEMOBILIZE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, RejectUnsyncedServer) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, + NTP_VERSION, + MODE_SERVER); + + EXPECT_EQ(SERVER_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, RejectWrongResponseServerMode) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + l_fp tmp; + tmp.l_ui = 1000UL; + tmp.l_uf = 0UL; + HTONL_FP(&tmp, &testpkt.org); + + tmp.l_ui = 2000UL; + tmp.l_uf = 0UL; + HTONL_FP(&tmp, &testspkt.xmt); + + EXPECT_EQ(PACKET_UNUSEABLE, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, AcceptNoSentPacketBroadcastMode) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + testpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, + NTP_VERSION, + MODE_BROADCAST); + + EXPECT_EQ(LEN_PKT_NOMAC, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_BROADCAST, NULL, "UnitTest")); +} + +TEST_F(packetProcessingTest, CorrectUnauthenticatedPacket) { + ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); + + EXPECT_EQ(LEN_PKT_NOMAC, + process_pkt(&testpkt, &testsock, LEN_PKT_NOMAC, + MODE_SERVER, &testspkt, "UnitTest")); +} + +TEST_F(packetProcessingTest, CorrectAuthenticatedPacketMD5) { + PrepareAuthenticationTest(10, 15, "123456789abcdef"); + ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); + + int pkt_len = LEN_PKT_NOMAC; + + // Prepare the packet. + testpkt.exten[0] = htonl(10); + int mac_len = make_mac((char*)&testpkt, pkt_len, + MAX_MD5_LEN, key_ptr, + (char*)&testpkt.exten[1]); + + pkt_len += 4 + mac_len; + + EXPECT_EQ(pkt_len, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); + +} + +TEST_F(packetProcessingTest, CorrectAuthenticatedPacketSHA1) { + PrepareAuthenticationTest(20, 15, "SHA1", "abcdefghijklmno"); + ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); + + int pkt_len = LEN_PKT_NOMAC; + + // Prepare the packet. + testpkt.exten[0] = htonl(20); + int mac_len = make_mac((char*)&testpkt, pkt_len, + MAX_MAC_LEN, key_ptr, + (char*)&testpkt.exten[1]); + + pkt_len += 4 + mac_len; + + EXPECT_EQ(pkt_len, + process_pkt(&testpkt, &testsock, pkt_len, + MODE_SERVER, &testspkt, "UnitTest")); +} |