From e8386bd14e9783f0bef39bdf577545522e33e719 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 3 Nov 2015 16:56:38 +0100 Subject: Provide an adhoc option to let user pass the cert verif for some IRC servers --- louloulibs/network/credentials_manager.cpp | 35 +++++++++++++++++++++++++----- louloulibs/network/credentials_manager.hpp | 11 +++++++--- louloulibs/network/tcp_socket_handler.cpp | 6 +++-- louloulibs/network/tcp_socket_handler.hpp | 12 +++++++++- 4 files changed, 53 insertions(+), 11 deletions(-) (limited to 'louloulibs') diff --git a/louloulibs/network/credentials_manager.cpp b/louloulibs/network/credentials_manager.cpp index 7c13319..b9a9af8 100644 --- a/louloulibs/network/credentials_manager.cpp +++ b/louloulibs/network/credentials_manager.cpp @@ -1,25 +1,48 @@ #include "louloulibs.h" #ifdef BOTAN_FOUND +#include #include #include #include -Basic_Credentials_Manager::Basic_Credentials_Manager(): - Botan::Credentials_Manager() +#ifdef USE_DATABASE +# include +#endif + +Botan::Certificate_Store_In_Memory Basic_Credentials_Manager::certificate_store; +bool Basic_Credentials_Manager::certs_loaded = false; + +Basic_Credentials_Manager::Basic_Credentials_Manager(const TCPSocketHandler* const socket_handler): + Botan::Credentials_Manager(), + socket_handler(socket_handler) { this->load_certs(); } + void Basic_Credentials_Manager::verify_certificate_chain(const std::string& type, const std::string& purported_hostname, const std::vector& certs) { log_debug("Checking remote certificate (" << type << ") for hostname " << purported_hostname); - Botan::Credentials_Manager::verify_certificate_chain(type, purported_hostname, certs); - log_debug("Certificate is valid"); + try + { + Botan::Credentials_Manager::verify_certificate_chain(type, purported_hostname, certs); + log_debug("Certificate is valid"); + } + catch (const std::exception& tls_exception) + { + log_warning("TLS certificate check failed: " << tls_exception.what()); + if (this->socket_handler->abort_on_invalid_cert()) + throw; + } } + void Basic_Credentials_Manager::load_certs() { + // Only load the certificates the first time + if (Basic_Credentials_Manager::certs_loaded) + return; const std::vector paths = {"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"}; for (const auto& path: paths) { @@ -27,10 +50,12 @@ void Basic_Credentials_Manager::load_certs() while (!bundle.end_of_data() && bundle.check_available(27)) { const Botan::X509_Certificate cert(bundle); - this->certificate_store.add_certificate(cert); + Basic_Credentials_Manager::certificate_store.add_certificate(cert); } } + Basic_Credentials_Manager::certs_loaded = true; } + std::vector Basic_Credentials_Manager::trusted_certificate_authorities(const std::string&, const std::string&) { return {&this->certificate_store}; diff --git a/louloulibs/network/credentials_manager.hpp b/louloulibs/network/credentials_manager.hpp index 8641f1d..e292321 100644 --- a/louloulibs/network/credentials_manager.hpp +++ b/louloulibs/network/credentials_manager.hpp @@ -8,10 +8,12 @@ #include #include +class TCPSocketHandler; + class Basic_Credentials_Manager: public Botan::Credentials_Manager { public: - Basic_Credentials_Manager(); + Basic_Credentials_Manager(const TCPSocketHandler* const socket_handler); void verify_certificate_chain(const std::string& type, const std::string& purported_hostname, const std::vector&) override final; @@ -19,8 +21,11 @@ public: const std::string& context) override final; private: - void load_certs(); - Botan::Certificate_Store_In_Memory certificate_store; + const TCPSocketHandler* const socket_handler; + + static void load_certs(); + static Botan::Certificate_Store_In_Memory certificate_store; + static bool certs_loaded; }; #endif //BOTAN_FOUND diff --git a/louloulibs/network/tcp_socket_handler.cpp b/louloulibs/network/tcp_socket_handler.cpp index 81a36ef..0ed74a2 100644 --- a/louloulibs/network/tcp_socket_handler.cpp +++ b/louloulibs/network/tcp_socket_handler.cpp @@ -19,7 +19,6 @@ # include Botan::AutoSeeded_RNG TCPSocketHandler::rng; -Basic_Credentials_Manager TCPSocketHandler::credential_manager; Botan::TLS::Policy TCPSocketHandler::policy; Botan::TLS::Session_Manager_In_Memory TCPSocketHandler::session_manager(TCPSocketHandler::rng); @@ -40,6 +39,9 @@ TCPSocketHandler::TCPSocketHandler(std::shared_ptr poller): connected(false), connecting(false), hostname_resolution_failed(false) +#ifdef BOTAN_FOUND + ,credential_manager(this) +#endif {} void TCPSocketHandler::init_socket(const struct addrinfo* rp) @@ -369,7 +371,7 @@ void TCPSocketHandler::start_tls() std::bind(&TCPSocketHandler::tls_data_cb, this, ph::_1, ph::_2), std::bind(&TCPSocketHandler::tls_alert_cb, this, ph::_1, ph::_2, ph::_3), std::bind(&TCPSocketHandler::tls_handshake_cb, this, ph::_1), - session_manager, credential_manager, policy, + session_manager, this->credential_manager, policy, rng, server_info, Botan::TLS::Protocol_Version::latest_tls_version()); } diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp index d173c1f..213e286 100644 --- a/louloulibs/network/tcp_socket_handler.hpp +++ b/louloulibs/network/tcp_socket_handler.hpp @@ -90,6 +90,16 @@ public: * The size argument is the size of the last chunk of data that was added to the buffer. */ virtual void parse_in_buffer(const size_t size) = 0; +#ifdef BOTAN_FOUND + /** + * Tell whether the credential manager should cancel the connection when the + * certificate is invalid. + */ + virtual bool abort_on_invalid_cert() const + { + return true; + } +#endif bool is_connected() const override final; bool is_connecting() const; @@ -230,9 +240,9 @@ private: * Botan stuff to manipulate a TLS session. */ static Botan::AutoSeeded_RNG rng; - static Basic_Credentials_Manager credential_manager; static Botan::TLS::Policy policy; static Botan::TLS::Session_Manager_In_Memory session_manager; + Basic_Credentials_Manager credential_manager; /** * We use a unique_ptr because we may not want to create the object at * all. The Botan::TLS::Client object generates a handshake message and -- cgit v1.2.3