You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2018/09/06 14:45:32 UTC
[trafficserver] branch master updated: Remove ssl_cert_loader.
Certifier is more complete version.
This is an automated email from the ASF dual-hosted git repository.
amc 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 9795337 Remove ssl_cert_loader. Certifier is more complete version.
9795337 is described below
commit 9795337070795088468faa317f955a645b697211
Author: Susan Hinrichs <sh...@apache.org>
AuthorDate: Tue Sep 4 11:16:43 2018 -0500
Remove ssl_cert_loader. Certifier is more complete version.
---
plugins/Makefile.am | 1 -
plugins/experimental/ssl_cert_loader/Makefile.inc | 23 -
.../experimental/ssl_cert_loader/domain-tree.cc | 200 --------
plugins/experimental/ssl_cert_loader/domain-tree.h | 98 ----
.../ssl_cert_loader/ssl-cert-loader.cc | 555 ---------------------
.../ssl_cert_loader/ssl_cert_loader.cfg | 150 ------
plugins/experimental/ssl_cert_loader/ssl_start.cfg | 72 ---
7 files changed, 1099 deletions(-)
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6115b21..8fa846e 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -75,7 +75,6 @@ include experimental/mp4/Makefile.inc
include experimental/multiplexer/Makefile.inc
include experimental/remap_purge/Makefile.inc
include experimental/server_push_preload/Makefile.inc
-include experimental/ssl_cert_loader/Makefile.inc
include experimental/sslheaders/Makefile.inc
include experimental/stale_while_revalidate/Makefile.inc
include experimental/stream_editor/Makefile.inc
diff --git a/plugins/experimental/ssl_cert_loader/Makefile.inc b/plugins/experimental/ssl_cert_loader/Makefile.inc
deleted file mode 100644
index 194b011..0000000
--- a/plugins/experimental/ssl_cert_loader/Makefile.inc
+++ /dev/null
@@ -1,23 +0,0 @@
-# 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.
-
-pkglib_LTLIBRARIES += experimental/ssl_cert_loader/ssl_cert_loader.la
-
-experimental_ssl_cert_loader_ssl_cert_loader_la_SOURCES = \
- experimental/ssl_cert_loader/ssl-cert-loader.cc \
- experimental/ssl_cert_loader/domain-tree.cc
-
-experimental_ssl_cert_loader_ssl_cert_loader_la_LIBADD = $(top_builddir)/lib/tsconfig/libtsconfig.la
diff --git a/plugins/experimental/ssl_cert_loader/domain-tree.cc b/plugins/experimental/ssl_cert_loader/domain-tree.cc
deleted file mode 100644
index b642ed7..0000000
--- a/plugins/experimental/ssl_cert_loader/domain-tree.cc
+++ /dev/null
@@ -1,200 +0,0 @@
-/** @file
- SSL dynamic certificate loader
- Loads certificates into a hash table as they are requested
-
- @section license License
-
- 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.
-*/
-#include <cstdio>
-#include <memory.h>
-#include <cinttypes>
-#include "domain-tree.h"
-
-// return true if comparable. Return type of compare in relative parameter
-// 0 if eq. < 0 if node key is broader. > 0 if parameter key is broader
-bool
-DomainNameTree::DomainNameNode::compare(std::string key, int &relative)
-{
- size_t star_loc = key.find('*');
- bool is_wild = false;
-
- if (star_loc != std::string::npos) {
- star_loc++;
- is_wild = true;
- key = key.substr(star_loc);
- }
-
- return this->prunedCompare(key, relative, is_wild);
-}
-
-bool
-DomainNameTree::DomainNameNode::prunedCompare(const std::string &key, int &relative, bool is_wild)
-{
- if (key == this->key) {
- relative = 0;
- return true;
- } else {
- if (this->is_wild) {
- size_t loc = key.find(this->key);
-
- if (this->key == "") { // Match all
- relative = -1;
- return true;
- } else if (loc != std::string::npos) {
- // node key is in search key
- if ((key.length() - this->key.length()) == loc) {
- // And node key is at the end of search key
- relative = -1;
- return true;
- }
- }
- }
- if (is_wild) {
- if (key == "") { // Match all
- relative = 1;
- return true;
- } else {
- size_t loc = this->key.find(key);
-
- if (loc != std::string::npos) {
- if ((this->key.length() - key.length()) == loc) {
- relative = 1;
- return true;
- }
- }
- }
- }
- }
-
- return false;
-}
-
-DomainNameTree::DomainNameNode *
-DomainNameTree::find(std::string key, bool best_match)
-{
- DomainNameNode *retval = nullptr;
- DomainNameNode *first = nullptr;
- size_t star_loc = key.find('*');
- bool is_wild = false;
-
- if (star_loc != std::string::npos) {
- key = key.substr(star_loc + 1);
- is_wild = true;
- }
-
- bool set_iter = false;
- DomainNameNode *current_node = root;
- std::deque<DomainNameNode *>::iterator sibPtr, endPtr;
-
- while (current_node != nullptr) {
- bool partial_match = false;
- int relative;
-
- if (current_node->prunedCompare(key, relative, is_wild)) {
- if (relative == 0) {
- retval = current_node;
- if (nullptr == first || retval->order < first->order) {
- first = retval;
- }
- current_node = nullptr;
- break;
- } else if (relative < 0) {
- retval = current_node;
- partial_match = true;
- if (nullptr == first || retval->order < first->order) {
- first = retval;
- }
- }
- }
- if (partial_match) {
- // Check out the children, maybe there is something better there
- sibPtr = current_node->children.begin();
- endPtr = current_node->children.end();
- set_iter = true;
- if (sibPtr == endPtr) {
- break; // We are done
- }
- current_node = *(sibPtr++);
- } else { // No match here. Look at next sibling?
- // Is there another sibling to look at?
- if (set_iter && sibPtr != endPtr) {
- current_node = *(sibPtr++);
- } else { // No more siblings to check, give it up.
- break;
- }
- }
- }
-
- return best_match ? retval : first;
-}
-
-DomainNameTree::DomainNameNode *
-DomainNameTree::insert(std::string key, void *payload, int order)
-{
- TSMutexLock(this->tree_mutex);
- DomainNameNode *retval = nullptr;
- DomainNameNode *node = this->findBestMatch(key);
- int relative;
-
- if (node->compare(key, relative)) {
- size_t star_loc = key.find('*');
- bool is_wild = false;
-
- if (star_loc != std::string::npos) {
- star_loc++;
- key = key.substr(star_loc);
- is_wild = true;
- }
- if (relative < 0) {
- // Make a new node that is a child of node
- DomainNameNode *new_node = new DomainNameNode(key, payload, order, is_wild);
-
- new_node->parent = node;
- node->children.push_back(new_node);
- retval = new_node;
- } else if (relative > 0) {
- // Insert new node as parent of node
- DomainNameNode *new_node = new DomainNameNode(key, payload, order, is_wild);
-
- new_node->parent = node->parent;
- new_node->children.push_back(node);
- node->parent = new_node;
-
- // Replace the node with new_node in the child list of the parent;
- for (std::deque<DomainNameNode *>::iterator iter = new_node->parent->children.begin();
- iter != new_node->parent->children.end(); ++iter) {
- if (*(iter) == node) {
- *(iter) = new_node;
- }
- }
- retval = new_node;
- } else {
- // Will not replace in the equal case
- // Unless this is the root node
- if (node->key == "" && node->order == 0x7fffffff) {
- node->key = key;
- node->payload = payload;
- node->order = order;
- retval = node;
- }
- }
- }
- TSMutexUnlock(this->tree_mutex);
-
- return retval;
-}
diff --git a/plugins/experimental/ssl_cert_loader/domain-tree.h b/plugins/experimental/ssl_cert_loader/domain-tree.h
deleted file mode 100644
index 4bbde85..0000000
--- a/plugins/experimental/ssl_cert_loader/domain-tree.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/** @file
-
- Include file for ...
-
- @section license License
-
- 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.
-
-*/
-#include <string>
-#include <deque>
-#include <ts/ts.h>
-
-class DomainNameTree
-{
-public:
- class DomainNameNode
- {
- public:
- DomainNameNode() : order(-1), payload(nullptr), parent(nullptr), is_wild(false) {}
- DomainNameNode(std::string key, void *payload, int order, bool is_wild)
- : key(key), order(order), payload(payload), parent(nullptr), is_wild(is_wild)
- {
- }
-
- DomainNameNode *match(std::string value);
-
- ~DomainNameNode()
- {
- std::deque<DomainNameNode *>::iterator iter = children.begin();
-
- for (; iter != children.end(); iter++) {
- delete *iter;
- }
- }
-
- // return true if comparable. Return type of compare in relative parameter
- // 0 if eq. < 0 if node key is broader. > 0 if parameter key is broader
- bool compare(std::string key, int &relative);
- // The wildcard is pruned out of the key
- bool prunedCompare(const std::string &key, int &relative, bool is_wild);
- std::string key; // The string trailing the * (if any)
- int order; // Track insert order for conflict resolution
- void *payload;
- std::deque<DomainNameNode *> children;
- DomainNameNode *parent;
- bool is_wild;
- };
-
- DomainNameTree()
- {
- root = new DomainNameNode();
- root->key = "";
- root->order = 0x7FFFFFFF;
- root->is_wild = true;
- tree_mutex = TSMutexCreate();
- }
-
- ~DomainNameTree() { delete root; }
- DomainNameNode *
- findBestMatch(std::string key)
- {
- TSMutexLock(this->tree_mutex);
- DomainNameNode *retval = this->find(key, true);
- TSMutexUnlock(this->tree_mutex);
- return retval;
- }
-
- DomainNameNode *
- findFirstMatch(std::string key)
- {
- TSMutexLock(this->tree_mutex);
- DomainNameNode *retval = this->find(key, false);
- TSMutexUnlock(this->tree_mutex);
- return retval;
- }
-
- DomainNameNode *find(std::string key, bool best_match);
- DomainNameNode *insert(std::string key, void *payload, int order);
-
-private:
- DomainNameNode *root;
- TSMutex tree_mutex;
-};
diff --git a/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc b/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc
deleted file mode 100644
index ef89cfa..0000000
--- a/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc
+++ /dev/null
@@ -1,555 +0,0 @@
-/** @file
-
- SSL dynamic certificate loader
- Loads certificates into a hash table as they are requested
-
- @section license License
-
- 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.
-*/
-
-#include <cstdio>
-#include <memory.h>
-#include <cinttypes>
-#include <ts/ts.h>
-#include <tsconfig/TsValue.h>
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <getopt.h>
-#include "domain-tree.h"
-
-#include "ts/ink_inet.h"
-#include "ts/ink_config.h"
-#include "ts/IpMap.h"
-
-using ts::config::Configuration;
-using ts::config::Value;
-
-#define PN "ssl-cert-loader"
-#define PCP "[" PN " Plugin] "
-
-namespace
-{
-class CertLookup
-{
-public:
- DomainNameTree tree;
- IpMap ipmap;
-} Lookup;
-
-typedef enum {
- SSL_HOOK_OP_DEFAULT, ///< Null / initialization value. Do normal processing.
- SSL_HOOK_OP_TUNNEL, ///< Switch to blind tunnel
- SSL_HOOK_OP_TERMINATE, ///< Termination connection / transaction.
- SSL_HOOK_OP_LAST = SSL_HOOK_OP_TERMINATE ///< End marker value.
-} SslVConnOp;
-
-class SslEntry
-{
-public:
- SslEntry() : ctx(nullptr), op(SSL_HOOK_OP_DEFAULT) { this->mutex = TSMutexCreate(); }
- ~SslEntry() {}
- SSL_CTX *ctx;
- SslVConnOp op;
- // If the CTX is not already created, use these
- // files to load things up
- std::string certFileName;
- std::string keyFileName;
- TSMutex mutex;
- std::deque<TSVConn> waitingVConns;
-};
-
-std::string ConfigPath;
-typedef std::pair<IpAddr, IpAddr> IpRange;
-using IpRangeQueue = std::deque<IpRange>;
-
-Configuration Config; // global configuration
-
-void
-Parse_Addr_String(std::string_view const &text, IpRange &range)
-{
- IpAddr newAddr;
- // Is there a hyphen?
- size_t hyphen_pos = text.find('-');
-
- if (hyphen_pos != std::string_view::npos) {
- std::string_view addr1 = text.substr(0, hyphen_pos);
- std::string_view addr2 = text.substr(hyphen_pos + 1);
- range.first.load(addr1);
- range.second.load(addr2);
- } else { // Assume it is a single address
- newAddr.load(text);
- range.first = newAddr;
- range.second = newAddr;
- }
-}
-
-int
-Load_Config_File()
-{
- ts::Rv<Configuration> cv = Configuration::loadFromPath(ConfigPath.c_str());
-
- if (!cv.isOK()) {
- char error_buffer[1024];
-
- cv._errata.write(error_buffer, sizeof(error_buffer), 0, 0, 0, "");
- TSDebug(PN, "Failed to parse %s as TSConfig format", ConfigPath.c_str());
- TSError(PCP "Failed to parse %s as TSConfig format", ConfigPath.c_str());
- TSDebug(PN, "Errors: %s", error_buffer);
- return -1;
- }
- Config = cv;
-
- return 1;
-}
-
-struct ParsedSslValues {
- std::string server_priv_key_file;
- std::string server_name;
- std::string server_cert_name;
- std::string action;
- IpRangeQueue server_ips;
-};
-
-void Parse_Config_Rules(Value &parent, ParsedSslValues &orig_values);
-
-int
-Load_Configuration()
-{
- int ret = Load_Config_File();
-
- if (ret != 0) {
- TSError(PCP "Failed to load the config file, check debug output for errata");
- }
-
- Value root = Config.getRoot();
- Value val = root["runtime-table-size"];
- if (val.isLiteral()) {
- // Not evicting yet
- }
- val = root["ssl-server-match"];
- if (val.isContainer()) {
- ParsedSslValues values;
- Parse_Config_Rules(val, values);
- }
-
- return 0;
-}
-
-SSL_CTX *
-Load_Certificate(SslEntry const *entry, std::deque<std::string> &names)
-{
- SSL_CTX *retval = SSL_CTX_new(SSLv23_client_method());
- X509 *cert = nullptr;
-
- if (entry->certFileName.length() > 0) {
- // Must load the cert file to fetch the names out later
- BIO *cert_bio = BIO_new_file(entry->certFileName.c_str(), "r");
- cert = PEM_read_bio_X509_AUX(cert_bio, nullptr, nullptr, nullptr);
- BIO_free(cert_bio);
-
- if (SSL_CTX_use_certificate(retval, cert) < 1) {
- TSDebug(PN, "Failed to load cert file %s", entry->certFileName.c_str());
- SSL_CTX_free(retval);
- return nullptr;
- }
- }
- if (entry->keyFileName.length() > 0) {
- if (!SSL_CTX_use_PrivateKey_file(retval, entry->keyFileName.c_str(), SSL_FILETYPE_PEM)) {
- TSDebug(PN, "Failed to load priv key file %s", entry->keyFileName.c_str());
- SSL_CTX_free(retval);
- return nullptr;
- }
- }
-
- // Fetch out the names associated with the certificate
- if (cert != nullptr) {
- X509_NAME *name = X509_get_subject_name(cert);
- char subjectCn[256];
-
- if (X509_NAME_get_text_by_NID(name, NID_commonName, subjectCn, sizeof(subjectCn)) >= 0) {
- std::string tmp_name(subjectCn);
- names.push_back(tmp_name);
- }
- // Look for alt names
- GENERAL_NAMES *alt_names = (GENERAL_NAMES *)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr);
- if (alt_names) {
- unsigned count = sk_GENERAL_NAME_num(alt_names);
- for (unsigned i = 0; i < count; i++) {
- GENERAL_NAME *alt_name = sk_GENERAL_NAME_value(alt_names, i);
-
- if (alt_name->type == GEN_DNS) {
- // Current name is a DNS name, let's check it
- char *name_ptr = (char *)ASN1_STRING_get0_data(alt_name->d.dNSName);
- std::string tmp_name(name_ptr);
- names.push_back(tmp_name);
- }
- }
- sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
- }
- }
-
- // Do we need to free cert? Did assigning to SSL_CTX increment its ref count
- return retval;
-}
-
-/*
- * Load the config information about the terminal config.
- * Only load the certificate if no server name or ip is specified
- */
-SslEntry *
-Load_Certificate_Entry(ParsedSslValues const &values, std::deque<std::string> &names)
-{
- SslEntry *retval = nullptr;
- std::string cert_file_path;
- std::string priv_file_path;
-
- retval = new SslEntry();
- if (values.server_cert_name.length() > 0) {
- if (values.server_cert_name[0] != '/') {
- cert_file_path = std::string(TSConfigDirGet()) + '/' + values.server_cert_name;
- } else {
- cert_file_path = values.server_cert_name;
- }
- retval->certFileName = cert_file_path;
- }
- if (values.server_priv_key_file.length() > 0) {
- if (values.server_priv_key_file[0] != '/') {
- priv_file_path = std::string(TSConfigDirGet()) + '/' + values.server_priv_key_file;
- } else {
- priv_file_path = values.server_priv_key_file;
- }
- retval->keyFileName = priv_file_path;
- }
- // Must go ahead and load the cert to get the names
- if (values.server_name.length() == 0 && values.server_ips.size() == 0) {
- retval->ctx = Load_Certificate(retval, names);
- }
- if (values.action.length() > 0) {
- if (values.action == "tunnel") {
- retval->op = SSL_HOOK_OP_TUNNEL;
- } else if (values.action == "teriminate") {
- retval->op = SSL_HOOK_OP_TERMINATE;
- }
- }
-
- return retval;
-}
-
-int Parse_order = 0;
-
-void
-Parse_Config(Value &parent, ParsedSslValues &orig_values)
-{
- ParsedSslValues cur_values(orig_values);
- Value val = parent.find("ssl-key-name");
-
- if (val.hasValue()) {
- cur_values.server_priv_key_file = std::string(val.getText()._ptr, val.getText()._size);
- }
- val = parent.find("server-ip");
- if (val) {
- IpRange ipRange;
- auto txt = val.getText();
-
- Parse_Addr_String(std::string_view(txt._ptr, txt._size), ipRange);
- cur_values.server_ips.push_back(ipRange);
- }
- val = parent.find("server-name");
- if (val) {
- cur_values.server_name = std::string(val.getText()._ptr, val.getText()._size);
- }
- val = parent.find("server-cert-name");
- if (val) {
- cur_values.server_cert_name = std::string(val.getText()._ptr, val.getText()._size);
- }
- val = parent.find("action");
- if (val) {
- cur_values.action = std::string(val.getText()._ptr, val.getText()._size);
- }
-
- val = parent.find("child-match");
- if (val) {
- Parse_Config_Rules(val, cur_values);
- } else { // We are terminal, enter a match case
- TSDebug(PN, "Terminal SSL Config: server_priv_key_file=%s server_name=%s server_cert_name=%s action=%s",
- cur_values.server_priv_key_file.c_str(), cur_values.server_name.c_str(), cur_values.server_cert_name.c_str(),
- cur_values.action.c_str());
- // Load the certificate and create a context if appropriate
- std::deque<std::string> cert_names;
- SslEntry *entry = Load_Certificate_Entry(cur_values, cert_names);
-
- if (entry) {
- bool inserted = false;
-
- // Store in appropriate table
- if (cur_values.server_name.length() > 0) {
- Lookup.tree.insert(cur_values.server_name, entry, Parse_order++);
- inserted = true;
- }
- if (cur_values.server_ips.size() > 0) {
- for (auto &server_ip : cur_values.server_ips) {
- IpEndpoint first, second;
- first.assign(server_ip.first);
- second.assign(server_ip.second);
- Lookup.ipmap.fill(&first, &second, entry);
- char val1[256], val2[256];
- server_ip.first.toString(val1, sizeof(val1));
- server_ip.second.toString(val2, sizeof(val2));
- inserted = true;
- }
- }
-
- if (cert_names.size() > 0) {
- for (const auto &cert_name : cert_names) {
- Lookup.tree.insert(cert_name, entry, Parse_order++);
- inserted = true;
- }
- }
-
- if (!inserted) {
- delete entry;
- TSError(PCP "cert_names is empty and entry not otherwise inserted!");
- }
- } else {
- TSError(PCP "failed to load the certificate entry");
- }
- }
-}
-
-void
-Parse_Config_Rules(Value &parent, ParsedSslValues &orig_values)
-{
- for (size_t i = 0; i < parent.childCount(); i++) {
- Value child = parent[i];
- Parse_Config(child, orig_values);
- }
-}
-
-void *
-Load_Certificate_Thread(void *arg)
-{
- SslEntry *entry = reinterpret_cast<SslEntry *>(arg);
-
- TSMutexLock(entry->mutex);
- if (entry->ctx == nullptr) {
- // Must load certificate
- std::deque<std::string> cert_names;
-
- entry->ctx = Load_Certificate(entry, cert_names);
- while (entry->waitingVConns.begin() != entry->waitingVConns.end()) {
- TSVConn vc = entry->waitingVConns.back();
- entry->waitingVConns.pop_back();
- TSSslConnection sslobj = TSVConnSSLConnectionGet(vc);
- SSL *ssl = reinterpret_cast<SSL *>(sslobj);
- SSL_set_SSL_CTX(ssl, entry->ctx);
- TSVConnReenable(vc);
- }
- TSMutexUnlock(entry->mutex);
- for (const auto &cert_name : cert_names) {
- Lookup.tree.insert(cert_name, entry, Parse_order++);
- }
- } else {
- TSMutexUnlock(entry->mutex);
- }
-
- return (void *)1;
-}
-
-int
-CB_Life_Cycle(TSCont, TSEvent, void *)
-{
- // By now the SSL library should have been initialized,
- // We can safely parse the config file and load the ctx tables
- Load_Configuration();
-
- return TS_SUCCESS;
-}
-
-int
-CB_Pre_Accept(TSCont /*contp*/, TSEvent event, void *edata)
-{
- TSVConn ssl_vc = reinterpret_cast<TSVConn>(edata);
- IpAddr ip(TSNetVConnLocalAddrGet(ssl_vc));
- char buff[INET6_ADDRSTRLEN];
- IpAddr ip_client(TSNetVConnRemoteAddrGet(ssl_vc));
- char buff2[INET6_ADDRSTRLEN];
-
- TSDebug(PN, "Pre accept callback %p - event is %s, target address %s, client address %s", ssl_vc,
- event == TS_EVENT_VCONN_START ? "good" : "bad", ip.toString(buff, sizeof(buff)),
- ip_client.toString(buff2, sizeof(buff2)));
-
- // Is there a cert already defined for this IP?
- //
- IpEndpoint key_endpoint;
- key_endpoint.assign(ip);
- void *payload;
- if (Lookup.ipmap.contains(&key_endpoint, &payload)) {
- // Set the stored cert on this SSL object
- TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc);
- SSL *ssl = reinterpret_cast<SSL *>(sslobj);
- SslEntry *entry = reinterpret_cast<SslEntry *>(payload);
- TSMutexLock(entry->mutex);
- if (entry->op == SSL_HOOK_OP_TUNNEL || entry->op == SSL_HOOK_OP_TERMINATE) {
- // Push everything to blind tunnel, or terminate
- if (entry->op == SSL_HOOK_OP_TUNNEL) {
- TSVConnTunnel(ssl_vc);
- }
- TSMutexUnlock(entry->mutex);
- } else {
- if (entry->ctx == nullptr) {
- if (entry->waitingVConns.begin() == entry->waitingVConns.end()) {
- entry->waitingVConns.push_back(ssl_vc);
- TSMutexUnlock(entry->mutex);
-
- TSThreadCreate(Load_Certificate_Thread, entry);
- } else { // Just add yourself to the queue
- entry->waitingVConns.push_back(ssl_vc);
- TSMutexUnlock(entry->mutex);
- }
- // Return before we reenable
- return TS_SUCCESS;
- } else { // if (entry->ctx != NULL) {
- SSL_set_SSL_CTX(ssl, entry->ctx);
- TSDebug(PN, "Replace cert based on IP");
- TSMutexUnlock(entry->mutex);
- }
- }
- }
-
- // All done, reactivate things
- TSVConnReenable(ssl_vc);
-
- return TS_SUCCESS;
-}
-
-int
-CB_servername(TSCont /*contp*/, TSEvent /*event*/, void *edata)
-{
- TSVConn ssl_vc = reinterpret_cast<TSVConn>(edata);
- TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc);
- SSL *ssl = reinterpret_cast<SSL *>(sslobj);
- const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-
- TSDebug(PN, "SNI callback %s", servername);
- if (servername != nullptr) {
- // Is there a certificated loaded up for this name
- DomainNameTree::DomainNameNode *node = Lookup.tree.findFirstMatch(servername);
- if (node != nullptr && node->payload != nullptr) {
- SslEntry *entry = reinterpret_cast<SslEntry *>(node->payload);
- if (entry->op == SSL_HOOK_OP_TUNNEL || entry->op == SSL_HOOK_OP_TERMINATE) {
- // Push everything to blind tunnel
- if (entry->op == SSL_HOOK_OP_TUNNEL) {
- TSVConnTunnel(ssl_vc);
- }
- // Make sure we stop out of the SNI callback
- // So return before re-enabling the SSL connection
- return TS_SUCCESS;
- }
- TSMutexLock(entry->mutex);
- if (entry->ctx == nullptr) {
- // Spawn off a thread to load a potentially expensive certificate
- if (entry->waitingVConns.begin() == entry->waitingVConns.end()) {
- entry->waitingVConns.push_back(ssl_vc);
- TSMutexUnlock(entry->mutex);
- TSThreadCreate(Load_Certificate_Thread, entry);
- } else { // Just add yourself to the queue
- entry->waitingVConns.push_back(ssl_vc);
- TSMutexUnlock(entry->mutex);
- }
- // Won't reenable until the certificate has been loaded
- return TS_SUCCESS;
- } else { // if (entry->ctx != NULL) {
- SSL_set_SSL_CTX(ssl, entry->ctx);
- TSDebug(PN, "Replace cert based on name %s", servername);
- }
- TSMutexUnlock(entry->mutex);
- }
- }
- // All done, reactivate things
- TSVConnReenable(ssl_vc);
-
- return TS_SUCCESS;
-}
-
-} // namespace
-
-// Called by ATS as our initialization point
-void
-TSPluginInit(int argc, const char *argv[])
-{
- bool success = false;
- TSPluginRegistrationInfo info;
- TSCont cb_pa = nullptr; // pre-accept callback continuation
- TSCont cb_lc = nullptr; // life cycle callback continuuation
- TSCont cb_sni = nullptr; // SNI callback continuuation
- static const struct option longopt[] = {
- {const_cast<char *>("config"), required_argument, nullptr, 'c'},
- {nullptr, no_argument, nullptr, '\0'},
- };
-
- info.plugin_name = const_cast<char *>("SSL Certificate Loader");
- info.vendor_name = const_cast<char *>("Network Geographics");
- info.support_email = const_cast<char *>("shinrich@network-geographics.com");
-
- int opt = 0;
- while (opt >= 0) {
- opt = getopt_long(argc, (char *const *)argv, "c:", longopt, nullptr);
- switch (opt) {
- case 'c':
- ConfigPath = optarg;
- ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(optarg);
- break;
- }
- }
- if (ConfigPath.length() == 0) {
- static const char *const DEFAULT_CONFIG_PATH = "ssl_start.cfg";
- ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(DEFAULT_CONFIG_PATH);
- TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH);
- }
-
- if (TS_SUCCESS != TSPluginRegister(&info)) {
- TSError(PCP "registration failed");
- } else if (TSTrafficServerVersionGetMajor() < 5) {
- TSError(PCP "requires Traffic Server 5.0 or later");
- } else if (nullptr == (cb_pa = TSContCreate(&CB_Pre_Accept, TSMutexCreate()))) {
- TSError(PCP "Failed to pre-accept callback");
- } else if (nullptr == (cb_lc = TSContCreate(&CB_Life_Cycle, TSMutexCreate()))) {
- TSError(PCP "Failed to lifecycle callback");
- } else if (nullptr == (cb_sni = TSContCreate(&CB_servername, TSMutexCreate()))) {
- TSError(PCP "Failed to create SNI callback");
- } else {
- TSLifecycleHookAdd(TS_LIFECYCLE_PORTS_INITIALIZED_HOOK, cb_lc);
- TSHttpHookAdd(TS_VCONN_START_HOOK, cb_pa);
- TSHttpHookAdd(TS_SSL_SNI_HOOK, cb_sni);
- success = true;
- }
-
- if (!success) {
- if (cb_pa) {
- TSContDestroy(cb_pa);
- }
- if (cb_lc) {
- TSContDestroy(cb_lc);
- }
- TSError(PCP "not initialized");
- }
- TSDebug(PN, "Plugin %s", success ? "online" : "offline");
-
- return;
-}
diff --git a/plugins/experimental/ssl_cert_loader/ssl_cert_loader.cfg b/plugins/experimental/ssl_cert_loader/ssl_cert_loader.cfg
deleted file mode 100644
index 20b1d1b..0000000
--- a/plugins/experimental/ssl_cert_loader/ssl_cert_loader.cfg
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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.
-
-// Describe how proxy should deal with the handshake process of SSL
-// connections passing though.
-version = "0.1";
-
-// Once the certificate load table surpasses this limit
-// Start evicting already loaded certificates
-runtime-table-size = "10000";
-
-// By default the proxy will participate in the handshake, so it needs
-// to have a certificate that it uses to handshake with the client, and
-// potentially another certificate to handshake with the origin server
-// In this case, the config must specify both the matching traffic conditions
-// and the connection attributes (certificates, tickets, etc).
-
-// Alternatively the proxy could be directed to get out of the way and
-// blind tunnel the SSL connection. There are no options to set in this
-// case. Only specify the matching traffic.
-
-// There are two rule lists. One that matches on characteristics of the
-// origin server.
-// Another that matches on characteristics of the client.
-
-// The attributes specified by matches in both rule lists will be used
-// to process the connection. If either rule list specifies a "tunnel" action
-// the connection will be blind tunneled. If either rule specifies a "deny"
-// action, the handshake processing will stop
-
-// Each rule list will be evaluated in order and stop on a match
-
-ssl-server-match =
-(
- { server-ip = "192.168.56.0-192.168.56.255";
- action="proxy"; /* Default if no action is specified */
- server-cert = "server1.pem";
- ssl-key-name = "privkey.pem";
- ssl-ticket-key-name = ( "ticket-key.blob", "ticket-key-old.blob" );
- child-match =
- // Doing something different for a couple servers in the range
- { server-ip = "192.168.56.45";
- server-cert = "server11.pem";
- },
- { server-ip = "192.168.56.46";
- server-cert = "server12.pem";
- },
- );
- },
- { server-name = "example.com";
- server-cert = "server2.pem";
- ssl-key-name = "privkey.pem";
- },
- {
- /* Could include characteristics of the offered ciphers in
- evaluating the actions */
- offered-cipher-constraint = {
- compare-op = "not-include";
- ciphers = ("3DES", "null");
- };
- server-cert = "server6.pem";
- ssl-key-name = "privkey.pem";
- },
-
- {
- /* Default, if no server-ip or server-name is specified,
- use the name in the certificate */
- server-name = "@";
- action="proxy";
- server-cert = "server3.pem";
- ssl-key-name = "privkey.pem";
- },
- {
- /* With the defaults, devolves to the base case of the
- ssl_multicert.config */
- server-cert = "server5.pem";
- ssl-key-name = "privkey.pem";
- },
- /* You can specify the SSL options (non matching state)
- in a separate entry and refer to it. Anything specified
- directly in the match rule will override the ssl-options
- */
- { server-ip = "192.168.100.0-192.168.100.100";
- ssl-options = <ssl-actions.ssl-info-1>;
- },
- { server-ip = "192.168.110.0-192.168.110.100";
- ssl-options = <ssl-actions.ssl-info-1>;
- },
- { server-name = "*.yahoo.com";
- action="tunnel";
- },
- /* All other traffic should be blind tunneled */
- { server-ip = "0.0.0.0-255.255.255.255";
- action = "tunnel";
- }
-);
-
-ssl-client-match:
-(
- // In all cases, use the same cipher-suites
- { use-client-cipher-suite = < cipher-suites.ecdhe >;
- child-match =
- (
- /* Traffic from lab should be blind tunneled */
- { client-ip = ("10.10.10.0-10.10.10.255", "10.10.50.152");
- action = "tunnel";
- }
- /* Clients from the office must use an authorized client certificate
- Proxy must verify. Must specify cert to use with origin server */
- { client-ip = "10.10.20.0-10.10.20.255";
- client-cert = "valid";
- /* Specify, or rely on your system settings for cert verification */
- ssl-signer-cert-name = "signers.pem";
- client-cert-name = "client1.pem";
- priv-key-name = "client-priv-key.pem";
- },
- /* Clients from the other office are not yet set up with client
- certs. But must provide client certs for the origin server */
- { client-ip = "10.10.30.0-10.10.30.255";
- /* Could be present or not, don't care, this is the default
- Other options are valid, present, or none
- */
- client-cert = "unknown";
- client-cert-name = "client1.pem";
- priv-key-name = "client-priv-key.pem";
- },
- }
-);
-
-
-ssl-actions =
-{
- ssl-info-1 = {
- server-cert = "server4.pem";
- ssl-key-name = "privkey.pem";
- };
-};
diff --git a/plugins/experimental/ssl_cert_loader/ssl_start.cfg b/plugins/experimental/ssl_cert_loader/ssl_start.cfg
deleted file mode 100644
index 48525bd..0000000
--- a/plugins/experimental/ssl_cert_loader/ssl_start.cfg
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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.
-
-// Describe how proxy should deal with the handshake process of SSL
-// connections passing though.
-version = "0.1"
-
-// Once the certificate load table surpasses this limit
-// Start evicting already loaded certificates
-runtime-table-size = "10000"
-
-// By default the proxy will participate in the handshake, so it needs
-// to have a certificate that it uses to handshake with the client, and
-// potentially another certificate to handshake with the origin server
-// In this case, the config must specify both the matching traffic conditions
-// and the connection attributes (certificates, tickets, etc).
-
-// Alternatively the proxy could be directed to get out of the way and
-// blind tunnel the SSL connection. There are no options to set in this
-// case. Only specify the matching traffic.
-
-// There are two rule lists. One that matches on characteristics of the
-// origin server.
-// Another that matches on characteristics of the client.
-
-// The attributes specified by matches in both rule lists will be used
-// to process the connection. If either rule list specifies a "tunnel" action
-// the connection will be blind tunneled. If either rule specifies a "deny"
-// action, the handshake processing will stop
-
-// Each rule list will be evaluated in order and stop on a match
-
-ssl-server-match =
-(
- // Using the same private key for all of my certs
- { ssl-key-name = "privkey.pem";
- child-match =
- (
- { server-ip = "107.23.60.186";
- action = "tunnel"
- },
- { server-cert-name = "safelyfiled.pem";
- server-name = "safelyfiled.com"
- },
- { server-cert-name = "asba.pem"
- },
- { server-name = "www.yahoo.com";
- server-cert-name = "asba.pem"
- },
- { server-cert-name = "buseyil.pem"
- },
- { server-cert-name = "busey.pem"
- },
- { server-cert-name = "wildgoogle.pem"
- }
- );
- }
-)
-