diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2009-06-05 14:46:49 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2009-06-05 14:46:49 +0000 |
commit | 4e63da06698fd217d89a5ec39fd0c7b26dc8d0c0 (patch) | |
tree | 802cf1019da632b42e72ee83b0eab381e8e58b60 /ssl | |
parent | 15b0a5651c78c7a7372497819f983541d3d2d9c4 (diff) |
PR: 1950
Submitted by: Robin Seggelmann <seggelmann@fh-muenster.de>
Reviewed by: steve@openssl.org
DTLS fragment retransmission bug.
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/d1_both.c | 8 | ||||
-rw-r--r-- | ssl/d1_clnt.c | 2 | ||||
-rw-r--r-- | ssl/d1_pkt.c | 10 | ||||
-rw-r--r-- | ssl/d1_srvr.c | 2 | ||||
-rw-r--r-- | ssl/dtls1.h | 1 |
5 files changed, 20 insertions, 3 deletions
diff --git a/ssl/d1_both.c b/ssl/d1_both.c index ebc03482f0..7039d05f0e 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -569,9 +569,13 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) item = pqueue_find(s->d1->buffered_messages, seq64be); /* Discard the message if sequence number was already there, is - * too far in the future or the fragment is already in the queue */ + * too far in the future, already in the queue or if we received + * a FINISHED before the SERVER_HELLO, which then must be a stale + * retransmit. + */ if (msg_hdr->seq <= s->d1->handshake_read_seq || - msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL) + msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || + s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED) { unsigned char devnull [256]; diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c index 2364ad2f8d..a4a438ac79 100644 --- a/ssl/d1_clnt.c +++ b/ssl/d1_clnt.c @@ -442,7 +442,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - + s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) goto end; diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index a89edbc7a7..394daf6258 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -1102,6 +1102,16 @@ start: s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg); + /* We can't process a CCS now, because previous handshake + * messages are still missing, so just drop it. + */ + if (!s->d1->change_cipher_spec_ok) + { + goto start; + } + + s->d1->change_cipher_spec_ok = 0; + s->s3->change_cipher_spec=1; if (!ssl3_do_change_cipher_spec(s)) goto err; diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index 6d6363f04f..ac09b45ef1 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -497,6 +497,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: + s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; @@ -508,6 +509,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: + s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; diff --git a/ssl/dtls1.h b/ssl/dtls1.h index 2fe0405011..73af56d45c 100644 --- a/ssl/dtls1.h +++ b/ssl/dtls1.h @@ -231,6 +231,7 @@ typedef struct dtls1_state_st unsigned int handshake_fragment_len; unsigned int retransmitting; + unsigned int change_cipher_spec_ok; } DTLS1_STATE; |