The current DTLS implementation always generates an  
SSL_R_UNEXPECTED_RECORD error if application data is received while  
handshaking. This is ok for the first handshake, but not necessary for  
renegotiations. Furthermore it's likely that the connection fails just  
because of unordered UDP packets. The DTLS specification does not  
mention this issue, but there is no reason not to accept belated  
application data while renegotiating, as long as the key material has  
not changed yet. With this patch the implementation will leave the  
handshake routine, return the application data and generate the error  
SSL_ERROR_WANT_READ, so that the application reads again to continue  
handshaking.


--- ssl/dtls1.h 2008-09-13 20:25:36.000000000 +0200
+++ ssl/dtls1.h 2009-01-27 10:39:42.000000000 +0100
@@ -178,6 +178,9 @@
        /* Buffered (sent) handshake records */
        pqueue sent_messages;

+       /* Buffered application records */
+       record_pqueue buffered_app_data;
+
        unsigned int mtu; /* max wire packet size */

        struct hm_header_st w_msg_hdr;

--- ssl/d1_lib.c        2008-10-13 08:43:05.000000000 +0200
+++ ssl/d1_lib.c        2009-01-14 10:20:23.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-01-27 10:35:38.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)
                        {


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

Reply via email to