mirror of
https://github.com/Stichting-MINIX-Research-Foundation/netbsd.git
synced 2025-08-09 05:59:13 -04:00
335 lines
8.8 KiB
C++
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"));
|
|
}
|