Don't add write errors into bytecounts
[openssl.git] / ssl / s3_srvr.c
index 14daf8fe4ec2fc0340e7fc98eb95964c319f844e..6bc80d579b7ec720494e5e0e7472a8263f83083b 100644 (file)
 #include <openssl/bn.h>
 #include <openssl/md5.h>
 
-#ifndef OPENSSL_NO_SSL3_METHOD
-static const SSL_METHOD *ssl3_get_server_method(int ver);
+static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p,
+    int num, STACK_OF(SSL_CIPHER) **skp, int sslv2format);
 
-static const SSL_METHOD *ssl3_get_server_method(int ver)
-{
-    if (ver == SSL3_VERSION)
-        return (SSLv3_server_method());
-    else
-        return (NULL);
-}
 
-IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
-                         ssl3_accept,
-                         ssl_undefined_function, ssl3_get_server_method)
-#endif
 #ifndef OPENSSL_NO_SRP
 static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
 {
@@ -894,14 +883,14 @@ int ssl3_send_hello_request(SSL *s)
 
 int ssl3_get_client_hello(SSL *s)
 {
-    int i, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
+    int i, complen, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
     unsigned int cookie_len;
     long n;
     unsigned long id;
     unsigned char *p, *d;
     SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
-    unsigned char *q;
+    unsigned char *q = NULL;
     SSL_COMP *comp = NULL;
 #endif
     STACK_OF(SSL_CIPHER) *ciphers = NULL;
@@ -932,13 +921,7 @@ int ssl3_get_client_hello(SSL *s)
     d = p = (unsigned char *)s->init_msg;
 
     /* First lets get s->client_version set correctly */
-    if (!s->read_hash && !s->enc_read_ctx
-            && RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
-        if (n < MIN_SSL2_RECORD_LEN) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
-        }
+    if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
         /*-
          * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
          * header is sent directly on the wire, not wrapped as a TLS
@@ -960,9 +943,8 @@ int ssl3_get_client_hello(SSL *s)
              * layer in order to have determined that this is a SSLv2 record
              * in the first place
              */
-            al = SSL_AD_HANDSHAKE_FAILURE;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            goto err;
         }
 
         if ((p[1] == 0x00) && (p[2] == 0x02)) {
@@ -998,15 +980,10 @@ int ssl3_get_client_hello(SSL *s)
     /* Do SSL/TLS version negotiation if applicable */
     if (!SSL_IS_DTLS(s)) {
         if (s->version != TLS_ANY_VERSION) {
-            if (s->client_version >= s->version
-                && (((s->client_version >> 8) & 0xff) == SSL3_VERSION_MAJOR)) {
+            if (s->client_version >= s->version) {
                 protverr = 0;
             }
-        } else {
-            /*
-             * We already know that this is an SSL3_VERSION_MAJOR protocol,
-             * so we're just testing the minor versions here
-             */
+        } else if (s->client_version >= SSL3_VERSION) {
             switch(s->client_version) {
             default:
             case TLS1_2_VERSION:
@@ -1034,17 +1011,20 @@ int ssl3_get_client_hello(SSL *s)
                 }
                 /* Deliberately fall through */
             case SSL3_VERSION:
+#ifndef OPENSSL_NO_SSL3
                 if(!(s->options & SSL_OP_NO_SSLv3)) {
                     s->version = SSL3_VERSION;
                     s->method = SSLv3_server_method();
                     protverr = 0;
                     break;
                 }
+#else
+                break;
+#endif
             }
         }
-    } else if (((s->client_version >> 8) & 0xff) == DTLS1_VERSION_MAJOR &&
-                (s->client_version <= s->version
-                || s->method->version == DTLS_ANY_VERSION)) {
+    } else if (s->client_version <= s->version
+                || s->method->version == DTLS_ANY_VERSION) {
         /*
          * For DTLS we just check versions are potentially compatible. Version
          * negotiation comes later.
@@ -1112,8 +1092,8 @@ int ssl3_get_client_hello(SSL *s)
         /* Set p to end of packet to ensure we don't look for extensions */
         p = d + n;
 
-        /* No compression, so set i to 0 */
-        i = 0;
+        /* No compression, so set complen to 0 */
+        complen = 0;
     } else {
         /* If we get here we've got SSLv3+ in an SSLv3+ record */
 
@@ -1357,8 +1337,8 @@ int ssl3_get_client_hello(SSL *s)
         }
 
         /* compression */
-        i = *(p++);
-        if ((p + i) > (d + n)) {
+        complen = *(p++);
+        if ((p + complen) > (d + n)) {
             /* not enough data */
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -1367,13 +1347,13 @@ int ssl3_get_client_hello(SSL *s)
 #ifndef OPENSSL_NO_COMP
         q = p;
 #endif
-        for (j = 0; j < i; j++) {
+        for (j = 0; j < complen; j++) {
             if (p[j] == 0)
                 break;
         }
 
-        p += i;
-        if (j >= i) {
+        p += complen;
+        if (j >= complen) {
             /* no compress */
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED);
@@ -1442,7 +1422,7 @@ int ssl3_get_client_hello(SSL *s)
 
     /*
      * Worst case, we will use the NULL compression, but if we have other
-     * options, we will now look for them.  We have i-1 compression
+     * options, we will now look for them.  We have complen-1 compression
      * algorithms from the client, starting at q.
      */
     s->s3->tmp.new_compression = NULL;
@@ -1471,11 +1451,11 @@ int ssl3_get_client_hello(SSL *s)
             goto f_err;
         }
         /* Look for resumed method in compression list */
-        for (m = 0; m < i; m++) {
+        for (m = 0; m < complen; m++) {
             if (q[m] == comp_id)
                 break;
         }
-        if (m >= i) {
+        if (m >= complen) {
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
                    SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
@@ -1491,7 +1471,7 @@ int ssl3_get_client_hello(SSL *s)
         for (m = 0; m < nn; m++) {
             comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
             v = comp->id;
-            for (o = 0; o < i; o++) {
+            for (o = 0; o < complen; o++) {
                 if (v == q[o]) {
                     done = 1;
                     break;
@@ -3556,3 +3536,119 @@ int ssl3_get_next_proto(SSL *s)
 # endif
 
 #endif
+
+#define SSLV2_CIPHER_LEN    3
+
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p,
+                                               int num,
+                                               STACK_OF(SSL_CIPHER) **skp,
+                                               int sslv2format)
+{
+    const SSL_CIPHER *c;
+    STACK_OF(SSL_CIPHER) *sk;
+    int i, n;
+
+    if (s->s3)
+        s->s3->send_connection_binding = 0;
+
+    if(sslv2format) {
+        n = SSLV2_CIPHER_LEN;
+    } else {
+        n = ssl_put_cipher_by_char(s, NULL, NULL);
+    }
+    if (n == 0 || (num % n) != 0) {
+        SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
+               SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+        return (NULL);
+    }
+    if ((skp == NULL) || (*skp == NULL)) {
+        sk = sk_SSL_CIPHER_new_null(); /* change perhaps later */
+        if(sk == NULL) {
+            SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+            return NULL;
+        }
+    } else {
+        sk = *skp;
+        sk_SSL_CIPHER_zero(sk);
+    }
+
+    OPENSSL_free(s->s3->tmp.ciphers_raw);
+    s->s3->tmp.ciphers_raw = BUF_memdup(p, num);
+    if (s->s3->tmp.ciphers_raw == NULL) {
+        SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    s->s3->tmp.ciphers_rawlen = (size_t)num;
+
+    for (i = 0; i < num; i += n) {
+        /* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */
+        if (s->s3 && (n != 3 || !p[0]) &&
+            (p[n - 2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
+            (p[n - 1] == (SSL3_CK_SCSV & 0xff))) {
+            /* SCSV fatal if renegotiating */
+            if (s->renegotiate) {
+                SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
+                       SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
+                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+                goto err;
+            }
+            s->s3->send_connection_binding = 1;
+            p += n;
+#ifdef OPENSSL_RI_DEBUG
+            fprintf(stderr, "SCSV received by server\n");
+#endif
+            continue;
+        }
+
+        /* Check for TLS_FALLBACK_SCSV */
+        if ((n != 3 || !p[0]) &&
+            (p[n - 2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) &&
+            (p[n - 1] == (SSL3_CK_FALLBACK_SCSV & 0xff))) {
+            /*
+             * The SCSV indicates that the client previously tried a higher
+             * version. Fail if the current version is an unexpected
+             * downgrade.
+             */
+            if (!SSL_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL)) {
+                SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
+                       SSL_R_INAPPROPRIATE_FALLBACK);
+                if (s->s3)
+                    ssl3_send_alert(s, SSL3_AL_FATAL,
+                                    SSL_AD_INAPPROPRIATE_FALLBACK);
+                goto err;
+            }
+            p += n;
+            continue;
+        }
+
+        if(sslv2format) {
+            /*
+             * We only support SSLv2 format ciphers in SSLv3+ using a
+             * SSLv2 backward compatible ClientHello. In this case the first
+             * byte is always 0 for SSLv3 compatible ciphers. Anything else
+             * is an SSLv2 cipher and we ignore it
+             */
+            if(p[0] == 0)
+                c = ssl_get_cipher_by_char(s, &p[1]);
+            else
+                c = NULL;
+        } else {
+            c = ssl_get_cipher_by_char(s, p);
+        }
+        p += n;
+        if (c != NULL) {
+            if (!sk_SSL_CIPHER_push(sk, c)) {
+                SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+        }
+    }
+
+    if (skp != NULL)
+        *skp = sk;
+    return (sk);
+ err:
+    if ((skp == NULL) || (*skp == NULL))
+        sk_SSL_CIPHER_free(sk);
+    return (NULL);
+}