Call OCSP Stapling callback after ciphersuite has been chosen, so the
authorBen Laurie <ben@openssl.org>
Tue, 11 Sep 2012 12:00:25 +0000 (12:00 +0000)
committerBen Laurie <ben@openssl.org>
Tue, 11 Sep 2012 12:00:25 +0000 (12:00 +0000)
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.

CHANGES
ssl/s3_srvr.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/t1_lib.c

diff --git a/CHANGES b/CHANGES
index 2bd941825e110e29a54b52d8c3ae95947bfdbbea..f84f028d10e3ad326e5098f3d213f78c3effbce7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 1.0.1 and 1.0.2 [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>]
+
   *) Support for linux-x32, ILP32 environment in x86_64 framework.
      [Andy Polyakov]
 
index 542ce184211b187c041c2cc5d6f84c7a90ccc0a7..fa21a8bd234b188253a82ef5cea446f6da2bcd7d 100644 (file)
@@ -1418,6 +1418,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)
                {
index 617526a66d46685ed95be940c3d31b400cd2ef03..555a630b1ba8da6e316c2e2ed5b6111c37135e8b 100644 (file)
@@ -2320,7 +2320,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
 #endif
 
 /* THIS NEEDS CLEANING UP */
-static int ssl_get_server_cert_index(SSL *s)
+static int ssl_get_server_cert_index(const SSL *s)
        {
        unsigned long alg_k, alg_a;
 
@@ -2371,7 +2371,7 @@ static int ssl_get_server_cert_index(SSL *s)
                }
        }
 
-CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
        {
        CERT *c;
        int i;
@@ -2840,6 +2840,14 @@ 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->server)
+               {
+               CERT_PKEY *certpkey;
+               certpkey = ssl_get_server_send_pkey(s);
+               if (certpkey && certpkey->x509)
+                       return certpkey->x509;
+               }
+
        if (s->cert != NULL)
                return(s->cert->key->x509);
        else
index 63a12e7b1a9d4d29e0e661a2d9aa52c0b9716243..90ef7cb5d602de7c61f97cec35032531e89ce950 100644 (file)
@@ -866,7 +866,7 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);
-CERT_PKEY *ssl_get_server_send_pkey(SSL *);
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
 unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length);
 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);
@@ -1133,6 +1133,7 @@ int tls1_shared_list(SSL *s,
 unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
 unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n);
+int ssl_check_clienthello_tlsext_late(SSL *s);
 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n);
 int ssl_prepare_clienthello_tlsext(SSL *s);
 int ssl_prepare_serverhello_tlsext(SSL *s);
index 48877031165fbe7114bca132f0967599e2131fa3..d0764e8cd329a16137b92dfc8728230af7efe779 100644 (file)
@@ -123,7 +123,7 @@ const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
 static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
                                const unsigned char *sess_id, int sesslen,
                                SSL_SESSION **psess);
-static int ssl_check_clienthello_tlsext(SSL *s);
+static int ssl_check_clienthello_tlsext_early(SSL *s);
 int ssl_check_serverhello_tlsext(SSL *s);
 #endif
 
@@ -1846,7 +1846,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                return 0;
                }
 
-       if (ssl_check_clienthello_tlsext(s) <= 0) 
+       if (ssl_check_clienthello_tlsext_early(s) <= 0) 
                {
                SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,SSL_R_CLIENTHELLO_TLSEXT);
                return 0;
@@ -2247,7 +2247,7 @@ int ssl_prepare_serverhello_tlsext(SSL *s)
        return 1;
        }
 
-static int ssl_check_clienthello_tlsext(SSL *s)
+static int ssl_check_clienthello_tlsext_early(SSL *s)
        {
        int ret=SSL_TLSEXT_ERR_NOACK;
        int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -2266,42 +2266,12 @@ static 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;
        
@@ -2353,8 +2323,8 @@ static int ssl_check_clienthello_tlsext(SSL *s)
                        }
        }
 
-#endif
  err:
+#endif
        switch (ret)
                {
                case SSL_TLSEXT_ERR_ALERT_FATAL:
@@ -2372,6 +2342,59 @@ static 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;