--- ssl/d1_both.c 2007-10-17 23:17:49.000000000 +0200 +++ ssl/d1_both.c 2009-06-05 13:49:32.000000000 +0200 @@ -561,7 +561,8 @@ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) goto err; - if (msg_hdr->seq <= s->d1->handshake_read_seq) + if (msg_hdr->seq <= s->d1->handshake_read_seq || + (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) { unsigned char devnull [256]; --- ssl/d1_clnt.c 2008-06-04 20:35:25.000000000 +0200 +++ ssl/d1_clnt.c 2009-06-05 13:49:32.000000000 +0200 @@ -433,7 +433,7 @@ 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; --- ssl/d1_pkt.c 2008-10-13 08:43:06.000000000 +0200 +++ ssl/d1_pkt.c 2009-06-05 13:49:32.000000000 +0200 @@ -1008,6 +1008,16 @@ 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; --- ssl/d1_srvr.c 2008-09-14 16:02:01.000000000 +0200 +++ ssl/d1_srvr.c 2009-06-05 13:55:17.000000000 +0200 @@ -459,6 +459,7 @@ 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; @@ -469,6 +470,7 @@ 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; --- ssl/dtls1.h 2008-09-13 20:25:36.000000000 +0200 +++ ssl/dtls1.h 2009-06-05 13:49:32.000000000 +0200 @@ -193,6 +193,7 @@ unsigned int handshake_fragment_len; unsigned int retransmitting; + unsigned int change_cipher_spec_ok; } DTLS1_STATE;