summaryrefslogtreecommitdiff
path: root/sntp/tests/packetProcessing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sntp/tests/packetProcessing.cpp')
-rw-r--r--sntp/tests/packetProcessing.cpp334
1 files changed, 334 insertions, 0 deletions
diff --git a/sntp/tests/packetProcessing.cpp b/sntp/tests/packetProcessing.cpp
new file mode 100644
index 0000000..322b893
--- /dev/null
+++ b/sntp/tests/packetProcessing.cpp
@@ -0,0 +1,334 @@
+#include "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"));
+}