s23_clnt.c: ensure interoperability by maitaining client "version capability"
authorAndy Polyakov <appro@openssl.org>
Wed, 25 Apr 2012 22:06:32 +0000 (22:06 +0000)
committerAndy Polyakov <appro@openssl.org>
Wed, 25 Apr 2012 22:06:32 +0000 (22:06 +0000)
vector contiguous.
PR: 2802

CHANGES
ssl/s23_clnt.c

diff --git a/CHANGES b/CHANGES
index 94cfe6e7848396e90d3f97d95c1ecb07f5fcbc3f..182a6da9d62e5405546bd15fee8b811bd12fd2ce 100644 (file)
--- a/CHANGES
+++ b/CHANGES
      is enable if DEBUG_UNUSED is set. Add to several functions in evp.h
      whose return value is often ignored. 
      [Steve Henson]
      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
  Changes between 1.0.1 and 1.0.1a [19 Apr 2012]
 
   *) Check for potentially exploitable overflows in asn1_d2i_read_bio
index a76eb469083beb54bf003b6c6fccbf6cea8a1707..47673e740abeacc3e276756f6ab1d7d62b5ec408 100644 (file)
@@ -282,32 +282,51 @@ static int ssl23_client_hello(SSL *s)
        SSL_COMP *comp;
 #endif
        int ret;
        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 (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;
                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;
                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;
                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;
                version = SSL2_VERSION;
-               }
+#endif
+
 #ifndef OPENSSL_NO_TLSEXT
        if (version != SSL2_VERSION)
                {
 #ifndef OPENSSL_NO_TLSEXT
        if (version != SSL2_VERSION)
                {