unsigned long frag_off,
unsigned long frag_len);
static long dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt,
- long max, int *ok);
+ int *ok);
+static int dtls_get_reassembled_message(SSL *s, long *len);
static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
int reassembly)
memset(msg_hdr, 0, sizeof(*msg_hdr));
again:
- i = dtls1_get_message_fragment(s, st1, stn, mt, max, ok);
+ i = dtls1_get_message_fragment(s, st1, stn, mt, ok);
if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) {
/* bad fragment received */
goto again;
msg_len += DTLS1_HM_HEADER_LENGTH;
}
+ if (msg_len > (unsigned long)max) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ goto f_err;
+ }
+
ssl3_finish_mac(s, p, msg_len);
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
return -1;
}
-static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr,
- int max)
+int dtls_get_message(SSL *s, int *mt, unsigned long *len)
+{
+ struct hm_header_st *msg_hdr;
+ unsigned char *p;
+ unsigned long msg_len;
+ int ok;
+ long tmplen;
+
+ msg_hdr = &s->d1->r_msg_hdr;
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ again:
+ ok = dtls_get_reassembled_message(s, &tmplen);
+ if (tmplen == DTLS1_HM_BAD_FRAGMENT
+ || tmplen == DTLS1_HM_FRAGMENT_RETRY) {
+ /* bad fragment received */
+ goto again;
+ } else if (tmplen <= 0 && !ok) {
+ return 0;
+ }
+
+ *mt = s->s3->tmp.message_type;
+
+ p = (unsigned char *)s->init_buf->data;
+
+ if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
+ p, 1, s, s->msg_callback_arg);
+ }
+ /*
+ * This isn't a real handshake message so skip the processing below.
+ */
+ return 1;
+ }
+
+ msg_len = msg_hdr->msg_len;
+
+ /* reconstruct message header */
+ *(p++) = msg_hdr->type;
+ l2n3(msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_len, p);
+ if (s->version != DTLS1_BAD_VER) {
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+ }
+
+ ssl3_finish_mac(s, p, msg_len);
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ p, msg_len, s, s->msg_callback_arg);
+
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ s->d1->handshake_read_seq++;
+
+
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ *len = s->init_num;
+
+ return 1;
+}
+
+static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
{
size_t frag_off, frag_len, msg_len;
return SSL_AD_ILLEGAL_PARAMETER;
}
- if ((frag_off + frag_len) > (unsigned long)max) {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
/*
* msg_len is limited to 2^24, but is effectively checked against max
return 0; /* no error */
}
-static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
+static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
{
/*-
* (0) check whether the desired fragment is available
unsigned long frag_len = frag->msg_header.frag_len;
pqueue_pop(s->d1->buffered_messages);
- al = dtls1_preprocess_fragment(s, &frag->msg_header, max);
+ al = dtls1_preprocess_fragment(s, &frag->msg_header);
if (al == 0) { /* no alert */
unsigned char *p =
}
static long
-dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt, long max, int *ok)
+dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt, int *ok)
+{
+ long len;
+
+ do {
+ *ok = dtls_get_reassembled_message(s, &len);
+ /* A CCS isn't a real handshake message, so if we get one there is no
+ * message sequence number to give us confidence that this was really
+ * intended to be at this point in the handshake sequence. Therefore we
+ * only allow this if we were explicitly looking for it (i.e. if |mt|
+ * is -1 we still don't allow it). If we get one when we're not
+ * expecting it then probably something got re-ordered or this is a
+ * retransmit. We should drop this and try again.
+ */
+ } while (*ok && mt != SSL3_MT_CHANGE_CIPHER_SPEC
+ && s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC);
+
+ if (*ok)
+ s->state = stn;
+
+ return len;
+}
+
+static int dtls_get_reassembled_message(SSL *s, long *len)
{
unsigned char wire[DTLS1_HM_HEADER_LENGTH];
- unsigned long len, frag_off, frag_len;
+ unsigned long mlen, frag_off, frag_len;
int i, al, recvd_type;
struct hm_header_st msg_hdr;
+ int ok;
redo:
/* see if we have the required fragment already */
- if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) {
- if (*ok)
+ if ((frag_len = dtls1_retrieve_buffered_fragment(s, &ok)) || ok) {
+ if (ok)
s->init_num = frag_len;
- return frag_len;
+ *len = frag_len;
+ return ok;
}
/* read handshake message header */
DTLS1_HM_HEADER_LENGTH, 0);
if (i <= 0) { /* nbio, or an error */
s->rwstate = SSL_READING;
- *ok = 0;
- return i;
+ *len = i;
+ return 0;
}
if(recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
- /* This isn't a real handshake message - its a CCS.
- * There is no message sequence number in a CCS to give us confidence
- * that this was really intended to be at this point in the handshake
- * sequence. Therefore we only allow this if we were explicitly looking
- * for it (i.e. if |mt| is -1 we still don't allow it).
- */
- if(mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- if (wire[0] != SSL3_MT_CCS) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_BAD_CHANGE_CIPHER_SPEC);
- goto f_err;
- }
-
- memcpy(s->init_buf->data, wire, i);
- s->init_num = i - 1;
- s->init_msg = s->init_buf->data + 1;
- s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
- s->s3->tmp.message_size = i - 1;
- s->state = stn;
- *ok = 1;
- return i-1;
- } else {
- /*
- * We weren't expecting a CCS yet. Probably something got
- * re-ordered or this is a retransmit. We should drop this and try
- * again.
- */
- s->init_num = 0;
- goto redo;
+ if (wire[0] != SSL3_MT_CCS) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
}
+
+ memcpy(s->init_buf->data, wire, i);
+ s->init_num = i - 1;
+ s->init_msg = s->init_buf->data + 1;
+ s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->s3->tmp.message_size = i - 1;
+ *len = i - 1;
+ return 1;
}
/* Handshake fails if message header is incomplete */
if (i != DTLS1_HM_HEADER_LENGTH) {
al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
/* parse the message fragment header */
dtls1_get_message_header(wire, &msg_hdr);
- len = msg_hdr.msg_len;
+ mlen = msg_hdr.msg_len;
frag_off = msg_hdr.frag_off;
frag_len = msg_hdr.frag_len;
*/
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);
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
goto f_err;
}
* While listening, we accept seq 1 (ClientHello with cookie)
* although we're still expecting seq 0 (ClientHello)
*/
- if (msg_hdr.seq != s->d1->handshake_read_seq)
- return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
+ if (msg_hdr.seq != s->d1->handshake_read_seq) {
+ *len = dtls1_process_out_of_seq_message(s, &msg_hdr, &ok);
+ return ok;
+ }
- if (frag_len && frag_len < len)
- return dtls1_reassemble_fragment(s, &msg_hdr, ok);
+ if (frag_len && frag_len < mlen) {
+ *len = dtls1_reassemble_fragment(s, &msg_hdr, &ok);
+ return ok;
+ }
if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
wire[0] == SSL3_MT_HELLO_REQUEST) {
} else { /* Incorrectly formated Hello request */
al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
}
- if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max)))
+ if ((al = dtls1_preprocess_fragment(s, &msg_hdr)))
goto f_err;
if (frag_len > 0) {
*/
if (i <= 0) {
s->rwstate = SSL_READING;
- *ok = 0;
- return i;
+ *len = i;
+ return 0;
}
} else
i = 0;
*/
if (i != (int)frag_len) {
al = SSL3_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL3_AD_ILLEGAL_PARAMETER);
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL3_AD_ILLEGAL_PARAMETER);
goto f_err;
}
- *ok = 1;
- s->state = stn;
-
/*
* Note that s->init_num is *not* used as current offset in
* s->init_buf->data, but as a counter summing up fragments' lengths: as
* soon as they sum up to handshake packet length, we assume we have got
* all the fragments.
*/
- s->init_num = frag_len;
- return frag_len;
+ *len = s->init_num = frag_len;
+ return 1;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
s->init_num = 0;
-
- *ok = 0;
- return (-1);
+ *len = -1;
+ return 0;
}
/*-