[31508] in CVS-changelog-for-Kerberos-V5

home help back first fref pref prev next nref lref last post

krb5 commit: Use X509_check_host() to verify KKDCP server cert

daemon@ATHENA.MIT.EDU (ghudson@mit.edu)
Wed Mar 4 02:09:39 2026

From: ghudson@mit.edu
To: cvs-krb5@mit.edu
Message-Id: <20260304070933.282FF1046F6@krbdev.mit.edu>
Date: Wed,  4 Mar 2026 02:09:33 -0500 (EST)
MIME-Version: 1.0
Reply-To: krbdev@mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu

https://github.com/krb5/krb5/commit/f5bbfa4821cf590a4748f96d0e016bc0485e95c4
commit f5bbfa4821cf590a4748f96d0e016bc0485e95c4
Author: Greg Hudson <ghudson@mit.edu>
Date:   Wed Feb 25 19:05:40 2026 -0500

    Use X509_check_host() to verify KKDCP server cert
    
    In the k5tls module, rely on X509_check_host() and
    X509_check_ip_asc(), which were added in OpenSSL 1.0.2, instead of
    doing our own verification.
    
    There is one notable difference in behavior: X509_check_host() admits
    wildcards with a prefix or suffix (but not both) within the label,
    like "kdc*.mydomain.com".  The old code only allows a wildcard to
    match a complete label.
    
    ticket: 9198 (new)

 src/plugins/tls/k5tls/openssl.c | 211 ++--------------------------------------
 1 file changed, 6 insertions(+), 205 deletions(-)

diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
index aab67c01c..42d72dc9e 100644
--- a/src/plugins/tls/k5tls/openssl.c
+++ b/src/plugins/tls/k5tls/openssl.c
@@ -71,218 +71,19 @@ flush_errors(krb5_context context)
     }
 }
 
-/* Return the passed-in character, lower-cased if it's an ASCII character. */
-static inline char
-ascii_tolower(char p)
-{
-    if (KRB5_UPPER(p))
-        return p + ('a' - 'A');
-    return p;
-}
-
-/*
- * Check a single label.  If allow_wildcard is true, and the presented name
- * includes a wildcard, return true and note that we matched a wildcard.
- * Otherwise, for both the presented and expected values, do a case-insensitive
- * comparison of ASCII characters, and a case-sensitive comparison of
- * everything else.
- */
-static krb5_boolean
-label_match(const char *presented, size_t plen, const char *expected,
-            size_t elen, krb5_boolean allow_wildcard, krb5_boolean *wildcard)
-{
-    unsigned int i;
-
-    if (allow_wildcard && plen == 1 && presented[0] == '*') {
-        *wildcard = TRUE;
-        return TRUE;
-    }
-
-    if (plen != elen)
-        return FALSE;
-
-    for (i = 0; i < elen; i++) {
-        if (ascii_tolower(presented[i]) != ascii_tolower(expected[i]))
-            return FALSE;
-    }
-    return TRUE;
-}
-
-/* Break up the two names and check them, label by label. */
-static krb5_boolean
-domain_match(const char *presented, size_t plen, const char *expected)
-{
-    const char *p, *q, *r, *s;
-    int n_label;
-    krb5_boolean used_wildcard = FALSE;
-
-    n_label = 0;
-    p = presented;
-    r = expected;
-    while (p < presented + plen && *r != '\0') {
-        q = memchr(p, '.', plen - (p - presented));
-        if (q == NULL)
-            q = presented + plen;
-        s = r + strcspn(r, ".");
-        if (!label_match(p, q - p, r, s - r, n_label == 0, &used_wildcard))
-            return FALSE;
-        p = q < presented + plen ? q + 1 : q;
-        r = *s ? s + 1 : s;
-        n_label++;
-    }
-    if (used_wildcard && n_label <= 2)
-        return FALSE;
-    if (p == presented + plen && *r == '\0')
-        return TRUE;
-    return FALSE;
-}
-
-/* Fetch the list of subjectAltNames from a certificate. */
-static GENERAL_NAMES *
-get_cert_sans(X509 *x)
-{
-    int ext;
-    X509_EXTENSION *san_ext;
-
-    ext = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
-    if (ext < 0)
-        return NULL;
-    san_ext = X509_get_ext(x, ext);
-    if (san_ext == NULL)
-        return NULL;
-    return X509V3_EXT_d2i(san_ext);
-}
-
-/* Fetch a CN value from the subjct name field, returning its length, or -1 if
- * there is no subject name or it contains no CN value. */
-static int
-get_cert_cn(X509 *x, char *buf, size_t bufsize)
-{
-    X509_NAME *name;
-
-    name = X509_get_subject_name(x);
-    if (name == NULL)
-        return -1;
-    return X509_NAME_get_text_by_NID(name, NID_commonName, buf, bufsize);
-}
-
-/* Return true if text matches any of the addresses we can recover from x. */
-static krb5_boolean
-check_cert_address(X509 *x, const char *text)
-{
-    char buf[1024];
-    GENERAL_NAMES *sans;
-    GENERAL_NAME *san = NULL;
-    ASN1_OCTET_STRING *ip;
-    krb5_boolean found_ip_san = FALSE, matched = FALSE;
-    int n_sans, i;
-    int name_length;
-    struct in_addr sin;
-    struct in6_addr sin6;
-
-    /* Parse the IP address into an octet string. */
-    ip = ASN1_OCTET_STRING_new();
-    if (ip == NULL)
-        return FALSE;
-    if (inet_pton(AF_INET, text, &sin)) {
-        ASN1_OCTET_STRING_set(ip, (unsigned char *)&sin, sizeof(sin));
-    } else if (inet_pton(AF_INET6, text, &sin6)) {
-        ASN1_OCTET_STRING_set(ip, (unsigned char *)&sin6, sizeof(sin6));
-    } else {
-        ASN1_OCTET_STRING_free(ip);
-        return FALSE;
-    }
-
-    /* Check for matches in ipaddress subjectAltName values. */
-    sans = get_cert_sans(x);
-    if (sans != NULL) {
-        n_sans = sk_GENERAL_NAME_num(sans);
-        for (i = 0; i < n_sans; i++) {
-            san = sk_GENERAL_NAME_value(sans, i);
-            if (san->type != GEN_IPADD)
-                continue;
-            found_ip_san = TRUE;
-            matched = (ASN1_OCTET_STRING_cmp(ip, san->d.iPAddress) == 0);
-            if (matched)
-                break;
-        }
-        sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free);
-    }
-    ASN1_OCTET_STRING_free(ip);
-
-    if (found_ip_san)
-        return matched;
-
-    /* Check for a match against the CN value in the peer's subject name. */
-    name_length = get_cert_cn(x, buf, sizeof(buf));
-    if (name_length >= 0) {
-        /* Do a string compare to check if it's an acceptable value. */
-        return strlen(text) == (size_t)name_length &&
-               strncmp(text, buf, name_length) == 0;
-    }
-
-    /* We didn't find a match. */
-    return FALSE;
-}
-
-/* Return true if expected matches any of the names we can recover from x. */
-static krb5_boolean
-check_cert_servername(X509 *x, const char *expected)
-{
-    char buf[1024];
-    GENERAL_NAMES *sans;
-    GENERAL_NAME *san = NULL;
-    unsigned char *dnsname;
-    krb5_boolean found_dns_san = FALSE, matched = FALSE;
-    int name_length, n_sans, i;
-
-    /* Check for matches in dnsname subjectAltName values. */
-    sans = get_cert_sans(x);
-    if (sans != NULL) {
-        n_sans = sk_GENERAL_NAME_num(sans);
-        for (i = 0; i < n_sans; i++) {
-            san = sk_GENERAL_NAME_value(sans, i);
-            if (san->type != GEN_DNS)
-                continue;
-            found_dns_san = TRUE;
-            dnsname = NULL;
-            name_length = ASN1_STRING_to_UTF8(&dnsname, san->d.dNSName);
-            if (dnsname == NULL)
-                continue;
-            matched = domain_match((char *)dnsname, name_length, expected);
-            OPENSSL_free(dnsname);
-            if (matched)
-                break;
-        }
-        sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free);
-    }
-
-    if (matched)
-        return TRUE;
-    if (found_dns_san)
-        return matched;
-
-    /* Check for a match against the CN value in the peer's subject name. */
-    name_length = get_cert_cn(x, buf, sizeof(buf));
-    if (name_length >= 0)
-        return domain_match(buf, name_length, expected);
-
-    /* We didn't find a match. */
-    return FALSE;
-}
-
 static krb5_boolean
 check_cert_name_or_ip(X509 *x, const char *expected_name)
 {
     struct in_addr in;
     struct in6_addr in6;
+    int r;
 
     if (inet_pton(AF_INET, expected_name, &in) != 0 ||
-        inet_pton(AF_INET6, expected_name, &in6) != 0) {
-        return check_cert_address(x, expected_name);
-    } else {
-        return check_cert_servername(x, expected_name);
-    }
+        inet_pton(AF_INET6, expected_name, &in6) != 0)
+        r = X509_check_ip_asc(x, expected_name, 0);
+    else
+        r = X509_check_host(x, expected_name, 0, 0, NULL);
+    return r == 1;
 }
 
 static int
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5

home help back first fref pref prev next nref lref last post