{
int atstart = (state & LABEL_START);
int atend = (i == len - 1 || p[i+i] == '.');
- /*
+ /*-
* At most one wildcard per pattern.
* No wildcards in IDNA labels.
* No wildcards after the first label.
star = &p[i];
state &= ~LABEL_START;
}
- else if ((state & LABEL_START) != 0)
- {
- /*
- * At the start of a label, skip any "xn--" and
- * remain in the LABEL_START state, but set the
- * IDNA label state
- */
- if ((state & LABEL_IDNA) == 0 && len - i >= 4
- && strncasecmp((char *)&p[i], "xn--", 4) == 0)
- {
- i += 3;
- state |= LABEL_IDNA;
- continue;
- }
- /* Labels must start with a letter or digit */
- state &= ~LABEL_START;
- if (('a' <= p[i] && p[i] <= 'z')
- || ('A' <= p[i] && p[i] <= 'Z')
- || ('0' <= p[i] && p[i] <= '9'))
- continue;
- return NULL;
- }
else if (('a' <= p[i] && p[i] <= 'z')
|| ('A' <= p[i] && p[i] <= 'Z')
|| ('0' <= p[i] && p[i] <= '9'))
{
- state &= LABEL_IDNA;
- continue;
+ if ((state & LABEL_START) != 0
+ && len - i >= 4
+ && strncasecmp((char *)&p[i], "xn--", 4) == 0)
+ state |= LABEL_IDNA;
+ state &= ~(LABEL_HYPHEN|LABEL_START);
}
else if (p[i] == '.')
{
- if (state & (LABEL_HYPHEN | LABEL_START))
+ if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
return NULL;
state = LABEL_START;
++dots;
}
else if (p[i] == '-')
{
- if (state & LABEL_HYPHEN)
+ if ((state & LABEL_HYPHEN) != 0)
return NULL;
state |= LABEL_HYPHEN;
}
*/
static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
- unsigned int flags,
- const unsigned char *b, size_t blen)
+ unsigned int flags, const char *b, size_t blen,
+ char **peername)
{
+ int rv = 0;
+
if (!a->data || !a->length)
return 0;
if (cmp_type > 0)
if (cmp_type != a->type)
return 0;
if (cmp_type == V_ASN1_IA5STRING)
- return equal(a->data, a->length, b, blen, flags);
- if (a->length == (int)blen && !memcmp(a->data, b, blen))
- return 1;
- else
- return 0;
+ rv = equal(a->data, a->length,
+ (unsigned char *)b, blen, flags);
+ else if (a->length == (int)blen && !memcmp(a->data, b, blen))
+ rv = 1;
+ if (rv > 0 && peername)
+ *peername = BUF_strndup((char *)a->data, a->length);
}
else
{
- int astrlen, rv;
+ int astrlen;
unsigned char *astr;
astrlen = ASN1_STRING_to_UTF8(&astr, a);
if (astrlen < 0)
return -1;
- rv = equal(astr, astrlen, b, blen, flags);
+ rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
+ if (rv > 0 && peername)
+ *peername = BUF_strndup((char *)astr, astrlen);
OPENSSL_free(astr);
- return rv;
}
+ return rv;
}
-static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags, int check_type)
+static int do_x509_check(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, int check_type,
+ char **peername)
{
GENERAL_NAMES *gens = NULL;
X509_NAME *name = NULL;
int cnid;
int alt_type;
int san_present = 0;
+ int rv = 0;
equal_fn equal;
/* See below, this flag is internal-only */
}
if (chklen == 0)
- chklen = strlen((const char *)chk);
+ chklen = strlen(chk);
gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
if (gens)
{
- int rv = 0;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
{
GENERAL_NAME *gen;
cstr = gen->d.dNSName;
else
cstr = gen->d.iPAddress;
- if (do_check_string(cstr, alt_type, equal, flags,
- chk, chklen))
- {
- rv = 1;
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(cstr, alt_type, equal, flags,
+ chk, chklen, peername)) != 0)
break;
- }
}
GENERAL_NAMES_free(gens);
- if (rv)
- return 1;
+ if (rv != 0)
+ return rv;
if (!cnid
|| (san_present
&& !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
ASN1_STRING *str;
ne = X509_NAME_get_entry(name, i);
str = X509_NAME_ENTRY_get_data(ne);
- if (do_check_string(str, -1, equal, flags, chk, chklen))
- return 1;
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(str, -1, equal, flags,
+ chk, chklen, peername)) != 0)
+ return rv;
}
return 0;
}
-int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags)
+int X509_check_host(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, char **peername)
{
+ if (chk == NULL)
+ return -2;
+ /*
+ * Embedded NULs are disallowed, except as the last character of a
+ * string of length 2 or more (tolerate caller including terminating
+ * NUL in string length).
+ */
if (chklen == 0)
- chklen = chk ? strlen((char *)chk) : 0;
- else if (chk && memchr(chk, '\0', chklen))
- return 0;
- return do_x509_check(x, chk, chklen, flags, GEN_DNS);
+ chklen = strlen(chk);
+ else if (memchr(chk, '\0', chklen > 1 ? chklen-1 : chklen))
+ return -2;
+ if (chklen > 1 && chk[chklen-1] == '\0')
+ --chklen;
+ return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
}
-int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags)
+int X509_check_email(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags)
{
- return do_x509_check(x, chk, chklen, flags, GEN_EMAIL);
+ if (chk == NULL)
+ return -2;
+ /*
+ * Embedded NULs are disallowed, except as the last character of a
+ * string of length 2 or more (tolerate caller including terminating
+ * NUL in string length).
+ */
+ if (chklen == 0)
+ chklen = strlen((char *)chk);
+ else if (memchr(chk, '\0', chklen > 1 ? chklen-1 : chklen))
+ return -2;
+ if (chklen > 1 && chk[chklen-1] == '\0')
+ --chklen;
+ return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
}
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags)
{
- return do_x509_check(x, chk, chklen, flags, GEN_IPADD);
+ if (chk == NULL)
+ return -2;
+ return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
}
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
{
unsigned char ipout[16];
- int iplen;
- iplen = a2i_ipadd(ipout, ipasc);
+ size_t iplen;
+
+ if (ipasc == NULL)
+ return -2;
+ iplen = (size_t) a2i_ipadd(ipout, ipasc);
if (iplen == 0)
return -2;
- return do_x509_check(x, ipout, (size_t)iplen, flags, GEN_IPADD);
+ return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
}
/* Convert IP addresses both IPv4 and IPv6 into an