/* $NetBSD: authkeys.c,v 1.3 2020/05/25 20:47:36 christos Exp $ */ /* This file contains test for both libntp/authkeys.c and libntp/authusekey.c */ #include "config.h" #include "ntp.h" #include "ntp_stdlib.h" #include "ntp_calendar.h" #include "unity.h" #ifdef OPENSSL # include "openssl/err.h" # include "openssl/rand.h" # include "openssl/evp.h" #endif #include u_long current_time = 4; int counter = 0; void setUp(void); void tearDown(void); void AddTrustedKey(keyid_t keyno); void AddUntrustedKey(keyid_t keyno); void setUp(void) { if (counter == 0) { counter++; init_auth(); // causes segfault if called more than once } /* * init_auth() is called by tests_main.cpp earlier. It * does not initialize global variables like * authnumkeys, so let's reset them to zero here. */ authnumkeys = 0; /* * Especially, empty the key cache! */ cache_keyid = 0; cache_type = 0; cache_flags = 0; cache_secret = NULL; cache_secretsize = 0; } void tearDown(void) { /*NOP*/ } static const int KEYTYPE = KEY_TYPE_MD5; static char msgbuf[128]; void AddTrustedKey(keyid_t keyno) { /* * We need to add a MD5-key in addition to setting the * trust, because authhavekey() requires type != 0. */ MD5auth_setkey(keyno, KEYTYPE, NULL, 0, NULL); authtrust(keyno, TRUE); } void AddUntrustedKey(keyid_t keyno) { authtrust(keyno, FALSE); } void test_AddTrustedKeys(void); void test_AddTrustedKeys(void) { const keyid_t KEYNO1 = 5; const keyid_t KEYNO2 = 8; AddTrustedKey(KEYNO1); AddTrustedKey(KEYNO2); TEST_ASSERT_TRUE(authistrusted(KEYNO1)); TEST_ASSERT_TRUE(authistrusted(KEYNO2)); } void test_AddUntrustedKey(void); void test_AddUntrustedKey(void) { const keyid_t KEYNO = 3; AddUntrustedKey(KEYNO); TEST_ASSERT_FALSE(authistrusted(KEYNO)); } void test_HaveKeyCorrect(void); void test_HaveKeyCorrect(void) { const keyid_t KEYNO = 3; AddTrustedKey(KEYNO); TEST_ASSERT_TRUE(auth_havekey(KEYNO)); TEST_ASSERT_TRUE(authhavekey(KEYNO)); } void test_HaveKeyIncorrect(void); void test_HaveKeyIncorrect(void) { const keyid_t KEYNO = 2; TEST_ASSERT_FALSE(auth_havekey(KEYNO)); TEST_ASSERT_FALSE(authhavekey(KEYNO)); } void test_AddWithAuthUseKey(void); void test_AddWithAuthUseKey(void) { const keyid_t KEYNO = 5; const char* KEY = "52a"; TEST_ASSERT_TRUE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY)); } void test_EmptyKey(void); void test_EmptyKey(void) { const keyid_t KEYNO = 3; const char* KEY = ""; TEST_ASSERT_FALSE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY)); } /* test the implementation of 'auth_log2' -- use a local copy of the code */ static u_short auth_log2( size_t x) { int s; int r = 0; size_t m = ~(size_t)0; for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { m <<= s; if (x & m) r += s; else x <<= s; } return (u_short)r; } void test_auth_log2(void); void test_auth_log2(void) { int l2; size_t tv; TEST_ASSERT_EQUAL_INT(0, auth_log2(0)); TEST_ASSERT_EQUAL_INT(0, auth_log2(1)); for (l2 = 1; l2 < sizeof(size_t)*CHAR_BIT; ++l2) { tv = (size_t)1 << l2; TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv )); TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv + 1 )); TEST_ASSERT_EQUAL_INT(l2, auth_log2(2*tv - 1)); } } /* Converting a string to a host address. Here we use 'getaddrinfo()' in * an independent implementation to avoid cross-reactions with the * object under test. 'inet_pton' is too dangerous to handle it * properly, and ultimate performance is *not* the goal here. */ static int/*BOOL*/ getaddr( int af, const char *astr, sockaddr_u * addr) { struct addrinfo hint; struct addrinfo *ares; memset(&hint, 0, sizeof(hint)); hint.ai_flags = AI_NUMERICHOST; hint.ai_family = af; if (getaddrinfo(astr, NULL, &hint, &ares)) return FALSE; if (ares->ai_addrlen > sizeof(*addr)) memcpy(addr, ares->ai_addr, sizeof(*addr)); else memcpy(addr, ares->ai_addr, ares->ai_addrlen); freeaddrinfo(ares); return TRUE; } void test_AddrMatch_anull(void); void test_AddrMatch_anull(void) { /* Check the not-an-address logic with a prefix/check length of * zero bits. Any compare with a NULL or AF_UNSPEC address * returns inequality (aka FALSE). */ sockaddr_u ip4, ip6, ipn; memset(&ipn, 0, sizeof(ipn)); AF(&ipn) = AF_UNSPEC; TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4)); TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6)); TEST_ASSERT_FALSE(keyacc_amatch(NULL, NULL, 0)); TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ipn, 0)); TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip4, 0)); TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip6, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ipn, NULL, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ipn, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip4, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip6, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ip4, NULL, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ipn, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ip6, NULL, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ipn, 0)); } void test_AddrMatch_self4(void); void test_AddrMatch_self4(void) { sockaddr_u ip4; unsigned int bits; TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.1.1", &ip4)); for (bits = 0; bits < 40; ++bits) TEST_ASSERT_TRUE(keyacc_amatch(&ip4, &ip4, bits)); } void test_AddrMatch_self6(void); void test_AddrMatch_self6(void) { sockaddr_u ip6; unsigned int bits; TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6)); for (bits = 0; bits < 136; ++bits) TEST_ASSERT_TRUE(keyacc_amatch(&ip6, &ip6, bits)); } void test_AddrMatch_afmix(void); void test_AddrMatch_afmix(void) { sockaddr_u ip6, ip4; TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4)); TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6)); TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ip6, 0)); TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ip4, 0)); } void test_AddrMatch_ipv4(void); void test_AddrMatch_ipv4(void) { sockaddr_u a1, a2; unsigned int bits; int want; TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.1", &a1)); TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.3.1", &a2)); /* the first 23 bits are equal, so any prefix <= 23 should match */ for (bits = 0; bits < 40; ++bits) { snprintf(msgbuf, sizeof(msgbuf), "keyacc_amatch(*,*,%u) wrong", bits); want = (bits <= 23); TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); } TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.127", &a1)); TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.128", &a2)); /* the first 24 bits are equal, so any prefix <= 24 should match */ for (bits = 0; bits < 40; ++bits) { snprintf(msgbuf, sizeof(msgbuf), "keyacc_amatch(*,*,%u) wrong", bits); want = (bits <= 24); TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); } } void test_AddrMatch_ipv6(void); void test_AddrMatch_ipv6(void) { sockaddr_u a1, a2; unsigned int bits; int want; TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:FFFF", &a1)); TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::3:FFFF", &a2)); /* the first 111 bits are equal, so any prefix <= 111 should match */ for (bits = 0; bits < 136; ++bits) { snprintf(msgbuf, sizeof(msgbuf), "keyacc_amatch(*,*,%u) wrong", bits); want = (bits <= 111); TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); } TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:7FFF", &a1)); TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:8000", &a2)); /* the first 112 bits are equal, so any prefix <= 112 should match */ for (bits = 0; bits < 136; ++bits) { snprintf(msgbuf, sizeof(msgbuf), "keyacc_amatch(*,*,%u) wrong", bits); want = (bits <= 112); TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); } }