]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
hostcheck: reduce strlen calls on chained certificates
authorHenrik Holst <henrik.holst@millistream.com>
Thu, 10 Feb 2022 20:04:52 +0000 (21:04 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 13 Feb 2022 10:42:47 +0000 (11:42 +0100)
Closes #8428

lib/vtls/hostcheck.c
lib/vtls/hostcheck.h
lib/vtls/openssl.c
lib/vtls/schannel_verify.c
lib/vtls/x509asn1.c
tests/unit/unit1397.c

index 08a347038379eb4d1d18e2868ac1bdb92805de4e..8dc97a27d04c08061d021b90a64812176278755b 100644 (file)
@@ -72,14 +72,15 @@ static bool pmatch(const char *hostname, size_t hostlen,
  * Return TRUE on a match. FALSE if not.
  */
 
-static bool hostmatch(const char *hostname, const char *pattern,
+static bool hostmatch(const char *hostname,
+                      size_t hostlen,
+                      const char *pattern,
                       size_t patternlen)
 {
   const char *pattern_label_end, *wildcard, *hostname_label_end;
   size_t prefixlen, suffixlen;
 
   /* normalize pattern and hostname by stripping off trailing dots */
-  size_t hostlen = strlen(hostname);
   DEBUGASSERT(patternlen);
   if(hostname[hostlen-1]=='.')
     hostlen--;
@@ -129,10 +130,10 @@ static bool hostmatch(const char *hostname, const char *pattern,
  * Curl_cert_hostcheck() returns TRUE if a match and FALSE if not.
  */
 bool Curl_cert_hostcheck(const char *match, size_t matchlen,
-                         const char *hostname)
+                         const char *hostname, size_t hostlen)
 {
   if(match && *match && hostname && *hostname)
-    return hostmatch(hostname, match, matchlen);
+    return hostmatch(hostname, hostlen, match, matchlen);
   return FALSE;
 }
 
index c8d0507ddc04a4e610bb422b48f61ca67fd20b9c..aa966403dd76317121a76ef7516f00488c51d22c 100644 (file)
@@ -26,6 +26,6 @@
 
 /* returns TRUE if there's a match */
 bool Curl_cert_hostcheck(const char *match_pattern, size_t matchlen,
-                         const char *hostname);
+                         const char *hostname, size_t hostlen);
 
 #endif /* HEADER_CURL_HOSTCHECK_H */
index a0a6730c1250e2d9538ff69f7a3b3b660298e12f..fe9a6860d95007b1cbac8968627093bae27707ef 100644 (file)
@@ -1615,13 +1615,14 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
                                const char *match_pattern,
                                size_t matchlen,
                                const char *hostname,
+                               size_t hostlen,
                                const char *dispname)
 {
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   (void)dispname;
   (void)data;
 #endif
-  if(Curl_cert_hostcheck(match_pattern, matchlen, hostname)) {
+  if(Curl_cert_hostcheck(match_pattern, matchlen, hostname, hostlen)) {
     infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"",
                   dispname, match_pattern);
     return TRUE;
@@ -1668,6 +1669,7 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
   bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
   const char * const hostname = SSL_HOST_NAME();
   const char * const dispname = SSL_HOST_DISPNAME();
+  size_t hostlen = strlen(hostname);
 
 #ifdef ENABLE_IPV6
   if(conn->bits.ipv6_ip &&
@@ -1730,7 +1732,9 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
           if((altlen == strlen(altptr)) &&
              /* if this isn't true, there was an embedded zero in the name
                 string and we cannot match it. */
-             subj_alt_hostcheck(data, altptr, altlen, hostname, dispname)) {
+             subj_alt_hostcheck(data,
+                                altptr,
+                                altlen, hostname, hostlen, dispname)) {
             dnsmatched = TRUE;
           }
           break;
@@ -1822,7 +1826,8 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
             "SSL: unable to obtain common name from peer certificate");
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
-    else if(!Curl_cert_hostcheck((const char *)peer_CN, peerlen, hostname)) {
+    else if(!Curl_cert_hostcheck((const char *)peer_CN,
+                                 peerlen, hostname, hostlen)) {
       failf(data, "SSL: certificate subject name '%s' does not match "
             "target host name '%s'", peer_CN, dispname);
       result = CURLE_PEER_FAILED_VERIFICATION;
index d2d3bf9233b8b9da10af7b8e92c1c89bb360ef85..01de3fc7328b01fbfc907b15e9f3b44e462f0f8f 100644 (file)
@@ -465,6 +465,7 @@ static CURLcode verify_host(struct Curl_easy *data,
   CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
   TCHAR *cert_hostname_buff = NULL;
   size_t cert_hostname_buff_index = 0;
+  size_t hostlen = strlen(conn_hostname);
   DWORD len = 0;
   DWORD actual_len = 0;
 
@@ -521,7 +522,7 @@ static CURLcode verify_host(struct Curl_easy *data,
     }
     else {
       if(Curl_cert_hostcheck(cert_hostname, strlen(cert_hostname),
-                             conn_hostname)) {
+                             conn_hostname, hostlen)) {
         infof(data,
               "schannel: connection hostname (%s) validated "
               "against certificate name (%s)",
index 13fa694f2a961160a7efdc724fcdcd729353b7f3..f64acb83c924750623da786338bed98abe1e8e8e 100644 (file)
@@ -1275,6 +1275,7 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
   ssize_t len;
   const char * const hostname = SSL_HOST_NAME();
   const char * const dispname = SSL_HOST_DISPNAME();
+  size_t hostlen = strlen(hostname);
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -1330,7 +1331,8 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
           len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
                             name.beg, name.end);
           if(len > 0 && (size_t)len == strlen(dnsname))
-            matched = Curl_cert_hostcheck(dnsname, (size_t)len, hostname);
+            matched = Curl_cert_hostcheck(dnsname,
+                                          (size_t)len, hostname, hostlen);
           else
             matched = 0;
           free(dnsname);
@@ -1389,7 +1391,8 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
     }
     if(strlen(dnsname) != (size_t) len)         /* Nul byte in string ? */
       failf(data, "SSL: illegal cert name field");
-    else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
+    else if(Curl_cert_hostcheck((const char *) dnsname,
+                                len, hostname, hostlen)) {
       infof(data, "  common name: %s (matched)", dnsname);
       free(dnsname);
       return CURLE_OK;
index 1b47b286a0315aa653d4534e8362c2564d193ec5..71ea4cfac25ea0ffda0b73bfe621228a22a83ef7 100644 (file)
@@ -41,39 +41,48 @@ UNITTEST_START
   /* here you start doing things and checking that the results are good */
 
 fail_unless(Curl_cert_hostcheck(STRCONST("www.example.com"),
-                                "www.example.com"), "good 1");
-fail_unless(Curl_cert_hostcheck(STRCONST("*.example.com"), "www.example.com"),
+                                STRCONST("www.example.com")), "good 1");
+fail_unless(Curl_cert_hostcheck(STRCONST("*.example.com"),
+                                STRCONST("www.example.com")),
             "good 2");
 fail_unless(Curl_cert_hostcheck(STRCONST("xxx*.example.com"),
-                                "xxxwww.example.com"), "good 3");
-fail_unless(Curl_cert_hostcheck(STRCONST("f*.example.com"), "foo.example.com"),
-            "good 4");
-fail_unless(Curl_cert_hostcheck(STRCONST("192.168.0.0"), "192.168.0.0"),
-            "good 5");
+                                STRCONST("xxxwww.example.com")), "good 3");
+fail_unless(Curl_cert_hostcheck(STRCONST("f*.example.com"),
+                                STRCONST("foo.example.com")), "good 4");
+fail_unless(Curl_cert_hostcheck(STRCONST("192.168.0.0"),
+                                STRCONST("192.168.0.0")), "good 5");
 
 fail_if(Curl_cert_hostcheck(STRCONST("xxx.example.com"),
-                            "www.example.com"), "bad 1");
-fail_if(Curl_cert_hostcheck(STRCONST("*"), "www.example.com"), "bad 2");
-fail_if(Curl_cert_hostcheck(STRCONST("*.*.com"), "www.example.com"), "bad 3");
+                            STRCONST("www.example.com")), "bad 1");
+fail_if(Curl_cert_hostcheck(STRCONST("*"),
+                            STRCONST("www.example.com")),"bad 2");
+fail_if(Curl_cert_hostcheck(STRCONST("*.*.com"),
+                            STRCONST("www.example.com")), "bad 3");
 fail_if(Curl_cert_hostcheck(STRCONST("*.example.com"),
-                            "baa.foo.example.com"), "bad 4");
+                            STRCONST("baa.foo.example.com")), "bad 4");
 fail_if(Curl_cert_hostcheck(STRCONST("f*.example.com"),
-                            "baa.example.com"), "bad 5");
-fail_if(Curl_cert_hostcheck(STRCONST("*.com"), "example.com"), "bad 6");
-fail_if(Curl_cert_hostcheck(STRCONST("*fail.com"), "example.com"), "bad 7");
-fail_if(Curl_cert_hostcheck(STRCONST("*.example."), "www.example."), "bad 8");
-fail_if(Curl_cert_hostcheck(STRCONST("*.example."), "www.example"), "bad 9");
-fail_if(Curl_cert_hostcheck(STRCONST(""), "www"), "bad 10");
-fail_if(Curl_cert_hostcheck(STRCONST("*"), "www"), "bad 11");
-fail_if(Curl_cert_hostcheck(STRCONST("*.168.0.0"), "192.168.0.0"), "bad 12");
+                            STRCONST("baa.example.com")), "bad 5");
+fail_if(Curl_cert_hostcheck(STRCONST("*.com"),
+                            STRCONST("example.com")), "bad 6");
+fail_if(Curl_cert_hostcheck(STRCONST("*fail.com"),
+                            STRCONST("example.com")), "bad 7");
+fail_if(Curl_cert_hostcheck(STRCONST("*.example."),
+                            STRCONST("www.example.")), "bad 8");
+fail_if(Curl_cert_hostcheck(STRCONST("*.example."),
+                            STRCONST("www.example")), "bad 9");
+fail_if(Curl_cert_hostcheck(STRCONST(""), STRCONST("www")), "bad 10");
+fail_if(Curl_cert_hostcheck(STRCONST("*"), STRCONST("www")), "bad 11");
+fail_if(Curl_cert_hostcheck(STRCONST("*.168.0.0"),
+                            STRCONST("192.168.0.0")), "bad 12");
 fail_if(Curl_cert_hostcheck(STRCONST("www.example.com"),
-                            "192.168.0.0"), "bad 13");
+                            STRCONST("192.168.0.0")), "bad 13");
 
 #ifdef ENABLE_IPV6
 fail_if(Curl_cert_hostcheck(STRCONST("*::3285:a9ff:fe46:b619"),
-                            "fe80::3285:a9ff:fe46:b619"), "bad 14");
+                            STRCONST("fe80::3285:a9ff:fe46:b619")), "bad 14");
 fail_unless(Curl_cert_hostcheck(STRCONST("fe80::3285:a9ff:fe46:b619"),
-                                "fe80::3285:a9ff:fe46:b619"), "good 6");
+                                STRCONST("fe80::3285:a9ff:fe46:b619")),
+            "good 6");
 #endif
 
 #endif