From f4d0954c5a2fff49de81153a2390fd1a34d84e1c Mon Sep 17 00:00:00 2001
From: "Tobias S. Josefowitz" <tobij@tobij.de>
Date: Tue, 21 Jan 2020 00:09:15 +0100
Subject: [PATCH] SSL: Only accept wildcards for one level

* in CN / SubjectAlternativeName:dNS is supposed to only match one level
of the hostname, i.e. *.example.com matches foo.example.com but not
www.foo.example.com.
---
 CHANGES                              |  6 ++++++
 lib/modules/SSL.pmod/Connection.pike | 21 +++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/CHANGES b/CHANGES
index a9c779b834..d54b5ae1a0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -170,6 +170,12 @@ o Sql.pgsql
   - Fix the only known deadlock-cause logged in the last year; only happened
     (rarely) on multiple parallel queries on a single connection.
 
+o SSL
+
+  When verifying the hostname against the certificate, only accept *
+  (wildcard) for one level, i.e. *.example.com matches foo.example.com,
+  but not www.foo.example.com. Previously, all levels were matched.
+
 o SSL.File
 
   Do not close automatically on write error.
diff --git a/lib/modules/SSL.pmod/Connection.pike b/lib/modules/SSL.pmod/Connection.pike
index 5a4986ff55..ef9c9a9643 100644
--- a/lib/modules/SSL.pmod/Connection.pike
+++ b/lib/modules/SSL.pmod/Connection.pike
@@ -279,8 +279,25 @@ int verify_certificate_chain(array(string) certs)
     if (cert->ext_subjectAltName_dNSName) {
       globs += cert->ext_subjectAltName_dNSName;
     }
-    result->verified = glob(map(globs, lower_case),
-			    lower_case(session->server_name));
+
+    array(string) split_server_name = lower_case(session->server_name) / ".";
+
+    result->verified = 0;
+
+OUTER: foreach (map(globs, lower_case);; string the_glob) {
+      array(string) split_glob = the_glob / ".";
+
+      if (sizeof(split_glob) != sizeof(split_server_name))
+        continue;
+
+      foreach (split_glob; int i; string the_glob) {
+        if (!glob(the_glob, split_server_name[i]))
+          continue OUTER;
+      }
+
+      result->verified = 1;
+      break;
+    }
   }
 
   return [int(0..1)](result->verified);
-- 
GitLab