Repository: envoyproxy/envoy
File: source/common/tls/cert_validator/default_validator.cc (C++)

Code before:
Envoy::Ssl::ClientValidationStatus
DefaultCertValidator::verifyCertificate(X509* cert, const std::vector<std::string>& verify_san_list,
                                        const std::vector<SanMatcherPtr>& subject_alt_name_matchers,
                                        OptRef<const StreamInfo::StreamInfo> stream_info,
                                        std::string* error_details, uint8_t* out_alert) {
  Envoy::Ssl::ClientValidationStatus validated = Envoy::Ssl::ClientValidationStatus::NotValidated;
  if (!verify_san_list.empty()) {
    if (!verifySubjectAltName(cert, verify_san_list)) {
      const std::string error_msg =
          fmt::format("verify cert failed: verify SAN list, SAN List is [{}]",
                      fmt::join(verify_san_list, ", "));

      if (error_details != nullptr) {
        *error_details = error_msg;
      }
      ENVOY_LOG(debug, error_msg);
      stats_.fail_verify_san_.inc();
      return Envoy::Ssl::ClientValidationStatus::Failed;
    }
    validated = Envoy::Ssl::ClientValidationStatus::Validated;
  }

  if (!subject_alt_name_matchers.empty()) {
    if (!matchSubjectAltName(cert, stream_info, subject_alt_name_matchers)) {
      const std::string error_msg =
          fmt::format("verify cert failed: SAN matcher, certificate SANs are [{}]",
                      fmt::join(CertValidatorUtil::getCertificateSans(cert), ", "));
      if (error_details != nullptr) {
        *error_details = error_msg;
      }
      ENVOY_LOG(debug, error_msg);
      stats_.fail_verify_san_.inc();
      return Envoy::Ssl::ClientValidationStatus::Failed;
    }
    validated = Envoy::Ssl::ClientValidationStatus::Validated;
  }

  if (!verify_certificate_hash_list_.empty() || !verify_certificate_spki_list_.empty()) {
    const bool valid_certificate_hash =
        !verify_certificate_hash_list_.empty() &&
        verifyCertificateHashList(cert, verify_certificate_hash_list_);
    const bool valid_certificate_spki =
        !verify_certificate_spki_list_.empty() &&
        verifyCertificateSpkiList(cert, verify_certificate_spki_list_);

    if (!valid_certificate_hash && !valid_certificate_spki) {
      if (out_alert != nullptr) {
        *out_alert = SSL_AD_BAD_CERTIFICATE_HASH_VALUE;
      }
      const char* error = "verify cert failed: cert hash and spki";
      if (error_details != nullptr) {

Review comment (bug):
is it possible to avoid this computation of SANs for logging in regular flows and only trigger when the debug mode is enabled for this component?

Code after:
Envoy::Ssl::ClientValidationStatus
DefaultCertValidator::verifyCertificate(X509* cert, const std::vector<std::string>& verify_san_list,
                                        const std::vector<SanMatcherPtr>& subject_alt_name_matchers,
                                        OptRef<const StreamInfo::StreamInfo> stream_info,
                                        std::string* error_details, uint8_t* out_alert) {
  Envoy::Ssl::ClientValidationStatus validated = Envoy::Ssl::ClientValidationStatus::NotValidated;
  if (!verify_san_list.empty()) {
    if (!verifySubjectAltName(cert, verify_san_list)) {
      const std::string error_msg = fmt::format(
          "verify cert failed: verify SAN list, expected SANs: [{}], certificate SANs: [{}]",
          fmt::join(verify_san_list, ", "),
          fmt::join(Utility::getCertificateSansForLogging(cert), ", "));

      if (error_details != nullptr) {
        *error_details = error_msg;
      }
      ENVOY_LOG(debug, error_msg);
      stats_.fail_verify_san_.inc();
      return Envoy::Ssl::ClientValidationStatus::Failed;
    }
    validated = Envoy::Ssl::ClientValidationStatus::Validated;
  }

  if (!subject_alt_name_matchers.empty()) {
    if (!matchSubjectAltName(cert, stream_info, subject_alt_name_matchers)) {
      const std::string error_msg =
          fmt::format("verify cert failed: SAN matcher, certificate SANs are [{}]",
                      fmt::join(Utility::getCertificateSansForLogging(cert), ", "));
      if (error_details != nullptr) {
        *error_details = error_msg;
      }
      ENVOY_LOG(debug, error_msg);
      stats_.fail_verify_san_.inc();
      return Envoy::Ssl::ClientValidationStatus::Failed;
    }
    validated = Envoy::Ssl::ClientValidationStatus::Validated;
  }

  if (!verify_certificate_hash_list_.empty() || !verify_certificate_spki_list_.empty()) {
    const bool valid_certificate_hash =
        !verify_certificate_hash_list_.empty() &&
        verifyCertificateHashList(cert, verify_certificate_hash_list_);
    const bool valid_certificate_spki =
        !verify_certificate_spki_list_.empty() &&
        verifyCertificateSpkiList(cert, verify_certificate_spki_list_);

    if (!valid_certificate_hash && !valid_certificate_spki) {
      if (out_alert != nullptr) {
        *out_alert = SSL_AD_BAD_CERTIFICATE_HASH_VALUE;
      }
      const char* error = "verify cert failed: cert hash and spki";