1 1.2 christos /* $NetBSD: authkeys.c,v 1.3 2020/05/25 20:47:36 christos Exp $ */ 2 1.2 christos 3 1.1 christos /* This file contains test for both libntp/authkeys.c and libntp/authusekey.c */ 4 1.1 christos 5 1.1 christos #include "config.h" 6 1.1 christos 7 1.1 christos #include "ntp.h" 8 1.1 christos #include "ntp_stdlib.h" 9 1.1 christos #include "ntp_calendar.h" 10 1.1 christos 11 1.1 christos #include "unity.h" 12 1.1 christos 13 1.1 christos #ifdef OPENSSL 14 1.1 christos # include "openssl/err.h" 15 1.1 christos # include "openssl/rand.h" 16 1.1 christos # include "openssl/evp.h" 17 1.1 christos #endif 18 1.2 christos #include <limits.h> 19 1.1 christos 20 1.1 christos u_long current_time = 4; 21 1.1 christos int counter = 0; 22 1.1 christos 23 1.2 christos void setUp(void); 24 1.2 christos void tearDown(void); 25 1.2 christos void AddTrustedKey(keyid_t keyno); 26 1.2 christos void AddUntrustedKey(keyid_t keyno); 27 1.2 christos 28 1.1 christos 29 1.2 christos void 30 1.2 christos setUp(void) 31 1.2 christos { 32 1.2 christos if (counter == 0) { 33 1.2 christos counter++; 34 1.2 christos init_auth(); // causes segfault if called more than once 35 1.1 christos } 36 1.2 christos /* 37 1.1 christos * init_auth() is called by tests_main.cpp earlier. It 38 1.1 christos * does not initialize global variables like 39 1.1 christos * authnumkeys, so let's reset them to zero here. 40 1.1 christos */ 41 1.1 christos authnumkeys = 0; 42 1.1 christos 43 1.1 christos /* 44 1.1 christos * Especially, empty the key cache! 45 1.1 christos */ 46 1.1 christos cache_keyid = 0; 47 1.1 christos cache_type = 0; 48 1.1 christos cache_flags = 0; 49 1.1 christos cache_secret = NULL; 50 1.1 christos cache_secretsize = 0; 51 1.1 christos } 52 1.1 christos 53 1.2 christos void 54 1.2 christos tearDown(void) 55 1.1 christos { 56 1.2 christos /*NOP*/ 57 1.1 christos } 58 1.1 christos 59 1.1 christos 60 1.1 christos static const int KEYTYPE = KEY_TYPE_MD5; 61 1.2 christos static char msgbuf[128]; 62 1.1 christos 63 1.2 christos void 64 1.2 christos AddTrustedKey(keyid_t keyno) 65 1.2 christos { 66 1.1 christos /* 67 1.1 christos * We need to add a MD5-key in addition to setting the 68 1.1 christos * trust, because authhavekey() requires type != 0. 69 1.1 christos */ 70 1.2 christos MD5auth_setkey(keyno, KEYTYPE, NULL, 0, NULL); 71 1.1 christos 72 1.1 christos authtrust(keyno, TRUE); 73 1.1 christos } 74 1.1 christos 75 1.2 christos void 76 1.2 christos AddUntrustedKey(keyid_t keyno) 77 1.2 christos { 78 1.1 christos authtrust(keyno, FALSE); 79 1.1 christos } 80 1.1 christos 81 1.2 christos void test_AddTrustedKeys(void); 82 1.2 christos void test_AddTrustedKeys(void) 83 1.2 christos { 84 1.1 christos const keyid_t KEYNO1 = 5; 85 1.1 christos const keyid_t KEYNO2 = 8; 86 1.1 christos 87 1.1 christos AddTrustedKey(KEYNO1); 88 1.1 christos AddTrustedKey(KEYNO2); 89 1.1 christos 90 1.1 christos TEST_ASSERT_TRUE(authistrusted(KEYNO1)); 91 1.1 christos TEST_ASSERT_TRUE(authistrusted(KEYNO2)); 92 1.1 christos } 93 1.1 christos 94 1.2 christos void test_AddUntrustedKey(void); 95 1.2 christos void test_AddUntrustedKey(void) 96 1.2 christos { 97 1.1 christos const keyid_t KEYNO = 3; 98 1.2 christos 99 1.1 christos AddUntrustedKey(KEYNO); 100 1.1 christos 101 1.1 christos TEST_ASSERT_FALSE(authistrusted(KEYNO)); 102 1.1 christos } 103 1.1 christos 104 1.2 christos void test_HaveKeyCorrect(void); 105 1.2 christos void test_HaveKeyCorrect(void) 106 1.2 christos { 107 1.1 christos const keyid_t KEYNO = 3; 108 1.1 christos 109 1.1 christos AddTrustedKey(KEYNO); 110 1.1 christos 111 1.1 christos TEST_ASSERT_TRUE(auth_havekey(KEYNO)); 112 1.1 christos TEST_ASSERT_TRUE(authhavekey(KEYNO)); 113 1.1 christos } 114 1.1 christos 115 1.2 christos void test_HaveKeyIncorrect(void); 116 1.2 christos void test_HaveKeyIncorrect(void) 117 1.2 christos { 118 1.1 christos const keyid_t KEYNO = 2; 119 1.1 christos 120 1.1 christos TEST_ASSERT_FALSE(auth_havekey(KEYNO)); 121 1.1 christos TEST_ASSERT_FALSE(authhavekey(KEYNO)); 122 1.1 christos } 123 1.1 christos 124 1.2 christos void test_AddWithAuthUseKey(void); 125 1.2 christos void test_AddWithAuthUseKey(void) 126 1.2 christos { 127 1.1 christos const keyid_t KEYNO = 5; 128 1.1 christos const char* KEY = "52a"; 129 1.1 christos 130 1.2 christos TEST_ASSERT_TRUE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY)); 131 1.1 christos } 132 1.1 christos 133 1.2 christos void test_EmptyKey(void); 134 1.2 christos void test_EmptyKey(void) 135 1.2 christos { 136 1.1 christos const keyid_t KEYNO = 3; 137 1.1 christos const char* KEY = ""; 138 1.1 christos 139 1.2 christos TEST_ASSERT_FALSE(authusekey(KEYNO, KEYTYPE, (const u_char*)KEY)); 140 1.2 christos } 141 1.2 christos 142 1.2 christos /* test the implementation of 'auth_log2' -- use a local copy of the code */ 143 1.2 christos 144 1.2 christos static u_short 145 1.2 christos auth_log2( 146 1.2 christos size_t x) 147 1.2 christos { 148 1.2 christos int s; 149 1.2 christos int r = 0; 150 1.2 christos size_t m = ~(size_t)0; 151 1.2 christos 152 1.2 christos for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { 153 1.2 christos m <<= s; 154 1.2 christos if (x & m) 155 1.2 christos r += s; 156 1.2 christos else 157 1.2 christos x <<= s; 158 1.2 christos } 159 1.2 christos return (u_short)r; 160 1.2 christos } 161 1.1 christos 162 1.2 christos void test_auth_log2(void); 163 1.2 christos void test_auth_log2(void) 164 1.2 christos { 165 1.2 christos int l2; 166 1.2 christos size_t tv; 167 1.2 christos 168 1.2 christos TEST_ASSERT_EQUAL_INT(0, auth_log2(0)); 169 1.2 christos TEST_ASSERT_EQUAL_INT(0, auth_log2(1)); 170 1.2 christos for (l2 = 1; l2 < sizeof(size_t)*CHAR_BIT; ++l2) { 171 1.2 christos tv = (size_t)1 << l2; 172 1.2 christos TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv )); 173 1.2 christos TEST_ASSERT_EQUAL_INT(l2, auth_log2( tv + 1 )); 174 1.2 christos TEST_ASSERT_EQUAL_INT(l2, auth_log2(2*tv - 1)); 175 1.2 christos } 176 1.2 christos } 177 1.2 christos 178 1.2 christos /* Converting a string to a host address. Here we use 'getaddrinfo()' in 179 1.2 christos * an independent implementation to avoid cross-reactions with the 180 1.2 christos * object under test. 'inet_pton' is too dangerous to handle it 181 1.2 christos * properly, and ultimate performance is *not* the goal here. 182 1.2 christos */ 183 1.2 christos static int/*BOOL*/ 184 1.2 christos getaddr( 185 1.2 christos int af, 186 1.2 christos const char *astr, 187 1.2 christos sockaddr_u * addr) 188 1.2 christos { 189 1.2 christos struct addrinfo hint; 190 1.2 christos struct addrinfo *ares; 191 1.2 christos 192 1.2 christos memset(&hint, 0, sizeof(hint)); 193 1.2 christos hint.ai_flags = AI_NUMERICHOST; 194 1.2 christos hint.ai_family = af; 195 1.2 christos if (getaddrinfo(astr, NULL, &hint, &ares)) 196 1.2 christos return FALSE; 197 1.2 christos if (ares->ai_addrlen > sizeof(*addr)) 198 1.2 christos memcpy(addr, ares->ai_addr, sizeof(*addr)); 199 1.2 christos else 200 1.2 christos memcpy(addr, ares->ai_addr, ares->ai_addrlen); 201 1.2 christos freeaddrinfo(ares); 202 1.2 christos return TRUE; 203 1.2 christos } 204 1.2 christos 205 1.2 christos void test_AddrMatch_anull(void); 206 1.2 christos void test_AddrMatch_anull(void) 207 1.2 christos { 208 1.2 christos /* Check the not-an-address logic with a prefix/check length of 209 1.2 christos * zero bits. Any compare with a NULL or AF_UNSPEC address 210 1.2 christos * returns inequality (aka FALSE). 211 1.2 christos */ 212 1.2 christos sockaddr_u ip4, ip6, ipn; 213 1.2 christos 214 1.2 christos memset(&ipn, 0, sizeof(ipn)); 215 1.2 christos AF(&ipn) = AF_UNSPEC; 216 1.2 christos 217 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4)); 218 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6)); 219 1.2 christos 220 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(NULL, NULL, 0)); 221 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ipn, 0)); 222 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip4, 0)); 223 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(NULL, &ip6, 0)); 224 1.2 christos 225 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, NULL, 0)); 226 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ipn, 0)); 227 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip4, 0)); 228 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ipn, &ip6, 0)); 229 1.2 christos 230 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ip4, NULL, 0)); 231 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ipn, 0)); 232 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ip6, NULL, 0)); 233 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ipn, 0)); 234 1.2 christos } 235 1.2 christos 236 1.2 christos void test_AddrMatch_self4(void); 237 1.2 christos void test_AddrMatch_self4(void) 238 1.2 christos { 239 1.2 christos sockaddr_u ip4; 240 1.2 christos unsigned int bits; 241 1.2 christos 242 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.1.1", &ip4)); 243 1.2 christos for (bits = 0; bits < 40; ++bits) 244 1.2 christos TEST_ASSERT_TRUE(keyacc_amatch(&ip4, &ip4, bits)); 245 1.2 christos } 246 1.2 christos 247 1.2 christos void test_AddrMatch_self6(void); 248 1.2 christos void test_AddrMatch_self6(void) 249 1.2 christos { 250 1.2 christos sockaddr_u ip6; 251 1.2 christos unsigned int bits; 252 1.2 christos 253 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6)); 254 1.2 christos for (bits = 0; bits < 136; ++bits) 255 1.2 christos TEST_ASSERT_TRUE(keyacc_amatch(&ip6, &ip6, bits)); 256 1.2 christos } 257 1.2 christos 258 1.2 christos void test_AddrMatch_afmix(void); 259 1.2 christos void test_AddrMatch_afmix(void) 260 1.2 christos { 261 1.2 christos sockaddr_u ip6, ip4; 262 1.2 christos 263 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET , "192.128.1.1", &ip4)); 264 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "::1" , &ip6)); 265 1.2 christos 266 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ip4, &ip6, 0)); 267 1.2 christos TEST_ASSERT_FALSE(keyacc_amatch(&ip6, &ip4, 0)); 268 1.2 christos } 269 1.2 christos 270 1.2 christos void test_AddrMatch_ipv4(void); 271 1.2 christos void test_AddrMatch_ipv4(void) 272 1.2 christos { 273 1.2 christos sockaddr_u a1, a2; 274 1.2 christos unsigned int bits; 275 1.2 christos int want; 276 1.2 christos 277 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.1", &a1)); 278 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.3.1", &a2)); 279 1.2 christos 280 1.2 christos /* the first 23 bits are equal, so any prefix <= 23 should match */ 281 1.2 christos for (bits = 0; bits < 40; ++bits) { 282 1.2 christos snprintf(msgbuf, sizeof(msgbuf), 283 1.2 christos "keyacc_amatch(*,*,%u) wrong", bits); 284 1.2 christos want = (bits <= 23); 285 1.2 christos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); 286 1.2 christos } 287 1.2 christos 288 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.127", &a1)); 289 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET, "192.128.2.128", &a2)); 290 1.2 christos 291 1.2 christos /* the first 24 bits are equal, so any prefix <= 24 should match */ 292 1.2 christos for (bits = 0; bits < 40; ++bits) { 293 1.2 christos snprintf(msgbuf, sizeof(msgbuf), 294 1.2 christos "keyacc_amatch(*,*,%u) wrong", bits); 295 1.2 christos want = (bits <= 24); 296 1.2 christos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); 297 1.2 christos } 298 1.2 christos } 299 1.2 christos 300 1.2 christos void test_AddrMatch_ipv6(void); 301 1.2 christos void test_AddrMatch_ipv6(void) 302 1.2 christos { 303 1.2 christos sockaddr_u a1, a2; 304 1.2 christos unsigned int bits; 305 1.2 christos int want; 306 1.2 christos 307 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:FFFF", &a1)); 308 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::3:FFFF", &a2)); 309 1.2 christos 310 1.2 christos /* the first 111 bits are equal, so any prefix <= 111 should match */ 311 1.2 christos for (bits = 0; bits < 136; ++bits) { 312 1.2 christos snprintf(msgbuf, sizeof(msgbuf), 313 1.2 christos "keyacc_amatch(*,*,%u) wrong", bits); 314 1.2 christos want = (bits <= 111); 315 1.2 christos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); 316 1.2 christos } 317 1.2 christos 318 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:7FFF", &a1)); 319 1.2 christos TEST_ASSERT_TRUE(getaddr(AF_INET6, "FEDC:BA98:7654:3210::2:8000", &a2)); 320 1.2 christos 321 1.2 christos /* the first 112 bits are equal, so any prefix <= 112 should match */ 322 1.2 christos for (bits = 0; bits < 136; ++bits) { 323 1.2 christos snprintf(msgbuf, sizeof(msgbuf), 324 1.2 christos "keyacc_amatch(*,*,%u) wrong", bits); 325 1.2 christos want = (bits <= 112); 326 1.2 christos TEST_ASSERT_EQUAL_MESSAGE(want, keyacc_amatch(&a1, &a2, bits), msgbuf); 327 1.2 christos } 328 1.1 christos } 329