This updated version includes the suggestions of Nagendra Modadugu.

--- ssl/d1_lib.c        2008-10-13 08:43:05.000000000 +0200
+++ ssl/d1_lib.c        2009-03-23 18:53:11.000000000 +0100
@@ -114,6 +114,7 @@
        d1->processed_rcds.q=pqueue_new();
        d1->buffered_messages = pqueue_new();
        d1->sent_messages=pqueue_new();
+       d1->buffered_app_data.q=pqueue_new();

        if ( s->server)
                {
@@ -121,12 +122,13 @@
                }

        if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q
-        || ! d1->buffered_messages || ! d1->sent_messages)
+        || ! d1->buffered_messages || ! d1->sent_messages || ! d1- 
 >buffered_app_data.q)
                {
          if ( d1->unprocessed_rcds.q) pqueue_free(d1- 
 >unprocessed_rcds.q);
          if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
          if ( d1->buffered_messages) pqueue_free(d1- 
 >buffered_messages);
                if ( d1->sent_messages) pqueue_free(d1->sent_messages);
+               if ( d1->buffered_app_data.q) 
pqueue_free(d1->buffered_app_data.q);
                OPENSSL_free(d1);
                return (0);
                }
@@ -175,6 +177,15 @@
          }
        pqueue_free(s->d1->sent_messages);

+       while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
+       {
+               frag = (hm_fragment *)item->data;
+               OPENSSL_free(frag->fragment);
+               OPENSSL_free(frag);
+               pitem_free(item);
+       }
+       pqueue_free(s->d1->buffered_app_data.q);
+       
        pq_64bit_free(&(s->d1->bitmap.map));
        pq_64bit_free(&(s->d1->bitmap.max_seq_num));

--- ssl/d1_pkt.c        2008-10-13 08:43:06.000000000 +0200
+++ ssl/d1_pkt.c        2009-03-23 18:53:12.000000000 +0100
@@ -703,6 +703,23 @@
         * 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 @@
                                       * 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 @@
                        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)
                        {
--- ssl/dtls1.h 2008-09-13 20:25:36.000000000 +0200
+++ ssl/dtls1.h 2009-03-23 19:00:41.000000000 +0100
@@ -178,6 +178,13 @@
        /* Buffered (sent) handshake records */
        pqueue sent_messages;

+       /* Buffered application records.
+        * Only for records between CCS and Finished
+        * to prevent either protocol violation or
+        * unnecessary message loss.
+        */
+       record_pqueue buffered_app_data;
+
        unsigned int mtu; /* max wire packet size */

        struct hm_header_st w_msg_hdr;




______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to