From f95cb4e9bf68b05ac9cd0d5ff4ac39cb88611f82 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 4 Nov 2025 17:01:14 +0100 Subject: [PATCH] Improve domain and IP address matching in certificate verification - Distinguish between domain and IP address checks. - Update curl action to test with httpd server --- .github/workflows/curl.yml | 6 +++--- src/internal.c | 31 +++++++++++++++++++------------ src/x509.c | 2 +- wolfssl/internal.h | 5 +++-- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.github/workflows/curl.yml b/.github/workflows/curl.yml index 19d3dcd49..90aaa7c2d 100644 --- a/.github/workflows/curl.yml +++ b/.github/workflows/curl.yml @@ -52,7 +52,7 @@ jobs: - name: Install test dependencies run: | sudo apt-get update - sudo apt-get install nghttp2 libpsl5 libpsl-dev python3-impacket + sudo apt-get install nghttp2 libpsl5 libpsl-dev python3-impacket apache2 apache2-dev - name: Download lib uses: actions/download-artifact@v4 @@ -68,9 +68,9 @@ jobs: repository: curl/curl path: curl ref: ${{ matrix.curl_ref }} - configure: --with-wolfssl=$GITHUB_WORKSPACE/build-dir + configure: --with-wolfssl=$GITHUB_WORKSPACE/build-dir --with-test-httpd=yes check: false - name: Test curl working-directory: curl - run: make -j $(nproc) test-ci + run: make -j $(nproc) test-nonflaky diff --git a/src/internal.c b/src/internal.c index 2b32acd70..88caf2d73 100644 --- a/src/internal.c +++ b/src/internal.c @@ -13103,12 +13103,14 @@ int MatchDomainName(const char* pattern, int patternLen, const char* str, * domain Domain name to compare against. * domainLen Length of the domain name. * checkCN Whether to check the common name. + * flags Matching flags. + * isIP Whether the domain is an IP address. * returns 1 : match was found. * 0 : no match found. * -1 : No matches and wild pattern match failed. */ int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, - int* checkCN, unsigned int flags) + int* checkCN, unsigned int flags, byte isIP) { int match = 0; DNS_entry* altName = NULL; @@ -13117,14 +13119,13 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, WOLFSSL_MSG("Checking AltNames"); - if (dCert) + if (dCert != NULL) altName = dCert->altNames; - if (checkCN != NULL) { + if (checkCN != NULL) *checkCN = (altName == NULL) ? 1 : 0; - } - while (altName) { + for (; altName != NULL; altName = altName->next) { WOLFSSL_MSG("\tindividual AltName check"); #ifdef WOLFSSL_IP_ALT_NAME @@ -13139,6 +13140,12 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, len = (word32)altName->len; } + if ((isIP && (altName->type != ASN_IP_TYPE)) || + (!isIP && (altName->type == ASN_IP_TYPE))) { + WOLFSSL_MSG("\tAltName type mismatch, continue"); + continue; + } + if (MatchDomainName(buf, (int)len, domain, domainLen, flags)) { match = 1; if (checkCN != NULL) { @@ -13152,8 +13159,6 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, match = -1; WOLFSSL_MSG("\twildcard match failed"); } - - altName = altName->next; } return match; @@ -13166,16 +13171,18 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, * dcert Decoded certificate. * domainName The domain name. * domainNameLen The length of the domain name. + * flags Matching flags. + * isIP Whether the domain name is an IP address. * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success. */ int CheckHostName(DecodedCert* dCert, const char *domainName, - size_t domainNameLen, unsigned int flags) + size_t domainNameLen, unsigned int flags, byte isIP) { int checkCN; int ret = WC_NO_ERR_TRACE(DOMAIN_NAME_MISMATCH); if (CheckForAltNames(dCert, domainName, (word32)domainNameLen, - &checkCN, flags) != 1) { + &checkCN, flags, isIP) != 1) { ret = DOMAIN_NAME_MISMATCH; WOLFSSL_MSG("DomainName match on alt names failed"); } @@ -13203,7 +13210,7 @@ int CheckIPAddr(DecodedCert* dCert, const char* ipasc) { WOLFSSL_MSG("Checking IPAddr"); - return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc), 0); + return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc), 0, 1); } @@ -14413,7 +14420,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int cert_err, /* If altNames names is present, then subject common name is ignored */ if (args->dCert->altNames != NULL) { if (CheckForAltNames(args->dCert, ssl->param->hostName, - (word32)XSTRLEN(ssl->param->hostName), NULL, 0) != 1) { + (word32)XSTRLEN(ssl->param->hostName), NULL, 0, 0) != 1) { if (cert_err == 0) { ret = DOMAIN_NAME_MISMATCH; WOLFSSL_ERROR_VERBOSE(ret); @@ -16452,7 +16459,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, (ssl->buffers.domainName.buffer == NULL ? 0 : (word32)XSTRLEN( (const char *)ssl->buffers.domainName.buffer)), - NULL, 0) != 1) { + NULL, 0, 0) != 1) { WOLFSSL_MSG("DomainName match on alt names failed"); /* try to get peer key still */ ret = DOMAIN_NAME_MISMATCH; diff --git a/src/x509.c b/src/x509.c index 575efc82f..ea9f9b743 100644 --- a/src/x509.c +++ b/src/x509.c @@ -14190,7 +14190,7 @@ int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, size_t chklen, chklen--; } - ret = CheckHostName(dCert, (char *)chk, chklen, flags); + ret = CheckHostName(dCert, (char *)chk, chklen, flags, 0); out: diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 58bc42c48..d1edbf21e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2210,7 +2210,7 @@ WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, #if !defined(NO_CERTS) && !defined(NO_ASN) WOLFSSL_LOCAL int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, int* checkCN, - unsigned int flags); + unsigned int flags, byte isIP); WOLFSSL_LOCAL int CheckIPAddr(DecodedCert* dCert, const char* ipasc); WOLFSSL_LOCAL void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType); #endif @@ -6388,7 +6388,8 @@ WOLFSSL_TEST_VIS void wolfSSL_ResourceFree(WOLFSSL* ssl); /* Micrium uses */ #ifndef NO_ASN WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, const char *domainName, - size_t domainNameLen, unsigned int flags); + size_t domainNameLen, unsigned int flags, + byte isIP); #endif #endif