From 2239cdae45b39e675877ae32c86c47bcadce3090 Mon Sep 17 00:00:00 2001
From: Tim Costen <tim.costen@isode.com>
Date: Fri, 4 Oct 2019 15:51:06 +0100
Subject: Add ability to set external Trust Anchors to Swift OpenSSL context

Add a new (optional) field to TLSContext, which allows a vector
of Trust Anchor certificates to be specified.

Inside OpenSSLContext::configure, pass the X509 components of
these certificates into the OpenSSL context: these are now
available for client certificate verification in any callback
method set via TLSOptions.verifyCertificateCallback.

JIRA: LINK-1765

Test-information:
Tested via MLink unit tests. No leaks reported.

Change-Id: Ie9cc2051ee212249a12a4bc71b62306b5bce3013

diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index d9560de..6dd75d6 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -396,6 +396,21 @@ bool OpenSSLContext::configure(const TLSOptions &options)
     updateOptionIfPresent(options.disableTLSRollBackBug, SSL_OP_TLS_ROLLBACK_BUG);
     updateOptionIfPresent(options.singleDHUse, SSL_OP_SINGLE_DH_USE);
 
+    if (options.trustAnchors) {
+        // Add any additional Trust Anchors which are present in the TLSOptions
+        X509_STORE* store = SSL_CTX_get_cert_store(context_.get());
+
+        if (store) {
+            for (auto& certificate : *options.trustAnchors) {
+                auto openSSLCert = dynamic_cast<OpenSSLCertificate*>(certificate.get());
+                if (openSSLCert && openSSLCert->getInternalX509()) {
+                    X509_STORE_add_cert(store, openSSLCert->getInternalX509().get());
+                    // Don't need to increment reference count as X509_STORE_add_cert does thiS
+                }
+            }
+        }
+    }
+
     return true;
 }
 
diff --git a/Swiften/TLS/TLSOptions.h b/Swiften/TLS/TLSOptions.h
index 56648a3..4109096 100644
--- a/Swiften/TLS/TLSOptions.h
+++ b/Swiften/TLS/TLSOptions.h
@@ -8,6 +8,7 @@
 
 namespace Swift {
     class TLSContext;
+    class Certificate;
 
     class TLSOptions {
       public:
@@ -62,5 +63,10 @@ namespace Swift {
          */
 
         boost::optional<std::function<int(const TLSContext *)>> verifyCertificateCallback;
+
+        /**
+         * Allows specification of application-specific Trust Anchors
+         */
+        boost::optional<std::vector<std::shared_ptr<Certificate>>> trustAnchors;
     };
 }
-- 
cgit v0.10.2-6-g49f6