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