summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Laurie <ben@openssl.org>2012-09-17 14:39:38 +0000
committerBen Laurie <ben@openssl.org>2012-09-17 14:39:38 +0000
commit70d91d60bc68ade5d12cc9de6c9f3f10f319a5c5 (patch)
tree6f7f99154ad449ad5391d728723a21c7aa3f1cd1
parentbc788830173a10023f567f959e434f74eceff694 (diff)
Call OCSP Stapling callback after ciphersuite has been chosen, so the
right response is stapled. Also change SSL_get_certificate() so it returns the certificate actually sent. See http://rt.openssl.org/Ticket/Display.html?id=2836.
-rw-r--r--CHANGES6
-rw-r--r--ssl/s3_srvr.c12
-rw-r--r--ssl/ssl_lib.c6
-rw-r--r--ssl/ssl_locl.h5
-rw-r--r--ssl/t1_lib.c91
5 files changed, 81 insertions, 39 deletions
diff --git a/CHANGES b/CHANGES
index abe3b49347..0daec2b509 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
Changes between 1.0.1c and 1.0.1d [xx XXX xxxx]
+ *) Call OCSP Stapling callback after ciphersuite has been chosen, so
+ the right response is stapled. Also change SSL_get_certificate()
+ so it returns the certificate actually sent.
+ See http://rt.openssl.org/Ticket/Display.html?id=2836.
+ [Rob Stradling <rob.stradling@comodo.com>]
+
*) Fix possible deadlock when decoding public keys.
[Steve Henson]
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 38e1281db2..5e1007077f 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1183,7 +1183,7 @@ int ssl3_get_client_hello(SSL *s)
goto f_err;
}
}
- if (ssl_check_clienthello_tlsext(s) <= 0) {
+ if (ssl_check_clienthello_tlsext_early(s) <= 0) {
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
@@ -1405,6 +1405,16 @@ int ssl3_get_client_hello(SSL *s)
* s->tmp.new_cipher - the new cipher to use.
*/
+ /* Handles TLS extensions that we couldn't check earlier */
+ if (s->version >= SSL3_VERSION)
+ {
+ if (ssl_check_clienthello_tlsext_late(s) <= 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+ }
+
if (ret < 0) ret=1;
if (0)
{
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index f232d55554..984895f2f1 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2287,7 +2287,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
#endif
/* THIS NEEDS CLEANING UP */
-X509 *ssl_get_server_send_cert(SSL *s)
+X509 *ssl_get_server_send_cert(const SSL *s)
{
unsigned long alg_k,alg_a;
CERT *c;
@@ -2780,7 +2780,9 @@ void ssl_clear_cipher_ctx(SSL *s)
/* Fix this function so that it takes an optional type parameter */
X509 *SSL_get_certificate(const SSL *s)
{
- if (s->cert != NULL)
+ if (s->server)
+ return(ssl_get_server_send_cert(s));
+ else if (s->cert != NULL)
return(s->cert->key->x509);
else
return(NULL);
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index d87fd51cfa..1fab632ddc 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -830,7 +830,7 @@ int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
int ssl_undefined_function(SSL *s);
int ssl_undefined_void_function(void);
int ssl_undefined_const_function(const SSL *s);
-X509 *ssl_get_server_send_cert(SSL *);
+X509 *ssl_get_server_send_cert(const SSL *);
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
@@ -1088,7 +1088,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d,
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
int ssl_prepare_clienthello_tlsext(SSL *s);
int ssl_prepare_serverhello_tlsext(SSL *s);
-int ssl_check_clienthello_tlsext(SSL *s);
+int ssl_check_clienthello_tlsext_early(SSL *s);
+int ssl_check_clienthello_tlsext_late(SSL *s);
int ssl_check_serverhello_tlsext(SSL *s);
#ifndef OPENSSL_NO_HEARTBEATS
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 05d69ae5d5..dc5be972d5 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1763,7 +1763,7 @@ int ssl_prepare_serverhello_tlsext(SSL *s)
return 1;
}
-int ssl_check_clienthello_tlsext(SSL *s)
+int ssl_check_clienthello_tlsext_early(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -1782,42 +1782,12 @@ int ssl_check_clienthello_tlsext(SSL *s)
else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)
ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
- /* If status request then ask callback what to do.
- * Note: this must be called after servername callbacks in case
- * the certificate has changed.
- */
- if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
- {
- int r;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- switch (r)
- {
- /* We don't want to send a status request response */
- case SSL_TLSEXT_ERR_NOACK:
- s->tlsext_status_expected = 0;
- break;
- /* status request response should be sent */
- case SSL_TLSEXT_ERR_OK:
- if (s->tlsext_ocsp_resp)
- s->tlsext_status_expected = 1;
- else
- s->tlsext_status_expected = 0;
- break;
- /* something bad happened */
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- al = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- }
- else
- s->tlsext_status_expected = 0;
-
#ifdef TLSEXT_TYPE_opaque_prf_input
{
/* This sort of belongs into ssl_prepare_serverhello_tlsext(),
* but we might be sending an alert in response to the client hello,
- * so this has to happen here in ssl_check_clienthello_tlsext(). */
+ * so this has to happen here in
+ * ssl_check_clienthello_tlsext_early(). */
int r = 1;
@@ -1869,8 +1839,8 @@ int ssl_check_clienthello_tlsext(SSL *s)
}
}
-#endif
err:
+#endif
switch (ret)
{
case SSL_TLSEXT_ERR_ALERT_FATAL:
@@ -1888,6 +1858,59 @@ int ssl_check_clienthello_tlsext(SSL *s)
}
}
+int ssl_check_clienthello_tlsext_late(SSL *s)
+ {
+ int ret = SSL_TLSEXT_ERR_OK;
+ int al;
+
+ /* If status request then ask callback what to do.
+ * Note: this must be called after servername callbacks in case
+ * the certificate has changed, and must be called after the cipher
+ * has been chosen because this may influence which certificate is sent
+ */
+ if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
+ {
+ int r;
+ r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+ switch (r)
+ {
+ /* We don't want to send a status request response */
+ case SSL_TLSEXT_ERR_NOACK:
+ s->tlsext_status_expected = 0;
+ break;
+ /* status request response should be sent */
+ case SSL_TLSEXT_ERR_OK:
+ if (s->tlsext_ocsp_resp)
+ s->tlsext_status_expected = 1;
+ else
+ s->tlsext_status_expected = 0;
+ break;
+ /* something bad happened */
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ }
+ else
+ s->tlsext_status_expected = 0;
+
+ err:
+ switch (ret)
+ {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return -1;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ ssl3_send_alert(s,SSL3_AL_WARNING,al);
+ return 1;
+
+ default:
+ return 1;
+ }
+ }
+
int ssl_check_serverhello_tlsext(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;