void DefaultCertificateVerifier::verify()

in fizz/protocol/DefaultCertificateVerifier.cpp [49:119]


void DefaultCertificateVerifier::verify(
    const std::vector<std::shared_ptr<const fizz::PeerCert>>& certs) const {
  if (certs.empty()) {
    throw std::runtime_error("no certificates to verify");
  }

  auto leafCert = certs.front()->getX509();

  auto certChainStack = std::unique_ptr<STACK_OF(X509), STACK_OF_X509_deleter>(
      sk_X509_new_null());
  if (!certChainStack) {
    throw std::bad_alloc();
  }

  for (size_t i = 1; i < certs.size(); i++) {
    sk_X509_push(certChainStack.get(), certs[i]->getX509().get());
  }

  auto ctx = folly::ssl::X509StoreCtxUniquePtr(X509_STORE_CTX_new());
  if (!ctx) {
    throw std::bad_alloc();
  }

  if (X509_STORE_CTX_init(
          ctx.get(),
          x509Store_ ? x509Store_.get() : getDefaultX509Store(),
          leafCert.get(),
          certChainStack.get()) != 1) {
    throw std::runtime_error("failed to initialize store context");
  }

  if (X509_STORE_CTX_set_default(
          ctx.get(),
          context_ == VerificationContext::Server ? "ssl_client"
                                                  : "ssl_server") != 1) {
    throw std::runtime_error("failed to set default verification method");
  }

  if (customVerifyCallback_) {
    X509_STORE_CTX_set_verify_cb(ctx.get(), customVerifyCallback_);
  }

  folly::ssl::X509VerifyParam param(X509_VERIFY_PARAM_new());
  if (!param) {
    throw std::bad_alloc();
  }

  if (X509_VERIFY_PARAM_set_flags(param.get(), X509_V_FLAG_X509_STRICT) != 1) {
    throw std::runtime_error("failed to set strict certificate checking");
  }

  if (X509_VERIFY_PARAM_set1(
          X509_STORE_CTX_get0_param(ctx.get()), param.get()) != 1) {
    throw std::runtime_error("failed to apply verification parameters");
  }

  int ret = 0;
  // if openssl is not built with TSAN then we can get a TSAN false positive
  // when calling X509_verify_cert from multiple threads
  {
    folly::annotate_ignore_thread_sanitizer_guard g(__FILE__, __LINE__);
    ret = X509_verify_cert(ctx.get());
  }

  if (ret != 1) {
    const auto errorInt = X509_STORE_CTX_get_error(ctx.get());
    std::string errorText =
        std::string(X509_verify_cert_error_string(errorInt));
    throw std::runtime_error("certificate verification failed: " + errorText);
  }
}