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.
diff --git a/CHANGES b/CHANGES
index a39ad94..9cb1778 100644
--- a/CHANGES
+++ b/CHANGES
@@ -346,6 +346,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]
 
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 76f49f7..3f0c1ef 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1432,6 +1432,16 @@
 	 * 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 4289a74..5a639c1 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2336,7 +2336,7 @@
 
 #endif
 
-static int ssl_get_server_cert_index(SSL *s)
+static int ssl_get_server_cert_index(const SSL *s)
 	{
 	int idx;
 	idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
@@ -2347,7 +2347,7 @@
 	return idx;
 	}
 
-CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
 	{
 	CERT *c;
 	int i;
@@ -2833,6 +2833,14 @@
 /* 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
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index eb6ef4c..cb72ba3 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -934,7 +934,7 @@
 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);
@@ -1201,6 +1201,7 @@
 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);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 8f54311..254221b 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -123,7 +123,7 @@
 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
 
@@ -2246,7 +2246,7 @@
 		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;
@@ -2647,7 +2647,7 @@
 	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;
@@ -2666,42 +2666,12 @@
 	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;
 	
@@ -2753,8 +2723,8 @@
 			}
 	}
 
-#endif
  err:
+#endif
 	switch (ret)
 		{
 		case SSL_TLSEXT_ERR_ALERT_FATAL:
@@ -2772,6 +2742,59 @@
 		}
 	}
 
+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;