summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbeck <>2023-09-29 15:53:59 +0000
committerbeck <>2023-09-29 15:53:59 +0000
commit266a46fc156d909c580ce8946cc574da9a2ee5b4 (patch)
tree9289b67644f1ef47e15e9b80e3105d2ff11da1d2 /src
parentf4f0e4daf1dec6165cb0996274d1ce8cd63b6dc6 (diff)
downloadopenbsd-266a46fc156d909c580ce8946cc574da9a2ee5b4.tar.gz
openbsd-266a46fc156d909c580ce8946cc574da9a2ee5b4.tar.bz2
openbsd-266a46fc156d909c580ce8946cc574da9a2ee5b4.zip
Allow IP addresses to be specified in a URI.
Our checking here was a bit too aggressive, and did not permit an IP address in a URI. IP's in a URI are allowed for things like CRLdp's AIA, SAN URI's etc.). The check for this was also slightly flawed as we would permit an IP if memory allocation failed while checking for an IP. Correct both issues. ok tb@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/x509/x509_constraints.c31
-rw-r--r--src/lib/libcrypto/x509/x509_internal.h4
-rw-r--r--src/regress/lib/libcrypto/x509/constraints.c54
3 files changed, 70 insertions, 19 deletions
diff --git a/src/lib/libcrypto/x509/x509_constraints.c b/src/lib/libcrypto/x509/x509_constraints.c
index 346cab0a40..0773d2ba71 100644
--- a/src/lib/libcrypto/x509/x509_constraints.c
+++ b/src/lib/libcrypto/x509/x509_constraints.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_constraints.c,v 1.31 2022/12/26 07:18:53 jmc Exp $ */ 1/* $OpenBSD: x509_constraints.c,v 1.32 2023/09/29 15:53:59 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -38,23 +38,23 @@
38#define MAX_IP_ADDRESS_LENGTH (size_t)46 38#define MAX_IP_ADDRESS_LENGTH (size_t)46
39 39
40static int 40static int
41cbs_is_ip_address(CBS *cbs) 41cbs_is_ip_address(CBS *cbs, int *is_ip)
42{ 42{
43 struct sockaddr_in6 sin6; 43 struct sockaddr_in6 sin6;
44 struct sockaddr_in sin4; 44 struct sockaddr_in sin4;
45 char *name = NULL; 45 char *name = NULL;
46 int ret = 0;
47 46
47 *is_ip = 0;
48 if (CBS_len(cbs) > MAX_IP_ADDRESS_LENGTH) 48 if (CBS_len(cbs) > MAX_IP_ADDRESS_LENGTH)
49 return 0; 49 return 1;
50 if (!CBS_strdup(cbs, &name)) 50 if (!CBS_strdup(cbs, &name))
51 return 0; 51 return 0;
52 if (inet_pton(AF_INET, name, &sin4) == 1 || 52 if (inet_pton(AF_INET, name, &sin4) == 1 ||
53 inet_pton(AF_INET6, name, &sin6) == 1) 53 inet_pton(AF_INET6, name, &sin6) == 1)
54 ret = 1; 54 *is_ip = 1;
55 55
56 free(name); 56 free(name);
57 return ret; 57 return 1;
58} 58}
59 59
60struct x509_constraints_name * 60struct x509_constraints_name *
@@ -264,16 +264,21 @@ x509_constraints_valid_domain_internal(CBS *cbs, int wildcards)
264} 264}
265 265
266int 266int
267x509_constraints_valid_host(CBS *cbs) 267x509_constraints_valid_host(CBS *cbs, int permit_ip)
268{ 268{
269 uint8_t first; 269 uint8_t first;
270 int is_ip;
270 271
271 if (!CBS_peek_u8(cbs, &first)) 272 if (!CBS_peek_u8(cbs, &first))
272 return 0; 273 return 0;
273 if (first == '.') 274 if (first == '.')
274 return 0; /* leading . not allowed in a host name */ 275 return 0; /* leading . not allowed in a host name or IP */
275 if (cbs_is_ip_address(cbs)) 276 if (!permit_ip) {
276 return 0; 277 if (!cbs_is_ip_address(cbs, &is_ip))
278 return 0;
279 if (is_ip)
280 return 0;
281 }
277 282
278 return x509_constraints_valid_domain_internal(cbs, 0); 283 return x509_constraints_valid_domain_internal(cbs, 0);
279} 284}
@@ -441,7 +446,7 @@ x509_constraints_parse_mailbox(CBS *candidate,
441 if (candidate_local == NULL || candidate_domain == NULL) 446 if (candidate_local == NULL || candidate_domain == NULL)
442 goto bad; 447 goto bad;
443 CBS_init(&domain_cbs, candidate_domain, strlen(candidate_domain)); 448 CBS_init(&domain_cbs, candidate_domain, strlen(candidate_domain));
444 if (!x509_constraints_valid_host(&domain_cbs)) 449 if (!x509_constraints_valid_host(&domain_cbs, 0))
445 goto bad; 450 goto bad;
446 451
447 if (name != NULL) { 452 if (name != NULL) {
@@ -558,7 +563,7 @@ x509_constraints_uri_host(uint8_t *uri, size_t len, char **hostpart)
558 if (host == NULL) 563 if (host == NULL)
559 host = authority; 564 host = authority;
560 CBS_init(&host_cbs, host, hostlen); 565 CBS_init(&host_cbs, host, hostlen);
561 if (!x509_constraints_valid_host(&host_cbs)) 566 if (!x509_constraints_valid_host(&host_cbs, 1))
562 return 0; 567 return 0;
563 if (hostpart != NULL && !CBS_strdup(&host_cbs, hostpart)) 568 if (hostpart != NULL && !CBS_strdup(&host_cbs, hostpart))
564 return 0; 569 return 0;
@@ -924,7 +929,7 @@ x509_constraints_extract_names(struct x509_constraints_names *names,
924 goto err; 929 goto err;
925 } 930 }
926 CBS_init(&cbs, aname->data, aname->length); 931 CBS_init(&cbs, aname->data, aname->length);
927 if (!x509_constraints_valid_host(&cbs)) 932 if (!x509_constraints_valid_host(&cbs, 0))
928 continue; /* ignore it if not a hostname */ 933 continue; /* ignore it if not a hostname */
929 if ((vname = x509_constraints_name_new()) == NULL) { 934 if ((vname = x509_constraints_name_new()) == NULL) {
930 *error = X509_V_ERR_OUT_OF_MEM; 935 *error = X509_V_ERR_OUT_OF_MEM;
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h
index c4222bcfe5..15efff6097 100644
--- a/src/lib/libcrypto/x509/x509_internal.h
+++ b/src/lib/libcrypto/x509/x509_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_internal.h,v 1.25 2023/01/28 19:08:09 tb Exp $ */ 1/* $OpenBSD: x509_internal.h,v 1.26 2023/09/29 15:53:59 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -111,7 +111,7 @@ struct x509_constraints_names *x509_constraints_names_new(size_t names_max);
111int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, 111int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes,
112 size_t *len); 112 size_t *len);
113void x509_constraints_names_free(struct x509_constraints_names *names); 113void x509_constraints_names_free(struct x509_constraints_names *names);
114int x509_constraints_valid_host(CBS *cbs); 114int x509_constraints_valid_host(CBS *cbs, int permit_ip);
115int x509_constraints_valid_sandns(CBS *cbs); 115int x509_constraints_valid_sandns(CBS *cbs);
116int x509_constraints_domain(char *domain, size_t dlen, char *constraint, 116int x509_constraints_domain(char *domain, size_t dlen, char *constraint,
117 size_t len); 117 size_t len);
diff --git a/src/regress/lib/libcrypto/x509/constraints.c b/src/regress/lib/libcrypto/x509/constraints.c
index 8771367bd6..90b7ffbaeb 100644
--- a/src/regress/lib/libcrypto/x509/constraints.c
+++ b/src/regress/lib/libcrypto/x509/constraints.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: constraints.c,v 1.15 2022/11/28 07:24:03 tb Exp $ */ 1/* $OpenBSD: constraints.c,v 1.16 2023/09/29 15:53:59 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -154,6 +154,12 @@ unsigned char *invaliduri[] = {
154 "https://.www.openbsd.org/", 154 "https://.www.openbsd.org/",
155 "https://www.ope|nbsd.org%", 155 "https://www.ope|nbsd.org%",
156 "https://www.openbsd.org.#", 156 "https://www.openbsd.org.#",
157 "https://192.168.1.1./",
158 "https://192.168.1.1|/",
159 "https://.192.168.1.1/",
160 "https://192.168..1.1/",
161 "https://.2001:0DB8:AC10:FE01::/",
162 "https://.2001:0DB8:AC10:FE01::|/",
157 "///", 163 "///",
158 "//", 164 "//",
159 "/", 165 "/",
@@ -161,6 +167,15 @@ unsigned char *invaliduri[] = {
161 NULL, 167 NULL,
162}; 168};
163 169
170unsigned char *validuri[] = {
171 "https://www.openbsd.org/meep/meep/meep/",
172 "https://192.168.1.1/",
173 "https://2001:0DB8:AC10:FE01::/",
174 "https://192.168.1/", /* Not an IP, but valid component */
175 "https://999.999.999.999/", /* Not an IP, but valid component */
176 NULL,
177};
178
164static int 179static int
165test_valid_hostnames(void) 180test_valid_hostnames(void)
166{ 181{
@@ -169,7 +184,7 @@ test_valid_hostnames(void)
169 for (i = 0; valid_hostnames[i] != NULL; i++) { 184 for (i = 0; valid_hostnames[i] != NULL; i++) {
170 CBS cbs; 185 CBS cbs;
171 CBS_init(&cbs, valid_hostnames[i], strlen(valid_hostnames[i])); 186 CBS_init(&cbs, valid_hostnames[i], strlen(valid_hostnames[i]));
172 if (!x509_constraints_valid_host(&cbs)) { 187 if (!x509_constraints_valid_host(&cbs, 0)) {
173 FAIL("Valid hostname '%s' rejected\n", 188 FAIL("Valid hostname '%s' rejected\n",
174 valid_hostnames[i]); 189 valid_hostnames[i]);
175 failure = 1; 190 failure = 1;
@@ -183,6 +198,7 @@ test_valid_hostnames(void)
183 goto done; 198 goto done;
184 } 199 }
185 } 200 }
201
186 done: 202 done:
187 return failure; 203 return failure;
188} 204}
@@ -202,6 +218,7 @@ test_valid_sandns_names(void)
202 goto done; 218 goto done;
203 } 219 }
204 } 220 }
221
205 done: 222 done:
206 return failure; 223 return failure;
207} 224}
@@ -221,6 +238,7 @@ test_valid_domain_constraints(void)
221 goto done; 238 goto done;
222 } 239 }
223 } 240 }
241
224 done: 242 done:
225 return failure; 243 return failure;
226} 244}
@@ -245,6 +263,7 @@ test_valid_mbox_names(void)
245 free(name.local); 263 free(name.local);
246 name.local = NULL; 264 name.local = NULL;
247 } 265 }
266
248 done: 267 done:
249 return failure; 268 return failure;
250} 269}
@@ -259,7 +278,7 @@ test_invalid_hostnames(void)
259 for (i = 0; invalid_hostnames[i] != NULL; i++) { 278 for (i = 0; invalid_hostnames[i] != NULL; i++) {
260 CBS_init(&cbs, invalid_hostnames[i], 279 CBS_init(&cbs, invalid_hostnames[i],
261 strlen(invalid_hostnames[i])); 280 strlen(invalid_hostnames[i]));
262 if (x509_constraints_valid_host(&cbs)) { 281 if (x509_constraints_valid_host(&cbs, 0)) {
263 FAIL("Invalid hostname '%s' accepted\n", 282 FAIL("Invalid hostname '%s' accepted\n",
264 invalid_hostnames[i]); 283 invalid_hostnames[i]);
265 failure = 1; 284 failure = 1;
@@ -267,7 +286,7 @@ test_invalid_hostnames(void)
267 } 286 }
268 } 287 }
269 CBS_init(&cbs, nulhost, strlen(nulhost) + 1); 288 CBS_init(&cbs, nulhost, strlen(nulhost) + 1);
270 if (x509_constraints_valid_host(&cbs)) { 289 if (x509_constraints_valid_host(&cbs, 0)) {
271 FAIL("hostname with NUL byte accepted\n"); 290 FAIL("hostname with NUL byte accepted\n");
272 failure = 1; 291 failure = 1;
273 goto done; 292 goto done;
@@ -278,6 +297,7 @@ test_invalid_hostnames(void)
278 failure = 1; 297 failure = 1;
279 goto done; 298 goto done;
280 } 299 }
300
281 done: 301 done:
282 return failure; 302 return failure;
283} 303}
@@ -297,6 +317,7 @@ test_invalid_sandns_names(void)
297 goto done; 317 goto done;
298 } 318 }
299 } 319 }
320
300 done: 321 done:
301 return failure; 322 return failure;
302} 323}
@@ -321,6 +342,7 @@ test_invalid_mbox_names(void)
321 free(name.local); 342 free(name.local);
322 name.local = NULL; 343 name.local = NULL;
323 } 344 }
345
324 done: 346 done:
325 return failure; 347 return failure;
326} 348}
@@ -340,6 +362,7 @@ test_invalid_domain_constraints(void)
340 goto done; 362 goto done;
341 } 363 }
342 } 364 }
365
343 done: 366 done:
344 return failure; 367 return failure;
345} 368}
@@ -365,6 +388,27 @@ test_invalid_uri(void)
365 done: 388 done:
366 return failure; 389 return failure;
367} 390}
391static int
392test_valid_uri(void)
393{
394 int j, failure = 0;
395 char *hostpart = NULL;
396
397 for (j = 0; validuri[j] != NULL; j++) {
398 if (x509_constraints_uri_host(validuri[j],
399 strlen(invaliduri[j]), &hostpart) == 0) {
400 FAIL("Valid URI '%s' NOT accepted\n",
401 validuri[j]);
402 failure = 1;
403 goto done;
404 }
405 free(hostpart);
406 hostpart = NULL;
407 }
408
409 done:
410 return failure;
411}
368 412
369static int 413static int
370test_constraints1(void) 414test_constraints1(void)
@@ -513,6 +557,7 @@ test_constraints1(void)
513 failure = 1; 557 failure = 1;
514 goto done; 558 goto done;
515 } 559 }
560
516 done: 561 done:
517 return failure; 562 return failure;
518} 563}
@@ -531,6 +576,7 @@ main(int argc, char **argv)
531 failed |= test_valid_domain_constraints(); 576 failed |= test_valid_domain_constraints();
532 failed |= test_invalid_domain_constraints(); 577 failed |= test_invalid_domain_constraints();
533 failed |= test_invalid_uri(); 578 failed |= test_invalid_uri();
579 failed |= test_valid_uri();
534 failed |= test_constraints1(); 580 failed |= test_constraints1();
535 581
536 return (failed); 582 return (failed);