diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 7fb9b96d1d..0ada7edf77 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -114,6 +114,12 @@ int dtls1_new(SSL *s) } static void dtls1_clear_queues(SSL *s) +{ + dtls1_clear_received_buffer(s); + dtls1_clear_sent_buffer(s); +} + +void dtls1_clear_received_buffer(SSL *s) { pitem *item = NULL; hm_fragment *frag = NULL; @@ -123,6 +129,12 @@ static void dtls1_clear_queues(SSL *s) dtls1_hm_fragment_free(frag); pitem_free(item); } +} + +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; @@ -131,6 +143,7 @@ static void dtls1_clear_queues(SSL *s) } } + void dtls1_free(SSL *s) { DTLS_RECORD_LAYER_free(&s->rlayer); @@ -325,7 +338,7 @@ void dtls1_stop_timer(SSL *s) 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 --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 6fba98325a..4079b31637 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1923,7 +1923,8 @@ __owur int dtls1_buffer_message(SSL *s, int ccs); __owur int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found); __owur 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); __owur long dtls1_default_timeout(void); diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c index 46843ce0fc..de2de09796 100644 --- a/ssl/statem/statem_dtls.c +++ b/ssl/statem/statem_dtls.c @@ -442,11 +442,23 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok) int al; *ok = 0; - item = pqueue_peek(s->d1->buffered_messages); - if (item == NULL) - return 0; - frag = (hm_fragment *)item->data; + 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); /* Don't return if reassembly still in progress */ if (frag->reassembly != NULL) @@ -1117,18 +1129,6 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found) 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); - } -} - void dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len, unsigned long frag_off, unsigned long frag_len) diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index fac9684ce2..19b75a7ac7 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -331,6 +331,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst) s->d1->handshake_read_seq = 0; s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); } } diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index ae1c65d9ae..95dcc9b60b 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -433,13 +433,13 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) case TLS_ST_SW_HELLO_REQ: s->shutdown = 0; if (SSL_IS_DTLS(s)) - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); break; case DTLS_ST_SW_HELLO_VERIFY_REQUEST: s->shutdown = 0; if (SSL_IS_DTLS(s)) { - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); /* We don't buffer this message so don't use the timer */ st->use_timer = 0; }