From: Dr. Stephen Henson Date: Fri, 21 Feb 2014 19:42:03 +0000 (+0000) Subject: Option to set current cert to server certificate. X-Git-Tag: OpenSSL_1_0_2-beta1~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58b86e4235cd420f607819727d372af9f7a80224;p=openssl Option to set current cert to server certificate. (cherry picked from commit daddd9a950e491c31f9500d5e570bc7eb96b2823) --- diff --git a/doc/ssl/SSL_CTX_add1_chain_cert.pod b/doc/ssl/SSL_CTX_add1_chain_cert.pod index 0c977aa1a7..7676a882ea 100644 --- a/doc/ssl/SSL_CTX_add1_chain_cert.pod +++ b/doc/ssl/SSL_CTX_add1_chain_cert.pod @@ -77,6 +77,14 @@ the first valid certificate or B to set the next valid certificate after the current certificate. These two operations can be used to iterate over all certificates in an B structure. +SSL_set_current_cert() also supports the option B. +If B 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 +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 diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 72ef809fed..f02bb7613d 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -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 diff --git a/ssl/ssl.h b/ssl/ssl.h index 85c7966634..88ee3db672 100644 --- 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) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index a893dbaf0e..0103296aa9 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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