summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2009-04-14 14:20:57 +0000
committerDr. Stephen Henson <steve@openssl.org>2009-04-14 14:20:57 +0000
commit3c0ce01cea2b601c5e20683084687b5a1b9bf331 (patch)
tree7d42a36d9df0606e17910a574c6660ddc24baa9d
parent9fcbefebdb3170bc91b4220505dd59a5b474f71f (diff)
PR: 1827
Submitted by: Robin Seggelmann <seggelmann@fh-muenster.de> Approved by: steve@openssl.org Updated patch for PR #1827
-rw-r--r--ssl/d1_lib.c13
-rw-r--r--ssl/d1_pkt.c57
-rw-r--r--ssl/dtls1.h7
3 files changed, 65 insertions, 12 deletions
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index bd28b75e84..be47541440 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -98,6 +98,7 @@ int dtls1_new(SSL *s)
d1->processed_rcds.q=pqueue_new();
d1->buffered_messages = pqueue_new();
d1->sent_messages=pqueue_new();
+ d1->buffered_app_data.q=pqueue_new();
if ( s->server)
{
@@ -105,12 +106,13 @@ int dtls1_new(SSL *s)
}
if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q
- || ! d1->buffered_messages || ! d1->sent_messages)
+ || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
{
if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
if ( d1->sent_messages) pqueue_free(d1->sent_messages);
+ if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
OPENSSL_free(d1);
return (0);
}
@@ -159,6 +161,15 @@ void dtls1_free(SSL *s)
}
pqueue_free(s->d1->sent_messages);
+ while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
+ {
+ frag = (hm_fragment *)item->data;
+ OPENSSL_free(frag->fragment);
+ OPENSSL_free(frag);
+ pitem_free(item);
+ }
+ pqueue_free(s->d1->buffered_app_data.q);
+
OPENSSL_free(s->d1);
}
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 8ce567dba4..2e9d5452f7 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -746,6 +746,23 @@ start:
* s->s3->rrec.length, - number of bytes. */
rr = &(s->s3->rrec);
+ /* We are not handshaking and have no data yet,
+ * so process data buffered during the last handshake
+ * in advance, if any.
+ */
+ if (s->state == SSL_ST_OK && rr->length == 0)
+ {
+ pitem *item;
+ item = pqueue_pop(s->d1->buffered_app_data.q);
+ if (item)
+ {
+ dtls1_copy_record(s, item);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+ }
+
/* get new packet if necessary */
if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
{
@@ -767,9 +784,14 @@ start:
* reset by ssl3_get_finished */
&& (rr->type != SSL3_RT_HANDSHAKE))
{
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
- goto err;
+ /* We now have application data between CCS and Finished.
+ * Most likely the packets were reordered on their way, so
+ * buffer the application data for later processing rather
+ * than dropping the connection.
+ */
+ dtls1_buffer_record(s, &(s->d1->buffered_app_data), 0);
+ rr->length = 0;
+ goto start;
}
/* If the other end has shut down, throw anything we read away
@@ -839,15 +861,28 @@ start:
dest = s->d1->alert_fragment;
dest_len = &s->d1->alert_fragment_len;
}
- /* else it's a CCS message, or it's wrong */
- else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
- {
- /* Not certain if this is the right error handling */
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
- goto f_err;
- }
+ /* else it's a CCS message, or application data or wrong */
+ else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
+ {
+ /* Application data while renegotiating
+ * is allowed. Try again reading.
+ */
+ if (rr->type == SSL3_RT_APPLICATION_DATA)
+ {
+ BIO *bio;
+ s->s3->in_read_app_data=2;
+ bio=SSL_get_rbio(s);
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return(-1);
+ }
+ /* Not certain if this is the right error handling */
+ al=SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
if (dest_maxlen > 0)
{
diff --git a/ssl/dtls1.h b/ssl/dtls1.h
index a267ae4377..efc8523308 100644
--- a/ssl/dtls1.h
+++ b/ssl/dtls1.h
@@ -196,6 +196,13 @@ typedef struct dtls1_state_st
/* Buffered (sent) handshake records */
pqueue sent_messages;
+ /* Buffered application records.
+ * Only for records between CCS and Finished
+ * to prevent either protocol violation or
+ * unnecessary message loss.
+ */
+ record_pqueue buffered_app_data;
+
unsigned int mtu; /* max wire packet size */
struct hm_header_st w_msg_hdr;