From 34cd12929b479f0c229bb9d564e2d2eec3d8df5d Mon Sep 17 00:00:00 2001
From: Laszlo Kovacs <lkovacs@akamai.com>
Date: Tue, 31 Mar 2015 16:20:03 -0400
Subject: [PATCH 18/26] RT3875 Add external X509_STORE to SSL_CTX

Add SSL_CTX_set_cert_store_ref() API to add an external X509_STORE to
an SSL_CTX

(cherry picked from commit da85fb4713bbd7ba92ab2c83602fc26a4613fb22)

Conflicts:
	include/openssl/ssl.h
	ssl/ssl_lib.c
---
 doc/ssl/SSL_CTX_set_cert_store.pod | 18 +++++++++++++++++-
 doc/ssl/ssl.pod                    |  2 ++
 include/openssl/ssl.h              |  1 +
 ssl/ssl_lib.c                      |  8 ++++++++
 4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/doc/ssl/SSL_CTX_set_cert_store.pod b/doc/ssl/SSL_CTX_set_cert_store.pod
index 846416e..37bba3b 100644
--- a/doc/ssl/SSL_CTX_set_cert_store.pod
+++ b/doc/ssl/SSL_CTX_set_cert_store.pod
@@ -2,13 +2,14 @@
 
 =head1 NAME
 
-SSL_CTX_set_cert_store, SSL_CTX_get_cert_store - manipulate X509 certificate verification storage
+SSL_CTX_set_cert_store, SSL_CTX_set_cert_store_ref, SSL_CTX_get_cert_store - manipulate X509 certificate verification storage
 
 =head1 SYNOPSIS
 
  #include <openssl/ssl.h>
 
  void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store);
+ void SSL_CTX_set_cert_store_ref(SSL_CTX *ctx, X509_STORE *store);
  X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx);
 
 =head1 DESCRIPTION
@@ -17,6 +18,10 @@ SSL_CTX_set_cert_store() sets/replaces the certificate verification storage
 of B<ctx> to/with B<store>. If another X509_STORE object is currently
 set in B<ctx>, it will be X509_STORE_free()ed.
 
+SSL_CTX_set_cert_store_ref() sets/replaces the certificate verification storage
+of B<ctx> to/with B<store>. The B<store>'s reference count is incremented.
+If another X509_STORE object is currently set in B<ctx>, it will be X509_STORE_free()ed. 
+
 SSL_CTX_get_cert_store() returns a pointer to the current certificate
 verification storage.
 
@@ -42,6 +47,15 @@ L<SSL_CTX_set_verify(3)|SSL_CTX_set_verify(3)> family of functions.
 This document must therefore be updated when documentation about the
 X509_STORE object and its handling becomes available.
 
+SSL_CTX_set_cert_store() does not increment the B<store>'s reference 
+count, so it should not be used to assign an X509_STORE that is owned
+by another SSL_CTX. 
+
+To share X509_STOREs between two SSL_CTXs, use SSL_CTX_get_cert_store()
+to get the X509_STORE from the first SSL_CTX, and then use
+SSL_CTX_set_cert_store_ref() to assign to the second SSL_CTX and
+increment the reference count fo the X509_STORE.
+
 =head1 RESTRICTIONS
 
 The X509_STORE structure used by an SSL_CTX is used for verifying peer
@@ -53,6 +67,8 @@ functions such as SSL_CTX_set1_verify_cert_store() instead.
 
 SSL_CTX_set_cert_store() does not return diagnostic output.
 
+SSL_CTX_set_cert_store_ref() does not return diagnostic output.
+
 SSL_CTX_get_cert_store() returns the current setting.
 
 =head1 SEE ALSO
diff --git a/doc/ssl/ssl.pod b/doc/ssl/ssl.pod
index be27482..ab6ccc1 100644
--- a/doc/ssl/ssl.pod
+++ b/doc/ssl/ssl.pod
@@ -286,6 +286,8 @@ protocol context defined in the B<SSL_CTX> structure.
 
 =item void B<SSL_CTX_set_cert_store>(SSL_CTX *ctx, X509_STORE *cs);
 
+=item void B<SSL_CTX_set_cert_store_ref>(SSL_CTX *ctx, X509_STORE *cs);
+
 =item void B<SSL_CTX_set_cert_verify_cb>(SSL_CTX *ctx, int (*cb)(), char *arg)
 
 =item int B<SSL_CTX_set_cipher_list>(SSL_CTX *ctx, char *str);
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 509997c..b4ecfa1 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1432,6 +1432,7 @@ __owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
 __owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
 void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
 __owur int SSL_want(const SSL *s);
+void SSL_CTX_set_cert_store_ref(SSL_CTX *, X509_STORE *);
 int SSL_signal_event_result(SSL *s, int event, int result, int errfunc, int errreason, const char *file, int line);
 # define SSL_signal_event(s, event, retcode) \
         SSL_signal_event_result(s, event, retcode, 0, 0, NULL, 0)
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c3ea67e..cd83393 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3538,6 +3538,14 @@ void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx)
     return ctx->cert->sec_ex;
 }
 
+void SSL_CTX_set_cert_store_ref(SSL_CTX *ctx, X509_STORE *store)
+{
+    if (ctx->cert_store != NULL)
+        X509_STORE_free(ctx->cert_store);
+    CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+    ctx->cert_store = store;
+}
+
 void SSL_CTX_share_session_cache(SSL_CTX *a, SSL_CTX *b)
 {
     CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
-- 
2.3.2 (Apple Git-55)

