Here is an updated version, the last didn't cover every variation of the handshake message flow because the CertificateVerify state is entered every time, not only when a CertificateVerify message is really expected.
--- crypto/bio/bss_dgram.c 5 Jun 2009 08:35:54 -0000 1.7.2.13
+++ crypto/bio/bss_dgram.c 5 Jun 2009 12:05:47 -0000
@@ -220,9 +220,10 @@
/* Adjust socket timeout if next handhake message timer
* will expire earlier.
*/
- if (data->socket_timeout.tv_sec < timeleft.tv_sec ||
+ if ((data->socket_timeout.tv_sec == 0 && data-
>socket_timeout.tv_usec == 0) ||
+ (data->socket_timeout.tv_sec > timeleft.tv_sec) ||
(data->socket_timeout.tv_sec == timeleft.tv_sec &&
- data->socket_timeout.tv_usec <= timeleft.tv_usec))
+ data->socket_timeout.tv_usec >= timeleft.tv_usec))
{
#ifdef OPENSSL_SYS_WINDOWS
timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec /
1000;
--- ssl/d1_both.c 16 May 2009 16:22:11 -0000 1.14.2.9
+++ ssl/d1_both.c 5 Jun 2009 12:05:47 -0000
@@ -569,9 +569,13 @@
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];
--- ssl/d1_clnt.c 31 May 2009 17:11:24 -0000 1.16.2.8
+++ ssl/d1_clnt.c 5 Jun 2009 12:05:47 -0000
@@ -442,7 +442,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 16 May 2009 16:17:46 -0000 1.27.2.8
+++ ssl/d1_pkt.c 5 Jun 2009 12:05:47 -0000
@@ -1102,6 +1102,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 31 May 2009 17:11:24 -0000 1.20.2.5
+++ ssl/d1_srvr.c 5 Jun 2009 12:05:47 -0000
@@ -497,6 +497,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;
@@ -508,6 +509,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 2 Jun 2009 11:23:30 -0000 1.12.2.9
+++ ssl/dtls1.h 5 Jun 2009 12:05:47 -0000
@@ -231,6 +231,7 @@
unsigned int handshake_fragment_len;
unsigned int retransmitting;
+ unsigned int change_cipher_spec_ok;
} DTLS1_STATE;
dtls-fragment-retransmission-bug-1.0.0.patch
Description: Binary data
dtls-fragment-retransmission-bug-0.9.8.patch
Description: Binary data
