From 0ebc965b9ca4352e407bb7cfa65ac235942117f6 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sat, 25 Jan 2014 13:31:07 +0000 Subject: [PATCH] Support retries in certificate callback --- ssl/s3_clnt.c | 17 +++++++++++++---- ssl/s3_srvr.c | 32 ++++++++++++++++++++++---------- ssl/ssl3.h | 1 + 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 5f547bb114..68d3131b1e 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -3307,11 +3307,20 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_A) { /* Let cert callback update client certificates if required */ - if (s->cert->cert_cb - && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + if (s->cert->cert_cb) { - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); - return 0; + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return -1; + } + if (i == 0) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } + s->rwstate=SSL_NOTHING; } if (ssl3_check_client_certificate(s)) s->state=SSL3_ST_CW_CERT_C; diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index a3baff93f9..29459f0490 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -352,12 +352,11 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: - if (s->rwstate != SSL_X509_LOOKUP) - { - ret=ssl3_get_client_hello(s); - if (ret <= 0) goto end; - } + ret=ssl3_get_client_hello(s); + if (ret <= 0) goto end; #ifndef OPENSSL_NO_SRP + s->state = SSL3_ST_SR_CLNT_HELLO_D; + case SSL3_ST_SR_CLNT_HELLO_D: { int al; if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) < 0) @@ -950,6 +949,9 @@ int ssl3_get_client_hello(SSL *s) #endif STACK_OF(SSL_CIPHER) *ciphers=NULL; + if (s->state == SSL3_ST_SR_CLNT_HELLO_C) + goto retry_cert; + /* We do this so that we will respond with our native type. * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, * This down switching should be handled by a different method. @@ -1394,12 +1396,22 @@ int ssl3_get_client_hello(SSL *s) } ciphers=NULL; /* Let cert callback update server certificates if required */ - if (s->cert->cert_cb - && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + retry_cert: + if (s->cert->cert_cb) { - al=SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR); - goto f_err; + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) + { + al=SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR); + goto f_err; + } + if (rv < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return -1; + } + s->rwstate = SSL_NOTHING; } c=ssl3_choose_cipher(s,s->session->ciphers, SSL_get_ciphers(s)); diff --git a/ssl/ssl3.h b/ssl/ssl3.h index c94b3a4290..8fe6949f6d 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -685,6 +685,7 @@ typedef struct ssl3_state_st #define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT) #define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT) #define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_D (0x115|SSL_ST_ACCEPT) #ifndef OPENSSL_NO_TLSEXT #define SSL3_ST_SR_SUPPLEMENTAL_DATA_A (0x212|SSL_ST_ACCEPT) #define SSL3_ST_SR_SUPPLEMENTAL_DATA_B (0x213|SSL_ST_ACCEPT) -- 2.34.1