summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2012-02-09 15:41:44 +0000
committerDr. Stephen Henson <steve@openssl.org>2012-02-09 15:41:44 +0000
commitfc6800d19f4a0ca852c07128952d4c347d2d7065 (patch)
treee02ba23553b8a930e042885a11b6630975c3109b /ssl
parentd06f047b04dbdcd151efc620bf91253f0d70117e (diff)
Modify client hello version when renegotiating to enhance interop with
some servers.
Diffstat (limited to 'ssl')
-rw-r--r--ssl/s3_clnt.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index ff1cff23d0..4511a914a4 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -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);