diff options
author | beck <> | 2023-09-29 15:53:59 +0000 |
---|---|---|
committer | beck <> | 2023-09-29 15:53:59 +0000 |
commit | 266a46fc156d909c580ce8946cc574da9a2ee5b4 (patch) | |
tree | 9289b67644f1ef47e15e9b80e3105d2ff11da1d2 /src | |
parent | f4f0e4daf1dec6165cb0996274d1ce8cd63b6dc6 (diff) | |
download | openbsd-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.c | 31 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_internal.h | 4 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/x509/constraints.c | 54 |
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 | ||
40 | static int | 40 | static int |
41 | cbs_is_ip_address(CBS *cbs) | 41 | cbs_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 | ||
60 | struct x509_constraints_name * | 60 | struct x509_constraints_name * |
@@ -264,16 +264,21 @@ x509_constraints_valid_domain_internal(CBS *cbs, int wildcards) | |||
264 | } | 264 | } |
265 | 265 | ||
266 | int | 266 | int |
267 | x509_constraints_valid_host(CBS *cbs) | 267 | x509_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); | |||
111 | int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, | 111 | int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, |
112 | size_t *len); | 112 | size_t *len); |
113 | void x509_constraints_names_free(struct x509_constraints_names *names); | 113 | void x509_constraints_names_free(struct x509_constraints_names *names); |
114 | int x509_constraints_valid_host(CBS *cbs); | 114 | int x509_constraints_valid_host(CBS *cbs, int permit_ip); |
115 | int x509_constraints_valid_sandns(CBS *cbs); | 115 | int x509_constraints_valid_sandns(CBS *cbs); |
116 | int x509_constraints_domain(char *domain, size_t dlen, char *constraint, | 116 | int 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 | ||
170 | unsigned 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 | |||
164 | static int | 179 | static int |
165 | test_valid_hostnames(void) | 180 | test_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 | } |
391 | static int | ||
392 | test_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 | ||
369 | static int | 413 | static int |
370 | test_constraints1(void) | 414 | test_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); |