diff options
| -rw-r--r-- | src/lib/libcrypto/x509/x509_constraints.c | 79 |
1 files changed, 34 insertions, 45 deletions
diff --git a/src/lib/libcrypto/x509/x509_constraints.c b/src/lib/libcrypto/x509/x509_constraints.c index caf56af045..5659d6e6a7 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.9 2020/09/21 05:20:20 tb Exp $ */ | 1 | /* $OpenBSD: x509_constraints.c,v 1.10 2020/09/21 05:41:43 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
| 4 | * | 4 | * |
| @@ -184,8 +184,7 @@ x509_constraints_valid_domain_internal(uint8_t *name, size_t len) | |||
| 184 | if (!isascii(c) || c == '\0') | 184 | if (!isascii(c) || c == '\0') |
| 185 | return 0; | 185 | return 0; |
| 186 | /* It must be alphanumeric, a '-', '.', '_' or '*' */ | 186 | /* It must be alphanumeric, a '-', '.', '_' or '*' */ |
| 187 | if (!isalnum(c) && c != '-' && c != '.' && c != '_' && | 187 | if (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != '*') |
| 188 | c != '*') | ||
| 189 | return 0; | 188 | return 0; |
| 190 | 189 | ||
| 191 | /* '*' can only be the first thing. */ | 190 | /* '*' can only be the first thing. */ |
| @@ -194,14 +193,14 @@ x509_constraints_valid_domain_internal(uint8_t *name, size_t len) | |||
| 194 | 193 | ||
| 195 | /* '-' must not start a component or be at the end. */ | 194 | /* '-' must not start a component or be at the end. */ |
| 196 | if (c == '-' && (component == 0 || i == len - 1)) | 195 | if (c == '-' && (component == 0 || i == len - 1)) |
| 197 | return 0; | 196 | return 0; |
| 198 | 197 | ||
| 199 | /* | 198 | /* |
| 200 | * '.' must not be at the end. It may be first overall | 199 | * '.' must not be at the end. It may be first overall |
| 201 | * but must not otherwise start a component. | 200 | * but must not otherwise start a component. |
| 202 | */ | 201 | */ |
| 203 | if (c == '.' && ((component == 0 && !first) || i == len - 1)) | 202 | if (c == '.' && ((component == 0 && !first) || i == len - 1)) |
| 204 | return 0; | 203 | return 0; |
| 205 | 204 | ||
| 206 | if (c == '.') { | 205 | if (c == '.') { |
| 207 | /* Components can not end with a dash. */ | 206 | /* Components can not end with a dash. */ |
| @@ -419,7 +418,7 @@ int | |||
| 419 | x509_constraints_valid_domain_constraint(uint8_t *constraint, size_t len) | 418 | x509_constraints_valid_domain_constraint(uint8_t *constraint, size_t len) |
| 420 | { | 419 | { |
| 421 | if (len == 0) | 420 | if (len == 0) |
| 422 | return 1; /* empty constraints match */ | 421 | return 1; /* empty constraints match */ |
| 423 | 422 | ||
| 424 | if (constraint[0] == '*') /* wildcard not allowed in a constraint */ | 423 | if (constraint[0] == '*') /* wildcard not allowed in a constraint */ |
| 425 | return 0; | 424 | return 0; |
| @@ -496,12 +495,11 @@ x509_constraints_uri_host(uint8_t *uri, size_t len, char **hostpart) | |||
| 496 | if (!x509_constraints_valid_host(host, hostlen)) | 495 | if (!x509_constraints_valid_host(host, hostlen)) |
| 497 | return 0; | 496 | return 0; |
| 498 | *hostpart = strndup(host, hostlen); | 497 | *hostpart = strndup(host, hostlen); |
| 499 | return 1; | 498 | return 1; |
| 500 | } | 499 | } |
| 501 | 500 | ||
| 502 | int | 501 | int |
| 503 | x509_constraints_sandns(char *sandns, size_t dlen, char *constraint, | 502 | x509_constraints_sandns(char *sandns, size_t dlen, char *constraint, size_t len) |
| 504 | size_t len) | ||
| 505 | { | 503 | { |
| 506 | char *suffix; | 504 | char *suffix; |
| 507 | 505 | ||
| @@ -529,8 +527,7 @@ x509_constraints_sandns(char *sandns, size_t dlen, char *constraint, | |||
| 529 | * starts with a '.'. | 527 | * starts with a '.'. |
| 530 | */ | 528 | */ |
| 531 | int | 529 | int |
| 532 | x509_constraints_domain(char *domain, size_t dlen, char *constraint, | 530 | x509_constraints_domain(char *domain, size_t dlen, char *constraint, size_t len) |
| 533 | size_t len) | ||
| 534 | { | 531 | { |
| 535 | if (len == 0) | 532 | if (len == 0) |
| 536 | return 1; /* an empty constraint matches everything */ | 533 | return 1; /* an empty constraint matches everything */ |
| @@ -558,8 +555,8 @@ x509_constraints_domain(char *domain, size_t dlen, char *constraint, | |||
| 558 | } | 555 | } |
| 559 | 556 | ||
| 560 | int | 557 | int |
| 561 | x509_constraints_uri(uint8_t *uri, size_t ulen, uint8_t *constraint, | 558 | x509_constraints_uri(uint8_t *uri, size_t ulen, uint8_t *constraint, size_t len, |
| 562 | size_t len, int *error) | 559 | int *error) |
| 563 | { | 560 | { |
| 564 | int ret = 0; | 561 | int ret = 0; |
| 565 | char *hostpart = NULL; | 562 | char *hostpart = NULL; |
| @@ -576,8 +573,8 @@ x509_constraints_uri(uint8_t *uri, size_t ulen, uint8_t *constraint, | |||
| 576 | *error = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; | 573 | *error = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; |
| 577 | goto err; | 574 | goto err; |
| 578 | } | 575 | } |
| 579 | ret = x509_constraints_domain(hostpart, strlen(hostpart), | 576 | ret = x509_constraints_domain(hostpart, strlen(hostpart), constraint, |
| 580 | constraint, len); | 577 | len); |
| 581 | err: | 578 | err: |
| 582 | free(hostpart); | 579 | free(hostpart); |
| 583 | return ret; | 580 | return ret; |
| @@ -591,8 +588,8 @@ x509_constraints_uri(uint8_t *uri, size_t ulen, uint8_t *constraint, | |||
| 591 | * 16 and 32 respectively for ipv6 address constraints by the caller. | 588 | * 16 and 32 respectively for ipv6 address constraints by the caller. |
| 592 | */ | 589 | */ |
| 593 | int | 590 | int |
| 594 | x509_constraints_ipaddr(uint8_t *address, size_t alen, | 591 | x509_constraints_ipaddr(uint8_t *address, size_t alen, uint8_t *constraint, |
| 595 | uint8_t *constraint, size_t len) | 592 | size_t len) |
| 596 | { | 593 | { |
| 597 | uint8_t *mask; | 594 | uint8_t *mask; |
| 598 | size_t i; | 595 | size_t i; |
| @@ -696,8 +693,7 @@ x509_constraints_extract_names(struct x509_constraints_names *names, | |||
| 696 | switch(name_type) { | 693 | switch(name_type) { |
| 697 | case GEN_DNS: | 694 | case GEN_DNS: |
| 698 | if (!x509_constraints_valid_sandns(bytes, len)) { | 695 | if (!x509_constraints_valid_sandns(bytes, len)) { |
| 699 | *error = | 696 | *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; |
| 700 | X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; | ||
| 701 | goto err; | 697 | goto err; |
| 702 | } | 698 | } |
| 703 | if ((vname->name = strdup(bytes)) == NULL) { | 699 | if ((vname->name = strdup(bytes)) == NULL) { |
| @@ -748,8 +744,7 @@ x509_constraints_extract_names(struct x509_constraints_names *names, | |||
| 748 | vname->af = AF_INET6; | 744 | vname->af = AF_INET6; |
| 749 | if (vname->af != AF_INET && vname->af != | 745 | if (vname->af != AF_INET && vname->af != |
| 750 | AF_INET6) { | 746 | AF_INET6) { |
| 751 | *error = | 747 | *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; |
| 752 | X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; | ||
| 753 | goto err; | 748 | goto err; |
| 754 | } | 749 | } |
| 755 | memcpy(vname->address, bytes, len); | 750 | memcpy(vname->address, bytes, len); |
| @@ -889,14 +884,13 @@ x509_constraints_validate(GENERAL_NAME *constraint, | |||
| 889 | return 0; | 884 | return 0; |
| 890 | } | 885 | } |
| 891 | if (len == 0) | 886 | if (len == 0) |
| 892 | goto err; /* XXX The RFC's are delightfully vague */ | 887 | goto err; /* XXX The RFCs are delightfully vague */ |
| 893 | memcpy(name->der, bytes, len); | 888 | memcpy(name->der, bytes, len); |
| 894 | name->der_len = len; | 889 | name->der_len = len; |
| 895 | name->type = GEN_DIRNAME; | 890 | name->type = GEN_DIRNAME; |
| 896 | break; | 891 | break; |
| 897 | case GEN_DNS: | 892 | case GEN_DNS: |
| 898 | if (!x509_constraints_valid_domain_constraint(bytes, | 893 | if (!x509_constraints_valid_domain_constraint(bytes, len)) |
| 899 | len)) | ||
| 900 | goto err; | 894 | goto err; |
| 901 | if ((name->name = strdup(bytes)) == NULL) { | 895 | if ((name->name = strdup(bytes)) == NULL) { |
| 902 | *error = X509_V_ERR_OUT_OF_MEM; | 896 | *error = X509_V_ERR_OUT_OF_MEM; |
| @@ -906,12 +900,11 @@ x509_constraints_validate(GENERAL_NAME *constraint, | |||
| 906 | break; | 900 | break; |
| 907 | case GEN_EMAIL: | 901 | case GEN_EMAIL: |
| 908 | if (memchr(bytes, '@', len) != NULL) { | 902 | if (memchr(bytes, '@', len) != NULL) { |
| 909 | if (!x509_constraints_parse_mailbox(bytes, len, | 903 | if (!x509_constraints_parse_mailbox(bytes, len, name)) |
| 910 | name)) | ||
| 911 | goto err; | 904 | goto err; |
| 912 | } else { | 905 | } else { |
| 913 | if (!x509_constraints_valid_domain_constraint( | 906 | if (!x509_constraints_valid_domain_constraint(bytes, |
| 914 | bytes, len)) | 907 | len)) |
| 915 | goto err; | 908 | goto err; |
| 916 | if ((name->name = strdup(bytes)) == NULL) { | 909 | if ((name->name = strdup(bytes)) == NULL) { |
| 917 | *error = X509_V_ERR_OUT_OF_MEM; | 910 | *error = X509_V_ERR_OUT_OF_MEM; |
| @@ -932,8 +925,7 @@ x509_constraints_validate(GENERAL_NAME *constraint, | |||
| 932 | name->type = GEN_IPADD; | 925 | name->type = GEN_IPADD; |
| 933 | break; | 926 | break; |
| 934 | case GEN_URI: | 927 | case GEN_URI: |
| 935 | if (!x509_constraints_valid_domain_constraint(bytes, | 928 | if (!x509_constraints_valid_domain_constraint(bytes, len)) |
| 936 | len)) | ||
| 937 | goto err; | 929 | goto err; |
| 938 | name->name = strdup(bytes); | 930 | name->name = strdup(bytes); |
| 939 | name->type = GEN_URI; | 931 | name->type = GEN_URI; |
| @@ -983,7 +975,7 @@ x509_constraints_extract_constraints(X509 *cert, | |||
| 983 | } | 975 | } |
| 984 | if (!x509_constraints_names_add(permitted, vname)) { | 976 | if (!x509_constraints_names_add(permitted, vname)) { |
| 985 | x509_constraints_name_free(vname); | 977 | x509_constraints_name_free(vname); |
| 986 | *error = X509_V_ERR_OUT_OF_MEM; | 978 | *error = X509_V_ERR_OUT_OF_MEM; |
| 987 | return 0; | 979 | return 0; |
| 988 | } | 980 | } |
| 989 | } | 981 | } |
| @@ -1009,7 +1001,7 @@ x509_constraints_extract_constraints(X509 *cert, | |||
| 1009 | } | 1001 | } |
| 1010 | if (!x509_constraints_names_add(excluded, vname)) { | 1002 | if (!x509_constraints_names_add(excluded, vname)) { |
| 1011 | x509_constraints_name_free(vname); | 1003 | x509_constraints_name_free(vname); |
| 1012 | *error = X509_V_ERR_OUT_OF_MEM; | 1004 | *error = X509_V_ERR_OUT_OF_MEM; |
| 1013 | return 0; | 1005 | return 0; |
| 1014 | } | 1006 | } |
| 1015 | } | 1007 | } |
| @@ -1028,13 +1020,11 @@ x509_constraints_match(struct x509_constraints_name *name, | |||
| 1028 | if (name->type != constraint->type) | 1020 | if (name->type != constraint->type) |
| 1029 | return 0; | 1021 | return 0; |
| 1030 | if (name->type == GEN_DNS) | 1022 | if (name->type == GEN_DNS) |
| 1031 | return x509_constraints_sandns(name->name, | 1023 | return x509_constraints_sandns(name->name, strlen(name->name), |
| 1032 | strlen(name->name), constraint->name, | 1024 | constraint->name, strlen(constraint->name)); |
| 1033 | strlen(constraint->name)); | ||
| 1034 | if (name->type == GEN_URI) | 1025 | if (name->type == GEN_URI) |
| 1035 | return x509_constraints_domain(name->name, | 1026 | return x509_constraints_domain(name->name, strlen(name->name), |
| 1036 | strlen(name->name), constraint->name, | 1027 | constraint->name, strlen(constraint->name)); |
| 1037 | strlen(constraint->name)); | ||
| 1038 | if (name->type == GEN_IPADD) { | 1028 | if (name->type == GEN_IPADD) { |
| 1039 | size_t nlen = name->af == AF_INET ? 4 : 16; | 1029 | size_t nlen = name->af == AF_INET ? 4 : 16; |
| 1040 | size_t clen = name->af == AF_INET ? 8 : 32; | 1030 | size_t clen = name->af == AF_INET ? 8 : 32; |
| @@ -1044,8 +1034,8 @@ x509_constraints_match(struct x509_constraints_name *name, | |||
| 1044 | return 0; | 1034 | return 0; |
| 1045 | if (name->af != constraint->af) | 1035 | if (name->af != constraint->af) |
| 1046 | return 0; | 1036 | return 0; |
| 1047 | return x509_constraints_ipaddr(name->address, | 1037 | return x509_constraints_ipaddr(name->address, nlen, |
| 1048 | nlen, constraint->address, clen); | 1038 | constraint->address, clen); |
| 1049 | } | 1039 | } |
| 1050 | if (name->type == GEN_EMAIL) { | 1040 | if (name->type == GEN_EMAIL) { |
| 1051 | if (constraint->local) { | 1041 | if (constraint->local) { |
| @@ -1054,9 +1044,8 @@ x509_constraints_match(struct x509_constraints_name *name, | |||
| 1054 | strcmp(name->name, constraint->name) == 0); | 1044 | strcmp(name->name, constraint->name) == 0); |
| 1055 | } | 1045 | } |
| 1056 | /* otherwise match the constraint to the domain part */ | 1046 | /* otherwise match the constraint to the domain part */ |
| 1057 | return x509_constraints_domain(name->name, | 1047 | return x509_constraints_domain(name->name, strlen(name->name), |
| 1058 | strlen(name->name), constraint->name, | 1048 | constraint->name, strlen(constraint->name)); |
| 1059 | strlen(constraint->name)); | ||
| 1060 | } | 1049 | } |
| 1061 | if (name->type == GEN_DIRNAME) | 1050 | if (name->type == GEN_DIRNAME) |
| 1062 | return x509_constraints_dirname(name->der, name->der_len, | 1051 | return x509_constraints_dirname(name->der, name->der_len, |
| @@ -1159,8 +1148,8 @@ x509_constraints_chain(STACK_OF(X509) *chain, int *error, int *depth) | |||
| 1159 | verify_err = X509_V_ERR_OUT_OF_MEM; | 1148 | verify_err = X509_V_ERR_OUT_OF_MEM; |
| 1160 | goto err; | 1149 | goto err; |
| 1161 | } | 1150 | } |
| 1162 | if (!x509_constraints_check(names, permitted, | 1151 | if (!x509_constraints_check(names, permitted, excluded, |
| 1163 | excluded, &verify_err)) | 1152 | &verify_err)) |
| 1164 | goto err; | 1153 | goto err; |
| 1165 | x509_constraints_names_free(excluded); | 1154 | x509_constraints_names_free(excluded); |
| 1166 | excluded = NULL; | 1155 | excluded = NULL; |
