summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);