Support retries in certificate callback
[openssl.git] / ssl / s3_srvr.c
index 41a5ba550361945c7900eb54de0c97fd4f938451..29459f0490e50ae1d8d52a74f81177cf14b2ef63 100644 (file)
@@ -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)
@@ -493,8 +492,8 @@ int ssl3_accept(SSL *s)
                            /* SRP: send ServerKeyExchange */
                            || (alg_k & SSL_kSRP)
 #endif
-                           || (alg_k & SSL_kEDH)
-                           || (alg_k & SSL_kEECDH)
+                           || (alg_k & SSL_kDHE)
+                           || (alg_k & SSL_kECDHE)
                            || ((alg_k & SSL_kRSA)
                                && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
                                    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
@@ -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));
@@ -1414,7 +1426,7 @@ int ssl3_get_client_hello(SSL *s)
                /* check whether we should disable session resumption */
                if (s->not_resumable_session_cb != NULL)
                        s->session->not_resumable=s->not_resumable_session_cb(s,
-                               ((c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)) != 0));
+                               ((c->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0));
                if (s->session->not_resumable)
                        /* do not send a session ticket */
                        s->tlsext_ticket_expected = 0;
@@ -1663,7 +1675,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                else
 #endif
 #ifndef OPENSSL_NO_DH
-                       if (type & SSL_kEDH)
+                       if (type & SSL_kDHE)
                        {
                        dhp=cert->dh_tmp;
                        if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
@@ -1719,7 +1731,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                else 
 #endif
 #ifndef OPENSSL_NO_ECDH
-                       if (type & SSL_kEECDH)
+                       if (type & SSL_kECDHE)
                        {
                        const EC_GROUP *group;
 
@@ -1935,7 +1947,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                        }
 
 #ifndef OPENSSL_NO_ECDH
-               if (type & SSL_kEECDH
+               if (type & SSL_kECDHE
                        {
                        /* XXX: For now, we only support named (not generic) curves.
                         * In this situation, the serverKeyExchange message has:
@@ -2346,7 +2358,7 @@ int ssl3_get_client_key_exchange(SSL *s)
        else
 #endif
 #ifndef OPENSSL_NO_DH
-               if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+               if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd))
                {
                int idx = -1;
                EVP_PKEY *skey = NULL;
@@ -2638,7 +2650,7 @@ int ssl3_get_client_key_exchange(SSL *s)
 #endif /* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
-               if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+               if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe))
                {
                int ret = 1;
                int field_size = 0;
@@ -2691,7 +2703,7 @@ int ssl3_get_client_key_exchange(SSL *s)
                        {
                        /* Client Publickey was in Client Certificate */
 
-                        if (alg_k & SSL_kEECDH)
+                        if (alg_k & SSL_kECDHE)
                                 {
                                 al=SSL_AD_HANDSHAKE_FAILURE;
                                 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);