Ver código fonte

case insensitive hostname validation (fix #2333) (#2337)

* Add Tests for case sensitive hostname verfication

* Modify check_host_name to perform case insensitive comparisons during ssl hostname validation

---------

Co-authored-by: Tabor, Chris <chris.tabor@commscope.com>
ctabor-itracs 1 semana atrás
pai
commit
fbec2a3466
2 arquivos alterados com 45 adições e 4 exclusões
  1. 20 4
      httplib.h
  2. 25 0
      test/test.cc

+ 20 - 4
httplib.h

@@ -13342,7 +13342,11 @@ inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const {
 
 inline bool SSLClient::check_host_name(const char *pattern,
                                        size_t pattern_len) const {
-  if (host_.size() == pattern_len && host_ == pattern) { return true; }
+  // Exact match (case-insensitive)
+  if (host_.size() == pattern_len &&
+      detail::case_ignore::equal(host_, std::string(pattern, pattern_len))) {
+    return true;
+  }
 
   // Wildcard match
   // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484
@@ -13357,9 +13361,21 @@ inline bool SSLClient::check_host_name(const char *pattern,
   auto itr = pattern_components.begin();
   for (const auto &h : host_components_) {
     auto &p = *itr;
-    if (p != h && p != "*") {
-      auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' &&
-                            !p.compare(0, p.size() - 1, h));
+    if (!httplib::detail::case_ignore::equal(p, h) && p != "*") {
+      bool partial_match = false;
+      if (!p.empty() && p[p.size() - 1] == '*') {
+        const auto prefix_length = p.size() - 1;
+        if (prefix_length == 0) {
+          partial_match = true;
+        } else if (h.size() >= prefix_length) {
+          partial_match =
+              std::equal(p.begin(), p.begin() + prefix_length, h.begin(),
+                         [](const char ca, const char cb) {
+                           return httplib::detail::case_ignore::to_lower(ca) ==
+                                  httplib::detail::case_ignore::to_lower(cb);
+                         });
+        }
+      }
       if (!partial_match) { return false; }
     }
     ++itr;

+ 25 - 0
test/test.cc

@@ -8717,6 +8717,31 @@ TEST(SSLClientTest, WildcardHostNameMatch_Online) {
   ASSERT_EQ(StatusCode::OK_200, res->status);
 }
 
+TEST(SSLClientTest, WildcardHostNameMatchCase_Online) {
+  SSLClient cli("wWw.YouTube.Com");
+
+  cli.set_ca_cert_path(CA_CERT_FILE);
+  cli.enable_server_certificate_verification(true);
+  cli.enable_server_hostname_verification(true);
+  cli.set_follow_location(true);
+
+  auto res = cli.Get("/");
+  ASSERT_TRUE(res);
+  ASSERT_EQ(StatusCode::OK_200, res->status);
+}
+
+TEST(SSLClientTest, HostNameMatchCase_Online) {
+  SSLClient cli("gOoGlE.COm");
+
+  cli.enable_server_certificate_verification(true);
+  cli.enable_server_hostname_verification(true);
+  cli.set_follow_location(true);
+
+  auto res = cli.Get("/");
+  ASSERT_TRUE(res);
+  ASSERT_EQ(StatusCode::OK_200, res->status);
+}
+
 TEST(SSLClientTest, Issue2004_Online) {
   Client client("https://google.com");
   client.set_follow_location(true);