PR: 1647
[oweals/openssl.git] / ssl / d1_pkt.c
index eb56cf987ba3a12a4da4be7af6f0a46abbe200a4..3fa4c430247e6041be6fd178c84c45cb09cec70f 100644 (file)
@@ -703,6 +703,23 @@ start:
         * s->s3->rrec.length,  - number of bytes. */
        rr = &(s->s3->rrec);
 
+       /* We are not handshaking and have no data yet,
+        * so process data buffered during the last handshake
+        * in advance, if any.
+        */
+       if (s->state == SSL_ST_OK && rr->length == 0)
+               {
+               pitem *item;
+               item = pqueue_pop(s->d1->buffered_app_data.q);
+               if (item)
+                       {
+                       dtls1_copy_record(s, item);
+
+                       OPENSSL_free(item->data);
+                       pitem_free(item);
+                       }
+               }
+               
        /* get new packet if necessary */
        if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
                {
@@ -724,9 +741,14 @@ start:
                                       * reset by ssl3_get_finished */
                && (rr->type != SSL3_RT_HANDSHAKE))
                {
-               al=SSL_AD_UNEXPECTED_MESSAGE;
-               SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
-               goto err;
+               /* We now have application data between CCS and Finished.
+                * Most likely the packets were reordered on their way, so
+                * buffer the application data for later processing rather
+                * than dropping the connection.
+                */
+               dtls1_buffer_record(s, &(s->d1->buffered_app_data), 0);
+               rr->length = 0;
+               goto start;
                }
 
        /* If the other end has shut down, throw anything we read away
@@ -796,15 +818,28 @@ start:
                        dest = s->d1->alert_fragment;
                        dest_len = &s->d1->alert_fragment_len;
                        }
-                /* else it's a CCS message, or it's wrong */
-                else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
-                        {
-                          /* Not certain if this is the right error handling */
-                          al=SSL_AD_UNEXPECTED_MESSAGE;
-                          SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
-                          goto f_err;
-                        }
+               /* else it's a CCS message, or application data or wrong */
+               else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
+                       {
+                       /* Application data while renegotiating
+                        * is allowed. Try again reading.
+                        */
+                       if (rr->type == SSL3_RT_APPLICATION_DATA)
+                               {
+                               BIO *bio;
+                               s->s3->in_read_app_data=2;
+                               bio=SSL_get_rbio(s);
+                               s->rwstate=SSL_READING;
+                               BIO_clear_retry_flags(bio);
+                               BIO_set_retry_read(bio);
+                               return(-1);
+                               }
 
+                       /* Not certain if this is the right error handling */
+                       al=SSL_AD_UNEXPECTED_MESSAGE;
+                       SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+                       goto f_err;
+                       }
 
                if (dest_maxlen > 0)
                        {
@@ -942,7 +977,9 @@ start:
                                n2s(p, seq);
                                n2l3(p, frag_off);
 
-                               dtls1_retransmit_message(s, seq, frag_off, &found);
+                               dtls1_retransmit_message(s,
+                                                                                dtls1_get_queue_priority(frag->msg_header.seq, 0),
+                                                                                frag_off, &found);
                                if ( ! found  && SSL_in_init(s))
                                        {
                                        /* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
@@ -1035,6 +1072,16 @@ start:
                        goto start;
                        }
 
+               /* If we are server, we may have a repeated FINISHED of the
+                * client here, then retransmit our CCS and FINISHED.
+                */
+               if (msg_hdr.type == SSL3_MT_FINISHED)
+                       {
+                       dtls1_retransmit_buffered_messages(s);
+                       rr->length = 0;
+                       goto start;
+                       }
+
                if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
                        !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
                        {
@@ -1758,6 +1805,7 @@ dtls1_reset_seq_numbers(SSL *s, int rw)
        else
                {
                seq = s->s3->write_sequence;
+               memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence));
                s->d1->w_epoch++;
                }