Call OCSP Stapling callback after ciphersuite has been chosen, so the
[openssl.git] / ssl / ssl_lib.c
index bec87d81413650a10dc0c74afb0dc265964654b0..5a639c1f49a21caaaefde08d695bde64d2d74f10 100644 (file)
@@ -263,7 +263,7 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth)
 
        sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
                &(ctx->cipher_list_by_id),
-               meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
+               meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ctx->cert);
        if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))
                {
                SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
@@ -1333,7 +1333,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
        STACK_OF(SSL_CIPHER) *sk;
        
        sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list,
-               &ctx->cipher_list_by_id,str);
+               &ctx->cipher_list_by_id,str, ctx->cert);
        /* ssl_create_cipher_list may return an empty stack if it
         * was unable to find a cipher matching the given rule string
         * (for example if the rule string specifies a cipher which
@@ -1357,7 +1357,7 @@ int SSL_set_cipher_list(SSL *s,const char *str)
        STACK_OF(SSL_CIPHER) *sk;
        
        sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list,
-               &s->cipher_list_by_id,str);
+               &s->cipher_list_by_id,str, s->cert);
        /* see comment in SSL_CTX_set_cipher_list */
        if (sk == NULL)
                return 0;
@@ -1787,7 +1787,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 
        ssl_create_cipher_list(ret->method,
                &ret->cipher_list,&ret->cipher_list_by_id,
-               meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
+               meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ret->cert);
        if (ret->cipher_list == NULL
            || sk_SSL_CIPHER_num(ret->cipher_list) <= 0)
                {
@@ -2336,59 +2336,18 @@ 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;
-
-       alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-       alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
-       if (alg_k & (SSL_kECDHr|SSL_kECDHe))
-               {
-               /* we don't need to look at SSL_kEECDH
-                * since no certificate is needed for
-                * anon ECDH and for authenticated
-                * EECDH, the check for the auth
-                * algorithm will set i correctly
-                * NOTE: For ECDH-RSA, we need an ECC
-                * not an RSA cert but for EECDH-RSA
-                * we need an RSA cert. Placing the
-                * checks for SSL_kECDH before RSA
-                * checks ensures the correct cert is chosen.
-                */
-               return SSL_PKEY_ECC;
-               }
-       else if (alg_a & SSL_aECDSA)
-               return SSL_PKEY_ECC;
-       else if (alg_k & SSL_kDHr)
-               return SSL_PKEY_DH_RSA;
-       else if (alg_k & SSL_kDHd)
-               return SSL_PKEY_DH_DSA;
-       else if (alg_a & SSL_aDSS)
-               return SSL_PKEY_DSA_SIGN;
-       else if (alg_a & SSL_aRSA)
-               {
-               if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
-                       return SSL_PKEY_RSA_SIGN;
-               else
-                       return SSL_PKEY_RSA_ENC;
-               }
-       else if (alg_a & SSL_aKRB5)
-               /* VRS something else here? */
-               return -1;
-       else if (alg_a & SSL_aGOST94) 
-               return SSL_PKEY_GOST94;
-       else if (alg_a & SSL_aGOST01)
-               return SSL_PKEY_GOST01;
-       else /* if (alg_a & SSL_aNULL) */
-               {
+       int idx;
+       idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+       if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
+               idx = SSL_PKEY_RSA_SIGN;
+       if (idx == -1)
                SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR);
-               return -1;
-               }
+       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;
@@ -2396,6 +2355,14 @@ CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
        c = s->cert;
        ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
 
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       /* Broken protocol test: return last used certificate: which may
+        * mismatch the one expected.
+        */
+       if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTCOL)
+               return c->key;
+#endif
+
        i = ssl_get_server_cert_index(s);
 
        /* This may or may not be an error. */
@@ -2415,6 +2382,15 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
        alg_a = cipher->algorithm_auth;
        c=s->cert;
 
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       /* Broken protocol test: use last key: which may
+        * mismatch the one expected.
+        */
+       if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTCOL)
+               idx = c->key - c->pkeys;
+       else
+#endif
+
        if ((alg_a & SSL_aDSS) &&
                (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
                idx = SSL_PKEY_DSA_SIGN;
@@ -2857,6 +2833,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