diff -up openssl-1.0.1e/ssl/d1_both.c.dtls1-dos2 openssl-1.0.1e/ssl/d1_both.c --- openssl-1.0.1e/ssl/d1_both.c.dtls1-dos2 2016-09-20 15:53:03.748445806 +0200 +++ openssl-1.0.1e/ssl/d1_both.c 2016-09-20 16:12:01.422861505 +0200 @@ -211,7 +211,7 @@ dtls1_hm_fragment_new(unsigned long frag return frag; } -static void +void dtls1_hm_fragment_free(hm_fragment *frag) { @@ -544,11 +544,26 @@ dtls1_retrieve_buffered_fragment(SSL *s, int al; *ok = 0; - item = pqueue_peek(s->d1->buffered_messages); - if ( item == NULL) - return 0; + do + { + item = pqueue_peek(s->d1->buffered_messages); + if (item == NULL) + return 0; + + frag = (hm_fragment *)item->data; + + if (frag->msg_header.seq < s->d1->handshake_read_seq) + { + /* This is a stale message that has been buffered so clear it */ + pqueue_pop(s->d1->buffered_messages); + dtls1_hm_fragment_free(frag); + pitem_free(item); + item = NULL; + frag = NULL; + } + } + while (item == NULL); - frag = (hm_fragment *)item->data; /* Don't return if reassembly still in progress */ if (frag->reassembly != NULL) @@ -1339,21 +1354,6 @@ dtls1_retransmit_message(SSL *s, unsigne return ret; } -/* call this function when the buffered messages are no longer needed */ -void -dtls1_clear_record_buffer(SSL *s) - { - pitem *item; - - for(item = pqueue_pop(s->d1->sent_messages); - item != NULL; item = pqueue_pop(s->d1->sent_messages)) - { - dtls1_hm_fragment_free((hm_fragment *)item->data); - pitem_free(item); - } - } - - unsigned char * dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, unsigned long len, unsigned long frag_off, unsigned long frag_len) diff -up openssl-1.0.1e/ssl/d1_clnt.c.dtls1-dos2 openssl-1.0.1e/ssl/d1_clnt.c --- openssl-1.0.1e/ssl/d1_clnt.c.dtls1-dos2 2016-09-20 15:53:03.748445806 +0200 +++ openssl-1.0.1e/ssl/d1_clnt.c 2016-09-20 15:58:38.292200957 +0200 @@ -739,6 +739,7 @@ int dtls1_connect(SSL *s) /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); goto end; /* break; */ diff -up openssl-1.0.1e/ssl/d1_lib.c.dtls1-dos2 openssl-1.0.1e/ssl/d1_lib.c --- openssl-1.0.1e/ssl/d1_lib.c.dtls1-dos2 2016-09-20 15:53:03.749445830 +0200 +++ openssl-1.0.1e/ssl/d1_lib.c 2016-09-20 16:18:10.046443374 +0200 @@ -133,7 +133,6 @@ int dtls1_new(SSL *s) static void dtls1_clear_queues(SSL *s) { pitem *item = NULL; - hm_fragment *frag = NULL; DTLS1_RECORD_DATA *rdata; while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) @@ -158,32 +157,45 @@ static void dtls1_clear_queues(SSL *s) pitem_free(item); } - while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL) - { + while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) + { + rdata = (DTLS1_RECORD_DATA *)item->data; + if (rdata->rbuf.buf) + { + OPENSSL_free(rdata->rbuf.buf); + } + OPENSSL_free(item->data); + pitem_free(item); + } + + dtls1_clear_received_buffer(s); + dtls1_clear_sent_buffer(s); + } + +void dtls1_clear_received_buffer(SSL *s) + { + pitem *item = NULL; + hm_fragment *frag = NULL; + + while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) + { frag = (hm_fragment *)item->data; - OPENSSL_free(frag->fragment); - OPENSSL_free(frag); + dtls1_hm_fragment_free(frag); pitem_free(item); } + } - while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL) - { +void dtls1_clear_sent_buffer(SSL *s) + { + pitem *item = NULL; + hm_fragment *frag = NULL; + + while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) + { frag = (hm_fragment *)item->data; - OPENSSL_free(frag->fragment); - OPENSSL_free(frag); + dtls1_hm_fragment_free(frag); pitem_free(item); } - - while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) - { - rdata = (DTLS1_RECORD_DATA *) item->data; - if (rdata->rbuf.buf) - { - OPENSSL_free(rdata->rbuf.buf); - } - OPENSSL_free(item->data); - pitem_free(item); - } } void dtls1_free(SSL *s) @@ -410,7 +422,7 @@ void dtls1_stop_timer(SSL *s) s->d1->timeout_duration = 1; BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); /* Clear retransmission buffer */ - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); } int dtls1_check_timeout_num(SSL *s) diff -up openssl-1.0.1e/ssl/d1_pkt.c.dtls1-dos2 openssl-1.0.1e/ssl/d1_pkt.c --- openssl-1.0.1e/ssl/d1_pkt.c.dtls1-dos2 2016-09-20 15:53:17.246758715 +0200 +++ openssl-1.0.1e/ssl/d1_pkt.c 2016-09-20 16:14:33.020390824 +0200 @@ -1900,6 +1900,12 @@ dtls1_reset_seq_numbers(SSL *s, int rw) s->d1->r_epoch++; memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP)); memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP)); + + /* + * We must not use any buffered messages received from the previous + * epoch + */ + dtls1_clear_received_buffer(s); } else { diff -up openssl-1.0.1e/ssl/d1_srvr.c.dtls1-dos2 openssl-1.0.1e/ssl/d1_srvr.c --- openssl-1.0.1e/ssl/d1_srvr.c.dtls1-dos2 2016-09-20 15:53:03.750445853 +0200 +++ openssl-1.0.1e/ssl/d1_srvr.c 2016-09-20 16:15:39.699943181 +0200 @@ -276,7 +276,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); dtls1_start_timer(s); ret=dtls1_send_hello_request(s); if (ret <= 0) goto end; @@ -811,6 +811,7 @@ int dtls1_accept(SSL *s) /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); goto end; /* break; */ diff -up openssl-1.0.1e/ssl/ssl_locl.h.dtls1-dos2 openssl-1.0.1e/ssl/ssl_locl.h --- openssl-1.0.1e/ssl/ssl_locl.h.dtls1-dos2 2016-09-20 15:53:03.751445876 +0200 +++ openssl-1.0.1e/ssl/ssl_locl.h 2016-09-20 16:11:36.288276350 +0200 @@ -974,7 +974,8 @@ int dtls1_retransmit_message(SSL *s, uns unsigned long frag_off, int *found); int dtls1_get_queue_priority(unsigned short seq, int is_ccs); int dtls1_retransmit_buffered_messages(SSL *s); -void dtls1_clear_record_buffer(SSL *s); +void dtls1_clear_received_buffer(SSL *s); +void dtls1_clear_sent_buffer(SSL *s); void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr); void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); void dtls1_reset_seq_numbers(SSL *s, int rw); @@ -989,6 +990,7 @@ int dtls1_is_timer_expired(SSL *s); void dtls1_double_timeout(SSL *s); int dtls1_send_newsession_ticket(SSL *s); unsigned int dtls1_min_mtu(void); +void dtls1_hm_fragment_free(hm_fragment *frag); /* some client-only functions */ int ssl3_client_hello(SSL *s);