Send an alert if we get a non-initial record with the wrong version
[openssl.git] / ssl / record / ssl3_record.c
index b4d89811fe520049396542f96db850044629decf..f67b85f0a9ae799ce3c886df2fcce15cc6228643 100644 (file)
@@ -160,12 +160,17 @@ int ssl3_get_record(SSL *s)
 
             /*
              * Check whether this is a regular record or an SSLv2 style record.
-             * The latter is only used in an initial ClientHello for old
-             * clients. We check s->read_hash and s->enc_read_ctx to ensure this
-             * does not apply during renegotiation
+             * The latter can only be used in the first record of an initial
+             * ClientHello for old clients. Initial ClientHello means
+             * s->first_packet is set and s->server is true.  The first record
+             * means s->rlayer.is_first_record is true. Probably this is
+             * sufficient in itself instead of s->first_packet, but I am
+             * cautious. We check s->read_hash and s->enc_read_ctx to ensure
+             * this does not apply during renegotiation.
              */
-            if (s->first_packet && s->server && !s->read_hash
-                    && !s->enc_read_ctx
+            if (s->first_packet && s->server
+                    && RECORD_LAYER_is_first_record(&s->rlayer)
+                    && s->read_hash == NULL && s->enc_read_ctx == NULL
                     && (p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) {
                 /*
                  *  SSLv2 style record
@@ -233,7 +238,7 @@ int ssl3_get_record(SSL *s)
                 }
 
                 if ((version >> 8) != SSL3_VERSION_MAJOR) {
-                    if (s->first_packet) {
+                    if (RECORD_LAYER_is_first_record(&s->rlayer)) {
                         /* Go back to start of packet, look at the five bytes
                          * that we have. */
                         p = RECORD_LAYER_get_packet(&s->rlayer);
@@ -248,9 +253,17 @@ int ssl3_get_record(SSL *s)
                                    SSL_R_HTTPS_PROXY_REQUEST);
                             goto err;
                         }
+
+                        /* Doesn't look like TLS - don't send an alert */
+                        SSLerr(SSL_F_SSL3_GET_RECORD,
+                               SSL_R_WRONG_VERSION_NUMBER);
+                        goto err;
+                    } else {
+                        SSLerr(SSL_F_SSL3_GET_RECORD,
+                               SSL_R_WRONG_VERSION_NUMBER);
+                        al = SSL_AD_PROTOCOL_VERSION;
+                        goto f_err;
                     }
-                    SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
-                    goto err;
                 }
 
                 if (rr[num_recs].length >
@@ -329,6 +342,7 @@ int ssl3_get_record(SSL *s)
 
         /* we have pulled in a full packet so zero things */
         RECORD_LAYER_reset_packet_length(&s->rlayer);
+        RECORD_LAYER_set_first_record(&s->rlayer, 0);
     } while (num_recs < max_recs
              && rr[num_recs-1].type == SSL3_RT_APPLICATION_DATA
              && SSL_USE_EXPLICIT_IV(s)
@@ -1143,9 +1157,9 @@ int tls1_cbc_remove_padding(const SSL *s,
      * maximum amount of padding possible. (Again, the length of the record
      * is public information so we can use it.)
      */
-    to_check = 255;             /* maximum amount of padding. */
-    if (to_check > rec->length - 1)
-        to_check = rec->length - 1;
+    to_check = 256;            /* maximum amount of padding, inc length byte. */
+    if (to_check > rec->length)
+        to_check = rec->length;
 
     for (i = 0; i < to_check; i++) {
         unsigned char mask = constant_time_ge_8(padding_length, i);