void SSLContextManager::SslContexts::insert()

in wangle/ssl/SSLContextManager.cpp [940:1014]


void SSLContextManager::SslContexts::insert(
    shared_ptr<ServerSSLContext> sslCtx,
    bool defaultFallback) {
  X509* x509 = getX509(sslCtx->getSSLCtx());
  if (!x509) {
    throw std::runtime_error("SSLCtx is invalid");
  }
  auto guard = folly::makeGuard([x509] { X509_free(x509); });

  auto identityResult = getCertIdentity(*x509);
  auto& identity = identityResult.first;
  auto identitySource = identityResult.second;

  if (!identity) {
    throw std::runtime_error("Cannot get certificate identity");
  }

  /**
   * 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.
   * ......"
   */

  // Not sure if we ever get this kind of X509...
  // If we do, assume '*' is always in the CN and ignore all subject alternative
  // names.
  if (identitySource == CertIdentitySource::CommonName &&
      identity->length() == 1 && (*identity)[0] == '*') {
    if (!defaultFallback) {
      throw std::runtime_error("STAR X509 is not the default");
    }
    return;
  }

  CertCrypto certCrypto;
  int sigAlg = X509_get_signature_nid(x509);
  if (sigAlg == NID_sha1WithRSAEncryption || sigAlg == NID_ecdsa_with_SHA1) {
    certCrypto = CertCrypto::SHA1_SIGNATURE;
    VLOG(4) << "Adding SSLContext with SHA1 Signature";
  } else {
    certCrypto = CertCrypto::BEST_AVAILABLE;
    VLOG(4) << "Adding SSLContext with best available crypto";
  }

  // Insert by identity.
  //
  // This will be used as the lookup key if this SSLContext is marked as
  // the default.
  insertSSLCtxByDomainName(*identity, sslCtx, certCrypto, defaultFallback);

  // Insert by subject alternative name(s)
  auto altNames = SSLUtil::getSubjectAltName(x509);
  if (altNames) {
    for (auto& name : *altNames) {
      insertSSLCtxByDomainName(name, sslCtx, certCrypto, defaultFallback);
    }
  }

  if (defaultFallback) {
    defaultCtxDomainName_ = *identity;
  } else {
    addServerContext(sslCtx);
  }
}