This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 34c122a  Generalize the wild-card fqdn's for user_agent attributes in 
ssl_server_name
34c122a is described below

commit 34c122a04211b4cff2d2d52df417128a1ce173bd
Author: Susan Hinrichs <[email protected]>
AuthorDate: Fri Nov 16 22:52:27 2018 +0000

    Generalize the wild-card fqdn's for user_agent attributes in ssl_server_name
---
 iocore/net/Makefile.am                             |   3 +-
 iocore/net/P_SNIActionPerformer.h                  |  37 +++--
 iocore/net/P_SSLConfig.h                           |   1 -
 iocore/net/P_SSLNetVConnection.h                   |  43 +++++-
 iocore/net/P_SSLSNI.h                              |  63 ++++++--
 iocore/net/P_SSLUtils.h                            |  45 ------
 iocore/net/SSLConfig.cc                            |   4 -
 iocore/net/SSLNetVConnection.cc                    |  21 +--
 iocore/net/SSLSNIConfig.cc                         | 127 +++++-----------
 iocore/net/SSLUtils.cc                             |  28 +++-
 iocore/net/YamlSNIConfig.h                         |   2 +-
 mgmt/RecordsConfig.cc                              |   2 -
 proxy/http/HttpSM.cc                               |  30 ++--
 tests/gold_tests/h2/h2disable.test.py              |  22 +--
 tests/gold_tests/tls/ssl/signed-bob-bar.pem        |  18 +++
 tests/gold_tests/tls/ssl/signed-bob-foo.pem        |  18 +++
 tests/gold_tests/tls/tls_client_cert2.test.py      | 169 +++++++++++++++++++++
 tests/gold_tests/tls/tls_client_verify.test.py     |  80 +++++++++-
 tests/gold_tests/tls/tls_client_verify2.test.py    |  77 +++++++++-
 tests/gold_tests/tls/tls_tunnel.test.py            |  31 +++-
 tests/gold_tests/tls/tls_verify.test.py            |  20 +--
 .../{tls_verify.test.py => tls_verify3.test.py}    |  68 +++++----
 22 files changed, 637 insertions(+), 272 deletions(-)

diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am
index 4248b38..e9efb3c 100644
--- a/iocore/net/Makefile.am
+++ b/iocore/net/Makefile.am
@@ -76,7 +76,7 @@ test_UDPNet_LDADD = \
        $(top_builddir)/src/tscore/libtscore.la 
$(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/proxy/ParentSelectionStrategy.o \
        $(top_builddir)/lib/tsconfig/libtsconfig.la \
-       @HWLOC_LIBS@ @OPENSSL_LIBS@ @YAMLCPP_LIBS@
+       @HWLOC_LIBS@ @OPENSSL_LIBS@ @LIBPCRE@ @YAMLCPP_LIBS@
 
 test_UDPNet_SOURCES = \
        test_I_UDPNet.cc
@@ -131,7 +131,6 @@ libinknet_a_SOURCES = \
        P_UnixPollDescriptor.h \
        P_UnixUDPConnection.h \
        Socks.cc \
-       SNIActionPerformer.cc \
        SSLCertLookup.cc \
        SSLSessionCache.cc \
        SSLConfig.cc \
diff --git a/iocore/net/P_SNIActionPerformer.h 
b/iocore/net/P_SNIActionPerformer.h
index 739abbb..8622ff2 100644
--- a/iocore/net/P_SNIActionPerformer.h
+++ b/iocore/net/P_SNIActionPerformer.h
@@ -51,7 +51,7 @@ enum PropertyActions { TS_VERIFY_SERVER = 200, TS_CLIENT_CERT 
};
 class ActionItem
 {
 public:
-  virtual int SNIAction(Continuation *cont) = 0;
+  virtual int SNIAction(Continuation *cont) const = 0;
   virtual ~ActionItem(){};
 };
 
@@ -62,9 +62,9 @@ public:
   ~DisableH2() override {}
 
   int
-  SNIAction(Continuation *cont) override
+  SNIAction(Continuation *cont) const override
   {
-    auto ssl_vc     = reinterpret_cast<SSLNetVConnection *>(cont);
+    auto ssl_vc     = dynamic_cast<SSLNetVConnection *>(cont);
     auto accept_obj = ssl_vc ? ssl_vc->accept_object : nullptr;
     if (accept_obj && accept_obj->snpa && ssl_vc) {
       if (auto it = snpsMap.find(accept_obj->id); it != snpsMap.end()) {
@@ -75,6 +75,25 @@ public:
   }
 };
 
+class TunnelDestination : public ActionItem
+{
+public:
+  TunnelDestination(const std::string_view &dest) : destination(dest) {}
+  ~TunnelDestination() {}
+
+  int
+  SNIAction(Continuation *cont) const override
+  {
+    // Set the netvc option?
+    SSLNetVConnection *ssl_netvc = dynamic_cast<SSLNetVConnection *>(cont);
+    if (ssl_netvc) {
+      ssl_netvc->set_tunnel_destination(destination);
+    }
+    return SSL_TLSEXT_ERR_OK;
+  }
+  std::string destination;
+};
+
 class VerifyClient : public ActionItem
 {
   uint8_t mode;
@@ -84,9 +103,9 @@ public:
   VerifyClient(uint8_t param) : mode(param) {}
   ~VerifyClient() override {}
   int
-  SNIAction(Continuation *cont) override
+  SNIAction(Continuation *cont) const override
   {
-    auto ssl_vc = reinterpret_cast<SSLNetVConnection *>(cont);
+    auto ssl_vc = dynamic_cast<SSLNetVConnection *>(cont);
     Debug("ssl_sni", "action verify param %d", this->mode);
     setClientCertLevel(ssl_vc->ssl, this->mode);
     return SSL_TLSEXT_ERR_OK;
@@ -98,7 +117,7 @@ class SNI_IpAllow : public ActionItem
   IpMap ip_map;
 
 public:
-  SNI_IpAllow(std::string const &ip_allow_list, const char *servername)
+  SNI_IpAllow(std::string &ip_allow_list, const std::string &servername)
   {
     // the server identified by item.fqdn requires ATS to do IP filtering
     if (ip_allow_list.length()) {
@@ -113,7 +132,7 @@ public:
           Debug("ssl_sni", "%.*s is not a valid format", 
static_cast<int>(list.size()), list.data());
           break;
         } else {
-          Debug("ssl_sni", "%.*s added to the ip_allow list %s", 
static_cast<int>(list.size()), list.data(), servername);
+          Debug("ssl_sni", "%.*s added to the ip_allow list %s", 
static_cast<int>(list.size()), list.data(), servername.c_str());
           ip_map.fill(IpEndpoint().assign(addr1), IpEndpoint().assign(addr2), 
reinterpret_cast<void *>(1));
         }
       }
@@ -121,14 +140,14 @@ public:
   } // end function SNI_IpAllow
 
   int
-  SNIAction(Continuation *cont) override
+  SNIAction(Continuation *cont) const override
   {
     // i.e, ip filtering is not required
     if (ip_map.count() == 0) {
       return SSL_TLSEXT_ERR_OK;
     }
 
-    auto ssl_vc = reinterpret_cast<SSLNetVConnection *>(cont);
+    auto ssl_vc = dynamic_cast<SSLNetVConnection *>(cont);
     auto ip     = ssl_vc->get_remote_endpoint();
 
     // check the allowed ips
diff --git a/iocore/net/P_SSLConfig.h b/iocore/net/P_SSLConfig.h
index b67944b..a691e5b 100644
--- a/iocore/net/P_SSLConfig.h
+++ b/iocore/net/P_SSLConfig.h
@@ -106,7 +106,6 @@ struct SSLConfigParams : public ConfigInfo {
   static size_t session_cache_number_buckets;
   static size_t session_cache_max_bucket_size;
   static bool session_cache_skip_on_lock_contention;
-  static bool sni_map_enable;
 
   // TS-3435 Wiretracing for SSL Connections
   static int ssl_wire_trace_enabled;
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index 72ef4d7..163709a 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -178,12 +178,6 @@ public:
     return transparentPassThrough;
   }
 
-  bool
-  GetSNIMapping()
-  {
-    return SNIMapping;
-  }
-
   void
   setTransparentPassThrough(bool val)
   {
@@ -318,6 +312,40 @@ public:
     return ssl ? SSL_get_cipher_name(ssl) : nullptr;
   }
 
+  bool
+  has_tunnel_destination() const
+  {
+    return tunnel_host != nullptr;
+  }
+
+  const char *
+  get_tunnel_host() const
+  {
+    return tunnel_host;
+  }
+
+  ushort
+  get_tunnel_port() const
+  {
+    return tunnel_port;
+  }
+
+  void
+  set_tunnel_destination(const std::string_view &destination)
+  {
+    auto pos = destination.find(":");
+    if (nullptr != tunnel_host) {
+      ats_free(tunnel_host);
+    }
+    if (pos != std::string::npos) {
+      tunnel_port = std::stoi(destination.substr(pos + 1).data());
+      tunnel_host = ats_strndup(destination.substr(0, pos).data(), pos);
+    } else {
+      tunnel_port = 0;
+      tunnel_host = ats_strndup(destination.data(), destination.length());
+    }
+  }
+
   int populate_protocol(std::string_view *results, int n) const override;
   const char *protocol_contains(std::string_view tag) const override;
 
@@ -378,8 +406,9 @@ private:
   Continuation *npnEndpoint        = nullptr;
   SessionAccept *sessionAcceptPtr  = nullptr;
   bool sslTrace                    = false;
-  bool SNIMapping                  = false;
   int64_t redoWriteSize            = 0;
+  char *tunnel_host                = nullptr;
+  in_port_t tunnel_port            = 0;
 };
 
 typedef int (SSLNetVConnection::*SSLNetVConnHandler)(int, void *);
diff --git a/iocore/net/P_SSLSNI.h b/iocore/net/P_SSLSNI.h
index c6545ab..781c4da 100644
--- a/iocore/net/P_SSLSNI.h
+++ b/iocore/net/P_SSLSNI.h
@@ -42,32 +42,73 @@
 
 // Properties for the next hop server
 struct NextHopProperty {
-  const char *name                               = nullptr;                    
     // name of the server
+  std::string name;                                                            
     // name of the server
   YamlSNIConfig::Policy verifyServerPolicy       = 
YamlSNIConfig::Policy::DISABLED; // whether to verify the next hop
   YamlSNIConfig::Property verifyServerProperties = 
YamlSNIConfig::Property::NONE;   // what to verify on the next hop
   SSL_CTX *ctx                                   = nullptr; // ctx generated 
off the certificate to present to this server
   NextHopProperty();
 };
 
-using actionVector         = std::vector<ActionItem *>;
-using SNIMap               = std::unordered_map<std::string, actionVector *>;
-using NextHopPropertyTable = std::unordered_map<std::string, NextHopProperty 
*>;
+using actionVector = std::vector<std::unique_ptr<ActionItem>>;
+
+struct namedElement {
+public:
+  namedElement() {}
+
+  void
+  setGlobName(std::string name)
+  {
+    std::string::size_type pos = 0;
+    while ((pos = name.find(".", pos)) != std::string::npos) {
+      name.replace(pos, 1, "\\.");
+      pos += 2;
+    }
+    pos = 0;
+    while ((pos = name.find("*", pos)) != std::string::npos) {
+      name.replace(pos, 1, ".{0,}");
+    }
+    Debug("ssl_sni", "Regexed fqdn=%s", name.c_str());
+    setRegexName(name);
+  }
+
+  void
+  setRegexName(const std::string &regexName)
+  {
+    const char *err_ptr;
+    int err_offset = 0;
+    match          = pcre_compile(regexName.c_str(), 0, &err_ptr, &err_offset, 
nullptr);
+  }
+
+  pcre *match = nullptr;
+};
+
+struct actionElement : public namedElement {
+public:
+  actionVector actions;
+};
+
+struct NextHopItem : public namedElement {
+public:
+  NextHopProperty prop;
+};
+
+// typedef HashMap<cchar *, StringHashFns, actionVector *> SNIMap;
+typedef std::vector<actionElement> SNIList;
+// typedef HashMap<cchar *, StringHashFns, NextHopProperty *> 
NextHopPropertyTable;
+typedef std::vector<NextHopItem> NextHopPropertyList;
 
 struct SNIConfigParams : public ConfigInfo {
   char *sni_filename = nullptr;
-  SNIMap sni_action_map;
-  SNIMap wild_sni_action_map;
-  NextHopPropertyTable next_hop_table;
-  NextHopPropertyTable wild_next_hop_table;
+  SNIList sni_action_list;
+  NextHopPropertyList next_hop_list;
   YamlSNIConfig Y_sni;
-  NextHopProperty *getPropertyConfig(const char *servername) const;
+  const NextHopProperty *getPropertyConfig(const std::string &servername) 
const;
   SNIConfigParams();
   ~SNIConfigParams() override;
   void cleanup();
   int Initialize();
   void loadSNIConfig();
-  actionVector *get(const char *servername) const;
-  void printSNImap() const;
+  const actionVector *get(const std::string &servername) const;
 };
 
 struct SNIConfig {
diff --git a/iocore/net/P_SSLUtils.h b/iocore/net/P_SSLUtils.h
index f70072b..3d2b01a 100644
--- a/iocore/net/P_SSLUtils.h
+++ b/iocore/net/P_SSLUtils.h
@@ -242,50 +242,5 @@ private:
   DFA regex;
 };
 
-class TunnelHashMap
-{
-public:
-  struct HostStruct {
-    std::string hostname;
-    int port;
-    HostStruct(const std::string_view &name, int port_) : hostname(name), 
port(port_) {}
-  };
-  using Tunnel_hashMap = std::unordered_map<std::string, HostStruct>;
-  Tunnel_hashMap TunnelhMap;
-
-  void
-  emplace(const std::string &key, const std::string &hostname)
-  {
-    std::string_view addr, port;
-    if (ats_ip_parse(std::string_view(hostname), &addr, &port) == 0) {
-      TunnelhMap.emplace(key, HostStruct(addr, atoi(port.data())));
-    }
-  }
-
-  void
-  emplace(const std::string &key, const std::string &name, int port_)
-  {
-    TunnelhMap.emplace(key, HostStruct(name, port_));
-  }
-
-  Tunnel_hashMap::const_iterator
-  find(const std::string &key) const
-  {
-    return TunnelhMap.find(key);
-  }
-
-  Tunnel_hashMap::const_iterator
-  begin() const
-  {
-    return TunnelhMap.begin();
-  }
-
-  Tunnel_hashMap::const_iterator
-  end() const
-  {
-    return TunnelhMap.end();
-  }
-};
-
 typedef ats_scoped_resource<ssl::detail::SCOPED_X509_TRAITS> scoped_X509;
 typedef ats_scoped_resource<ssl::detail::SCOPED_BIO_TRAITS> scoped_BIO;
diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc
index ba03ba4..9c1a6d9 100644
--- a/iocore/net/SSLConfig.cc
+++ b/iocore/net/SSLConfig.cc
@@ -57,7 +57,6 @@ bool SSLConfigParams::session_cache_skip_on_lock_contention = 
false;
 size_t SSLConfigParams::session_cache_max_bucket_size       = 100;
 init_ssl_ctx_func SSLConfigParams::init_ssl_ctx_cb          = nullptr;
 load_ssl_file_func SSLConfigParams::load_ssl_file_cb        = nullptr;
-bool SSLConfigParams::sni_map_enable                        = false;
 
 // TS-3534 Wiretracing for SSL Connections
 int SSLConfigParams::ssl_wire_trace_enabled       = 0;
@@ -437,9 +436,6 @@ SSLConfigParams::initialize()
 
   REC_ReadConfigStringAlloc(client_groups_list, 
"proxy.config.ssl.client.groups_list");
 
-  // Enable/disable sni mapping
-  REC_ReadConfigInteger(sni_map_enable, "proxy.config.ssl.sni.map.enable");
-
   REC_ReadConfigInt32(ssl_allow_client_renegotiation, 
"proxy.config.ssl.allow_client_renegotiation");
 
   // SSL Wire Trace configurations
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index c16d52d..e222d8e 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -914,6 +914,8 @@ SSLNetVConnection::free(EThread *t)
   }
   con.close();
 
+  ats_free(tunnel_host);
+
   clear();
   SET_CONTINUATION_HANDLER(this, 
(SSLNetVConnHandler)&SSLNetVConnection::startEvent);
   ink_assert(con.fd == NO_FD);
@@ -972,9 +974,7 @@ SSLNetVConnection::sslStartHandShake(int event, int &err)
           this->ssl = nullptr;
           return EVENT_DONE;
         } else {
-          SSLConfig::scoped_config params;
-          this->SNIMapping = params->sni_map_enable;
-          hookOpRequested  = SSL_HOOK_OP_TUNNEL;
+          hookOpRequested = SSL_HOOK_OP_TUNNEL;
         }
       }
 
@@ -1080,7 +1080,7 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err)
   // without data replay.
   // Note we can't arrive here if a hook is active.
 
-  if (SSL_HOOK_OP_TUNNEL == hookOpRequested && !SNIMapping) {
+  if (SSL_HOOK_OP_TUNNEL == hookOpRequested) {
     this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
     SSL_free(this->ssl);
     this->ssl = nullptr;
@@ -1607,8 +1607,6 @@ SSLNetVConnection::sslContextSet(void *ctx)
   return zret;
 }
 
-extern TunnelHashMap TunnelMap; // stores the name of the servers to tunnel to
-
 bool
 SSLNetVConnection::callHooks(TSEvent eventId)
 {
@@ -1712,15 +1710,12 @@ SSLNetVConnection::callHooks(TSEvent eventId)
   bool reenabled = true;
 
   this->serverName = const_cast<char *>(SSL_get_servername(this->ssl, 
TLSEXT_NAMETYPE_host_name));
-  if (this->serverName) {
-    if (auto it = TunnelMap.find(this->serverName); it != TunnelMap.end()) {
-      this->SNIMapping = true;
-      this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
-      return reenabled;
-    }
+  if (this->has_tunnel_destination()) {
+    this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
+    return reenabled;
   }
 
-  if (SSL_HOOK_OP_TUNNEL == hookOpRequested && SNIMapping) {
+  if (SSL_HOOK_OP_TUNNEL == hookOpRequested) {
     this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
     // Don't mark the handshake as complete yet,
     // Will be checking for that flag not being set after
diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc
index ad988c8..ca4f193 100644
--- a/iocore/net/SSLSNIConfig.cc
+++ b/iocore/net/SSLSNIConfig.cc
@@ -35,56 +35,49 @@
 #include "P_SSLConfig.h"
 #include "tscore/ink_memory.h"
 #include "tscpp/util/TextView.h"
+#include <sstream>
+#include <pcre.h>
 
 static ConfigUpdateHandler<SNIConfig> *sniConfigUpdate;
 struct NetAccept;
 std::unordered_map<int, SSLNextProtocolSet *> snpsMap;
-extern TunnelHashMap TunnelMap;
 NextHopProperty::NextHopProperty() {}
 
-NextHopProperty *
-SNIConfigParams::getPropertyConfig(const char *servername) const
+const NextHopProperty *
+SNIConfigParams::getPropertyConfig(const std::string &servername) const
 {
-  if (auto it = next_hop_table.find(servername); it != next_hop_table.end()) {
-    return it->second;
-  }
-  if (auto it = wild_next_hop_table.find(servername); it != 
wild_next_hop_table.end()) {
-    return it->second;
+  const NextHopProperty *nps = nullptr;
+  for (auto &&item : next_hop_list) {
+    if (pcre_exec(item.match, nullptr, servername.c_str(), 
servername.length(), 0, 0, nullptr, 0) >= 0) {
+      // Found a match
+      nps = &item.prop;
+      break;
+    }
   }
-  return nullptr;
+  return nps;
 }
 
 void
 SNIConfigParams::loadSNIConfig()
 {
-  for (const auto &item : Y_sni.items) {
-    actionVector *aiVec = new actionVector();
+  for (auto &item : Y_sni.items) {
+    auto ai = sni_action_list.emplace(sni_action_list.end());
+    ai->setGlobName(item.fqdn);
     Debug("ssl", "name: %s", item.fqdn.data());
-    const char *servername = item.fqdn.data();
-    ats_wildcard_matcher w_Matcher;
-    auto wildcard = w_Matcher.match(servername);
 
     // set SNI based actions to be called in the ssl_servername_only callback
-    auto ai1 = new DisableH2();
-    aiVec->push_back(ai1);
-    auto ai2 = new VerifyClient(item.verify_client_level);
-    aiVec->push_back(ai2);
-    if (wildcard) {
-      ts::TextView domain{servername, strlen(servername)};
-      domain.take_prefix_at('.');
-      if (!domain.empty()) {
-        wild_sni_action_map.emplace(domain, aiVec);
-      }
-    } else {
-      sni_action_map.emplace(servername, aiVec);
+    if (item.disable_h2) {
+      ai->actions.push_back(std::make_unique<DisableH2>());
     }
-
-    if (item.tunnel_destination.length()) {
-      TunnelMap.emplace(item.fqdn, item.tunnel_destination);
+    if (item.verify_client_level != 255) {
+      
ai->actions.push_back(std::make_unique<VerifyClient>(item.verify_client_level));
+    }
+    if (item.tunnel_destination.length() > 0) {
+      
ai->actions.push_back(std::make_unique<TunnelDestination>(item.tunnel_destination));
     }
 
-    auto ai3 = new SNI_IpAllow(item.ip_allow, servername);
-    aiVec->push_back(ai3);
+    ai->actions.push_back(std::make_unique<SNI_IpAllow>(item.ip_allow, 
item.fqdn));
+
     // set the next hop properties
     SSLConfig::scoped_config params;
     auto clientCTX       = params->getClientSSL_CTX();
@@ -93,19 +86,12 @@ SNIConfigParams::loadSNIConfig()
     if (certFile) {
       clientCTX = params->getNewCTX(certFile, keyFile);
     }
-    if (servername) { // a safety check
-      NextHopProperty *nps = new NextHopProperty();
-
-      nps->name                   = ats_strdup(servername);
-      nps->verifyServerPolicy     = item.verify_server_policy;
-      nps->verifyServerProperties = item.verify_server_properties;
-      nps->ctx                    = clientCTX;
-      if (wildcard) {
-        wild_next_hop_table.emplace(nps->name, nps);
-      } else {
-        next_hop_table.emplace(nps->name, nps);
-      }
-    }
+
+    auto nps = next_hop_list.emplace(next_hop_list.end());
+    nps->setGlobName(item.fqdn);
+    nps->prop.verifyServerPolicy     = item.verify_server_policy;
+    nps->prop.verifyServerProperties = item.verify_server_properties;
+    nps->prop.ctx                    = clientCTX;
   } // end for
 }
 
@@ -113,29 +99,15 @@ int SNIConfig::configid = 0;
 /*definition of member functions of SNIConfigParams*/
 SNIConfigParams::SNIConfigParams() {}
 
-actionVector *
-SNIConfigParams::get(const char *servername) const
+const actionVector *
+SNIConfigParams::get(const std::string &servername) const
 {
-  auto action_it = sni_action_map.find(servername);
-  if (action_it != sni_action_map.end()) {
-    for (const auto &it : wild_sni_action_map) {
-      std::string_view sv{servername};
-      std::string_view key_sv{it.first};
-      if (sv.size() >= key_sv.size() && sv.substr(sv.size() - key_sv.size()) 
== key_sv) {
-        auto wild_action_it = wild_sni_action_map.find(key_sv.data());
-        return wild_action_it != wild_sni_action_map.end() ? 
wild_action_it->second : nullptr;
-      }
+  for (auto retval = sni_action_list.begin(); retval != sni_action_list.end(); 
++retval) {
+    if (pcre_exec(retval->match, nullptr, servername.c_str(), 
servername.length(), 0, 0, nullptr, 0) >= 0) {
+      return &retval->actions;
     }
   }
-  return action_it != sni_action_map.end() ? action_it->second : nullptr;
-}
-
-void
-SNIConfigParams::printSNImap() const
-{
-  for (const auto &it : sni_action_map) {
-    Debug("ssl", "Domain name in the map %s: # of registered action items 
%lu", it.first.c_str(), it.second->size());
-  }
+  return nullptr;
 }
 
 int
@@ -166,34 +138,9 @@ SNIConfigParams::Initialize()
   return 0;
 }
 
-void
-SNIConfigParams::cleanup()
-{
-  for (const auto &it : sni_action_map) {
-    auto actionVec = it.second;
-    for (const auto &ai : *actionVec) {
-      delete ai;
-    }
-    delete actionVec;
-  }
-  for (const auto &it : wild_sni_action_map) {
-    auto actionVec = it.second;
-    for (const auto &ai : *actionVec) {
-      delete ai;
-    }
-    delete actionVec;
-  }
-  for (const auto &it : next_hop_table) {
-    delete it.second;
-  }
-  for (const auto &it : wild_next_hop_table) {
-    delete it.second;
-  }
-}
-
 SNIConfigParams::~SNIConfigParams()
 {
-  cleanup();
+  // sni_action_list and next_hop_list should cleanup with the params object
 }
 
 /*definition of member functions of SNIConfig*/
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index 8830d70..335ae53 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -30,6 +30,7 @@
 #include "SSLSessionCache.h"
 #include "InkAPIInternal.h"
 #include "SSLDynlock.h"
+#include "P_SSLSNI.h"
 
 #include <string>
 #include <openssl/err.h>
@@ -45,7 +46,6 @@
 #include <unistd.h>
 #include <termios.h>
 #include <vector>
-#include "P_SNIActionPerformer.h"
 
 #if HAVE_OPENSSL_EVP_H
 #include <openssl/evp.h>
@@ -88,7 +88,6 @@
 #endif
 #endif
 
-TunnelHashMap TunnelMap; // stores the name of the servers to tunnel to
 /*
  * struct ssl_user_config: gather user provided settings from 
ssl_multicert.config in to this single struct
  * ssl_ticket_enabled - session ticket enabled
@@ -446,10 +445,27 @@ ssl_cert_callback(SSL *ssl, void * /*arg*/)
   return retval;
 }
 
+static int
+PerformAction(Continuation *cont, const char *servername)
+{
+  SNIConfig::scoped_config params;
+  const actionVector *actionvec = params->get(servername);
+  if (!actionvec) {
+    Debug("ssl_sni", "%s not available in the map", servername);
+  } else {
+    for (auto &&item : *actionvec) {
+      auto ret = item->SNIAction(cont);
+      if (ret != SSL_TLSEXT_ERR_OK) {
+        return ret;
+      }
+    }
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
 /*
  * Cannot stop this callback. Always reeneabled
  */
-extern SNIActionPerformer sni_action_performer;
 static int
 ssl_servername_only_callback(SSL *ssl, int * /* ad */, void * /*arg*/)
 {
@@ -458,7 +474,7 @@ ssl_servername_only_callback(SSL *ssl, int * /* ad */, void 
* /*arg*/)
   const char *servername   = SSL_get_servername(ssl, 
TLSEXT_NAMETYPE_host_name);
   Debug("ssl", "Requested servername is %s", servername);
   if (servername != nullptr) {
-    ret = sni_action_performer.PerformAction(netvc, servername);
+    ret = PerformAction(netvc, servername);
   }
   if (ret != SSL_TLSEXT_ERR_OK)
     return SSL_TLSEXT_ERR_ALERT_FATAL;
@@ -1579,6 +1595,10 @@ setClientCertLevel(SSL *ssl, uint8_t certLevel)
     server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | 
SSL_VERIFY_CLIENT_ONCE;
   } else if (certLevel == 1) {
     server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+  } else if (certLevel == 0) {
+    server_verify_client = SSL_VERIFY_NONE;
+  } else {
+    ink_release_assert(!"Invalid client verify level");
   }
 
   Debug("ssl", "setting cert level to %d", server_verify_client);
diff --git a/iocore/net/YamlSNIConfig.h b/iocore/net/YamlSNIConfig.h
index 444ae6b..e36fe91 100644
--- a/iocore/net/YamlSNIConfig.h
+++ b/iocore/net/YamlSNIConfig.h
@@ -58,7 +58,7 @@ struct YamlSNIConfig {
   struct Item {
     std::string fqdn;
     bool disable_h2             = false;
-    uint8_t verify_client_level = 0;
+    uint8_t verify_client_level = 255;
     std::string tunnel_destination;
     Policy verify_server_policy       = Policy::DISABLED;
     Property verify_server_properties = Property::NONE;
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index dff7e28..41fd5a1 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1180,8 +1180,6 @@ static const RecordElement RecordsConfig[] =
   ,
   {RECT_CONFIG, "proxy.config.ssl.handshake_timeout_in", RECD_INT, "0", 
RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-65535]", RECA_NULL}
   ,
-  {RECT_CONFIG, "proxy.config.ssl.sni.map.enable", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
-  ,
   {RECT_CONFIG, "proxy.config.ssl.wire_trace_enabled", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-2]", RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.ssl.wire_trace_addr", RECD_STRING, nullptr , 
RECU_DYNAMIC, RR_NULL, RECC_IP, R"([0-255]\.[0-255]\.[0-255]\.[0-255])", 
RECA_NULL}
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 58cf9d5..52d4dde 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -70,7 +70,6 @@
 #define USE_NEW_EMPTY_MIOBUFFER
 
 extern int cache_config_read_while_writer;
-extern TunnelHashMap TunnelMap; // stores the name of the servers to tunnel to
 
 // We have a debugging list that can use to find stuck
 //  state machines
@@ -565,7 +564,7 @@ HttpSM::setup_blind_tunnel_port()
   NetVConnection *netvc     = ua_txn->get_netvc();
   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(netvc);
   int host_len;
-  if (ssl_vc && ssl_vc->GetSNIMapping()) {
+  if (ssl_vc) {
     if (!t_state.hdr_info.client_request.url_get()->host_get(&host_len)) {
       // the URL object has not been created in the start of the transaction. 
Hence, we need to create the URL here
       URL u;
@@ -575,10 +574,11 @@ HttpSM::setup_blind_tunnel_port()
       t_state.hdr_info.client_request.url_create(&u);
       u.scheme_set(URL_SCHEME_TUNNEL, URL_LEN_TUNNEL);
       t_state.hdr_info.client_request.url_set(&u);
-      if (auto it = TunnelMap.find(ssl_vc->serverName); it != TunnelMap.end()) 
{
-        
t_state.hdr_info.client_request.url_get()->host_set(it->second.hostname.c_str(),
 it->second.hostname.size());
-        if (it->second.port > 0) {
-          t_state.hdr_info.client_request.url_get()->port_set(it->second.port);
+      if (ssl_vc->has_tunnel_destination()) {
+        const char *tunnel_host = ssl_vc->get_tunnel_host();
+        t_state.hdr_info.client_request.url_get()->host_set(tunnel_host, 
strlen(tunnel_host));
+        if (ssl_vc->get_tunnel_port() > 0) {
+          
t_state.hdr_info.client_request.url_get()->port_set(ssl_vc->get_tunnel_port());
         } else {
           
t_state.hdr_info.client_request.url_get()->port_set(t_state.state_machine->ua_txn->get_netvc()->get_local_port());
         }
@@ -1384,18 +1384,18 @@ plugins required to work with sni_routing.
       NetVConnection *netvc     = ua_txn->get_netvc();
       SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(netvc);
 
-      if (ssl_vc && ssl_vc->GetSNIMapping()) {
-        if (auto it = TunnelMap.find(ssl_vc->serverName); it != 
TunnelMap.end()) {
-          
t_state.hdr_info.client_request.url_get()->host_set(it->second.hostname.c_str(),
 it->second.hostname.size());
-          if (it->second.port > 0) {
-            
t_state.hdr_info.client_request.url_get()->port_set(it->second.port);
-          } else {
-            
t_state.hdr_info.client_request.url_get()->port_set(t_state.state_machine->ua_txn->get_netvc()->get_local_port());
-          }
+      if (ssl_vc && ssl_vc->has_tunnel_destination()) {
+        const char *tunnel_host = ssl_vc->get_tunnel_host();
+        t_state.hdr_info.client_request.url_get()->host_set(tunnel_host, 
strlen(tunnel_host));
+        ushort tunnel_port = ssl_vc->get_tunnel_port();
+        if (tunnel_port > 0) {
+          t_state.hdr_info.client_request.url_get()->port_set(tunnel_port);
         } else {
-          
t_state.hdr_info.client_request.url_get()->host_set(ssl_vc->serverName, 
strlen(ssl_vc->serverName));
           
t_state.hdr_info.client_request.url_get()->port_set(t_state.state_machine->ua_txn->get_netvc()->get_local_port());
         }
+      } else if (ssl_vc) {
+        
t_state.hdr_info.client_request.url_get()->host_set(ssl_vc->serverName, 
strlen(ssl_vc->serverName));
+        
t_state.hdr_info.client_request.url_get()->port_set(t_state.state_machine->ua_txn->get_netvc()->get_local_port());
       }
     }
   // FALLTHROUGH
diff --git a/tests/gold_tests/h2/h2disable.test.py 
b/tests/gold_tests/h2/h2disable.test.py
index 1e64b92..ebeb688 100644
--- a/tests/gold_tests/h2/h2disable.test.py
+++ b/tests/gold_tests/h2/h2disable.test.py
@@ -63,8 +63,8 @@ ts.Disk.records_config.update({
 ts.Disk.ssl_server_name_yaml.AddLines([
   '- fqdn: bar.com',
   '  disable_h2: true',
-#  '- fqdn: bob.*.com',
-#  '  disable_h2: true',
+  '- fqdn: bob.*.com',
+  '  disable_h2: true',
 ])
 
 tr = Test.AddTestRun("Negotiate-h2")
@@ -89,14 +89,14 @@ tr2.Processes.Default.Streams.All = 
Testers.ExcludesExpression("Could Not Connec
 tr2.Processes.Default.Streams.All += Testers.ExcludesExpression("Using HTTP2", 
"Curl should not negotiate HTTP2")
 tr2.TimeOut = 5
 
-#tr2 = Test.AddTestRun("Do not negotiate h2")
-#tr2.Processes.Default.Command = "curl -v -k --resolve 
'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}".format(ts.Variables.ssl_port)
-#tr2.ReturnCode = 0
-#tr2.StillRunningAfter = server
-#tr2.Processes.Default.TimeOut = 5
-#tr2.StillRunningAfter = ts
-#tr2.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should have succeeded")
-#tr2.Processes.Default.Streams.All += Testers.ExcludesExpression("Using 
HTTP2", "Curl should not negotiate HTTP2")
-#tr2.TimeOut = 5
+tr2 = Test.AddTestRun("Do not negotiate h2")
+tr2.Processes.Default.Command = "curl -v -k --resolve 
'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}".format(ts.Variables.ssl_port)
+tr2.ReturnCode = 0
+tr2.StillRunningAfter = server
+tr2.Processes.Default.TimeOut = 5
+tr2.StillRunningAfter = ts
+tr2.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should have succeeded")
+tr2.Processes.Default.Streams.All += Testers.ExcludesExpression("Using HTTP2", 
"Curl should not negotiate HTTP2")
+tr2.TimeOut = 5
 
 
diff --git a/tests/gold_tests/tls/ssl/signed-bob-bar.pem 
b/tests/gold_tests/tls/ssl/signed-bob-bar.pem
new file mode 100644
index 0000000..cca4c2f
--- /dev/null
+++ b/tests/gold_tests/tls/ssl/signed-bob-bar.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC2jCCAkMCCQC81MtBCwmQuTANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
+aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
+ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
+b20wHhcNMTgxMTIwMTQ1NDEyWhcNMjgxMTE3MTQ1NDEyWjBBMQswCQYDVQQGEwJV
+UzELMAkGA1UECAwCSUwxDzANBgNVBAoMBkFwYWNoZTEUMBIGA1UEAwwLYm9iLmJh
+ci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDuzA6e4MZp98m/
+XuhRAZMCaq9fM5zRBDsY5fpx3zUkJwJtZa4ALk6Adusovfh3t6qYJJ47TItnNG9Z
+nAvYQhOccZNkj8xbPytuj5pQzu3CAR/IsBBWtG8O0SLRHNVOmgu3bdXuJca+3LKR
+X3qFJbReqd9OI9vGxrxKg9NPUeGpzAuUTplmfs8O70g8l0ZBJ7l/0VmsA5lUDZxV
+NjcacVYHc+ApujuLz5drVRKeLxTrtc6DksP7uruT5ZVrWbL35hoviwUilugz9ZDI
+SQl0T6cIus8CyUjs8/iJEln9AnxAZ8Muz5+pQ3G/4BsabKlEHf0+GYinXxiTMT1V
+Cr9botZ/AgMBAAEwDQYJKoZIhvcNAQELBQADgYEAnPW5NsSCI95ETnx9b1ZJv8wo
+EIWqxzD7Wm9CIL8gUmVGrEJpHrsfpuXEN/jKqVFxUr3d2ZI40P8BrO73BGHo2F0M
+ISDxiRSs7tR5xl5WmmErzK8TpDHU9fhkCqlblk7lzPLalIXCQ0y8qDjACBbh3tfj
+0grbVmTy66u6TxI5FTE=
+-----END CERTIFICATE-----
diff --git a/tests/gold_tests/tls/ssl/signed-bob-foo.pem 
b/tests/gold_tests/tls/ssl/signed-bob-foo.pem
new file mode 100644
index 0000000..05db399
--- /dev/null
+++ b/tests/gold_tests/tls/ssl/signed-bob-foo.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC2jCCAkMCCQC81MtBCwmQujANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
+aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
+ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
+b20wHhcNMTgxMTIwMTQ1NTA4WhcNMjgxMTE3MTQ1NTA4WjBBMQswCQYDVQQGEwJV
+UzELMAkGA1UECAwCSUwxDzANBgNVBAoMBkFwYWNoZTEUMBIGA1UEAwwLYm9iLmZv
+by5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJheOsr0o4C0QV
+elo8viYl/IjWvkj4Y6YojnO/E9T5HSfWxkRikRT8X7yqs9ClrjNcYoPNNQP5vgl1
+qAIeixUrbZZklcZ3kHF/MXdzuYV//uT3YfWrsOTdfbcu6adHtBr/Qc0w9GSbBpp4
+2ZALxzjZ2hZZq51XmKvcz55/gm/9YvlGErzvsPzkejdH6U1GKeLqGaZOqkV7N2J4
+zKmJyiPzwrmR/8y7k+9jDHQX+A2wa5gaiAMGdIM8aTV+XsNNAvespvXyX7UhwxDs
+w0er0GLv4ssYCru5hF+tUcjeOCHxSnCoEC45b2zDZHATLLjr7AIJ52TcSo1kTaTi
+rAOAiHRLAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAvrrtNDsSbjVhwOlAm7MFwbxp
+EUh1jYk07C6vxz7dFAcEXh33Sx4LsD0sI2TSbV5swGtPqMVTxbA+Ok6S/2lfxUeT
+h7B6GrWvHtzQdPZbkoTEyehH5fOFLchbwGbecugYLjAK9wtatDZhFnuKRq8aiqml
+GuDJPQLfKB9APLyxIbA=
+-----END CERTIFICATE-----
diff --git a/tests/gold_tests/tls/tls_client_cert2.test.py 
b/tests/gold_tests/tls/tls_client_cert2.test.py
new file mode 100644
index 0000000..0c085fd
--- /dev/null
+++ b/tests/gold_tests/tls/tls_client_cert2.test.py
@@ -0,0 +1,169 @@
+'''
+Test offering client cert to origin
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+import os
+import re
+
+Test.Summary = '''
+Test client certs to origin selected via wildcard names in ssl_server_name
+'''
+
+Test.SkipUnless(Condition.HasProgram("grep", "grep needs to be installed on 
system for this test to work"))
+
+ts = Test.MakeATSProcess("ts", command="traffic_server", select_ports=False)
+cafile = "{0}/signer.pem".format(Test.RunDirectory)
+cafile2 = "{0}/signer2.pem".format(Test.RunDirectory)
+server = Test.MakeOriginServer("server", ssl=True, options = { "--clientCA": 
cafile, "--clientverify": "true"}, 
clientcert="{0}/signed-foo.pem".format(Test.RunDirectory), 
clientkey="{0}/signed-foo.key".format(Test.RunDirectory))
+server2 = Test.MakeOriginServer("server2", ssl=True, options = { "--clientCA": 
cafile2, "--clientverify": "true"}, 
clientcert="{0}/signed2-bar.pem".format(Test.RunDirectory), 
clientkey="{0}/signed-bar.key".format(Test.RunDirectory))
+server.Setup.Copy("ssl/signer.pem")
+server.Setup.Copy("ssl/signer2.pem")
+server.Setup.Copy("ssl/signed-foo.pem")
+server.Setup.Copy("ssl/signed-foo.key")
+server.Setup.Copy("ssl/signed2-foo.pem")
+server.Setup.Copy("ssl/signed2-bar.pem")
+server.Setup.Copy("ssl/signed-bar.key")
+server2.Setup.Copy("ssl/signer.pem")
+server2.Setup.Copy("ssl/signer2.pem")
+server2.Setup.Copy("ssl/signed-foo.pem")
+server2.Setup.Copy("ssl/signed-foo.key")
+server2.Setup.Copy("ssl/signed2-foo.pem")
+server2.Setup.Copy("ssl/signed2-bar.pem")
+server2.Setup.Copy("ssl/signed-bar.key")
+
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n", 
"timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", 
"timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionlog.json", request_header, response_header)
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: bar.com\r\n\r\n", 
"timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", 
"timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionlog.json", request_header, response_header)
+
+ts.addSSLfile("ssl/server.pem")
+ts.addSSLfile("ssl/server.key")
+ts.addSSLfile("ssl/signed-foo.pem")
+ts.addSSLfile("ssl/signed-foo.key")
+ts.addSSLfile("ssl/signed2-foo.pem")
+ts.addSSLfile("ssl/signed-bar.pem")
+ts.addSSLfile("ssl/signed2-bar.pem")
+ts.addSSLfile("ssl/signed-bar.key")
+
+ts.Variables.ssl_port = 4443
+ts.Disk.records_config.update({
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'ssl_verify_test',
+    'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.ssl.server.private_key.path': 
'{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.http.server_ports': '{0}'.format(ts.Variables.port),
+    'proxy.config.ssl.client.verify.server':  0,
+    'proxy.config.ssl.server.cipher_suite': 
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2',
+    'proxy.config.url_remap.pristine_host_hdr' : 1,
+})
+
+ts.Disk.ssl_multicert_config.AddLine(
+    'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
+)
+
+ts.Disk.remap_config.AddLine(
+    'map /case1 https://127.0.0.1:{0}/'.format(server.Variables.Port)
+)
+ts.Disk.remap_config.AddLine(
+    'map /case2 https://127.0.0.1:{0}/'.format(server2.Variables.Port)
+)
+
+ts.Disk.ssl_server_name_yaml.AddLines([
+    '- fqdn: bob.bar.com',
+    '  client_cert: {0}/signed-bar.pem'.format(ts.Variables.SSLDir),
+    '  client_key: {0}/signed-bar.key'.format(ts.Variables.SSLDir),
+    '- fqdn: bob.*.com',
+    '  client_cert: {0}/signed-foo.pem'.format(ts.Variables.SSLDir),
+    '  client_key: {0}/signed-foo.key'.format(ts.Variables.SSLDir),
+    '- fqdn: "*bar.com"',
+    '  client_cert: {0}/signed2-bar.pem'.format(ts.Variables.SSLDir),
+    '  client_key: {0}/signed-bar.key'.format(ts.Variables.SSLDir),
+])
+
+
+# Should succeed
+tr = Test.AddTestRun("bob.bar.com to server 1")
+tr.Processes.Default.StartBefore(Test.Processes.ts, 
ready=When.PortOpen(ts.Variables.port))
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(server2)
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.StillRunningAfter = server2
+tr.Processes.Default.Command = "curl -H host:bob.bar.com  
http://127.0.0.1:{0}/case1".format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Check response")
+tr.TimeOut = 5
+
+#Should fail
+trfail = Test.AddTestRun("bob.bar.com to server 2")
+trfail.StillRunningAfter = ts
+trfail.StillRunningAfter = server
+trfail.StillRunningAfter = server2
+trfail.Processes.Default.Command = 'curl -H host:bob.bar.com  
http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
+trfail.Processes.Default.ReturnCode = 0
+trfail.Processes.Default.TimeOut = 5
+trfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could 
Not Connect", "Check response")
+trfail.TimeOut = 5
+
+# Should succeed
+tr = Test.AddTestRun("bob.foo.com to server 1")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.StillRunningAfter = server2
+tr.Processes.Default.Command = "curl -H host:bob.foo.com  
http://127.0.0.1:{0}/case1".format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Check response")
+tr.TimeOut = 5
+
+#Should fail
+trfail = Test.AddTestRun("bob.foo.com to server 2")
+trfail.StillRunningAfter = ts
+trfail.StillRunningAfter = server
+trfail.StillRunningAfter = server2
+trfail.Processes.Default.Command = 'curl -H host:bob.foo.com  
http://127.0.0.1:{0}/case2'.format(ts.Variables.port)
+trfail.Processes.Default.ReturnCode = 0
+trfail.Processes.Default.TimeOut = 5
+trfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could 
Not Connect", "Check response")
+trfail.TimeOut = 5
+
+# Should succeed
+tr = Test.AddTestRun("random.bar.com to server 2")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.StillRunningAfter = server2
+tr.Processes.Default.Command = "curl -H host:random.bar.com  
http://127.0.0.1:{0}/case2".format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Check response")
+tr.TimeOut = 5
+
+#Should fail
+trfail = Test.AddTestRun("random.bar.com to server 1")
+trfail.StillRunningAfter = ts
+trfail.StillRunningAfter = server
+trfail.StillRunningAfter = server2
+trfail.Processes.Default.Command = 'curl -H host:random.bar.com  
http://127.0.0.1:{0}/case1'.format(ts.Variables.port)
+trfail.Processes.Default.ReturnCode = 0
+trfail.Processes.Default.TimeOut = 5
+trfail.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could 
Not Connect", "Check response")
+trfail.TimeOut = 5
+
diff --git a/tests/gold_tests/tls/tls_client_verify.test.py 
b/tests/gold_tests/tls/tls_client_verify.test.py
index d629853..f0abd7e 100644
--- a/tests/gold_tests/tls/tls_client_verify.test.py
+++ b/tests/gold_tests/tls/tls_client_verify.test.py
@@ -68,8 +68,12 @@ ts.Disk.remap_config.AddLine(
 
 # Scenario 1:  Default no client cert required.  cert required for bar.com
 ts.Disk.ssl_server_name_yaml.AddLines([
-    '- fqdn: bar.com',
+    '- fqdn: bob.bar.com',
     '  verify_client: NONE',
+    '- fqdn: bob.*.com',
+    '  verify_client: NONE',
+    '- fqdn: "*bar.com"',
+    '  verify_client: STRICT',
 ])
 
 # to foo.com w/o client cert.  Should fail
@@ -107,15 +111,77 @@ tr.Processes.Default.TimeOut = 5
 tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
 tr.TimeOut = 5
 
-tr = Test.AddTestRun("Connect to bar.com without cert")
+tr = Test.AddTestRun("Connect to bob.bar.com without cert")
 tr.StillRunningAfter = ts
 tr.StillRunningAfter = server
-tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bar.com:{0}:127.0.0.1' https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("alert", "TLS 
handshake should succeed")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.bar.com with cert")
+tr.Setup.Copy("ssl/signed-bob-bar.pem")
+tr.Setup.Copy("ssl/signed-bar.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert 
signed-bob-bar.pem --key signed-bar.key --resolve 'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.bar.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key 
server.key --resolve 'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.foo.com without cert")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/case1".format(ts.Variables.ssl_port)
 tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.TimeOut = 5
 tr.Processes.Default.Streams.All = Testers.ExcludesExpression("alert", "TLS 
handshake should succeed")
 tr.TimeOut = 5
 
+tr = Test.AddTestRun("Connect to bob.foo.com with cert")
+tr.Setup.Copy("ssl/signed-bob-foo.pem")
+tr.Setup.Copy("ssl/signed-foo.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert 
signed-bob-foo.pem --key signed-foo.key --resolve 'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.foo.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key 
server.key --resolve 'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com without cert")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bar.com:{0}:127.0.0.1' https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 35
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert handshake 
failure", "TLS handshake should fail")
+tr.TimeOut = 5
+
 tr = Test.AddTestRun("Connect to bar.com with cert")
 tr.Setup.Copy("ssl/signed-bar.pem")
 tr.Setup.Copy("ssl/signed-bar.key")
@@ -124,7 +190,7 @@ tr.StillRunningAfter = server
 tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert signed-bar.pem 
--key signed-bar.key --resolve 'bar.com:{0}:127.0.0.1' 
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
 tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.TimeOut = 5
-tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "TLS 
handshake should succeed")
 tr.TimeOut = 5
 
 tr = Test.AddTestRun("Connect to bar.com with bad cert")
@@ -133,9 +199,9 @@ tr.Setup.Copy("ssl/server.key")
 tr.StillRunningAfter = ts
 tr.StillRunningAfter = server
 tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key 
server.key --resolve 'bar.com:{0}:127.0.0.1' 
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
-# Should fail with badly signed certs
-tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.ReturnCode = 35
 tr.Processes.Default.TimeOut = 5
-tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert unknown 
ca", "TLS handshake should fail")
 tr.TimeOut = 5
 
+
diff --git a/tests/gold_tests/tls/tls_client_verify2.test.py 
b/tests/gold_tests/tls/tls_client_verify2.test.py
index 8848dc2..a435e94 100644
--- a/tests/gold_tests/tls/tls_client_verify2.test.py
+++ b/tests/gold_tests/tls/tls_client_verify2.test.py
@@ -68,8 +68,12 @@ ts.Disk.remap_config.AddLine(
 
 # Scenario 1:  Default no client cert required.  cert required for bar.com
 ts.Disk.ssl_server_name_yaml.AddLines([
-    '- fqdn: bar.com',
+    '- fqdn: bob.bar.com',
     '  verify_client: STRICT',
+    '- fqdn: bob.*.com',
+    '  verify_client: STRICT',
+    '- fqdn: "*bar.com"',
+    '  verify_client: NONE',
 ])
 
 # to foo.com w/o client cert.  Should succeed
@@ -95,15 +99,77 @@ tr.Processes.Default.TimeOut = 5
 tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check 
response")
 tr.TimeOut = 5
 
-tr = Test.AddTestRun("Connect to bar.com without cert")
+tr = Test.AddTestRun("Connect to bob.bar.com without cert")
 tr.StillRunningAfter = ts
 tr.StillRunningAfter = server
-tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bar.com:{0}:127.0.0.1' https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 35 
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert", "TLS 
handshake should fail")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.bar.com with cert")
+tr.Setup.Copy("ssl/signed-bob-bar.pem")
+tr.Setup.Copy("ssl/signed-bar.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert 
signed-bob-bar.pem --key signed-bar.key --resolve 'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "TLS 
handshake should succeed")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.bar.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key 
server.key --resolve 'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 35 
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("error", "TLS 
handshake should fail")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.foo.com without cert")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/case1".format(ts.Variables.ssl_port)
 tr.Processes.Default.ReturnCode = 35 
 tr.Processes.Default.TimeOut = 5
 tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert", "TLS 
handshake should fail")
 tr.TimeOut = 5
 
+tr = Test.AddTestRun("Connect to bob.foo.com with cert")
+tr.Setup.Copy("ssl/signed-bob-foo.pem")
+tr.Setup.Copy("ssl/signed-foo.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert 
signed-bob-foo.pem --key signed-foo.key --resolve 'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "TLS 
handshake should succeed")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bob.foo.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key 
server.key --resolve 'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 35 
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("error", "TLS 
handshake should fail")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com without cert")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve 
'bar.com:{0}:127.0.0.1' https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0 
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("alert", "TLS 
handshake should succeed")
+tr.TimeOut = 5
+
 tr = Test.AddTestRun("Connect to bar.com with cert")
 tr.Setup.Copy("ssl/signed-bar.pem")
 tr.Setup.Copy("ssl/signed-bar.key")
@@ -121,9 +187,8 @@ tr.Setup.Copy("ssl/server.key")
 tr.StillRunningAfter = ts
 tr.StillRunningAfter = server
 tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key 
server.key --resolve 'bar.com:{0}:127.0.0.1' 
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
-# Should fail with badly signed certs
-tr.Processes.Default.ReturnCode = 35
+tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.TimeOut = 5
-tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert unknown 
ca", "TLS handshake should fail")
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("alert unknown 
ca", "TLS handshake should succeed")
 tr.TimeOut = 5
 
diff --git a/tests/gold_tests/tls/tls_tunnel.test.py 
b/tests/gold_tests/tls/tls_tunnel.test.py
index 390a11e..e92c4a1 100644
--- a/tests/gold_tests/tls/tls_tunnel.test.py
+++ b/tests/gold_tests/tls/tls_tunnel.test.py
@@ -76,9 +76,12 @@ ts.Disk.records_config.update({
 # bar.com should terminate.  Forward its tcp stream to server_bar
 ts.Disk.ssl_server_name_yaml.AddLines([
   '- fqdn: foo.com',
-  "  tunnel_route: localhost:{0}".format(server_foo.Variables.Port) ])
+  "  tunnel_route: localhost:{0}".format(server_foo.Variables.Port),
+  "- fqdn: bob.*.com",
+  "  tunnel_route: localhost:{0}".format(server_foo.Variables.Port),
+])
 
-tr = Test.AddTestRun("Tunnel-test")
+tr = Test.AddTestRun("foo.com Tunnel-test")
 tr.Processes.Default.Command = "curl -v --resolve 'foo.com:{0}:127.0.0.1' -k  
https://foo.com:{0}".format(ts.Variables.ssl_port)
 tr.ReturnCode = 0
 tr.Processes.Default.StartBefore(server_foo)
@@ -91,5 +94,29 @@ tr.Processes.Default.Streams.All += 
Testers.ExcludesExpression("Could Not Connec
 tr.Processes.Default.Streams.All += Testers.ExcludesExpression("Not Found on 
Accelerato", "Should not try to remap on Traffic Server")
 tr.Processes.Default.Streams.All += Testers.ExcludesExpression("CN=foo.com", 
"Should not TLS terminate on Traffic Server")
 tr.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 200 
OK", "Should get a successful response")
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression("ATS", "Do not 
terminate on Traffic Server")
+
+tr = Test.AddTestRun("bob.bar.com Tunnel-test")
+tr.Processes.Default.Command = "curl -v --resolve 'bob.bar.com:{0}:127.0.0.1' 
-k  https://bob.bar.com:{0}".format(ts.Variables.ssl_port)
+tr.ReturnCode = 0
+tr.StillRunningAfter = ts
+tr.Processes.Default.TimeOut = 5
+tr.TimeOut = 5
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should have succeeded")
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression("Not Found on 
Accelerato", "Should not try to remap on Traffic Server")
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression("CN=foo.com", 
"Should not TLS terminate on Traffic Server")
+tr.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 200 
OK", "Should get a successful response")
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression("ATS", "Do not 
terminate on Traffic Server")
+
+tr = Test.AddTestRun("bar.com no Tunnel-test")
+tr.Processes.Default.Command = "curl -v --resolve 'bar.com:{0}:127.0.0.1' -k  
https://bar.com:{0}".format(ts.Variables.ssl_port)
+tr.ReturnCode = 0
+tr.StillRunningAfter = ts
+tr.Processes.Default.TimeOut = 5
+tr.TimeOut = 5
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should have succeeded")
+tr.Processes.Default.Streams.All += Testers.ContainsExpression("Not Found on 
Accelerato", "Terminates on on Traffic Server")
+tr.Processes.Default.Streams.All += Testers.ContainsExpression("ATS", 
"Terminate on Traffic Server")
+
 
 
diff --git a/tests/gold_tests/tls/tls_verify.test.py 
b/tests/gold_tests/tls/tls_verify.test.py
index d95ec16..81164e8 100644
--- a/tests/gold_tests/tls/tls_verify.test.py
+++ b/tests/gold_tests/tls/tls_verify.test.py
@@ -86,18 +86,14 @@ ts.Disk.records_config.update({
     'proxy.config.url_remap.pristine_host_hdr': 1
 })
 
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '- fqdn: bar.com')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_policy: ENFORCED')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_properties: ALL')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '- fqdn: bad_bar.com')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_policy: ENFORCED')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_properties: ALL')
+ts.Disk.ssl_server_name_yaml.AddLines([
+  '- fqdn: bar.com',
+  '  verify_server_policy: ENFORCED',
+  '  verify_server_properties: ALL',
+  '- fqdn: bad_bar.com',
+  '  verify_server_policy: ENFORCED',
+  '  verify_server_properties: ALL'
+])
 
 tr = Test.AddTestRun("Permissive-Test")
 tr.Setup.Copy("ssl/signed-foo.key")
diff --git a/tests/gold_tests/tls/tls_verify.test.py 
b/tests/gold_tests/tls/tls_verify3.test.py
similarity index 70%
copy from tests/gold_tests/tls/tls_verify.test.py
copy to tests/gold_tests/tls/tls_verify3.test.py
index d95ec16..222222d 100644
--- a/tests/gold_tests/tls/tls_verify.test.py
+++ b/tests/gold_tests/tls/tls_verify3.test.py
@@ -54,15 +54,15 @@ ts.addSSLfile("ssl/signer.key")
 
 ts.Variables.ssl_port = 4443
 ts.Disk.remap_config.AddLine(
-    'map / https://127.0.0.1:{0}'.format(server.Variables.Port))
+    'map https://foo.com:{1}/ 
https://127.0.0.1:{0}'.format(server_foo.Variables.Port, ts.Variables.ssl_port))
 ts.Disk.remap_config.AddLine(
-    'map https://foo.com/ 
https://127.0.0.1:{0}'.format(server_foo.Variables.Port))
+    'map https://bob.foo.com:{1}/ 
https://127.0.0.1:{0}'.format(server_foo.Variables.Port, ts.Variables.ssl_port))
 ts.Disk.remap_config.AddLine(
-    'map https://bad_foo.com/ 
https://127.0.0.1:{0}'.format(server_foo.Variables.Port))
+    'map https://bar.com:{1}/ 
https://127.0.0.1:{0}'.format(server_bar.Variables.Port, ts.Variables.ssl_port))
 ts.Disk.remap_config.AddLine(
-    'map https://bar.com/ 
https://127.0.0.1:{0}'.format(server_bar.Variables.Port))
+    'map https://bob.bar.com:{1}/ 
https://127.0.0.1:{0}'.format(server_bar.Variables.Port,ts.Variables.ssl_port))
 ts.Disk.remap_config.AddLine(
-    'map https://bad_bar.com/ 
https://127.0.0.1:{0}'.format(server_bar.Variables.Port))
+    'map / https://127.0.0.1:{0}'.format(server.Variables.Port))
 
 ts.Disk.ssl_multicert_config.AddLine(
     'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
@@ -71,8 +71,8 @@ ts.Disk.ssl_multicert_config.AddLine(
 # Case 1, global config policy=permissive properties=signature
 #         override for foo.com policy=enforced properties=all
 ts.Disk.records_config.update({
-    'proxy.config.diags.debug.enabled': 0,
-    'proxy.config.diags.debug.tags': 'http|ssl',
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'ssl|http|url',
     'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
     'proxy.config.ssl.server.private_key.path': 
'{0}'.format(ts.Variables.SSLDir),
     # enable ssl port
@@ -80,33 +80,30 @@ ts.Disk.records_config.update({
     'proxy.config.ssl.server.cipher_suite': 
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2',
     # set global policy
     'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE',
-    'proxy.config.ssl.client.verify.server.properties': 'SIGNATURE',
+    'proxy.config.ssl.client.verify.server.properties': 'ALL',
     'proxy.config.ssl.client.CA.cert.path': '{0}'.format(ts.Variables.SSLDir),
     'proxy.config.ssl.client.CA.cert.filename': 'signer.pem',
     'proxy.config.url_remap.pristine_host_hdr': 1
 })
 
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '- fqdn: bar.com')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_policy: ENFORCED')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_properties: ALL')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '- fqdn: bad_bar.com')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_policy: ENFORCED')
-ts.Disk.ssl_server_name_yaml.AddLine(
-  '  verify_server_properties: ALL')
+ts.Disk.ssl_server_name_yaml.AddLines([
+  '- fqdn: bob.bar.com',
+  '  verify_server_policy: ENFORCED',
+  '  verify_server_properties: ALL',
+  '- fqdn: bob.*.com',
+  '  verify_server_policy: ENFORCED',
+  '  verify_server_properties: SIGNATURE',
+  "- fqdn: '*bar.com'",
+  '  verify_server_policy: DISABLED',
+])
 
-tr = Test.AddTestRun("Permissive-Test")
+tr = Test.AddTestRun("foo.com Permissive-Test")
 tr.Setup.Copy("ssl/signed-foo.key")
 tr.Setup.Copy("ssl/signed-foo.pem")
 tr.Setup.Copy("ssl/signed-bar.key")
 tr.Setup.Copy("ssl/signed-bar.pem")
-tr.Processes.Default.Command = "curl -v -k -H \"host: foo.com\" 
https://127.0.0.1:{0}".format(ts.Variables.ssl_port)
+tr.Processes.Default.Command = "curl -v -k --resolve 'foo.com:{0}:127.0.0.1' 
https://foo.com:{0}".format(ts.Variables.ssl_port)
 tr.ReturnCode = 0
-# time delay as proxy.config.http.wait_for_cache could be broken
 tr.Processes.Default.StartBefore(server_foo)
 tr.Processes.Default.StartBefore(server_bar)
 tr.Processes.Default.StartBefore(server)
@@ -117,23 +114,34 @@ tr.Processes.Default.TimeOut = 5
 tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should have succeeded")
 tr.TimeOut = 5
 
-tr2 = Test.AddTestRun("Override-enforcing-Test")
-tr2.Processes.Default.Command = "curl -v -k -H \"host: bar.com\"  
https://127.0.0.1:{0}".format(ts.Variables.ssl_port)
+tr2 = Test.AddTestRun("bob.bar.com Override-enforcing-Test")
+tr2.Processes.Default.Command = "curl -v -k --resolve 
'bob.bar.com:{0}:127.0.0.1' 
https://bob.bar.com:{0}/".format(ts.Variables.ssl_port)
 tr2.ReturnCode = 0
 tr2.StillRunningAfter = server
 tr2.Processes.Default.TimeOut = 5
 tr2.StillRunningAfter = ts
-tr2.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should have succeeded")
+tr2.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not 
Connect", "Curl attempt should have succeeded")
 tr2.TimeOut = 5
 
-tr3 = Test.AddTestRun("Override-enforcing-Test-fail-name-check")
-tr3.Processes.Default.Command = "curl -v -k -H \"host: bad_bar.com\"  
https://127.0.0.1:{0}".format(ts.Variables.ssl_port)
-tr3.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not 
Connect", "Curl attempt should have failed")
+tr3 = Test.AddTestRun("bob.foo.com override-enforcing-name-test")
+tr3.Processes.Default.Command = "curl -v -k --resolve 
'bob.foo.com:{0}:127.0.0.1' 
https://bob.foo.com:{0}/".format(ts.Variables.ssl_port)
+tr3.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should not fail")
+tr3.ReturnCode = 0
+tr3.StillRunningAfter = server
+tr3.StillRunningAfter = ts
+tr3.Processes.Default.TimeOut = 5
+tr3.TimeOut = 5
+
+tr3 = Test.AddTestRun("random.bar.com override-no-test")
+tr3.Processes.Default.Command = "curl -v -k --resolve 
'random.bar.com:{0}:127.0.0.1' 
https://random.bar.com:{0}".format(ts.Variables.ssl_port)
+tr3.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not 
Connect", "Curl attempt should not fail")
 tr3.ReturnCode = 0
 tr3.StillRunningAfter = server
 tr3.StillRunningAfter = ts
 tr3.Processes.Default.TimeOut = 5
+tr3.TimeOut = 5
+
 
 # Over riding the built in ERROR check since we expect tr3 to fail
 ts.Disk.diags_log.Content = Testers.ExcludesExpression("verification failed", 
"Make sure the signatures didn't fail")
-ts.Disk.diags_log.Content += Testers.ContainsExpression("WARNING: SNI 
\(bad_bar.com\) not in certificate", "Make sure bad_bar name checked failed.")
+ts.Disk.diags_log.Content += Testers.ContainsExpression("WARNING: SNI 
\(bob.bar.com\) not in certificate", "Make sure bob.bar name checked failed.")

Reply via email to