@@ -5670,95 +5670,12 @@ static int MatchIpName(const char* name, int nameSz, WOLFSSL_GENERAL_NAME* gn)
56705670 constraintData, constraintLen);
56715671}
56725672
5673- /* Extract host from URI for name constraint matching.
5674- * URI format: scheme://[userinfo@]host[:port][/path][?query][#fragment]
5675- * IPv6 literals are enclosed in brackets: scheme://[ipv6addr]:port/path
5676- * Returns pointer to host start and sets hostLen, or NULL on failure. */
5677- static const char* ExtractHostFromUri(const char* uri, int uriLen, int* hostLen)
5678- {
5679- const char* hostStart;
5680- const char* hostEnd;
5681- const char* p;
5682- const char* uriEnd;
5683-
5684- if (uri == NULL || uriLen <= 0 || hostLen == NULL) {
5685- return NULL;
5686- }
5687-
5688- uriEnd = uri + uriLen;
5689-
5690- /* Find "://" to skip scheme */
5691- hostStart = NULL;
5692- for (p = uri; p < uriEnd - 2; p++) {
5693- if (p[0] == ':' && p[1] == '/' && p[2] == '/') {
5694- hostStart = p + 3;
5695- break;
5696- }
5697- }
5698- if (hostStart == NULL || hostStart >= uriEnd) {
5699- return NULL;
5700- }
5701-
5702- /* Skip userinfo if present (look for @ before any /, ?, #)
5703- * userinfo can contain ':' (ex: user:pass@host), don't stop at ':'
5704- * For IPv6, also don't stop at '[' in userinfo */
5705- for (p = hostStart; p < uriEnd; p++) {
5706- if (*p == '@') {
5707- hostStart = p + 1;
5708- break;
5709- }
5710- if (*p == '/' || *p == '?' || *p == '#') {
5711- /* No userinfo found */
5712- break;
5713- }
5714- /* If '[' before '@', found IPv6 literal, not userinfo */
5715- if (*p == '[') {
5716- break;
5717- }
5718- }
5719- if (hostStart >= uriEnd) {
5720- return NULL;
5721- }
5722-
5723- /* Check for IPv6 literal */
5724- if (*hostStart == '[') {
5725- /* Find closing bracket, skip opening one */
5726- hostStart++;
5727- hostEnd = hostStart;
5728- while (hostEnd < uriEnd && *hostEnd != ']') {
5729- hostEnd++;
5730- }
5731- if (hostEnd >= uriEnd) {
5732- /* No closing bracket found, malformed */
5733- return NULL;
5734- }
5735- /* hostEnd points to closing bracket, extract content between */
5736- *hostLen = (int)(hostEnd - hostStart);
5737- if (*hostLen <= 0) {
5738- return NULL;
5739- }
5740- return hostStart;
5741- }
5742-
5743- /* Regular hostname, find end */
5744- hostEnd = hostStart;
5745- while (hostEnd < uriEnd && *hostEnd != ':' && *hostEnd != '/' &&
5746- *hostEnd != '?' && *hostEnd != '#') {
5747- hostEnd++;
5748- }
5749-
5750- *hostLen = (int)(hostEnd - hostStart);
5751- if (*hostLen <= 0) {
5752- return NULL;
5753- }
5754-
5755- return hostStart;
5756- }
5757-
57585673/* Helper to check if name string matches a single GENERAL_NAME constraint.
5674+ * permitted selects subtree semantics for wildcard DNS names: containment
5675+ * for permitted subtrees, intersection for excluded subtrees.
57595676 * Returns 1 if matches, 0 if not. */
57605677static int MatchNameConstraint(int type, const char* name, int nameSz,
5761- WOLFSSL_GENERAL_NAME* gn)
5678+ WOLFSSL_GENERAL_NAME* gn, int permitted )
57625679{
57635680 const char* baseStr;
57645681 int baseLen;
@@ -5788,21 +5705,13 @@ static int MatchNameConstraint(int type, const char* name, int nameSz,
57885705 nameSz, baseStr, baseLen);
57895706 }
57905707 else if (type == WOLFSSL_GEN_URI) {
5791- const char* host;
5792- int hostLen;
5793-
5794- /* For URI, extract host and match against DNS-style */
5795- host = ExtractHostFromUri(name, nameSz, &hostLen);
5796- if (host == NULL) {
5797- return 0;
5798- }
5799- return wolfssl_local_MatchBaseName(ASN_DNS_TYPE, host, hostLen,
5708+ return wolfssl_local_MatchUriNameConstraint(name, nameSz,
58005709 baseStr, baseLen);
58015710 }
58025711 else {
58035712 /* WOLFSSL_GEN_DNS uses DNS-style matching */
5804- return wolfssl_local_MatchBaseName(ASN_DNS_TYPE, name, nameSz,
5805- baseStr, baseLen);
5713+ return wolfssl_local_MatchDnsNameConstraint( name, nameSz,
5714+ baseStr, baseLen, permitted );
58065715 }
58075716
58085717 default:
@@ -5811,6 +5720,29 @@ static int MatchNameConstraint(int type, const char* name, int nameSz,
58115720 }
58125721}
58135722
5723+ static int NameConstraintsHasType(const WOLFSSL_STACK* sk, int type)
5724+ {
5725+ int i;
5726+ int num;
5727+
5728+ if (sk == NULL) {
5729+ return 0;
5730+ }
5731+
5732+ num = wolfSSL_sk_GENERAL_SUBTREE_num(sk);
5733+ for (i = 0; i < num; i++) {
5734+ WOLFSSL_GENERAL_SUBTREE* subtree;
5735+
5736+ subtree = wolfSSL_sk_GENERAL_SUBTREE_value(sk, i);
5737+ if (subtree != NULL && subtree->base != NULL &&
5738+ subtree->base->type == type) {
5739+ return 1;
5740+ }
5741+ }
5742+
5743+ return 0;
5744+ }
5745+
58145746/*
58155747 * Check if a name string satisfies given name constraints.
58165748 *
@@ -5841,6 +5773,14 @@ int wolfSSL_NAME_CONSTRAINTS_check_name(WOLFSSL_NAME_CONSTRAINTS* nc,
58415773 return 0;
58425774 }
58435775
5776+ if (type == WOLFSSL_GEN_URI &&
5777+ (NameConstraintsHasType(nc->permittedSubtrees, type) ||
5778+ NameConstraintsHasType(nc->excludedSubtrees, type)) &&
5779+ !wolfssl_local_UriNameHasDnsHost(name, nameSz)) {
5780+ WOLFSSL_MSG("URI name constraint applied to URI without DNS host");
5781+ return 0;
5782+ }
5783+
58445784 /* Check permitted subtrees */
58455785 if (nc->permittedSubtrees != NULL) {
58465786 num = wolfSSL_sk_GENERAL_SUBTREE_num(nc->permittedSubtrees);
@@ -5857,7 +5797,7 @@ int wolfSSL_NAME_CONSTRAINTS_check_name(WOLFSSL_NAME_CONSTRAINTS* nc,
58575797 }
58585798 hasPermittedType = 1;
58595799
5860- if (MatchNameConstraint(type, name, nameSz, gn)) {
5800+ if (MatchNameConstraint(type, name, nameSz, gn, 1 )) {
58615801 matchedPermitted = 1;
58625802 break;
58635803 }
@@ -5884,7 +5824,7 @@ int wolfSSL_NAME_CONSTRAINTS_check_name(WOLFSSL_NAME_CONSTRAINTS* nc,
58845824 continue;
58855825 }
58865826
5887- if (MatchNameConstraint(type, name, nameSz, gn)) {
5827+ if (MatchNameConstraint(type, name, nameSz, gn, 0 )) {
58885828 WOLFSSL_MSG("Name in excluded subtrees");
58895829 return 0;
58905830 }
0 commit comments