Support retries in certificate callback
authorDr. Stephen Henson <steve@openssl.org>
Sat, 25 Jan 2014 13:31:07 +0000 (13:31 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 27 Jan 2014 14:41:38 +0000 (14:41 +0000)
(cherry picked from commit 0ebc965b9ca4352e407bb7cfa65ac235942117f6)

Conflicts:

ssl/s3_srvr.c
ssl/ssl3.h

ssl/s3_clnt.c
ssl/s3_srvr.c
ssl/ssl3.h

index 6aeab442e1166ccc9d21f0864501878043073bc7..9e3c847de9dcb21e32746855ea106d11d020f494 100644 (file)
@@ -3301,11 +3301,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;
index 619c710ca4226eb97ad8942e729cc1afae1254ec..8e8daf2997fc0ee356ad4dedb9df03d53640597a 100644 (file)
@@ -353,12 +353,11 @@ int ssl3_accept(SSL *s)
                case SSL3_ST_SR_CLNT_HELLO_C:
 
                        s->shutdown=0;
-                       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)
@@ -940,6 +939,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.
@@ -1384,12 +1386,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));
index 57b568a4776d25fb4f4a5c21ef3664f458635dcc..e2a58c30cc0bad95f67a0037a891e5fbd8cefdc5 100644 (file)
@@ -669,6 +669,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)
 /* write to client */
 #define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
 #define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)