proxygen
wangle::SSLContextManager Class Reference

#include <SSLContextManager.h>

Inheritance diagram for wangle::SSLContextManager:
wangle::SSLContextManagerForTest

Classes

struct  ClientCertVerifyCallback
 
struct  SslContexts
 

Public Member Functions

 SSLContextManager (folly::EventBase *eventBase, const std::string &vipName, bool strict, SSLStats *stats)
 
virtual ~SSLContextManager ()
 
void addSSLContextConfig (const SSLContextConfig &ctxConfig, const SSLCacheOptions &cacheOptions, const TLSTicketKeySeeds *ticketSeeds, const folly::SocketAddress &vipAddress, const std::shared_ptr< SSLCacheProvider > &externalCache, SslContexts *contexts=nullptr)
 
void resetSSLContextConfigs (const std::vector< SSLContextConfig > &ctxConfig, const SSLCacheOptions &cacheOptions, const TLSTicketKeySeeds *ticketSeeds, const folly::SocketAddress &vipAddress, const std::shared_ptr< SSLCacheProvider > &externalCache)
 
void clear ()
 
std::shared_ptr< folly::SSLContextgetDefaultSSLCtx () const
 
std::shared_ptr< folly::SSLContextgetSSLCtx (const SSLContextKey &key) const
 
std::shared_ptr< folly::SSLContextgetSSLCtxBySuffix (const SSLContextKey &key) const
 
std::shared_ptr< folly::SSLContextgetSSLCtxByExactDomain (const SSLContextKey &key) const
 
void reloadTLSTicketKeys (const std::vector< std::string > &oldSeeds, const std::vector< std::string > &currentSeeds, const std::vector< std::string > &newSeeds)
 
void setSSLStats (SSLStats *stats)
 
void setClientHelloExtStats (ClientHelloExtStats *stats)
 
void setClientVerifyCallback (std::unique_ptr< ClientCertVerifyCallback > cb)
 

Protected Member Functions

virtual void loadCertKeyPairExternal (const std::shared_ptr< folly::SSLContext > &, const SSLContextConfig &, const std::string &)
 
virtual void overrideConfiguration (const std::shared_ptr< folly::SSLContext > &, const SSLContextConfig &)
 
void insertSSLCtxByDomainName (const char *dn, size_t len, std::shared_ptr< folly::SSLContext > sslCtx, SslContexts &contexts, CertCrypto certCrypto=CertCrypto::BEST_AVAILABLE)
 
void insertSSLCtxByDomainName (const char *dn, size_t len, std::shared_ptr< folly::SSLContext > sslCtx, CertCrypto certCrypto=CertCrypto::BEST_AVAILABLE)
 

Protected Attributes

std::string vipName_
 
SSLStatsstats_ {nullptr}
 

Private Member Functions

 SSLContextManager (const SSLContextManager &)=delete
 
void ctxSetupByOpensslFeature (std::shared_ptr< ServerSSLContext > sslCtx, const SSLContextConfig &ctxConfig, SslContexts &contexts)
 
void insert (std::shared_ptr< ServerSSLContext > sslCtx, bool defaultFallback, SslContexts &contexts)
 
void insertSSLCtxByDomainNameImpl (const char *dn, size_t len, std::shared_ptr< folly::SSLContext > sslCtx, SslContexts &contexts, CertCrypto certCrypto)
 
void insertIntoDnMap (SSLContextKey key, std::shared_ptr< folly::SSLContext > sslCtx, bool overwrite, SslContexts &contexts)
 

Private Attributes

SslContexts contexts_
 
folly::EventBaseeventBase_
 
ClientHelloExtStatsclientHelloTLSExtStats_ {nullptr}
 
SSLContextConfig::SNINoMatchFn noMatchFn_
 
bool strict_ {true}
 
std::unique_ptr< ClientCertVerifyCallbackclientCertVerifyCallback_ {nullptr}
 

Detailed Description

Definition at line 47 of file SSLContextManager.h.

Constructor & Destructor Documentation

wangle::SSLContextManager::SSLContextManager ( folly::EventBase eventBase,
const std::string vipName,
bool  strict,
SSLStats stats 
)
explicit

Definition at line 186 of file SSLContextManager.cpp.

190  :
191  vipName_(vipName),
192  stats_(stats),
193  eventBase_(eventBase),
194  strict_(strict) {
195 
196 }
folly::EventBase * eventBase_
wangle::SSLContextManager::~SSLContextManager ( )
virtualdefault
wangle::SSLContextManager::SSLContextManager ( const SSLContextManager )
privatedelete

Member Function Documentation

void wangle::SSLContextManager::addSSLContextConfig ( const SSLContextConfig ctxConfig,
const SSLCacheOptions cacheOptions,
const TLSTicketKeySeeds ticketSeeds,
const folly::SocketAddress vipAddress,
const std::shared_ptr< SSLCacheProvider > &  externalCache,
SslContexts contexts = nullptr 
)

Add a new X509 to SSLContextManager. The details of a X509 is passed as a SSLContextConfig object.

Parameters
ctxConfigDetails of a X509, its private key, password, etc.
cacheOptionsOptions for how to do session caching.
ticketSeedsIf non-null, the initial ticket key seeds to use.
vipAddressWhich VIP are the X509(s) used for? It is only for for user friendly log message
externalCacheOptional external provider for the session cache; may be null

Definition at line 248 of file SSLContextManager.cpp.

References wangle::BEST_AVAILABLE, wangle::SSLContextConfig::certificates, wangle::SSLContextConfig::clientCAFile, clientCertVerifyCallback_, clientHelloTLSExtStats_, wangle::SSLContextConfig::clientVerification, contexts_, count, ctxSetupByOpensslFeature(), wangle::SSLContextManager::SslContexts::defaultCtxDomainName, folly::SocketAddress::describe(), wangle::SSLContextConfig::eccCurveName, folly::exceptionStr(), folly::AsyncSSLSocket::getClientHelloInfo(), wangle::SSLUtil::getCommonName(), folly::AsyncSSLSocket::getFromSSL(), getSSLCtx(), wangle::SSLUtil::getSubjectAltName(), folly::gen::guard(), insert(), wangle::SSLContextConfig::isDefault, wangle::SSLContextConfig::keyOffloadParams, loadCertKeyPairExternal(), folly::makeGuard(), folly::gen::move, noMatchFn_, wangle::SSLContextConfig::KeyOffloadParams::offloadType, overrideConfiguration(), wangle::ClientHelloExtStats::recordAbsentHostname(), wangle::ClientHelloExtStats::recordCertCrypto(), wangle::ClientHelloExtStats::recordMatch(), wangle::ClientHelloExtStats::recordNotMatch(), folly::ssl::SERVER_NAME, wangle::SSLContextConfig::sessionContext, wangle::SHA1_SIGNATURE, folly::ssl::SHA256, wangle::SSLContextConfig::sslCiphers, wangle::SSLContextConfig::sslVersion, stats_, string, folly::stringPrintf(), uint32_t, and vipName_.

Referenced by resetSSLContextConfigs(), and wangle::TEST().

254  {
255 
256  if (!contexts) {
257  contexts = &contexts_;
258  }
259 
260  unsigned numCerts = 0;
261  std::string commonName;
262  std::string lastCertPath;
263  std::unique_ptr<std::list<std::string>> subjectAltName;
264  auto sslCtx =
265  std::make_shared<ServerSSLContext>(ctxConfig.sslVersion);
266  for (const auto& cert : ctxConfig.certificates) {
267  try {
268  if (ctxConfig.keyOffloadParams.offloadType.empty()) {
269  // The private key lives in the same process
270  // This needs to be called before loadPrivateKey().
271  if (!cert.passwordPath.empty()) {
272  auto sslPassword = std::make_shared<folly::PasswordInFile>(
273  cert.passwordPath);
274  sslCtx->passwordCollector(std::move(sslPassword));
275  }
276  sslCtx->loadCertKeyPairFromFiles(
277  cert.certPath.c_str(),
278  cert.keyPath.c_str(),
279  "PEM",
280  "PEM");
281  } else {
282  loadCertKeyPairExternal(sslCtx, ctxConfig, cert.certPath);
283  }
284  } catch (const std::exception& ex) {
285  // The exception isn't very useful without the certificate path name,
286  // so throw a new exception that includes the path to the certificate.
287  string msg = folly::to<string>("error loading SSL certificate ",
288  cert.certPath, ": ",
289  folly::exceptionStr(ex));
290  LOG(ERROR) << msg;
291  throw std::runtime_error(msg);
292  }
293 
294  // Verify that the Common Name and (if present) Subject Alternative Names
295  // are the same for all the certs specified for the SSL context.
296  numCerts++;
297  X509* x509 = getX509(sslCtx->getSSLCtx());
298  if (!x509) {
299  throw std::runtime_error(
300  folly::to<std::string>(
301  "Certificate: ", cert.certPath, " is invalid"));
302  }
303  auto guard = folly::makeGuard([x509] { X509_free(x509); });
304  auto cn = SSLUtil::getCommonName(x509);
305  if (!cn) {
306  throw std::runtime_error(folly::to<string>("Cannot get CN for X509 ",
307  cert.certPath));
308  }
309  auto altName = SSLUtil::getSubjectAltName(x509);
310  VLOG(2) << "cert " << cert.certPath << " CN: " << *cn;
311  if (altName) {
312  altName->sort();
313  VLOG(2) << "cert " << cert.certPath << " SAN: " << flattenList(*altName);
314  } else {
315  VLOG(2) << "cert " << cert.certPath << " SAN: " << "{none}";
316  }
317  if (numCerts == 1) {
318  commonName = *cn;
319  subjectAltName = std::move(altName);
320  } else {
321  if (commonName != *cn) {
322  throw std::runtime_error(folly::to<string>("X509 ", cert.certPath,
323  " does not have same CN as ",
324  lastCertPath));
325  }
326  if (altName == nullptr) {
327  if (subjectAltName != nullptr) {
328  throw std::runtime_error(folly::to<string>("X509 ", cert.certPath,
329  " does not have same SAN as ",
330  lastCertPath));
331  }
332  } else {
333  if ((subjectAltName == nullptr) || (*altName != *subjectAltName)) {
334  throw std::runtime_error(folly::to<string>("X509 ", cert.certPath,
335  " does not have same SAN as ",
336  lastCertPath));
337  }
338  }
339  }
340  lastCertPath = cert.certPath;
341  }
342 
343  overrideConfiguration(sslCtx, ctxConfig);
344 
345  // Let the server pick the highest performing cipher from among the client's
346  // choices.
347  //
348  // Let's use a unique private key for all DH key exchanges.
349  //
350  // Because some old implementations choke on empty fragments, most SSL
351  // applications disable them (it's part of SSL_OP_ALL). This
352  // will improve performance and decrease write buffer fragmentation.
353  sslCtx->setOptions(SSL_OP_CIPHER_SERVER_PREFERENCE |
354  SSL_OP_SINGLE_DH_USE |
355  SSL_OP_SINGLE_ECDH_USE |
356  SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
357 
358  // Important that we do this *after* checking the TLS1.1 ciphers above,
359  // since we test their validity by actually setting them.
360  sslCtx->ciphers(ctxConfig.sslCiphers);
361 
362  // Use a fix DH param
363  DH* dh = get_dh2048();
364  SSL_CTX_set_tmp_dh(sslCtx->getSSLCtx(), dh);
365  DH_free(dh);
366 
367  const string& curve = ctxConfig.eccCurveName;
368  if (!curve.empty()) {
369  set_key_from_curve(sslCtx->getSSLCtx(), curve);
370  }
371 
372  if (!ctxConfig.clientCAFile.empty()) {
373  try {
374  sslCtx->loadTrustedCertificates(ctxConfig.clientCAFile.c_str());
375  sslCtx->loadClientCAList(ctxConfig.clientCAFile.c_str());
376 
377  // Only allow over-riding of verification callback if one
378  // isn't explicitly set on the context
379  if (clientCertVerifyCallback_ == nullptr) {
380  sslCtx->setVerificationOption(ctxConfig.clientVerification);
381  } else {
382  clientCertVerifyCallback_->attachSSLContext(sslCtx);
383  }
384 
385  } catch (const std::exception& ex) {
386  string msg = folly::to<string>("error loading client CA",
387  ctxConfig.clientCAFile, ": ",
388  folly::exceptionStr(ex));
389  LOG(ERROR) << msg;
390  throw std::runtime_error(msg);
391  }
392  }
393 
394  // we always want to setup the session id context
395  // to make session resumption work (tickets or session cache)
396  std::string sessionIdContext = commonName;
397  if (ctxConfig.sessionContext && !ctxConfig.sessionContext->empty()) {
398  sessionIdContext = *ctxConfig.sessionContext;
399  }
400  VLOG(2) << "For vip " << vipName_ << ", CN " << commonName
401  << ", setting sid_ctx " << sessionIdContext;
402  sslCtx->setSessionCacheContext(sessionIdContext);
403 
404  sslCtx->setupSessionCache(
405  ctxConfig,
406  cacheOptions,
407  externalCache,
408  sessionIdContext,
409  stats_);
410  sslCtx->setupTicketManager(ticketSeeds, ctxConfig, stats_);
411  VLOG(2) << "On VipID=" << vipAddress.describe() << " context=" << sslCtx;
412 
413  // finalize sslCtx setup by the individual features supported by openssl
414  ctxSetupByOpensslFeature(sslCtx, ctxConfig, *contexts);
415 
416  try {
417  insert(sslCtx,
418  ctxConfig.isDefault,
419  *contexts);
420  } catch (const std::exception& ex) {
421  string msg = folly::to<string>("Error adding certificate : ",
422  folly::exceptionStr(ex));
423  LOG(ERROR) << msg;
424  throw std::runtime_error(msg);
425  }
426 
427 }
virtual void loadCertKeyPairExternal(const std::shared_ptr< folly::SSLContext > &, const SSLContextConfig &, const std::string &)
static std::unique_ptr< std::list< std::string > > getSubjectAltName(const X509 *cert)
Definition: SSLUtil.cpp:70
virtual void overrideConfiguration(const std::shared_ptr< folly::SSLContext > &, const SSLContextConfig &)
fbstring exceptionStr(const std::exception &e)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::string describe() const
void insert(std::shared_ptr< ServerSSLContext > sslCtx, bool defaultFallback, SslContexts &contexts)
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
static std::unique_ptr< std::string > getCommonName(const X509 *cert)
Definition: SSLUtil.cpp:54
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
Definition: ScopeGuard.h:184
const char * string
Definition: Conv.cpp:212
void ctxSetupByOpensslFeature(std::shared_ptr< ServerSSLContext > sslCtx, const SSLContextConfig &ctxConfig, SslContexts &contexts)
std::unique_ptr< ClientCertVerifyCallback > clientCertVerifyCallback_
void wangle::SSLContextManager::clear ( )

Clears all ssl contexts

Definition at line 751 of file SSLContextManager.cpp.

References wangle::SSLContextManager::SslContexts::clear(), and contexts_.

void wangle::SSLContextManager::ctxSetupByOpensslFeature ( std::shared_ptr< ServerSSLContext sslCtx,
const SSLContextConfig ctxConfig,
SslContexts contexts 
)
private

Definition at line 526 of file SSLContextManager.cpp.

References folly::netops::bind(), wangle::SSLContextManager::SslContexts::ctxs, wangle::SSLContextManager::SslContexts::defaultCtx, wangle::SSLContextConfig::isDefault, wangle::SSLContextConfig::nextProtocols, noMatchFn_, OPENSSL_MISSING_FEATURE, and wangle::SSLContextConfig::sniNoMatchFn.

Referenced by addSSLContextConfig().

529  {
530  // Disable compression - profiling shows this to be very expensive in
531  // terms of CPU and memory consumption.
532  //
533 #ifdef SSL_OP_NO_COMPRESSION
534  sslCtx->setOptions(SSL_OP_NO_COMPRESSION);
535 #endif
536 
537  // Enable early release of SSL buffers to reduce the memory footprint
538 #ifdef SSL_MODE_RELEASE_BUFFERS
539  // Note: SSL_CTX_set_mode doesn't set, just ORs the arg with existing mode
540  SSL_CTX_set_mode(sslCtx->getSSLCtx(), SSL_MODE_RELEASE_BUFFERS);
541 
542 #endif
543 #ifdef SSL_MODE_EARLY_RELEASE_BBIO
544  // Note: SSL_CTX_set_mode doesn't set, just ORs the arg with existing mode
545  SSL_CTX_set_mode(sslCtx->getSSLCtx(), SSL_MODE_EARLY_RELEASE_BBIO);
546 #endif
547 
548  // This number should (probably) correspond to HTTPSession::kMaxReadSize
549  // For now, this number must also be large enough to accommodate our
550  // largest certificate, because some older clients (IE6/7) require the
551  // cert to be in a single fragment.
552 #ifdef SSL_CTRL_SET_MAX_SEND_FRAGMENT
553  SSL_CTX_set_max_send_fragment(sslCtx->getSSLCtx(), 8000);
554 #endif
555 
556  // NPN (Next Protocol Negotiation)
557  if (!ctxConfig.nextProtocols.empty()) {
558 #if FOLLY_OPENSSL_HAS_ALPN
559  sslCtx->setRandomizedAdvertisedNextProtocols(
560  ctxConfig.nextProtocols);
561 #else
563 #endif
564  }
565 
566  // SNI
567 #ifdef PROXYGEN_HAVE_SERVERNAMECALLBACK
568  noMatchFn_ = ctxConfig.sniNoMatchFn;
569  if (ctxConfig.isDefault) {
570  if (contexts.defaultCtx) {
571  throw std::runtime_error(">1 X509 is set as default");
572  }
573 
574  contexts.defaultCtx = sslCtx;
575  contexts.defaultCtx->setServerNameCallback(
576  std::bind(&SSLContextManager::serverNameCallback, this,
577  std::placeholders::_1));
578  }
579 #else
580  if (contexts.ctxs.size() > 1) {
582  }
583 #endif
584 }
SSLContextConfig::SNINoMatchFn noMatchFn_
#define OPENSSL_MISSING_FEATURE(name)
int bind(NetworkSocket s, const sockaddr *name, socklen_t namelen)
Definition: NetOps.cpp:76
shared_ptr< SSLContext > wangle::SSLContextManager::getDefaultSSLCtx ( ) const

Get the default SSL_CTX for a VIP

Definition at line 803 of file SSLContextManager.cpp.

References contexts_, and wangle::SSLContextManager::SslContexts::defaultCtx.

803  {
804  return contexts_.defaultCtx;
805 }
std::shared_ptr< ServerSSLContext > defaultCtx
shared_ptr< SSLContext > wangle::SSLContextManager::getSSLCtx ( const SSLContextKey key) const

Search first by exact domain, then by one level up

Definition at line 756 of file SSLContextManager.cpp.

References getSSLCtxByExactDomain(), and getSSLCtxBySuffix().

Referenced by addSSLContextConfig(), and wangle::TEST().

757 {
758  auto ctx = getSSLCtxByExactDomain(key);
759  if (ctx) {
760  return ctx;
761  }
762  return getSSLCtxBySuffix(key);
763 }
std::shared_ptr< folly::SSLContext > getSSLCtxByExactDomain(const SSLContextKey &key) const
std::shared_ptr< folly::SSLContext > getSSLCtxBySuffix(const SSLContextKey &key) const
shared_ptr< SSLContext > wangle::SSLContextManager::getSSLCtxByExactDomain ( const SSLContextKey key) const

Search by the full-string domain name

Definition at line 788 of file SSLContextManager.cpp.

References contexts_, wangle::SSLContextManager::SslContexts::dnMap, wangle::SSLContextKey::dnString, and folly::stringPrintf().

Referenced by getSSLCtx(), and wangle::TEST().

789 {
790  const auto v = contexts_.dnMap.find(key);
791  if (v == contexts_.dnMap.end()) {
792  VLOG(6) << folly::stringPrintf("\"%s\" is not an exact match",
793  key.dnString.c_str());
794  return shared_ptr<SSLContext>();
795  } else {
796  VLOG(6) << folly::stringPrintf("\"%s\" is an exact match",
797  key.dnString.c_str());
798  return v->second;
799  }
800 }
std::string stringPrintf(const char *format,...)
Definition: String.cpp:223
std::unordered_map< SSLContextKey, std::shared_ptr< folly::SSLContext >, SSLContextKeyHash > dnMap
shared_ptr< SSLContext > wangle::SSLContextManager::getSSLCtxBySuffix ( const SSLContextKey key) const

Search by the one level up subdomain

Definition at line 766 of file SSLContextManager.cpp.

References wangle::SSLContextKey::certCrypto, contexts_, wangle::SSLContextManager::SslContexts::dnMap, wangle::SSLContextKey::dnString, GCC61971::dot, and folly::stringPrintf().

Referenced by getSSLCtx(), and wangle::TEST().

767 {
768  size_t dot;
769 
770  if ((dot = key.dnString.find_first_of(".")) != DNString::npos) {
771  SSLContextKey suffixKey(DNString(key.dnString, dot),
772  key.certCrypto);
773  const auto v = contexts_.dnMap.find(suffixKey);
774  if (v != contexts_.dnMap.end()) {
775  VLOG(6) << folly::stringPrintf("\"%s\" is a willcard match to \"%s\"",
776  key.dnString.c_str(),
777  suffixKey.dnString.c_str());
778  return v->second;
779  }
780  }
781 
782  VLOG(6) << folly::stringPrintf("\"%s\" is not a wildcard match",
783  key.dnString.c_str());
784  return shared_ptr<SSLContext>();
785 }
std::basic_string< char, dn_char_traits > DNString
std::string stringPrintf(const char *format,...)
Definition: String.cpp:223
std::unordered_map< SSLContextKey, std::shared_ptr< folly::SSLContext >, SSLContextKeyHash > dnMap
constexpr auto dot
void wangle::SSLContextManager::insert ( std::shared_ptr< ServerSSLContext sslCtx,
bool  defaultFallback,
SslContexts contexts 
)
private

Callback function from openssl to find the right X509 to use during SSL handshake The following functions help to maintain the data structure for domain name matching in SNI. Some notes:

  1. It is a best match.
  2. It allows wildcard CN and wildcard subject alternative name in a X509. The wildcard name must be prefixed by '*.'. It errors out whenever it sees '*' in any other locations.
  3. It uses one std::unordered_map<DomainName, SSL_CTX> object to do this. For wildcard name like "*.facebook.com", ".facebook.com" is used as the key.
  4. After getting tlsext_hostname from the client hello message, it will do a full string search first and then try one level up to match any wildcard name (if any) in the X509. [Note, browser also only looks one level up when matching the requesting domain name with the wildcard name in the server X509].

Some notes from RFC 2818. Only for future quick references in case of bugs

RFC 2818 section 3.1: "...... If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead. ...... In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI. ......"

Definition at line 587 of file SSLContextManager.cpp.

References wangle::BEST_AVAILABLE, wangle::SSLContextManager::SslContexts::ctxs, wangle::SSLUtil::getCommonName(), wangle::SSLUtil::getSubjectAltName(), folly::gen::guard(), insertSSLCtxByDomainName(), folly::makeGuard(), name, and wangle::SHA1_SIGNATURE.

Referenced by addSSLContextConfig().

589  {
590  X509* x509 = getX509(sslCtx->getSSLCtx());
591  if (!x509) {
592  throw std::runtime_error("SSLCtx is invalid");
593  }
594  auto guard = folly::makeGuard([x509] { X509_free(x509); });
595  auto cn = SSLUtil::getCommonName(x509);
596  if (!cn) {
597  throw std::runtime_error("Cannot get CN");
598  }
599 
617  // Not sure if we ever get this kind of X509...
618  // If we do, assume '*' is always in the CN and ignore all subject alternative
619  // names.
620  if (cn->length() == 1 && (*cn)[0] == '*') {
621  if (!defaultFallback) {
622  throw std::runtime_error("STAR X509 is not the default");
623  }
624  contexts.ctxs.emplace_back(sslCtx);
625  return;
626  }
627 
628  CertCrypto certCrypto;
629  int sigAlg = X509_get_signature_nid(x509);
630  if (sigAlg == NID_sha1WithRSAEncryption ||
631  sigAlg == NID_ecdsa_with_SHA1) {
632  certCrypto = CertCrypto::SHA1_SIGNATURE;
633  VLOG(4) << "Adding SSLContext with SHA1 Signature";
634  } else {
635  certCrypto = CertCrypto::BEST_AVAILABLE;
636  VLOG(4) << "Adding SSLContext with best available crypto";
637  }
638 
639  // Insert by CN
640  insertSSLCtxByDomainName(cn->c_str(),
641  cn->length(),
642  sslCtx,
643  contexts,
644  certCrypto);
645 
646  // Insert by subject alternative name(s)
647  auto altNames = SSLUtil::getSubjectAltName(x509);
648  if (altNames) {
649  for (auto& name : *altNames) {
651  name.length(),
652  sslCtx,
653  contexts,
654  certCrypto);
655  }
656  }
657 
658  if (defaultFallback) {
659  contexts.defaultCtxDomainName = *cn;
660  }
661 
662  contexts.ctxs.emplace_back(sslCtx);
663 }
static std::unique_ptr< std::list< std::string > > getSubjectAltName(const X509 *cert)
Definition: SSLUtil.cpp:70
const char * name
Definition: http_parser.c:437
void insertSSLCtxByDomainName(const char *dn, size_t len, std::shared_ptr< folly::SSLContext > sslCtx, SslContexts &contexts, CertCrypto certCrypto=CertCrypto::BEST_AVAILABLE)
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
static std::unique_ptr< std::string > getCommonName(const X509 *cert)
Definition: SSLUtil.cpp:54
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
Definition: ScopeGuard.h:184
void wangle::SSLContextManager::insertIntoDnMap ( SSLContextKey  key,
std::shared_ptr< folly::SSLContext sslCtx,
bool  overwrite,
SslContexts contexts 
)
private

Definition at line 731 of file SSLContextManager.cpp.

References wangle::SSLContextManager::SslContexts::dnMap.

Referenced by insertSSLCtxByDomainNameImpl().

735 {
736  const auto v = contexts.dnMap.find(key);
737  if (v == contexts.dnMap.end()) {
738  VLOG(6) << "Inserting SSLContext into map.";
739  contexts.dnMap.emplace(key, sslCtx);
740  } else if (v->second == sslCtx) {
741  VLOG(6)<< "Duplicate CN or subject alternative name found in the same X509."
742  " Ignore the later name.";
743  } else if (overwrite) {
744  VLOG(6) << "Overwriting SSLContext.";
745  v->second = sslCtx;
746  } else {
747  VLOG(6) << "Leaving existing SSLContext in map.";
748  }
749 }
void wangle::SSLContextManager::insertSSLCtxByDomainName ( const char *  dn,
size_t  len,
std::shared_ptr< folly::SSLContext sslCtx,
SslContexts contexts,
CertCrypto  certCrypto = CertCrypto::BEST_AVAILABLE 
)
protected

Insert a SSLContext by domain name.

Definition at line 666 of file SSLContextManager.cpp.

References insertSSLCtxByDomainNameImpl(), and strict_.

Referenced by insert(), and wangle::TEST().

670  {
671  try {
672  insertSSLCtxByDomainNameImpl(dn, len, sslCtx, contexts, certCrypto);
673  } catch (const std::runtime_error& ex) {
674  if (strict_) {
675  throw ex;
676  } else {
677  LOG(ERROR) << ex.what() << " DN=" << dn;
678  }
679  }
680 }
void insertSSLCtxByDomainNameImpl(const char *dn, size_t len, std::shared_ptr< folly::SSLContext > sslCtx, SslContexts &contexts, CertCrypto certCrypto)
void wangle::SSLContextManager::insertSSLCtxByDomainName ( const char *  dn,
size_t  len,
std::shared_ptr< folly::SSLContext sslCtx,
CertCrypto  certCrypto = CertCrypto::BEST_AVAILABLE 
)
inlineprotected

Definition at line 198 of file SSLContextManager.h.

202  {
203  insertSSLCtxByDomainName(dn, len, sslCtx, contexts_, certCrypto);
204  }
void insertSSLCtxByDomainName(const char *dn, size_t len, std::shared_ptr< folly::SSLContext > sslCtx, SslContexts &contexts, CertCrypto certCrypto=CertCrypto::BEST_AVAILABLE)
void wangle::SSLContextManager::insertSSLCtxByDomainNameImpl ( const char *  dn,
size_t  len,
std::shared_ptr< folly::SSLContext sslCtx,
SslContexts contexts,
CertCrypto  certCrypto 
)
private

Definition at line 682 of file SSLContextManager.cpp.

References wangle::BEST_AVAILABLE, insertIntoDnMap(), string, and folly::stringPrintf().

Referenced by insertSSLCtxByDomainName().

687 {
688  VLOG(4) <<
689  folly::stringPrintf("Adding CN/Subject-alternative-name \"%s\" for "
690  "SNI search", dn);
691 
692  // Only support wildcard domains which are prefixed exactly by "*." .
693  // "*" appearing at other locations is not accepted.
694 
695  if (len > 2 && dn[0] == '*') {
696  if (dn[1] == '.') {
697  // skip the first '*'
698  dn++;
699  len--;
700  } else {
701  throw std::runtime_error(
702  "Invalid wildcard CN/subject-alternative-name \"" + std::string(dn) + "\" "
703  "(only allow character \".\" after \"*\"");
704  }
705  }
706 
707  if (len == 1 && *dn == '.') {
708  throw std::runtime_error("X509 has only '.' in the CN or subject alternative name "
709  "(after removing any preceding '*')");
710  }
711 
712  if (strchr(dn, '*')) {
713  throw std::runtime_error("X509 has '*' in the the CN or subject alternative name "
714  "(after removing any preceding '*')");
715  }
716 
717  DNString dnstr(dn, len);
718  insertIntoDnMap(SSLContextKey(dnstr, certCrypto), sslCtx, true, contexts);
719  if (certCrypto != CertCrypto::BEST_AVAILABLE) {
720  // Note: there's no partial ordering here (you either get what you request,
721  // or you get best available).
722  VLOG(6) << "Attempting insert of weak crypto SSLContext as best available.";
724  SSLContextKey(dnstr, CertCrypto::BEST_AVAILABLE),
725  sslCtx,
726  false,
727  contexts);
728  }
729 }
std::basic_string< char, dn_char_traits > DNString
std::string stringPrintf(const char *format,...)
Definition: String.cpp:223
void insertIntoDnMap(SSLContextKey key, std::shared_ptr< folly::SSLContext > sslCtx, bool overwrite, SslContexts &contexts)
const char * string
Definition: Conv.cpp:212
virtual void wangle::SSLContextManager::loadCertKeyPairExternal ( const std::shared_ptr< folly::SSLContext > &  ,
const SSLContextConfig ,
const std::string  
)
inlineprotectedvirtual

Definition at line 174 of file SSLContextManager.h.

References folly::FATAL.

Referenced by addSSLContextConfig().

177  {
178  LOG(FATAL) << "Unsupported in base SSLContextManager";
179  }
virtual void wangle::SSLContextManager::overrideConfiguration ( const std::shared_ptr< folly::SSLContext > &  ,
const SSLContextConfig  
)
inlineprotectedvirtual

Definition at line 181 of file SSLContextManager.h.

Referenced by addSSLContextConfig().

183  {}
void wangle::SSLContextManager::reloadTLSTicketKeys ( const std::vector< std::string > &  oldSeeds,
const std::vector< std::string > &  currentSeeds,
const std::vector< std::string > &  newSeeds 
)

Definition at line 808 of file SSLContextManager.cpp.

References contexts_, and wangle::SSLContextManager::SslContexts::ctxs.

811  {
812 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
813  for (auto& ctx : contexts_.ctxs) {
814  auto tmgr = ctx->getTicketManager();
815  if (tmgr) {
816  tmgr->setTLSTicketKeySeeds(oldSeeds, currentSeeds, newSeeds);
817  }
818  }
819 #endif
820 }
std::vector< std::shared_ptr< ServerSSLContext > > ctxs
void wangle::SSLContextManager::resetSSLContextConfigs ( const std::vector< SSLContextConfig > &  ctxConfig,
const SSLCacheOptions cacheOptions,
const TLSTicketKeySeeds ticketSeeds,
const folly::SocketAddress vipAddress,
const std::shared_ptr< SSLCacheProvider > &  externalCache 
)

Resets SSLContextManager with new X509s

Parameters
ctxConfigsDetails of a X509s, private key, password, etc.
cacheOptionsOptions for how to do session caching.
ticketSeedsIf non-null, the initial ticket key seeds to use.
vipAddressWhich VIP are the X509(s) used for? It is only for for user friendly log message
externalCacheOptional external provider for the session cache; may be null

Definition at line 212 of file SSLContextManager.cpp.

References addSSLContextConfig(), contexts_, wangle::SSLContextManager::SslContexts::ctxs, wangle::TLSTicketKeySeeds::currentSeeds, wangle::TLSTicketKeySeeds::newSeeds, wangle::TLSTicketKeySeeds::oldSeeds, and wangle::SSLContextManager::SslContexts::swap().

217  {
218 
219  SslContexts contexts;
220  TLSTicketKeySeeds oldTicketSeeds;
221  // This assumes that all ctxs have the same ticket seeds. Which we assume in
222  // other places as well
223  if (!ticketSeeds) {
224  // find first non null ticket manager and update seeds from it
225  for (auto& ctx : contexts_.ctxs) {
226  auto ticketManager = ctx->getTicketManager();
227  if (ticketManager) {
228  ticketManager->getTLSTicketKeySeeds(
229  oldTicketSeeds.oldSeeds,
230  oldTicketSeeds.currentSeeds,
231  oldTicketSeeds.newSeeds);
232  break;
233  }
234  }
235  }
236 
237  for (const auto& ctxConfig : ctxConfigs) {
238  addSSLContextConfig(ctxConfig,
239  cacheOptions,
240  ticketSeeds ? ticketSeeds : &oldTicketSeeds,
241  vipAddress,
242  externalCache,
243  &contexts);
244  }
245  contexts_.swap(contexts);
246 }
std::vector< std::shared_ptr< ServerSSLContext > > ctxs
void addSSLContextConfig(const SSLContextConfig &ctxConfig, const SSLCacheOptions &cacheOptions, const TLSTicketKeySeeds *ticketSeeds, const folly::SocketAddress &vipAddress, const std::shared_ptr< SSLCacheProvider > &externalCache, SslContexts *contexts=nullptr)
void swap(SslContexts &other) noexcept
void wangle::SSLContextManager::setClientHelloExtStats ( ClientHelloExtStats stats)
inline

SSLContextManager only collects SNI stats now

Definition at line 165 of file SSLContextManager.h.

165  {
166  clientHelloTLSExtStats_ = stats;
167  }
ClientHelloExtStats * clientHelloTLSExtStats_
void wangle::SSLContextManager::setClientVerifyCallback ( std::unique_ptr< ClientCertVerifyCallback cb)
inline

Definition at line 169 of file SSLContextManager.h.

References folly::gen::move.

169  {
171  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::unique_ptr< ClientCertVerifyCallback > clientCertVerifyCallback_
void wangle::SSLContextManager::setSSLStats ( SSLStats stats)
inline

Definition at line 158 of file SSLContextManager.h.

158  {
159  stats_ = stats;
160  }

Member Data Documentation

std::unique_ptr<ClientCertVerifyCallback> wangle::SSLContextManager::clientCertVerifyCallback_ {nullptr}
private

Definition at line 267 of file SSLContextManager.h.

Referenced by addSSLContextConfig().

ClientHelloExtStats* wangle::SSLContextManager::clientHelloTLSExtStats_ {nullptr}
private

Definition at line 264 of file SSLContextManager.h.

Referenced by addSSLContextConfig().

folly::EventBase* wangle::SSLContextManager::eventBase_
private

Definition at line 263 of file SSLContextManager.h.

SSLContextConfig::SNINoMatchFn wangle::SSLContextManager::noMatchFn_
private

Definition at line 265 of file SSLContextManager.h.

Referenced by addSSLContextConfig(), and ctxSetupByOpensslFeature().

SSLStats* wangle::SSLContextManager::stats_ {nullptr}
protected

Definition at line 186 of file SSLContextManager.h.

Referenced by addSSLContextConfig().

bool wangle::SSLContextManager::strict_ {true}
private

Definition at line 266 of file SSLContextManager.h.

Referenced by insertSSLCtxByDomainName().

std::string wangle::SSLContextManager::vipName_
protected

Definition at line 185 of file SSLContextManager.h.

Referenced by addSSLContextConfig().


The documentation for this class was generated from the following files: