TS-1147: Implement default certificate fallback. Since we removed the certificate specification from records.config, implement a new default fallback mechanism in ssl_multicert.config. We can now use this default when the client does not give us a hostname, or when the the hostname lookup fails.
Update the ssl_multicert.config parser to accept lines that don't have a dest_ip field. Update the documentation in ssl_multicert.config. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/cadc9b6c Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/cadc9b6c Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/cadc9b6c Branch: refs/heads/master Commit: cadc9b6ce808cfb1832568676ef1592a19768f5f Parents: e2827c0 Author: James Peach <[email protected]> Authored: Mon Apr 2 21:36:11 2012 -0700 Committer: James Peach <[email protected]> Committed: Fri Apr 6 21:20:11 2012 -0700 ---------------------------------------------------------------------- iocore/net/P_SSLCertLookup.h | 5 +- iocore/net/SSLCertLookup.cc | 37 +++++++++-------- iocore/net/SSLNetVConnection.cc | 13 +++++- lib/ts/MatcherUtils.cc | 2 +- lib/ts/MatcherUtils.h | 13 +++++- proxy/config/ssl_multicert.config.default | 50 +++++++++++++++++++----- 6 files changed, 85 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cadc9b6c/iocore/net/P_SSLCertLookup.h ---------------------------------------------------------------------- diff --git a/iocore/net/P_SSLCertLookup.h b/iocore/net/P_SSLCertLookup.h index 817cd1f..da18345 100644 --- a/iocore/net/P_SSLCertLookup.h +++ b/iocore/net/P_SSLCertLookup.h @@ -34,13 +34,14 @@ class SSLCertLookup const char *extractIPAndCert( matcher_line * line_info, char **addr, char **cert, char **ca, char **priKey) const; bool addInfoToHash( - const char *strAddr, const char *cert, const char *ca, const char *serverPrivateKey) const; + const char *strAddr, const char *cert, const char *ca, const char *serverPrivateKey); char config_file_path[PATH_NAME_MAX]; SslConfigParams *param; bool multipleCerts; SSLContextStorage * ssl_storage; + SSL_CTX * ssl_default; public: bool hasMultipleCerts() const { return multipleCerts; } @@ -49,7 +50,7 @@ public: SSL_CTX *findInfoInHash(const char * address) const; // Return the last-resort default TLS context if there is no name or address match. - SSL_CTX *defaultContext() const { return NULL; } + SSL_CTX *defaultContext() const { return ssl_default; } SSLCertLookup(); ~SSLCertLookup(); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cadc9b6c/iocore/net/SSLCertLookup.cc ---------------------------------------------------------------------- diff --git a/iocore/net/SSLCertLookup.cc b/iocore/net/SSLCertLookup.cc index fb50a1d..82baf3c 100644 --- a/iocore/net/SSLCertLookup.cc +++ b/iocore/net/SSLCertLookup.cc @@ -80,18 +80,19 @@ SSLCertLookup sslCertLookup; static void insert_ssl_certificate(SSLContextStorage *, SSL_CTX *, const char *); -#define SSL_IP_TAG "dest_ip" -#define SSL_CERT_TAG "ssl_cert_name" -#define SSL_PRIVATE_KEY_TAG "ssl_key_name" -#define SSL_CA_TAG "ssl_ca_name" -const char *moduleName = "SSLCertLookup"; - -const matcher_tags sslCertTags = { - NULL, NULL, SSL_IP_TAG, NULL, NULL, false +#define SSL_IP_TAG "dest_ip" +#define SSL_CERT_TAG "ssl_cert_name" +#define SSL_PRIVATE_KEY_TAG "ssl_key_name" +#define SSL_CA_TAG "ssl_ca_name" + +static const char *moduleName = "SSLCertLookup"; + +static const matcher_tags sslCertTags = { + NULL, NULL, NULL, NULL, NULL, false }; SSLCertLookup::SSLCertLookup() - : param(NULL), multipleCerts(false), ssl_storage(NEW(new SSLContextStorage())) + : param(NULL), multipleCerts(false), ssl_storage(NEW(new SSLContextStorage())), ssl_default(NULL) { *config_file_path = '\0'; } @@ -166,8 +167,6 @@ SSLCertLookup::buildTable() moduleName, configFilePath, line_num, errPtr); IOCORE_SignalError(errBuf, alarmAlready); } else { - ink_assert(line_info.type == MATCH_IP); - errPtr = extractIPAndCert(&line_info, &addr, &sslCert, &sslCa, &priKey); if (errPtr != NULL) { @@ -175,7 +174,7 @@ SSLCertLookup::buildTable() moduleName, configFilePath, line_num, errPtr); IOCORE_SignalError(errBuf, alarmAlready); } else { - if (addr != NULL && sslCert != NULL) { + if (sslCert != NULL) { addInfoToHash(addr, sslCert, sslCa, priKey); ret = 1; } @@ -271,7 +270,7 @@ SSLCertLookup::extractIPAndCert(matcher_line * line_info, char **addr, char **ce bool SSLCertLookup::addInfoToHash( const char *strAddr, const char *cert, - const char *caCert, const char *serverPrivateKey) const + const char *caCert, const char *serverPrivateKey) { ink_ssl_method_t meth = NULL; @@ -281,14 +280,18 @@ SSLCertLookup::addInfoToHash( SSLNetProcessor::logSSLError("Cannot create new server contex."); return (false); } -// if (serverPrivateKey == NULL) -// serverPrivateKey = cert; if (ssl_NetProcessor.initSSLServerCTX(ctx, this->param, cert, caCert, serverPrivateKey) == 0) { char * certpath = Layout::relative_to(this->param->getServerCertPathOnly(), cert); - // Index this certificate by the specified IP(v6) address; - this->ssl_storage->insert(ctx, strAddr); + // Index this certificate by the specified IP(v6) address. If the address is "*", make it the default context. + if (strAddr) { + if (strcmp(strAddr, "*") == 0) { + this->ssl_default = ctx; + } else { + this->ssl_storage->insert(ctx, strAddr); + } + } // Insert additional mappings. Note that this maps multiple keys to the same value, so when // this code is updated to reconfigure the SSL certificates, it will need some sort of http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cadc9b6c/iocore/net/SSLNetVConnection.cc ---------------------------------------------------------------------- diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 0fd34a3..e9372e9 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -51,13 +51,20 @@ ClassAllocator<SSLNetVConnection> sslNetVCAllocator("sslNetVCAllocator"); static int ssl_servername_callback(SSL * ssl, int * ad, void * arg) { - SSL_CTX * ctx; + SSL_CTX * ctx = NULL; SSLCertLookup * lookup = (SSLCertLookup *) arg; - const char * servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + const char * servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); Debug("ssl", "ssl=%p ad=%d lookup=%p server=%s", ssl, *ad, lookup, servername); - ctx = lookup->findInfoInHash((char *)servername); + if (likely(servername)) { + ctx = lookup->findInfoInHash((char *)servername); + } + + if (ctx == NULL) { + ctx = lookup->defaultContext(); + } + if (ctx == NULL) { return SSL_TLSEXT_ERR_NOACK; } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cadc9b6c/lib/ts/MatcherUtils.cc ---------------------------------------------------------------------- diff --git a/lib/ts/MatcherUtils.cc b/lib/ts/MatcherUtils.cc index 1cab191..632ed25 100644 --- a/lib/ts/MatcherUtils.cc +++ b/lib/ts/MatcherUtils.cc @@ -585,7 +585,7 @@ parseConfigLine(char *line, matcher_line *p_line, const matcher_tags * tags) return "Malformed entry"; } - if (p_line->type == MATCH_NONE) { + if (!tags->empty() && p_line->type == MATCH_NONE) { if (tags->dest_error_msg == false) { return "No source specifier"; } else { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cadc9b6c/lib/ts/MatcherUtils.h ---------------------------------------------------------------------- diff --git a/lib/ts/MatcherUtils.h b/lib/ts/MatcherUtils.h index 94fd2b7..7bd4133 100644 --- a/lib/ts/MatcherUtils.h +++ b/lib/ts/MatcherUtils.h @@ -95,9 +95,18 @@ struct matcher_tags const char *match_ip; const char *match_regex; const char *match_host_regex; - bool dest_error_msg; // wether to use src or destination in any - // errog messages + bool dest_error_msg; // whether to use src or destination in any error messages + + bool empty() const { + return this->match_host == NULL && + this->match_domain == NULL && + this->match_ip == NULL && + this->match_regex == NULL && + this->match_host_regex == NULL; + } + }; + extern const matcher_tags http_dest_tags; extern const matcher_tags ip_allow_tags; extern const matcher_tags socks_server_tags; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cadc9b6c/proxy/config/ssl_multicert.config.default ---------------------------------------------------------------------- diff --git a/proxy/config/ssl_multicert.config.default b/proxy/config/ssl_multicert.config.default index 23b71b1..2c21808 100644 --- a/proxy/config/ssl_multicert.config.default +++ b/proxy/config/ssl_multicert.config.default @@ -1,12 +1,42 @@ # # ssl_multicert.config -# Allows an ssl_cert and private key to be tied to a specific -# IP address on a multihomed machine. If the key is contained in the -# certificate file, just do not specify an ssl_key_name. -# If the your certificates have differen Certificate Authorities, you -# can specify this on a per-host basis using ssl_ca_name. -# The certificate file path, ca path and key path specified in -# records.config will be used # for all certificates, CAs and keys -# specified here. Example: -# -#dest_ip=209.131.48.79 ssl_cert_name=server.pem ssl_key_name=serverKey.pem +# +# Allows a TLS certificate and private key to be tied to a specific +# hostname or IP address. At load time, the certificate is parsed to +# extract the subject CN and all the DNS subjectAltNames. The +# certificate will be presented for connections requesting any of the +# hostnames found in the certificate. Wildcard names are supported, +# but only of the form '*.domain.com', ie. where '*' is the leftmost +# domain component. +# +# The certificate file path, CA path and key path specified in +# records.config will be used for all certificates, CAs and keys +# specified here. +# +# Fields: +# +# dest_ip=ADDRESS +# The IP (v4 or v6) address that the certificate should be presented +# on. This is now only used as a fallback in the case that the TLS +# SubjectNameIndication extension is not supported. If ADDRESS is +# '*', the certificate will be used as teh default fallback if no +# other match can be made. +# +# ssl_key_name=FILENAME +# The name of the file containg the private key for this certificate. +# If the key is contained in the certificate file, this field can be +# omitted. +# +# ssl_ca_name=FILENAME +# If your certificates have different Certificate Authorities, you +# can optionally specify the corresponding file here. +# +# ssl_cert_name=FILENAME +# The name of the file containing the TLS certificate. This is the +# only field that is required to be present. +# +# Examples: +# ssl_cert_name=foo.pem +# dest_ip=* ssl_cert_name=bar.pem ssl_key_name=barKey.pem +# dest_ip=209.131.48.79 ssl_cert_name=server.pem ssl_key_name=serverKey.pem +
