~singpolyma/biboumi

7784c568432231c737c789b065af6b81e038c54d — louiz’ 7 years ago a66c67e
Update the verify_certificate_chain code to work with botan >= 1.11.34 as well
M louloulibs/network/credentials_manager.cpp => louloulibs/network/credentials_manager.cpp +27 -8
@@ 37,6 37,28 @@ void BasicCredentialsManager::set_trusted_fingerprint(const std::string& fingerp
  this->trusted_fingerprint = fingerprint;
}

const std::string& BasicCredentialsManager::get_trusted_fingerprint() const
{
  return this->trusted_fingerprint;
}

void check_tls_certificate(const std::vector<Botan::X509_Certificate>& certs,
                           const std::string& hostname, const std::string& trusted_fingerprint,
                           std::exception_ptr exc)
{

  if (!trusted_fingerprint.empty() && !certs.empty() &&
      trusted_fingerprint == certs[0].fingerprint() &&
      certs[0].matches_dns_name(hostname))
    // We trust the certificate, based on the trusted fingerprint and
    // the fact that the hostname matches
    return;

  if (exc)
    std::rethrow_exception(exc);
}

#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,34)
void BasicCredentialsManager::verify_certificate_chain(const std::string& type,
                                                       const std::string& purported_hostname,
                                                       const std::vector<Botan::X509_Certificate>& certs)


@@ 50,17 72,14 @@ void BasicCredentialsManager::verify_certificate_chain(const std::string& type,
  catch (const std::exception& tls_exception)
    {
      log_warning("TLS certificate check failed: ", tls_exception.what());
      if (!this->trusted_fingerprint.empty() && !certs.empty() &&
          this->trusted_fingerprint == certs[0].fingerprint() &&
          certs[0].matches_dns_name(purported_hostname))
        // We trust the certificate, based on the trusted fingerprint and
        // the fact that the hostname matches
        return;

      std::exception_ptr exception_ptr{};
      if (this->socket_handler->abort_on_invalid_cert())
        throw;
        exception_ptr = std::current_exception();

      check_tls_certificate(certs, purported_hostname, this->trusted_fingerprint, exception_ptr);
    }
}
#endif

bool BasicCredentialsManager::try_to_open_one_ca_bundle(const std::vector<std::string>& paths)
{

M louloulibs/network/credentials_manager.hpp => louloulibs/network/credentials_manager.hpp +15 -0
@@ 9,6 9,18 @@

class TCPSocketHandler;

/**
 * If the given cert isn’t valid, based on the given hostname
 * and fingerprint, then throws the exception if it’s non-empty.
 *
 * Must be called after the standard (from Botan) way of
 * checking the certificate, if we want to also accept certificates based
 * on a trusted fingerprint.
 */
void check_tls_certificate(const std::vector<Botan::X509_Certificate>& certs,
                           const std::string& hostname, const std::string& trusted_fingerprint,
                           std::exception_ptr exc);

class BasicCredentialsManager: public Botan::Credentials_Manager
{
public:


@@ 19,12 31,15 @@ public:
  BasicCredentialsManager& operator=(const BasicCredentialsManager&) = delete;
  BasicCredentialsManager& operator=(BasicCredentialsManager&&) = delete;

#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,34)
  void verify_certificate_chain(const std::string& type,
                                const std::string& purported_hostname,
                                const std::vector<Botan::X509_Certificate>&) override final;
#endif
  std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(const std::string& type,
                                                                         const std::string& context) override final;
  void set_trusted_fingerprint(const std::string& fingerprint);
  const std::string& get_trusted_fingerprint() const;

private:
  const TCPSocketHandler* const socket_handler;

M louloulibs/network/tcp_socket_handler.cpp => louloulibs/network/tcp_socket_handler.cpp +25 -0
@@ 311,6 311,31 @@ bool TCPSocketHandler::tls_session_established(const Botan::TLS::Session& sessio
  return true;
}

#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
void TCPSocketHandler::tls_verify_cert_chain(const std::vector<Botan::X509_Certificate>& cert_chain,
                                             const std::vector<std::shared_ptr<const Botan::OCSP::Response>>& ocsp_responses,
                                             const std::vector<Botan::Certificate_Store*>& trusted_roots,
                                             Botan::Usage_Type usage, const std::string& hostname,
                                             const Botan::TLS::Policy& policy)
{
  log_debug("Checking remote certificate for hostname ", hostname);
  try
    {
      Botan::TLS::Callbacks::tls_verify_cert_chain(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
      log_debug("Certificate is valid");
    }
  catch (const std::exception& tls_exception)
    {
      log_warning("TLS certificate check failed: ", tls_exception.what());
      std::exception_ptr exception_ptr{};
      if (this->abort_on_invalid_cert())
        exception_ptr = std::current_exception();

      check_tls_certificate(cert_chain, hostname, this->credential_manager.get_trusted_fingerprint(), exception_ptr);
    }
}
#endif

void TCPSocketHandler::on_tls_activated()
{
  this->send_data({});

M louloulibs/network/tcp_socket_handler.hpp => louloulibs/network/tcp_socket_handler.hpp +9 -0
@@ 172,6 172,15 @@ private:
   * anything here appart from logging the TLS session information.
   */
  bool tls_session_established(const Botan::TLS::Session& session) BOTAN_TLS_CALLBACKS_OVERRIDE;

#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
  void tls_verify_cert_chain(const std::vector<Botan::X509_Certificate>& cert_chain,
                             const std::vector<std::shared_ptr<const Botan::OCSP::Response>>& ocsp_responses,
                             const std::vector<Botan::Certificate_Store*>& trusted_roots,
                             Botan::Usage_Type usage,
                             const std::string& hostname,
                             const Botan::TLS::Policy& policy) BOTAN_TLS_CALLBACKS_OVERRIDE;
#endif
  /**
   * Called whenever the tls session goes from inactive to active. This
   * means that the handshake has just been successfully done, and we can