sha512-x86_64.pl: upcoming-Atom-specific optimization.
[openssl.git] / ssl / s3_srvr.c
index 0c322cb2b17ce6d133ee9b28b0054cfa5a273ce0..ea4e132d979ca254c4dae3415948b4a951190bdb 100644 (file)
@@ -967,8 +967,9 @@ int ssl3_get_client_hello(SSL *s)
        s->client_version=(((int)p[0])<<8)|(int)p[1];
        p+=2;
 
-       if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
-           (s->version != DTLS1_VERSION && s->client_version < s->version))
+       if ((SSL_IS_DTLS(s) && s->client_version > s->version
+                       && s->method->version != DTLS_ANY_VERSION) ||
+           (!SSL_IS_DTLS(s) && s->client_version < s->version))
                {
                SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
                if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
@@ -1081,11 +1082,42 @@ int ssl3_get_client_hello(SSL *s)
                                                SSL_R_COOKIE_MISMATCH);
                                        goto f_err;
                                }
-
-                       ret = 2;
+                       /* Set to -2 so if successful we return 2 */
+                       ret = -2;
                        }
 
                p += cookie_len;
+               if (s->method->version == DTLS_ANY_VERSION)
+                       {
+                       /* Select version to use */
+                       if (s->client_version <= DTLS1_2_VERSION &&
+                               !(s->options & SSL_OP_NO_DTLSv1_2))
+                               {
+                               s->version = DTLS1_2_VERSION;
+                               s->method = DTLSv1_2_server_method();
+                               }
+                       else if (tls1_suiteb(s))
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+                               s->version = s->client_version;
+                               al = SSL_AD_PROTOCOL_VERSION;
+                               goto f_err;
+                               }
+                       else if (s->client_version <= DTLS1_VERSION &&
+                               !(s->options & SSL_OP_NO_DTLSv1))
+                               {
+                               s->version = DTLS1_VERSION;
+                               s->method = DTLSv1_server_method();
+                               }
+                       else
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
+                               s->version = s->client_version;
+                               al = SSL_AD_PROTOCOL_VERSION;
+                               goto f_err;
+                               }
+                       s->session->ssl_version = s->version;
+                       }
                }
 
        n2s(p,i);
@@ -1436,7 +1468,7 @@ int ssl3_get_client_hello(SSL *s)
                        }
                }
 
-       if (ret < 0) ret=1;
+       if (ret < 0) ret=-ret;
        if (0)
                {
 f_err:
@@ -1444,7 +1476,7 @@ f_err:
                }
 err:
        if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
-       return(ret);
+       return ret < 0 ? -1 : ret;
        }
 
 int ssl3_send_server_hello(SSL *s)