dtls1_read_bytes() uses dtls1_get_record() to get a record from the 
wire. There's an agreement between those two functions that says that 
ssl->s3->rrec.length contains the length of the record just read. If 
ssl->s3->rrec.length equals 0 then there's no record in the buffer.

dtls1_get_record() fails to set ssl->s3->rrec.length to 0 if it drops a 
record for various reasons. Therefore dtls1_read_bytes() wrongly 
interprets this bogus piece of data which should have been ignored.

This patch aims to fix this bug by assigning 0 to rrec->length in those 
places.

Version affected: HEAD

Index: ssl/d1_pkt.c
===================================================================
RCS file: /v/openssl/cvs/openssl/ssl/d1_pkt.c,v
retrieving revision 1.33
diff -u -8 -p -r1.33 d1_pkt.c
--- ssl/d1_pkt.c        5 Jun 2009 14:59:26 -0000       1.33
+++ ssl/d1_pkt.c        29 Jun 2009 18:46:39 -0000
@@ -618,29 +618,31 @@ again:
                /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
                i=rr->length;
                n=ssl3_read_n(s,i,i,1);
                if (n <= 0) return(n); /* error or non-blocking io */
 
                /* this packet contained a partial record, dump it */
                if ( n != i)
                        {
+                       rr->length = 0;
                        s->packet_length = 0;
                        goto again;
                        }
 
                /* now n == rr->length,
                 * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length 
*/
                }
        s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
 
        /* match epochs.  NULL means the packet is dropped on the floor */
        bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
        if ( bitmap == NULL)
                {
+               rr->length = 0;
                s->packet_length = 0;  /* dump this record */
                goto again;   /* get another record */
                }
 
        /* check whether this is a repeat, or aged record */
        if ( ! dtls1_record_replay_check(s, bitmap))
                {
                rr->length = 0;
@@ -655,16 +657,17 @@ again:
         * buffer it since it cannot be processed at this time. Records
         * from the next epoch are marked as received even though they
         * are not processed, so as to prevent any potential resource
         * DoS attack */
        if (is_next_epoch)
                {
                dtls1_record_bitmap_update(s, bitmap);
                dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
+               rr->length = 0;
                s->packet_length = 0;
                goto again;
                }
 
        if ( ! dtls1_process_record(s))
                return(0);
 
        dtls1_clear_timeouts(s);  /* done waiting */

Reply via email to