DTLS handshake message fragments musn't span packets

It should not be possible for DTLS message fragments to span multiple
packets. However previously if the message header fitted exactly into one
packet, and the fragment body was in the next packet then this would work.
Obviously this would fail if packets get re-ordered mid-flight.

Reviewed-by: Tim Hudson <tjh@openssl.org>
This commit is contained in:
Matt Caswell 2015-06-01 17:25:29 +01:00
parent b821df5f5b
commit 91d13f1a76

View file

@ -868,6 +868,20 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
/* parse the message fragment header */
dtls1_get_message_header(wire, &msg_hdr);
len = msg_hdr.msg_len;
frag_off = msg_hdr.frag_off;
frag_len = msg_hdr.frag_len;
/*
* We must have at least frag_len bytes left in the record to be read.
* Fragments must not span records.
*/
if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
al = SSL3_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_BAD_LENGTH);
goto f_err;
}
/*
* if this is a future (or stale) message it gets buffered
* (or dropped)--no further processing at this time
@ -878,10 +892,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
&& !(s->d1->listen && msg_hdr.seq == 1))
return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
len = msg_hdr.msg_len;
frag_off = msg_hdr.frag_off;
frag_len = msg_hdr.frag_len;
if (frag_len && frag_len < len)
return dtls1_reassemble_fragment(s, &msg_hdr, ok);
@ -912,17 +922,16 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max)))
goto f_err;
/* XDTLS: ressurect this when restart is in place */
s->state = stn;
if (frag_len > 0) {
unsigned char *p =
(unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
&p[frag_off], frag_len, 0);
/*
* XDTLS: fix this--message fragments cannot span multiple packets
* This shouldn't ever fail due to NBIO because we already checked
* that we have enough data in the record
*/
if (i <= 0) {
s->rwstate = SSL_READING;
@ -943,6 +952,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
}
*ok = 1;
s->state = stn;
/*
* Note that s->init_num is *not* used as current offset in