netbsd/external/bsd/ntp/dist/sntp/tests/g_packetProcessing.cpp
2015-10-15 10:25:28 +02:00

335 lines
8.8 KiB
C++

#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"));
}