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.
This commit is contained in:
Ben Laurie 2012-09-11 12:00:25 +00:00
parent d46a1a6178
commit da8512aaff
5 changed files with 87 additions and 39 deletions

View file

@ -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]

View 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)
{

View 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

View 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);

View 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;