-/* $OpenBSD: x509_constraints.c,v 1.15 2021/03/12 15:57:30 tb Exp $ */
+/* $OpenBSD: x509_constraints.c,v 1.16 2021/04/27 03:35:29 beck Exp $ */
/*
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
*
/*
* Validate that the name contains only a hostname consisting of RFC
* 5890 compliant A-labels (see RFC 6066 section 3). This is more
- * permissive to allow for a leading '*' for a SAN DNSname wildcard,
- * or a leading '.' for a subdomain based constraint, as well as
- * allowing for '_' which is commonly accepted by nonconformant
- * DNS implementaitons.
+ * permissive to allow for a leading '.' for a subdomain based
+ * constraint, as well as allowing for '_' which is commonly accepted
+ * by nonconformant DNS implementaitons.
+ *
+ * if "wildcards" is set it allows '*' to occur in the string at the end of a
+ * component.
*/
static int
-x509_constraints_valid_domain_internal(uint8_t *name, size_t len)
+x509_constraints_valid_domain_internal(uint8_t *name, size_t len, int wildcards)
{
uint8_t prev, c = 0;
int component = 0;
if (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != '*')
return 0;
- /* '*' can only be the first thing. */
- if (c == '*' && !first)
+ /* if it is a '*', fail if not wildcards */
+ if (!wildcards && c == '*')
return 0;
/* '-' must not start a component or be at the end. */
component = 0;
continue;
}
+ /*
+ * Wildcards can only occur at the end of a component.
+ * c*.com is valid, c*c.com is not.
+ */
+ if (prev == '*')
+ return 0;
+
/* Components must be 63 chars or less. */
if (++component > 63)
return 0;
{
if (len == 0)
return 0;
- if (name[0] == '*') /* wildcard not allowed in a domain name */
- return 0;
/*
* A domain may not be less than two characters, so you can't
* have a require subdomain name with less than that.
*/
if (len < 3 && name[0] == '.')
return 0;
- return x509_constraints_valid_domain_internal(name, len);
+ return x509_constraints_valid_domain_internal(name, len, 0);
}
int
if (len == 0)
return 0;
- if (name[0] == '*') /* wildcard not allowed in a host name */
- return 0;
if (name[0] == '.') /* leading . not allowed in a host name*/
return 0;
if (inet_pton(AF_INET, name, &sin4) == 1)
return 0;
if (inet_pton(AF_INET6, name, &sin6) == 1)
return 0;
- return x509_constraints_valid_domain_internal(name, len);
+ return x509_constraints_valid_domain_internal(name, len, 0);
}
int
if (len >= 4 && name[0] == '*' && name[1] != '.')
return 0;
- return x509_constraints_valid_domain_internal(name, len);
+ return x509_constraints_valid_domain_internal(name, len, 1);
}
static inline int
if (len == 0)
return 1; /* empty constraints match */
- if (constraint[0] == '*') /* wildcard not allowed in a constraint */
- return 0;
-
/*
* A domain may not be less than two characters, so you
* can't match a single domain of less than that
*/
if (len < 3 && constraint[0] == '.')
return 0;
- return x509_constraints_valid_domain_internal(constraint, len);
+ return x509_constraints_valid_domain_internal(constraint, len, 0);
}
/*