aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2012-04-25 22:06:32 +0000
committerAndy Polyakov <appro@openssl.org>2012-04-25 22:06:32 +0000
commitf2ad35821cadeaf71df0e6050059ca64d24c6ebc (patch)
treebbede45f0890e38de4fee306d1f8b1602a67fd3c
parent09e4e4b98e40b4283d2405ba418d6e2876f4448d (diff)
downloadopenssl-f2ad35821cadeaf71df0e6050059ca64d24c6ebc.tar.gz
s23_clnt.c: ensure interoperability by maitaining client "version capability"
vector contiguous. PR: 2802
-rw-r--r--CHANGES12
-rw-r--r--ssl/s23_clnt.c53
2 files changed, 47 insertions, 18 deletions
diff --git a/CHANGES b/CHANGES
index 94cfe6e784..182a6da9d6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -288,7 +288,17 @@
is enable if DEBUG_UNUSED is set. Add to several functions in evp.h
whose return value is often ignored.
[Steve Henson]
-
+
+ Changes between 1.0.1a and 1.0.1b [xx XXX xxxx]
+
+ *) In order to ensure interoperabilty SSL_OP_NO_protocolX does not
+ disable just protocol X, but all protocols above X *if* there are
+ protocols *below* X still enabled. In more practical terms it means
+ that if application wants to disable TLS1.0 in favor of TLS1.1 and
+ above, it's not sufficient to pass SSL_OP_NO_TLSv1, one has to pass
+ SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
+ [Andy Polyakov]
+
Changes between 1.0.1 and 1.0.1a [19 Apr 2012]
*) Check for potentially exploitable overflows in asn1_d2i_read_bio
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index a76eb46908..47673e740a 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -282,32 +282,51 @@ static int ssl23_client_hello(SSL *s)
SSL_COMP *comp;
#endif
int ret;
+ unsigned long mask, options = s->options;
- ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1;
+ ssl2_compat = (options & SSL_OP_NO_SSLv2) ? 0 : 1;
if (ssl2_compat && ssl23_no_ssl2_ciphers(s))
ssl2_compat = 0;
- if (!(s->options & SSL_OP_NO_TLSv1_2))
- {
- version = TLS1_2_VERSION;
- }
- else if (!(s->options & SSL_OP_NO_TLSv1_1))
- {
+ /*
+ * SSL_OP_NO_X disables all protocols above X *if* there are
+ * some protocols below X enabled. This is required in order
+ * to maintain "version capability" vector contiguous. So
+ * that if application wants to disable TLS1.0 in favour of
+ * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
+ * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
+ */
+ mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
+#if !defined(OPENSSL_NO_SSL3)
+ |SSL_OP_NO_SSLv3
+#endif
+#if !defined(OPENSSL_NO_SSL2)
+ |(ssl2_compat?SSL_OP_NO_SSLv2:0)
+#endif
+ ;
+#if !defined(OPENSSL_NO_TLS1_2_CLIENT)
+ version = TLS1_2_VERSION;
+
+ if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask)
version = TLS1_1_VERSION;
- }
- else if (!(s->options & SSL_OP_NO_TLSv1))
- {
+#else
+ version = TLS1_1_VERSION;
+#endif
+ mask &= ~SSL_OP_NO_TLSv1_1;
+ if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
version = TLS1_VERSION;
- }
- else if (!(s->options & SSL_OP_NO_SSLv3))
- {
+ mask &= ~SSL_OP_NO_TLSv1;
+#if !defined(OPENSSL_NO_SSL3)
+ if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask)
version = SSL3_VERSION;
- }
- else if (!(s->options & SSL_OP_NO_SSLv2))
- {
+ mask &= ~SSL_OP_NO_SSLv3;
+#endif
+#if !defined(OPENSSL_NO_SSL2)
+ if ((options & SSL_OP_NO_SSLv3) && (options & mask) != mask)
version = SSL2_VERSION;
- }
+#endif
+
#ifndef OPENSSL_NO_TLSEXT
if (version != SSL2_VERSION)
{