Exemple #1
0
static void dtls1_clear_queues (SSL * s)
{
    pitem *item = NULL;

    hm_fragment *frag = NULL;

    DTLS1_RECORD_DATA *rdata;

    while ((item = pqueue_pop (s->d1->unprocessed_rcds.q)) != NULL)
    {
        rdata = (DTLS1_RECORD_DATA *) item->data;
        if (rdata->rbuf.buf)
        {
            OPENSSL_free (rdata->rbuf.buf);
        }
        OPENSSL_free (item->data);
        pitem_free (item);
    }

    while ((item = pqueue_pop (s->d1->processed_rcds.q)) != NULL)
    {
        rdata = (DTLS1_RECORD_DATA *) item->data;
        if (rdata->rbuf.buf)
        {
            OPENSSL_free (rdata->rbuf.buf);
        }
        OPENSSL_free (item->data);
        pitem_free (item);
    }

    while ((item = pqueue_pop (s->d1->buffered_messages)) != NULL)
    {
        frag = (hm_fragment *) item->data;
        dtls1_hm_fragment_free (frag);
        pitem_free (item);
    }

    while ((item = pqueue_pop (s->d1->sent_messages)) != NULL)
    {
        frag = (hm_fragment *) item->data;
        dtls1_hm_fragment_free (frag);
        pitem_free (item);
    }

    while ((item = pqueue_pop (s->d1->buffered_app_data.q)) != NULL)
    {
        rdata = (DTLS1_RECORD_DATA *) item->data;
        if (rdata->rbuf.buf)
        {
            OPENSSL_free (rdata->rbuf.buf);
        }
        OPENSSL_free (item->data);
        pitem_free (item);
    }
}
Exemple #2
0
static void dtls1_clear_queues(SSL *s) {
  pitem *item = NULL;
  hm_fragment *frag = NULL;

  while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
    frag = (hm_fragment *)item->data;
    dtls1_hm_fragment_free(frag);
    pitem_free(item);
  }

  while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
    frag = (hm_fragment *)item->data;
    dtls1_hm_fragment_free(frag);
    pitem_free(item);
  }
}
static int
dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr)
{
    hm_fragment *frag = NULL;
    pitem *item = NULL;
	PQ_64BIT seq64;

    frag = dtls1_hm_fragment_new(msg_hdr->frag_len);
    if ( frag == NULL)
        goto err;

    memcpy(frag->fragment, &(s->init_buf->data[s->init_num]),
        msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH);

    memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

    pq_64bit_init(&seq64);
    pq_64bit_assign_word(&seq64, msg_hdr->seq);

    item = pitem_new(seq64, frag);
    if ( item == NULL)
        goto err;

    pq_64bit_free(&seq64);

    pqueue_insert(s->d1->buffered_messages, item);
    return 1;

err:
    if ( frag != NULL) dtls1_hm_fragment_free(frag);
    if ( item != NULL) OPENSSL_free(item);
    return 0;
}
Exemple #4
0
static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
{
	int i=-1;
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	if (msg_hdr->seq <= s->d1->handshake_read_seq)
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		}

	frag = dtls1_hm_fragment_new(frag_len);
	if ( frag == NULL)
		goto err;

	memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

	if (frag_len)
		{
		/* read the body of the fragment (header has already been read */
		i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
			frag->fragment,frag_len,0);
		if (i<=0 || (unsigned long)i!=frag_len)
			goto err;
		}

	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);

	item = pitem_new(seq64, frag);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		goto err;

	pqueue_insert(s->d1->buffered_messages, item);
	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if ( frag != NULL) dtls1_hm_fragment_free(frag);
	if ( item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}
Exemple #5
0
int
dtls1_buffer_message(SSL *s, int is_ccs)
	{
	pitem *item;
	hm_fragment *frag;
	PQ_64BIT seq64;
	unsigned int epoch = s->d1->w_epoch;

	/* this function is called immediately after a message has 
	 * been serialized */
	OPENSSL_assert(s->init_off == 0);

	frag = dtls1_hm_fragment_new(s->init_num);

	memcpy(frag->fragment, s->init_buf->data, s->init_num);

	if ( is_ccs)
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
		epoch++;
		}
	else
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
		}

	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
	frag->msg_header.type = s->d1->w_msg_hdr.type;
	frag->msg_header.frag_off = 0;
	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.is_ccs = is_ccs;

	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, epoch<<16 | frag->msg_header.seq);

	item = pitem_new(seq64, frag);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		{
		dtls1_hm_fragment_free(frag);
		return 0;
		}

#if 0
	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
#endif

	pqueue_insert(s->d1->sent_messages, item);
	return 1;
	}
Exemple #6
0
static int
dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
	{
	/* (0) check whether the desired fragment is available
	 * if so:
	 * (1) copy over the fragment to s->init_buf->data[]
	 * (2) update s->init_num
	 */
	pitem *item;
	hm_fragment *frag;
	int al;

	*ok = 0;
	item = pqueue_peek(s->d1->buffered_messages);
	if ( item == NULL)
		return 0;

	frag = (hm_fragment *)item->data;
	
	/* Don't return if reassembly still in progress */
	if (frag->reassembly != NULL)
		return 0;

	if ( s->d1->handshake_read_seq == frag->msg_header.seq)
		{
		unsigned long frag_len = frag->msg_header.frag_len;
		pqueue_pop(s->d1->buffered_messages);

		al=dtls1_preprocess_fragment(s,&frag->msg_header,max);

		if (al==0) /* no alert */
			{
			unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
			memcpy(&p[frag->msg_header.frag_off],
				frag->fragment,frag->msg_header.frag_len);
			}

		dtls1_hm_fragment_free(frag);
		pitem_free(item);

		if (al==0)
			{
			*ok = 1;
			return frag_len;
			}

		ssl3_send_alert(s,SSL3_AL_FATAL,al);
		s->init_num = 0;
		*ok = 0;
		return -1;
		}
	else
		return 0;
	}
Exemple #7
0
/* call this function when the buffered messages are no longer needed */
void
dtls1_clear_record_buffer(SSL *s)
	{
	pitem *item;

	for(item = pqueue_pop(s->d1->sent_messages);
		item != NULL; item = pqueue_pop(s->d1->sent_messages))
		{
		dtls1_hm_fragment_free((hm_fragment *)item->data);
		pitem_free(item);
		}
	}
Exemple #8
0
static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
{
	int i=-1;
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	/* Try to find item in queue, to prevent duplicate entries */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);
	item = pqueue_find(s->d1->buffered_messages, seq64);
	pq_64bit_free(&seq64);

	/* If we already have an entry and this one is a fragment,
	 * don't discard it and rather try to reassemble it.
	 */
	if (item != NULL && frag_len < msg_hdr->msg_len)
		item = NULL;

	/* Discard the message if sequence number was already there, is
	 * 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 ||
		(s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		}
	else
		{
		if (frag_len && frag_len < msg_hdr->msg_len)
			return dtls1_reassemble_fragment(s, msg_hdr, ok);

		frag = dtls1_hm_fragment_new(frag_len, 0);
		if ( frag == NULL)
			goto err;

		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

		if (frag_len)
			{
			/* read the body of the fragment (header has already been read) */
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				frag->fragment,frag_len,0);
			if (i<=0 || (unsigned long)i!=frag_len)
				goto err;
			}

		pq_64bit_init(&seq64);
		pq_64bit_assign_word(&seq64, msg_hdr->seq);

		item = pitem_new(seq64, frag);
		pq_64bit_free(&seq64);
		if ( item == NULL)
			goto err;

		pqueue_insert(s->d1->buffered_messages, item);
		}

	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if ( frag != NULL) dtls1_hm_fragment_free(frag);
	if ( item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}
Exemple #9
0
static int
dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
	{
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	int i = -1, is_complete;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len, max_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	/* Determine maximum allowed message size. Depends on (user set)
	 * maximum certificate length, but 16k is minimum.
	 */
	if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
		max_len = s->max_cert_list;
	else
		max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;

	if ((msg_hdr->frag_off+frag_len) > max_len)
		goto err;

	/* Try to find item in queue */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);
	item = pqueue_find(s->d1->buffered_messages, seq64);
	pq_64bit_free(&seq64);

	if (item == NULL)
		{
		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
		if ( frag == NULL)
			goto err;
		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
		frag->msg_header.frag_len = frag->msg_header.msg_len;
		frag->msg_header.frag_off = 0;
		}
	else
		{
		frag = (hm_fragment*) item->data;
		if (frag->msg_header.msg_len != msg_hdr->msg_len)
			{
			item = NULL;
			frag = NULL;
			goto err;
			}
		}


	/* If message is already reassembled, this must be a
	 * retransmit and can be dropped.
	 */
	if (frag->reassembly == NULL)
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		return DTLS1_HM_FRAGMENT_RETRY;
		}

	/* read the body of the fragment (header has already been read */
	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
		frag->fragment + msg_hdr->frag_off,frag_len,0);
	if (i<=0 || (unsigned long)i!=frag_len)
		goto err;

	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
	                    (long)(msg_hdr->frag_off + frag_len));

	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
	                           is_complete);

	if (is_complete)
		{
		OPENSSL_free(frag->reassembly);
		frag->reassembly = NULL;
		}

	if (item == NULL)
		{
		pq_64bit_init(&seq64);
		pq_64bit_assign_word(&seq64, msg_hdr->seq);
		item = pitem_new(seq64, frag);
		pq_64bit_free(&seq64);

		if (item == NULL)
			{
			i = -1;
			goto err;
			}

		pqueue_insert(s->d1->buffered_messages, item);
		}

	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if (frag != NULL) dtls1_hm_fragment_free(frag);
	if (item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}
Exemple #10
0
int
dtls1_buffer_message(SSL *s, int is_ccs)
	{
	pitem *item;
	hm_fragment *frag;
	PQ_64BIT seq64;

	/* this function is called immediately after a message has 
	 * been serialized */
	OPENSSL_assert(s->init_off == 0);

	frag = dtls1_hm_fragment_new(s->init_num, 0);

	memcpy(frag->fragment, s->init_buf->data, s->init_num);

	if ( is_ccs)
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
		}
	else
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
		}

	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
	frag->msg_header.type = s->d1->w_msg_hdr.type;
	frag->msg_header.frag_off = 0;
	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.is_ccs = is_ccs;

	/* save current state*/
	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
	frag->msg_header.saved_retransmit_state.compress = s->compress;
	frag->msg_header.saved_retransmit_state.session = s->session;
	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;

	pq_64bit_init(&seq64);

	pq_64bit_assign_word(&seq64,
						 dtls1_get_queue_priority(frag->msg_header.seq,
												  frag->msg_header.is_ccs));
		
	item = pitem_new(seq64, frag);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		{
		dtls1_hm_fragment_free(frag);
		return 0;
		}

#if 0
	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
#endif

	pqueue_insert(s->d1->sent_messages, item);
	return 1;
	}
Exemple #11
0
static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
{
	int i=-1;
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	/* Try to find item in queue, to prevent duplicate entries */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);
	item = pqueue_find(s->d1->buffered_messages, seq64);
	pq_64bit_free(&seq64);
	
	/* Discard the message if sequence number was already there, is
	 * too far in the future or the fragment is already in the queue */
	if (msg_hdr->seq <= s->d1->handshake_read_seq ||
		msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL)
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		}

	if (frag_len)
	{
		frag = dtls1_hm_fragment_new(frag_len);
		if ( frag == NULL)
			goto err;

		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

		/* read the body of the fragment (header has already been read) */
		i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
			frag->fragment,frag_len,0);
		if (i<=0 || (unsigned long)i!=frag_len)
			goto err;

		pq_64bit_init(&seq64);
		pq_64bit_assign_word(&seq64, msg_hdr->seq);

		item = pitem_new(seq64, frag);
		pq_64bit_free(&seq64);
		if ( item == NULL)
			goto err;

		pqueue_insert(s->d1->buffered_messages, item);
	}

	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if ( frag != NULL) dtls1_hm_fragment_free(frag);
	if ( item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}