From 27940ecdd136c247a7daf78f30642bbf816648ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?louiz=E2=80=99?= <louiz@louiz.org>
Date: Tue, 21 Mar 2017 11:32:05 +0100
Subject: Backport the master FindBOTAN.cmake, to find botan 2.0 as well

ref #3245
---
 louloulibs/cmake/Modules/FindBOTAN.cmake | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

(limited to 'louloulibs')

diff --git a/louloulibs/cmake/Modules/FindBOTAN.cmake b/louloulibs/cmake/Modules/FindBOTAN.cmake
index a12bd35..13d2de4 100644
--- a/louloulibs/cmake/Modules/FindBOTAN.cmake
+++ b/louloulibs/cmake/Modules/FindBOTAN.cmake
@@ -15,21 +15,29 @@
 #
 # This file is in the public domain
 
-find_path(BOTAN_INCLUDE_DIRS NAMES botan/botan.h
-  PATH_SUFFIXES botan-1.11
-  DOC "The botan include directory")
+include(FindPkgConfig)
 
-find_library(BOTAN_LIBRARIES NAMES botan botan-1.11
-  DOC "The botan library")
+pkg_check_modules(BOTAN botan-2)
+pkg_check_modules(BOTAN botan-1.11)
 
-# Use some standard module to handle the QUIETLY and REQUIRED arguments, and
-# set BOTAN_FOUND to TRUE if these two variables are set.
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(BOTAN REQUIRED_VARS BOTAN_LIBRARIES BOTAN_INCLUDE_DIRS)
+if(NOT BOTAN_FOUND)
+  find_path(BOTAN_INCLUDE_DIRS NAMES botan/botan.h
+      PATH_SUFFIXES botan-2 botan-1.11
+      DOC "The botan include directory")
 
-if(BOTAN_FOUND)
-  set(BOTAN_LIBRARY ${BOTAN_LIBRARIES})
-  set(BOTAN_INCLUDE_DIR ${BOTAN_INCLUDE_DIRS})
+  find_library(BOTAN_LIBRARIES NAMES botan botan-2 botan-1.11
+      DOC "The botan library")
+
+  # Use some standard module to handle the QUIETLY and REQUIRED arguments, and
+  # set BOTAN_FOUND to TRUE if these two variables are set.
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(BOTAN REQUIRED_VARS BOTAN_LIBRARIES BOTAN_INCLUDE_DIRS)
+
+  if(BOTAN_FOUND)
+    set(BOTAN_LIBRARY ${BOTAN_LIBRARIES} CACHE INTERNAL "")
+    set(BOTAN_INCLUDE_DIR ${BOTAN_INCLUDE_DIRS} CACHE INTERNAL "")
+    set(BOTAN_FOUND ${BOTAN_FOUND} CACHE INTERNAL "")
+  endif()
 endif()
 
 mark_as_advanced(BOTAN_INCLUDE_DIRS BOTAN_LIBRARIES)
-- 
cgit v1.2.3


From 395297e488cee2d19eb75f5a42102f1f5daa3a40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?louiz=E2=80=99?= <louiz@louiz.org>
Date: Fri, 2 Dec 2016 16:50:28 +0100
Subject: Use the new botan 1.11.32 Tls::Client API (but stay compatible with
 older ones)

ref #3245
---
 louloulibs/network/tcp_socket_handler.cpp | 20 ++++++++++++--------
 louloulibs/network/tcp_socket_handler.hpp | 30 ++++++++++++++++++++++++++----
 2 files changed, 38 insertions(+), 12 deletions(-)

(limited to 'louloulibs')

diff --git a/louloulibs/network/tcp_socket_handler.cpp b/louloulibs/network/tcp_socket_handler.cpp
index 1dddde5..d509a63 100644
--- a/louloulibs/network/tcp_socket_handler.cpp
+++ b/louloulibs/network/tcp_socket_handler.cpp
@@ -419,10 +419,14 @@ void TCPSocketHandler::start_tls()
 {
   Botan::TLS::Server_Information server_info(this->address, "irc", std::stoul(this->port));
   this->tls = std::make_unique<Botan::TLS::Client>(
-      std::bind(&TCPSocketHandler::tls_output_fn, this, ph::_1, ph::_2),
-      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),
+# if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,32)
+      *this,
+# else
+      [this](const Botan::byte* data, size_t size) { this->tls_emit_data(data, size); },
+      [this](const Botan::byte* data, size_t size) { this->tls_record_received(0, data, size); },
+      [this](Botan::TLS::Alert alert, const Botan::byte*, size_t) { this->tls_alert(alert); },
+      [this](const Botan::TLS::Session& session) { return this->tls_session_established(session); },
+# endif
       session_manager, this->credential_manager, policy,
       rng, server_info, Botan::TLS::Protocol_Version::latest_tls_version());
 }
@@ -475,7 +479,7 @@ void TCPSocketHandler::tls_send(std::string&& data)
                          std::make_move_iterator(data.end()));
 }
 
-void TCPSocketHandler::tls_data_cb(const Botan::byte* data, size_t size)
+void TCPSocketHandler::tls_record_received(uint64_t, const Botan::byte *data, size_t size)
 {
   this->in_buf += std::string(reinterpret_cast<const char*>(data),
                               size);
@@ -483,17 +487,17 @@ void TCPSocketHandler::tls_data_cb(const Botan::byte* data, size_t size)
     this->parse_in_buffer(size);
 }
 
-void TCPSocketHandler::tls_output_fn(const Botan::byte* data, size_t size)
+void TCPSocketHandler::tls_emit_data(const Botan::byte *data, size_t size)
 {
   this->raw_send(std::string(reinterpret_cast<const char*>(data), size));
 }
 
-void TCPSocketHandler::tls_alert_cb(Botan::TLS::Alert alert, const Botan::byte*, size_t)
+void TCPSocketHandler::tls_alert(Botan::TLS::Alert alert)
 {
   log_debug("tls_alert: ", alert.type_string());
 }
 
-bool TCPSocketHandler::tls_handshake_cb(const Botan::TLS::Session& session)
+bool TCPSocketHandler::tls_session_established(const Botan::TLS::Session& session)
 {
   log_debug("Handshake with ", session.server_info().hostname(), " complete.",
             " Version: ", session.version().to_string(),
diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp
index 20a3e5a..40532f0 100644
--- a/louloulibs/network/tcp_socket_handler.hpp
+++ b/louloulibs/network/tcp_socket_handler.hpp
@@ -19,6 +19,25 @@
 #include <string>
 #include <list>
 
+#ifdef BOTAN_FOUND
+class BiboumiTLSPolicy: public Botan::TLS::Policy
+{
+public:
+# if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+  bool use_ecc_point_compression() const override
+  {
+    return true;
+  }
+# endif
+};
+
+# if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,32)
+#  define BOTAN_TLS_CALLBACKS_OVERRIDE override final
+# else
+#  define BOTAN_TLS_CALLBACKS_OVERRIDE
+# endif
+#endif
+
 /**
  * An interface, with a series of callbacks that should be implemented in
  * subclasses that deal with a socket. These callbacks are called on various events
@@ -26,6 +45,9 @@
  * (select/poll/epoll etc)
  */
 class TCPSocketHandler: public SocketHandler
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,32)
+    ,public Botan::TLS::Callbacks
+#endif
 {
 protected:
   ~TCPSocketHandler();
@@ -158,22 +180,22 @@ private:
    * Called by the tls object that some data has been decrypt. We call
    * parse_in_buffer() to handle that unencrypted data.
    */
-  void tls_data_cb(const Botan::byte* data, size_t size);
+  void tls_record_received(uint64_t rec_no, const Botan::byte* data, size_t size) BOTAN_TLS_CALLBACKS_OVERRIDE;
   /**
    * Called by the tls object to indicate that some data has been encrypted
    * and is now ready to be sent on the socket as is.
    */
-  void tls_output_fn(const Botan::byte* data, size_t size);
+  void tls_emit_data(const Botan::byte* data, size_t size) BOTAN_TLS_CALLBACKS_OVERRIDE;
   /**
    * Called by the tls object to indicate that a TLS alert has been
    * received. We don’t use it, we just log some message, at the moment.
    */
-  void tls_alert_cb(Botan::TLS::Alert alert, const Botan::byte*, size_t);
+  void tls_alert(Botan::TLS::Alert alert) BOTAN_TLS_CALLBACKS_OVERRIDE;
   /**
    * Called by the tls object at the end of the TLS handshake. We don't do
    * anything here appart from logging the TLS session information.
    */
-  bool tls_handshake_cb(const Botan::TLS::Session& session);
+  bool tls_session_established(const Botan::TLS::Session& session) BOTAN_TLS_CALLBACKS_OVERRIDE;
   /**
    * Called whenever the tls session goes from inactive to active. This
    * means that the handshake has just been successfully done, and we can
-- 
cgit v1.2.3


From cb79fc1b3d492af60404b5be1c0cb1c8c8065801 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?louiz=E2=80=99?= <louiz@louiz.org>
Date: Sun, 4 Dec 2016 22:17:37 +0100
Subject: Update the verify_certificate_chain code to work with botan >=
 1.11.34 as well

ref #3245
---
 louloulibs/network/credentials_manager.cpp | 35 +++++++++++++++++++++++-------
 louloulibs/network/credentials_manager.hpp | 15 +++++++++++++
 louloulibs/network/tcp_socket_handler.cpp  | 25 +++++++++++++++++++++
 louloulibs/network/tcp_socket_handler.hpp  |  9 ++++++++
 4 files changed, 76 insertions(+), 8 deletions(-)

(limited to 'louloulibs')

diff --git a/louloulibs/network/credentials_manager.cpp b/louloulibs/network/credentials_manager.cpp
index ed04d24..289307b 100644
--- a/louloulibs/network/credentials_manager.cpp
+++ b/louloulibs/network/credentials_manager.cpp
@@ -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)
 {
diff --git a/louloulibs/network/credentials_manager.hpp b/louloulibs/network/credentials_manager.hpp
index 7557372..29ee024 100644
--- a/louloulibs/network/credentials_manager.hpp
+++ b/louloulibs/network/credentials_manager.hpp
@@ -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;
diff --git a/louloulibs/network/tcp_socket_handler.cpp b/louloulibs/network/tcp_socket_handler.cpp
index d509a63..d9ec226 100644
--- a/louloulibs/network/tcp_socket_handler.cpp
+++ b/louloulibs/network/tcp_socket_handler.cpp
@@ -509,6 +509,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({});
diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp
index 40532f0..8baa1d1 100644
--- a/louloulibs/network/tcp_socket_handler.hpp
+++ b/louloulibs/network/tcp_socket_handler.hpp
@@ -196,6 +196,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
-- 
cgit v1.2.3


From 8ce6759eae618cb1109bd5dea70c3eb17f733445 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?louiz=E2=80=99?= <louiz@louiz.org>
Date: Tue, 21 Mar 2017 15:04:45 +0100
Subject: Add missing botan/version.h includes

---
 louloulibs/network/credentials_manager.hpp | 1 +
 louloulibs/network/tcp_socket_handler.hpp  | 2 ++
 2 files changed, 3 insertions(+)

(limited to 'louloulibs')

diff --git a/louloulibs/network/credentials_manager.hpp b/louloulibs/network/credentials_manager.hpp
index 29ee024..9f42782 100644
--- a/louloulibs/network/credentials_manager.hpp
+++ b/louloulibs/network/credentials_manager.hpp
@@ -6,6 +6,7 @@
 
 #include <botan/botan.h>
 #include <botan/tls_client.h>
+#include <botan/version.h>
 
 class TCPSocketHandler;
 
diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp
index 8baa1d1..4c1df64 100644
--- a/louloulibs/network/tcp_socket_handler.hpp
+++ b/louloulibs/network/tcp_socket_handler.hpp
@@ -20,6 +20,8 @@
 #include <list>
 
 #ifdef BOTAN_FOUND
+#include <botan/version.h>
+
 class BiboumiTLSPolicy: public Botan::TLS::Policy
 {
 public:
-- 
cgit v1.2.3


From abb9c08828561be1c4463c5eaf8be62d0065eec7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?louiz=E2=80=99?= <louiz@louiz.org>
Date: Tue, 21 Mar 2017 15:12:02 +0100
Subject: Add a missing ifndef BOTAN

---
 louloulibs/network/tcp_socket_handler.hpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'louloulibs')

diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp
index 4c1df64..c850f43 100644
--- a/louloulibs/network/tcp_socket_handler.hpp
+++ b/louloulibs/network/tcp_socket_handler.hpp
@@ -47,8 +47,10 @@ public:
  * (select/poll/epoll etc)
  */
 class TCPSocketHandler: public SocketHandler
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,32)
+#ifdef BOTAN_FOUND
+# if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,32)
     ,public Botan::TLS::Callbacks
+# endif
 #endif
 {
 protected:
-- 
cgit v1.2.3