Option to set current cert to server certificate.
authorDr. Stephen Henson <steve@openssl.org>
Fri, 21 Feb 2014 19:42:03 +0000 (19:42 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 23 Feb 2014 13:49:21 +0000 (13:49 +0000)
(cherry picked from commit daddd9a950e491c31f9500d5e570bc7eb96b2823)

doc/ssl/SSL_CTX_add1_chain_cert.pod
ssl/s3_lib.c
ssl/ssl.h
ssl/ssl_lib.c

index 0c977aa1a722d318cb23de062b51ce91aa801cb1..7676a882ea8f01e1989647f59ebf36e2b193706c 100644 (file)
@@ -77,6 +77,14 @@ the first valid certificate or B<SSL_CERT_SET_NEXT> to set the next valid
 certificate after the current certificate. These two operations can be
 used to iterate over all certificates in an B<SSL_CTX> structure.
 
+SSL_set_current_cert() also supports the option B<SSL_CERT_SET_SERVER>.
+If B<ssl> is a server and has sent a certificate to a connected client
+this option sets that certificate to the current certificate and returns 1.
+If the negotiated ciphersuite is anonymous (and thus no certificate will
+be sent) 2 is returned and the current certificate is unchanged. If B<ssl>
+is not a server or a certificate has not been sent 0 is returned and
+the current certificate is unchanged.
+
 All these functions are implemented as macros. Those containing a B<1>
 increment the reference count of the supplied certificate or chain so it must
 be freed at some point after the operation. Those containing a B<0> do
index 72ef809fedc05ca0fb20a49fa98c4a4e4e7edd4c..f02bb7613df1c645b57c2dacc19bab538a8ee5da 100644 (file)
@@ -3432,6 +3432,24 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
                return ssl_cert_select_current(s->cert, (X509 *)parg);
 
        case SSL_CTRL_SET_CURRENT_CERT:
+               if (larg == SSL_CERT_SET_SERVER)
+                       {
+                       CERT_PKEY *cpk;
+                       const SSL_CIPHER *cipher;
+                       if (!s->server)
+                               return 0;
+                       cipher = s->s3->tmp.new_cipher;
+                       if (!cipher)
+                               return 0;
+                       /* No certificate for unauthenticated ciphersuites */
+                       if (cipher->algorithm_auth & SSL_aNULL)
+                               return 2;
+                       cpk = ssl_get_server_send_pkey(s);
+                       if (!cpk)
+                               return 0;
+                       s->cert->key = cpk;
+                       return 1;
+                       }
                return ssl_cert_set_current(s->cert, larg);
 
 #ifndef OPENSSL_NO_EC
index 85c796663414c57149111334554a48d47a9db8a0..88ee3db6722535c26c0c15f1fd064dfe719791af 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1942,6 +1942,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 
 #define SSL_CERT_SET_FIRST                     1
 #define SSL_CERT_SET_NEXT                      2
+#define SSL_CERT_SET_SERVER                    3
 
 #define DTLSv1_get_timeout(ssl, arg) \
        SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
index a893dbaf0e13485aee0da5ceec92adbf3a137b44..0103296aa9075ff5dc1b67b4ade2baa36ecc7bde 100644 (file)
@@ -2672,6 +2672,8 @@ CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
        int i;
 
        c = s->cert;
+       if (!s->s3 || !s->s3->tmp.new_cipher)
+               return NULL;
        ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
 
 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL