diff options
Diffstat (limited to '')
| -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); |
