1*cdfa2a7eSchristos /* $NetBSD: authkeys.c,v 1.3 2020/05/25 20:47:36 christos Exp $ */
248f8ae19Schristos
3f17b710fSchristos /* This file contains test for both libntp/authkeys.c and libntp/authusekey.c */
4f17b710fSchristos
5f17b710fSchristos #include "config.h"
6f17b710fSchristos
7f17b710fSchristos #include "ntp.h"
8f17b710fSchristos #include "ntp_stdlib.h"
9f17b710fSchristos #include "ntp_calendar.h"
10f17b710fSchristos
11f17b710fSchristos #include "unity.h"
12f17b710fSchristos
13f17b710fSchristos #ifdef OPENSSL
14f17b710fSchristos # include "openssl/err.h"
15f17b710fSchristos # include "openssl/rand.h"
16f17b710fSchristos # include "openssl/evp.h"
17f17b710fSchristos #endif
18ae49d4a4Schristos #include <limits.h>
19f17b710fSchristos
20f17b710fSchristos u_long current_time = 4;
21f17b710fSchristos int counter = 0;
22f17b710fSchristos
23a6f3f22fSchristos void setUp(void);
24a6f3f22fSchristos void tearDown(void);
25a6f3f22fSchristos void AddTrustedKey(keyid_t keyno);
26a6f3f22fSchristos void AddUntrustedKey(keyid_t keyno);
27f17b710fSchristos
28a6f3f22fSchristos
29a6f3f22fSchristos void
setUp(void)30a6f3f22fSchristos setUp(void)
31f17b710fSchristos {
32f17b710fSchristos if (counter == 0) {
33f17b710fSchristos counter++;
34f17b710fSchristos init_auth(); // causes segfault if called more than once
35f17b710fSchristos }
36f17b710fSchristos /*
37f17b710fSchristos * init_auth() is called by tests_main.cpp earlier. It
38f17b710fSchristos * does not initialize global variables like
39f17b710fSchristos * authnumkeys, so let's reset them to zero here.
40f17b710fSchristos */
41f17b710fSchristos authnumkeys = 0;
42f17b710fSchristos
43f17b710fSchristos /*
44f17b710fSchristos * Especially, empty the key cache!
45f17b710fSchristos */
46f17b710fSchristos cache_keyid = 0;
47f17b710fSchristos cache_type = 0;
48f17b710fSchristos cache_flags = 0;
49f17b710fSchristos cache_secret = NULL;
50f17b710fSchristos cache_secretsize = 0;
51f17b710fSchristos }
52f17b710fSchristos
53a6f3f22fSchristos void
tearDown(void)54a6f3f22fSchristos tearDown(void)
55f17b710fSchristos {
5656f2724eSchristos /*NOP*/
57a6f3f22fSchristos }
58f17b710fSchristos
5956f2724eSchristos
60f17b710fSchristos static const int KEYTYPE = KEY_TYPE_MD5;
6156f2724eSchristos static char msgbuf[128];
62f17b710fSchristos
63a6f3f22fSchristos void
AddTrustedKey(keyid_t keyno)644c290c01Schristos AddTrustedKey(keyid_t keyno)
654c290c01Schristos {
66f17b710fSchristos /*
67f17b710fSchristos * We need to add a MD5-key in addition to setting the
68f17b710fSchristos * trust, because authhavekey() requires type != 0.
69f17b710fSchristos */
70ae49d4a4Schristos MD5auth_setkey(keyno, KEYTYPE, NULL, 0, NULL);
71f17b710fSchristos
72f17b710fSchristos authtrust(keyno, TRUE);
73f17b710fSchristos }
74f17b710fSchristos
75a6f3f22fSchristos void
AddUntrustedKey(keyid_t keyno)764c290c01Schristos AddUntrustedKey(keyid_t keyno)
774c290c01Schristos {
78f17b710fSchristos authtrust(keyno, FALSE);
79f17b710fSchristos }
80f17b710fSchristos
8156f2724eSchristos void test_AddTrustedKeys(void);
test_AddTrustedKeys(void)8256f2724eSchristos void test_AddTrustedKeys(void)
834c290c01Schristos {
84f17b710fSchristos const keyid_t KEYNO1 = 5;
85f17b710fSchristos const keyid_t KEYNO2 = 8;
86f17b710fSchristos
87f17b710fSchristos AddTrustedKey(KEYNO1);
88f17b710fSchristos AddTrustedKey(KEYNO2);
89f17b710fSchristos
90f17b710fSchristos TEST_ASSERT_TRUE(authistrusted(KEYNO1));
91f17b710fSchristos TEST_ASSERT_TRUE(authistrusted(KEYNO2));
92f17b710fSchristos }
93f17b710fSchristos
9456f2724eSchristos void test_AddUntrustedKey(void);
test_AddUntrustedKey(void)9556f2724eSchristos void test_AddUntrustedKey(void)
964c290c01Schristos {
97f17b710fSchristos const keyid_t KEYNO = 3;
98f17b710fSchristos
99f17b710fSchristos AddUntrustedKey(KEYNO);
100f17b710fSchristos
101f17b710fSchristos TEST_ASSERT_FALSE(authistrusted(KEYNO));
102f17b710fSchristos }
103f17b710fSchristos
10456f2724eSchristos void test_HaveKeyCorrect(void);
test_HaveKeyCorrect(void)10556f2724eSchristos void test_HaveKeyCorrect(void)
1064c290c01Schristos {
107f17b710fSchristos const keyid_t KEYNO = 3;
108f17b710fSchristos
109f17b710fSchristos AddTrustedKey(KEYNO);
110f17b710fSchristos
111f17b710fSchristos TEST_ASSERT_TRUE(auth_havekey(KEYNO));
112f17b710fSchristos TEST_ASSERT_TRUE(authhavekey(KEYNO));
113f17b710fSchristos }
114f17b710fSchristos
11556f2724eSchristos void test_HaveKeyIncorrect(void);
test_HaveKeyIncorrect(void)11656f2724eSchristos void test_HaveKeyIncorrect(void)
1174c290c01Schristos {
118f17b710fSchristos const keyid_t KEYNO = 2;
119f17b710fSchristos
120f17b710fSchristos TEST_ASSERT_FALSE(auth_havekey(KEYNO));
121f17b710fSchristos TEST_ASSERT_FALSE(authhavekey(KEYNO));
122f17b710fSchristos }
123f17b710fSchristos
12456f2724eSchristos void test_AddWithAuthUseKey(void);
test_AddWithAuthUseKey(void)12556f2724eSchristos void test_AddWithAuthUseKey(void)
1264c290c01Schristos {
127f17b710fSchristos const keyid_t KEYNO = 5;
128f17b710fSchristos const char* KEY = "52a";
129f17b710fSchristos
1304c290c01Schristos TEST_ASSERT_TRUE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY));
131f17b710fSchristos }
132f17b710fSchristos
13356f2724eSchristos void test_EmptyKey(void);
test_EmptyKey(void)13456f2724eSchristos void test_EmptyKey(void)
1354c290c01Schristos {
136f17b710fSchristos const keyid_t KEYNO = 3;
137f17b710fSchristos const char* KEY = "";
138f17b710fSchristos
1394c290c01Schristos TEST_ASSERT_FALSE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY));
140f17b710fSchristos }
141ae49d4a4Schristos
142ae49d4a4Schristos /* test the implementation of 'auth_log2' -- use a local copy of the code */
143ae49d4a4Schristos
144ae49d4a4Schristos static u_short
auth_log2(size_t x)145ae49d4a4Schristos auth_log2(
146ae49d4a4Schristos size_t x)
147ae49d4a4Schristos {
148ae49d4a4Schristos int s;
149ae49d4a4Schristos int r = 0;
150ae49d4a4Schristos size_t m = ~(size_t)0;
151ae49d4a4Schristos
152ae49d4a4Schristos for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
153ae49d4a4Schristos m <<= s;
154ae49d4a4Schristos if (x & m)
155ae49d4a4Schristos r += s;
156ae49d4a4Schristos else
157ae49d4a4Schristos x <<= s;
158ae49d4a4Schristos }
159ae49d4a4Schristos return (u_short)r;
160ae49d4a4Schristos }
161ae49d4a4Schristos
16256f2724eSchristos void test_auth_log2(void);
test_auth_log2(void)16356f2724eSchristos void test_auth_log2(void)
164ae49d4a4Schristos {
165ae49d4a4Schristos int l2;
166ae49d4a4Schristos size_t tv;
167ae49d4a4Schristos
168ae49d4a4Schristos TEST_ASSERT_EQUAL_INT(0, auth_log2(0));
169ae49d4a4Schristos TEST_ASSERT_EQUAL_INT(0, auth_log2(1));
170ae49d4a4Schristos for (l2 = 1; l2 < sizeof(size_t)*CHAR_BIT; ++l2) {
171ae49d4a4Schristos tv = (size_t)1 << l2;
172ae49d4a4Schristos TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv ));
173ae49d4a4Schristos TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv + 1 ));
174ae49d4a4Schristos TEST_ASSERT_EQUAL_INT(l2, auth_log2(2*tv - 1));
175ae49d4a4Schristos }
176ae49d4a4Schristos }
17756f2724eSchristos
17856f2724eSchristos /* Converting a string to a host address. Here we use 'getaddrinfo()' in
17956f2724eSchristos * an independent implementation to avoid cross-reactions with the
18056f2724eSchristos * object under test. 'inet_pton' is too dangerous to handle it
18156f2724eSchristos * properly, and ultimate performance is *not* the goal here.
18256f2724eSchristos */
18356f2724eSchristos static int/*BOOL*/
getaddr(int af,const char * astr,sockaddr_u * addr)18456f2724eSchristos getaddr(
18556f2724eSchristos int af,
18656f2724eSchristos const char *astr,
18756f2724eSchristos sockaddr_u * addr)
18856f2724eSchristos {
18956f2724eSchristos struct addrinfo hint;
19056f2724eSchristos struct addrinfo *ares;
19156f2724eSchristos
19256f2724eSchristos memset(&hint, 0, sizeof(hint));
19356f2724eSchristos hint.ai_flags = AI_NUMERICHOST;
19456f2724eSchristos hint.ai_family = af;
19556f2724eSchristos if (getaddrinfo(astr, NULL, &hint, &ares))
19656f2724eSchristos return FALSE;
19756f2724eSchristos if (ares->ai_addrlen > sizeof(*addr))
19856f2724eSchristos memcpy(addr, ares->ai_addr, sizeof(*addr));
19956f2724eSchristos else
20056f2724eSchristos memcpy(addr, ares->ai_addr, ares->ai_addrlen);
20156f2724eSchristos freeaddrinfo(ares);
20256f2724eSchristos return TRUE;
20356f2724eSchristos }
20456f2724eSchristos
20556f2724eSchristos void test_AddrMatch_anull(void);
test_AddrMatch_anull(void)20656f2724eSchristos void test_AddrMatch_anull(void)
20756f2724eSchristos {
20856f2724eSchristos /* Check the not-an-address logic with a prefix/check length of
20956f2724eSchristos * zero bits. Any compare with a NULL or AF_UNSPEC address
21056f2724eSchristos * returns inequality (aka FALSE).
21156f2724eSchristos */
21256f2724eSchristos sockaddr_u ip4, ip6, ipn;
21356f2724eSchristos
21456f2724eSchristos memset(&ipn, 0, sizeof(ipn));
21556f2724eSchristos AF(&ipn) = AF_UNSPEC;
21656f2724eSchristos
21756f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4));
21856f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6));
21956f2724eSchristos
22056f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(NULL, NULL, 0));
22156f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ipn, 0));
22256f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip4, 0));
22356f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip6, 0));
22456f2724eSchristos
22556f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, NULL, 0));
22656f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ipn, 0));
22756f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip4, 0));
22856f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip6, 0));
22956f2724eSchristos
23056f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ip4, NULL, 0));
23156f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ipn, 0));
23256f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ip6, NULL, 0));
23356f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ipn, 0));
23456f2724eSchristos }
23556f2724eSchristos
23656f2724eSchristos void test_AddrMatch_self4(void);
test_AddrMatch_self4(void)23756f2724eSchristos void test_AddrMatch_self4(void)
23856f2724eSchristos {
23956f2724eSchristos sockaddr_u ip4;
24056f2724eSchristos unsigned int bits;
24156f2724eSchristos
24256f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.1.1", &ip4));
24356f2724eSchristos for (bits = 0; bits < 40; ++bits)
24456f2724eSchristos TEST_ASSERT_TRUE(keyacc_amatch(&ip4, &ip4, bits));
24556f2724eSchristos }
24656f2724eSchristos
24756f2724eSchristos void test_AddrMatch_self6(void);
test_AddrMatch_self6(void)24856f2724eSchristos void test_AddrMatch_self6(void)
24956f2724eSchristos {
25056f2724eSchristos sockaddr_u ip6;
25156f2724eSchristos unsigned int bits;
25256f2724eSchristos
25356f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6));
25456f2724eSchristos for (bits = 0; bits < 136; ++bits)
25556f2724eSchristos TEST_ASSERT_TRUE(keyacc_amatch(&ip6, &ip6, bits));
25656f2724eSchristos }
25756f2724eSchristos
25856f2724eSchristos void test_AddrMatch_afmix(void);
test_AddrMatch_afmix(void)25956f2724eSchristos void test_AddrMatch_afmix(void)
26056f2724eSchristos {
26156f2724eSchristos sockaddr_u ip6, ip4;
26256f2724eSchristos
26356f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4));
26456f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6));
26556f2724eSchristos
26656f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ip6, 0));
26756f2724eSchristos TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ip4, 0));
26856f2724eSchristos }
26956f2724eSchristos
27056f2724eSchristos void test_AddrMatch_ipv4(void);
test_AddrMatch_ipv4(void)27156f2724eSchristos void test_AddrMatch_ipv4(void)
27256f2724eSchristos {
27356f2724eSchristos sockaddr_u a1, a2;
27456f2724eSchristos unsigned int bits;
27556f2724eSchristos int want;
27656f2724eSchristos
27756f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.1", &a1));
27856f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.3.1", &a2));
27956f2724eSchristos
28056f2724eSchristos /* the first 23 bits are equal, so any prefix <= 23 should match */
28156f2724eSchristos for (bits = 0; bits < 40; ++bits) {
28256f2724eSchristos snprintf(msgbuf, sizeof(msgbuf),
28356f2724eSchristos "keyacc_amatch(*,*,%u) wrong", bits);
28456f2724eSchristos want = (bits <= 23);
28556f2724eSchristos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
28656f2724eSchristos }
28756f2724eSchristos
28856f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.127", &a1));
28956f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.128", &a2));
29056f2724eSchristos
29156f2724eSchristos /* the first 24 bits are equal, so any prefix <= 24 should match */
29256f2724eSchristos for (bits = 0; bits < 40; ++bits) {
29356f2724eSchristos snprintf(msgbuf, sizeof(msgbuf),
29456f2724eSchristos "keyacc_amatch(*,*,%u) wrong", bits);
29556f2724eSchristos want = (bits <= 24);
29656f2724eSchristos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
29756f2724eSchristos }
29856f2724eSchristos }
29956f2724eSchristos
30056f2724eSchristos void test_AddrMatch_ipv6(void);
test_AddrMatch_ipv6(void)30156f2724eSchristos void test_AddrMatch_ipv6(void)
30256f2724eSchristos {
30356f2724eSchristos sockaddr_u a1, a2;
30456f2724eSchristos unsigned int bits;
30556f2724eSchristos int want;
30656f2724eSchristos
30756f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:FFFF", &a1));
30856f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::3:FFFF", &a2));
30956f2724eSchristos
31056f2724eSchristos /* the first 111 bits are equal, so any prefix <= 111 should match */
31156f2724eSchristos for (bits = 0; bits < 136; ++bits) {
31256f2724eSchristos snprintf(msgbuf, sizeof(msgbuf),
31356f2724eSchristos "keyacc_amatch(*,*,%u) wrong", bits);
31456f2724eSchristos want = (bits <= 111);
31556f2724eSchristos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
31656f2724eSchristos }
31756f2724eSchristos
31856f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:7FFF", &a1));
31956f2724eSchristos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:8000", &a2));
32056f2724eSchristos
32156f2724eSchristos /* the first 112 bits are equal, so any prefix <= 112 should match */
32256f2724eSchristos for (bits = 0; bits < 136; ++bits) {
32356f2724eSchristos snprintf(msgbuf, sizeof(msgbuf),
32456f2724eSchristos "keyacc_amatch(*,*,%u) wrong", bits);
32556f2724eSchristos want = (bits <= 112);
32656f2724eSchristos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf);
32756f2724eSchristos }
32856f2724eSchristos }
329