oops, not yet ;-)
[openssl.git] / ssl / s3_clnt.c
index 4f884c69c1303b86299c5d5fcb041ff22444bcce..ee8aeb05f8cc15d5d84e513a7ae2b55cdbe9f81a 100644 (file)
@@ -689,9 +689,43 @@ int ssl3_client_hello(SSL *s)
                /* Do the message type and length last */
                d=p= &(buf[4]);
 
+               /* version indicates the negotiated version: for example from
+                * an SSLv2/v3 compatible client hello). The client_version
+                * field is the maximum version we permit and it is also
+                * used in RSA encrypted premaster secrets. Some servers can
+                * choke if we initially report a higher version then
+                * renegotiate to a lower one in the premaster secret. This
+                * didn't happen with TLS 1.0 as most servers supported it
+                * but it can with TLS 1.1 or later if the server only supports
+                * 1.0.
+                *
+                * Possible scenario with previous logic:
+                *      1. Client hello indicates TLS 1.2
+                *      2. Server hello says TLS 1.0
+                *      3. RSA encrypted premaster secret uses 1.2.
+                *      4. Handhaked proceeds using TLS 1.0.
+                *      5. Server sends hello request to renegotiate.
+                *      6. Client hello indicates TLS v1.0 as we now
+                *         know that is maximum server supports.
+                *      7. Server chokes on RSA encrypted premaster secret
+                *         containing version 1.0.
+                *
+                * For interoperability it should be OK to always use the
+                * maximum version we support in client hello and then rely
+                * on the checking of version to ensure the servers isn't
+                * being inconsistent: for example initially negotiating with
+                * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
+                * client_version in client hello and not resetting it to
+                * the negotiated version.
+                */
+#if 0
                *(p++)=s->version>>8;
                *(p++)=s->version&0xff;
                s->client_version=s->version;
+#else
+               *(p++)=s->client_version>>8;
+               *(p++)=s->client_version&0xff;
+#endif
 
                /* Random stuff */
                memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
@@ -721,6 +755,15 @@ int ssl3_client_hello(SSL *s)
                        SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
                        goto err;
                        }
+#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
+                       /* Some servers hang if client hello > 256 bytes
+                        * as hack workaround chop number of supported ciphers
+                        * to keep it well below this if we use TLS v1.2
+                        */
+                       if (TLS1_get_version(s) >= TLS1_2_VERSION
+                               && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
+                               i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
+#endif
                s2n(i,p);
                p+=i;
 
@@ -2432,6 +2475,7 @@ int ssl3_send_client_key_exchange(SSL *s)
                                {
                                /* Use client certificate key */
                                EVP_PKEY *clkey = s->cert->key->privatekey;
+                               dh_clnt = NULL;
                                if (clkey)
                                        dh_clnt = EVP_PKEY_get1_DH(clkey);
                                if (dh_clnt == NULL)
@@ -3176,7 +3220,7 @@ int ssl3_send_client_certificate(SSL *s)
                {
                s->state=SSL3_ST_CW_CERT_D;
                l=ssl3_output_cert_chain(s,
-                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
+                       (s->s3->tmp.cert_req == 2)?NULL:s->cert->key);
                s->init_num=(int)l;
                s->init_off=0;
                }