Commit message: A memory leak can occur in dtls1_buffer_record if either of the calls to
ssl3_setup_buffers or pqueue_insert fail. The former will fail if there is a
malloc failure, whilst the latter will fail if attempting to add a duplicate
record to the queue. This should never happen because duplicate records should
be detected and dropped before any attempt to add them to the queue.
Unfortunately records that arrive that are for the next epoch are not being
recorded correctly, and therefore replays are not being detected.
Additionally, these "should not happen" failures that can occur in
dtls1_buffer_record are not being treated as fatal and therefore an attacker
could exploit this by sending repeated replay records for the next epoch,
eventually causing a DoS through memory exhaustion.

Thanks to Chris Mueller for reporting this issue and providing initial
analysis and a patch. Further analysis and the final patch was performed by
Matt Caswell from the OpenSSL development team.

CVE-2015-0206

Reviewed-by: Dr Stephen Henson <steve@openssl.org>
CVE: CVE-2015-0206
CWE: CWE-119
Vulnerability description: Memory leak in the dtls1_buffer_record function in d1_pkt.c in OpenSSL 1.0.0 before 1.0.0p and 1.0.1 before 1.0.1k allows remote attackers to cause a denial of service (memory consumption) by sending many duplicate records for the next epoch, leading to failure of replay detection.

Project: openssl

dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
	{
	DTLS1_RECORD_DATA *rdata;
	pitem *item;

 	/* Limit the size of the queue to prevent DOS attacks */
 	if (pqueue_size(queue->q) >= 100)
 		return 0;

 	rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
 	item = pitem_new(priority, rdata);
 	if (rdata == NULL || item == NULL)
		{
		if (rdata != NULL) OPENSSL_free(rdata);
		if (item != NULL) pitem_free(item);
		
		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
		return(0);
		}
	
	rdata->packet = s->packet;
	rdata->packet_length = s->packet_length;
	memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
	memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));

	item->data = rdata;

#ifndef OPENSSL_NO_SCTP
	/* Store bio_dgram_sctp_rcvinfo struct */
	if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
	    (s->state == SSL3_ST_SR_FINISHED_A || s->state == SSL3_ST_CR_FINISHED_A)) {
		BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo);
	}
#endif

	s->packet = NULL;
	s->packet_length = 0;
	memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
	memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
	
 	if (!ssl3_setup_buffers(s))
 		{
 		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
		if (rdata->rbuf.buf != NULL)
			OPENSSL_free(rdata->rbuf.buf);
 		OPENSSL_free(rdata);
 		pitem_free(item);
		return(-1);
 		}
 
 	/* insert should not fail, since duplicates are dropped */
 	if (pqueue_insert(queue->q, item) == NULL)
 		{
 		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
		if (rdata->rbuf.buf != NULL)
			OPENSSL_free(rdata->rbuf.buf);
 		OPENSSL_free(rdata);
 		pitem_free(item);
		return(-1);
 		}
 
 	return(1);
	}

Project: openssl

int dtls1_get_record(SSL *s)
	{
	int ssl_major,ssl_minor;
	int i,n;
	SSL3_RECORD *rr;
	unsigned char *p = NULL;
	unsigned short version;
	DTLS1_BITMAP *bitmap;
	unsigned int is_next_epoch;

	rr= &(s->s3->rrec);
 
 	/* The epoch may have changed.  If so, process all the
 	 * pending records.  This is a non-blocking operation. */
	if(dtls1_process_buffered_records(s)<0)
		return -1;
 
 	/* if we're renegotiating, then there may be buffered records */
 	if (dtls1_get_processed_record(s))
		return 1;

	/* get something from the wire */
again:
	/* check if we have the header */
	if (	(s->rstate != SSL_ST_READ_BODY) ||
		(s->packet_length < DTLS1_RT_HEADER_LENGTH)) 
		{
		n=ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
		/* read timeout is handled by dtls1_read_bytes */
		if (n <= 0) return(n); /* error or non-blocking */

		/* this packet contained a partial record, dump it */
		if (s->packet_length != DTLS1_RT_HEADER_LENGTH)
			{
			s->packet_length = 0;
			goto again;
			}

		s->rstate=SSL_ST_READ_BODY;

		p=s->packet;

		if (s->msg_callback)
			s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);

		/* Pull apart the header into the DTLS1_RECORD */
		rr->type= *(p++);
		ssl_major= *(p++);
		ssl_minor= *(p++);
		version=(ssl_major<<8)|ssl_minor;

		/* sequence number is 64 bits, with top 2 bytes = epoch */ 
		n2s(p,rr->epoch);

		memcpy(&(s->s3->read_sequence[2]), p, 6);
		p+=6;

		n2s(p,rr->length);

		/* Lets check version */
		if (!s->first_packet)
			{
			if (version != s->version)
				{
				/* unexpected version, silently discard */
				rr->length = 0;
				s->packet_length = 0;
				goto again;
				}
			}

		if ((version & 0xff00) != (s->version & 0xff00))
			{
			/* wrong version, silently discard record */
			rr->length = 0;
			s->packet_length = 0;
			goto again;
			}

		if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
			{
			/* record too long, silently discard it */
			rr->length = 0;
			s->packet_length = 0;
			goto again;
			}

		/* now s->rstate == SSL_ST_READ_BODY */
		}

	/* s->rstate == SSL_ST_READ_BODY, get and decode the data */

	if (rr->length > s->packet_length-DTLS1_RT_HEADER_LENGTH)
		{
		/* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
		i=rr->length;
		n=ssl3_read_n(s,i,i,1);
		/* this packet contained a partial record, dump it */
		if ( n != i)
			{
			rr->length = 0;
			s->packet_length = 0;
			goto again;
			}

		/* now n == rr->length,
		 * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length */
		}
	s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */

	/* match epochs.  NULL means the packet is dropped on the floor */
	bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
	if ( bitmap == NULL)
		{
		rr->length = 0;
		s->packet_length = 0;  /* dump this record */
		goto again;   /* get another record */
		}

#ifndef OPENSSL_NO_SCTP
	/* Only do replay check if no SCTP bio */
	if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
  		{
#endif
		/* Check whether this is a repeat, or aged record.
		 * Don't check if we're listening and this message is
		 * a ClientHello. They can look as if they're replayed,
		 * since they arrive from different connections and
		 * would be dropped unnecessarily.
		 */
		if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
		    s->packet_length > DTLS1_RT_HEADER_LENGTH &&
		    s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
		    !dtls1_record_replay_check(s, bitmap))
			{
			rr->length = 0;
			s->packet_length=0; /* dump this record */
			goto again;     /* get another record */
			}
#ifndef OPENSSL_NO_SCTP
  		}
#endif

	/* just read a 0 length packet */
	if (rr->length == 0) goto again;

	/* If this record is from the next epoch (either HM or ALERT),
	 * and a handshake is currently in progress, buffer it since it
	 * cannot be processed at this time. However, do not buffer
	 * anything while listening.
	 */
	if (is_next_epoch)
 		{
 		if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen)
 			{
			if(dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num)<0)
				return -1;
			dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
 			}
 		rr->length = 0;
 		s->packet_length = 0;
		goto again;
		}

	if (!dtls1_process_record(s))
		{
		rr->length = 0;
 		s->packet_length = 0;  /* dump this record */
 		goto again;   /* get another record */
 		}
	dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
 
 	return(1);
 
	}

Project: openssl

dtls1_process_buffered_records(SSL *s)
    {
    pitem *item;
    
    item = pqueue_peek(s->d1->unprocessed_rcds.q);
    if (item)
        {
        /* Check if epoch is current. */
        if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
            return(1);  /* Nothing to do. */
        
        /* Process all the records. */
        while (pqueue_peek(s->d1->unprocessed_rcds.q))
            {
             dtls1_get_unprocessed_record(s);
             if ( ! dtls1_process_record(s))
                 return(0);
            if(dtls1_buffer_record(s, &(s->d1->processed_rcds),
                s->s3->rrec.seq_num)<0)
                return -1;
             }
         }
 
    /* sync epoch numbers once all the unprocessed records 
     * have been processed */
    s->d1->processed_rcds.epoch = s->d1->r_epoch;
    s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;

    return(1);
    }

Project: openssl

int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
	{
	int al,i,j,ret;
	unsigned int n;
	SSL3_RECORD *rr;
	void (*cb)(const SSL *ssl,int type2,int val)=NULL;

	if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
		if (!ssl3_setup_buffers(s))
			return(-1);

	if ((type && (type != SSL3_RT_APPLICATION_DATA) && 
		(type != SSL3_RT_HANDSHAKE)) ||
	    (peek && (type != SSL3_RT_APPLICATION_DATA)))
		{
		SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
		return -1;
		}

	/* check whether there's a handshake message (client hello?) waiting */
	if ( (ret = have_handshake_fragment(s, type, buf, len, peek)))
		return ret;

	/* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */

#ifndef OPENSSL_NO_SCTP
	/* Continue handshake if it had to be interrupted to read
	 * app data with SCTP.
	 */
	if ((!s->in_handshake && SSL_in_init(s)) ||
	    (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
	     (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK) &&
	     s->s3->in_read_app_data != 2))
#else
	if (!s->in_handshake && SSL_in_init(s))
#endif
		{
		/* type == SSL3_RT_APPLICATION_DATA */
		i=s->handshake_func(s);
		if (i < 0) return(i);
		if (i == 0)
			{
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
			return(-1);
			}
		}

start:
	s->rwstate=SSL_NOTHING;

	/*-
	 * s->s3->rrec.type	    - is the type of record
	 * s->s3->rrec.data,    - data
	 * s->s3->rrec.off,     - offset into 'data' for next read
	 * 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)
			{
#ifndef OPENSSL_NO_SCTP
			/* Restore bio_dgram_sctp_rcvinfo struct */
			if (BIO_dgram_is_sctp(SSL_get_rbio(s)))
				{
				DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *) item->data;
				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo);
				}
#endif

			dtls1_copy_record(s, item);

			OPENSSL_free(item->data);
			pitem_free(item);
			}
		}

	/* Check for timeout */
	if (dtls1_handle_timeout(s) > 0)
		goto start;

	/* get new packet if necessary */
	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
		{
		ret=dtls1_get_record(s);
		if (ret <= 0) 
			{
			ret = dtls1_read_failed(s, ret);
			/* anything other than a timeout is an error */
			if (ret <= 0)  
				return(ret);
			else
				goto start;
			}
		}

	if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE)
		{
		rr->length = 0;
		goto start;
		}

	/* we now have a packet which can be read and processed */

	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
	                               * reset by ssl3_get_finished */
		&& (rr->type != SSL3_RT_HANDSHAKE))
		{
		/* 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.
 		 */
		if(dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num)<0)
			{
			SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
			return -1;
			}
 		rr->length = 0;
 		goto start;
 		}

	/* If the other end has shut down, throw anything we read away
	 * (even in 'peek' mode) */
	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
		{
		rr->length=0;
		s->rwstate=SSL_NOTHING;
		return(0);
		}


	if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
		{
		/* make sure that we are not getting application data when we
		 * are doing a handshake for the first time */
		if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
			(s->enc_read_ctx == NULL))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
			goto f_err;
			}

		if (len <= 0) return(len);

		if ((unsigned int)len > rr->length)
			n = rr->length;
		else
			n = (unsigned int)len;

		memcpy(buf,&(rr->data[rr->off]),n);
		if (!peek)
			{
			rr->length-=n;
			rr->off+=n;
			if (rr->length == 0)
				{
				s->rstate=SSL_ST_READ_HEADER;
				rr->off=0;
				}
			}

#ifndef OPENSSL_NO_SCTP
			/* We were about to renegotiate but had to read
			 * belated application data first, so retry.
			 */
			if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
			    rr->type == SSL3_RT_APPLICATION_DATA &&
			    (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK))
				{
				s->rwstate=SSL_READING;
				BIO_clear_retry_flags(SSL_get_rbio(s));
				BIO_set_retry_read(SSL_get_rbio(s));
				}

			/* We might had to delay a close_notify alert because
			 * of reordered app data. If there was an alert and there
			 * is no message to read anymore, finally set shutdown.
			 */
			if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
			    s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
				{
				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
				return(0);
				}
#endif			
		return(n);
		}


	/* If we get here, then type != rr->type; if we have a handshake
	 * message, then it was unexpected (Hello Request or Client Hello). */

	/* In case of record types for which we have 'fragment' storage,
	 * fill that so that we can process the data at a fixed place.
	 */
		{
		unsigned int k, dest_maxlen = 0;
		unsigned char *dest = NULL;
		unsigned int *dest_len = NULL;

		if (rr->type == SSL3_RT_HANDSHAKE)
			{
			dest_maxlen = sizeof s->d1->handshake_fragment;
			dest = s->d1->handshake_fragment;
			dest_len = &s->d1->handshake_fragment_len;
			}
		else if (rr->type == SSL3_RT_ALERT)
			{
			dest_maxlen = sizeof(s->d1->alert_fragment);
			dest = s->d1->alert_fragment;
			dest_len = &s->d1->alert_fragment_len;
			}
#ifndef OPENSSL_NO_HEARTBEATS
		else if (rr->type == TLS1_RT_HEARTBEAT)
			{
			dtls1_process_heartbeat(s);

			/* Exit and notify application to read again */
			rr->length = 0;
			s->rwstate=SSL_READING;
			BIO_clear_retry_flags(SSL_get_rbio(s));
			BIO_set_retry_read(SSL_get_rbio(s));
			return(-1);
			}
#endif
		/* 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)
			{
            /* XDTLS:  In a pathalogical case, the Client Hello
             *  may be fragmented--don't always expect dest_maxlen bytes */
			if ( rr->length < dest_maxlen)
				{
#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
				/*
				 * for normal alerts rr->length is 2, while
				 * dest_maxlen is 7 if we were to handle this
				 * non-existing alert...
				 */
				FIX ME
#endif
				s->rstate=SSL_ST_READ_HEADER;
				rr->length = 0;
				goto start;
				}

			/* now move 'n' bytes: */
			for ( k = 0; k < dest_maxlen; k++)
				{
				dest[k] = rr->data[rr->off++];
				rr->length--;
				}
			*dest_len = dest_maxlen;
			}
		}

	/* s->d1->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
	 * s->d1->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
	 * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */

	/* If we are a client, check for an incoming 'Hello Request': */
	if ((!s->server) &&
		(s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
		(s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
		(s->session != NULL) && (s->session->cipher != NULL))
		{
		s->d1->handshake_fragment_len = 0;

		if ((s->d1->handshake_fragment[1] != 0) ||
			(s->d1->handshake_fragment[2] != 0) ||
			(s->d1->handshake_fragment[3] != 0))
			{
			al=SSL_AD_DECODE_ERROR;
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
			goto err;
			}

		/* no need to check sequence number on HELLO REQUEST messages */

		if (s->msg_callback)
			s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
				s->d1->handshake_fragment, 4, s, s->msg_callback_arg);

		if (SSL_is_init_finished(s) &&
			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
			!s->s3->renegotiate)
			{
			s->d1->handshake_read_seq++;
			s->new_session = 1;
			ssl3_renegotiate(s);
			if (ssl3_renegotiate_check(s))
				{
				i=s->handshake_func(s);
				if (i < 0) return(i);
				if (i == 0)
					{
					SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
					return(-1);
					}

				if (!(s->mode & SSL_MODE_AUTO_RETRY))
					{
					if (s->s3->rbuf.left == 0) /* no read-ahead left? */
						{
						BIO *bio;
						/* In the case where we try to read application data,
						 * but we trigger an SSL handshake, we return -1 with
						 * the retry option set.  Otherwise renegotiation may
						 * cause nasty problems in the blocking world */
						s->rwstate=SSL_READING;
						bio=SSL_get_rbio(s);
						BIO_clear_retry_flags(bio);
						BIO_set_retry_read(bio);
						return(-1);
						}
					}
				}
			}
		/* we either finished a handshake or ignored the request,
		 * now try again to obtain the (application) data we were asked for */
		goto start;
		}

	if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH)
		{
		int alert_level = s->d1->alert_fragment[0];
		int alert_descr = s->d1->alert_fragment[1];

		s->d1->alert_fragment_len = 0;

		if (s->msg_callback)
			s->msg_callback(0, s->version, SSL3_RT_ALERT, 
				s->d1->alert_fragment, 2, s, s->msg_callback_arg);

		if (s->info_callback != NULL)
			cb=s->info_callback;
		else if (s->ctx->info_callback != NULL)
			cb=s->ctx->info_callback;

		if (cb != NULL)
			{
			j = (alert_level << 8) | alert_descr;
			cb(s, SSL_CB_READ_ALERT, j);
			}

		if (alert_level == 1) /* warning */
			{
			s->s3->warn_alert = alert_descr;
			if (alert_descr == SSL_AD_CLOSE_NOTIFY)
				{
#ifndef OPENSSL_NO_SCTP
				/* With SCTP and streams the socket may deliver app data
				 * after a close_notify alert. We have to check this
				 * first so that nothing gets discarded.
				 */
				if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
					BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
					{
					s->d1->shutdown_received = 1;
					s->rwstate=SSL_READING;
					BIO_clear_retry_flags(SSL_get_rbio(s));
					BIO_set_retry_read(SSL_get_rbio(s));
					return -1;
					}
#endif
				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
				return(0);
				}
#if 0
            /* XXX: this is a possible improvement in the future */
			/* now check if it's a missing record */
			if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
				{
				unsigned short seq;
				unsigned int frag_off;
				unsigned char *p = &(s->d1->alert_fragment[2]);

				n2s(p, seq);
				n2l3(p, frag_off);

				dtls1_retransmit_message(s,
										 dtls1_get_queue_priority(frag->msg_header.seq, 0),
										 frag_off, &found);
				if ( ! found  && SSL_in_init(s))
					{
					/* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
					/* requested a message not yet sent, 
					   send an alert ourselves */
					ssl3_send_alert(s,SSL3_AL_WARNING,
						DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
					}
				}
#endif
			}
		else if (alert_level == 2) /* fatal */
			{
			char tmp[16];

			s->rwstate=SSL_NOTHING;
			s->s3->fatal_alert = alert_descr;
			SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
			BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
			ERR_add_error_data(2,"SSL alert number ",tmp);
			s->shutdown|=SSL_RECEIVED_SHUTDOWN;
			SSL_CTX_remove_session(s->ctx,s->session);
			return(0);
			}
		else
			{
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
			goto f_err;
			}

		goto start;
		}

	if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
		{
		s->rwstate=SSL_NOTHING;
		rr->length=0;
		return(0);
		}

	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
		{
		struct ccs_header_st ccs_hdr;
		unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;

		dtls1_get_ccs_header(rr->data, &ccs_hdr);

		if (s->version == DTLS1_BAD_VER)
			ccs_hdr_len = 3;

		/* 'Change Cipher Spec' is just a single byte, so we know
		 * exactly what the record payload has to look like */
		/* XDTLS: check that epoch is consistent */
		if (	(rr->length != ccs_hdr_len) || 
			(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
			{
			i=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
			goto err;
			}

		rr->length=0;

		if (s->msg_callback)
			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;

		/* do this whenever CCS is processed */
		dtls1_reset_seq_numbers(s, SSL3_CC_READ);

		if (s->version == DTLS1_BAD_VER)
			s->d1->handshake_read_seq++;

#ifndef OPENSSL_NO_SCTP
		/* Remember that a CCS has been received,
		 * so that an old key of SCTP-Auth can be
		 * deleted when a CCS is sent. Will be ignored
		 * if no SCTP is used
		 */
		BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
#endif

		goto start;
		}

	/* Unexpected handshake message (Client Hello, or protocol violation) */
	if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && 
		!s->in_handshake)
		{
		struct hm_header_st msg_hdr;
		
		/* this may just be a stale retransmit */
		dtls1_get_message_header(rr->data, &msg_hdr);
		if( rr->epoch != s->d1->r_epoch)
			{
			rr->length = 0;
			goto start;
			}

		/* If we are server, we may have a repeated FINISHED of the
		 * client here, then retransmit our CCS and FINISHED.
		 */
		if (msg_hdr.type == SSL3_MT_FINISHED)
			{
			if (dtls1_check_timeout_num(s) < 0)
				return -1;

			dtls1_retransmit_buffered_messages(s);
			rr->length = 0;
			goto start;
			}

		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
			{
#if 0 /* worked only because C operator preferences are not as expected (and
       * because this is not really needed for clients except for detecting
       * protocol violations): */
			s->state=SSL_ST_BEFORE|(s->server)
				?SSL_ST_ACCEPT
				:SSL_ST_CONNECT;
#else
			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
#endif
			s->renegotiate=1;
			s->new_session=1;
			}
		i=s->handshake_func(s);
		if (i < 0) return(i);
		if (i == 0)
			{
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
			return(-1);
			}

		if (!(s->mode & SSL_MODE_AUTO_RETRY))
			{
			if (s->s3->rbuf.left == 0) /* no read-ahead left? */
				{
				BIO *bio;
				/* In the case where we try to read application data,
				 * but we trigger an SSL handshake, we return -1 with
				 * the retry option set.  Otherwise renegotiation may
				 * cause nasty problems in the blocking world */
				s->rwstate=SSL_READING;
				bio=SSL_get_rbio(s);
				BIO_clear_retry_flags(bio);
				BIO_set_retry_read(bio);
				return(-1);
				}
			}
		goto start;
		}

	switch (rr->type)
		{
	default:
#ifndef OPENSSL_NO_TLS
		/* TLS just ignores unknown message types */
		if (s->version == TLS1_VERSION)
			{
			rr->length = 0;
			goto start;
			}
#endif
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
		goto f_err;
	case SSL3_RT_CHANGE_CIPHER_SPEC:
	case SSL3_RT_ALERT:
	case SSL3_RT_HANDSHAKE:
		/* we already handled all of these, with the possible exception
		 * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
		 * should not happen when type != rr->type */
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_DTLS1_READ_BYTES,ERR_R_INTERNAL_ERROR);
		goto f_err;
	case SSL3_RT_APPLICATION_DATA:
		/* At this point, we were expecting handshake data,
		 * but have application data.  If the library was
		 * running inside ssl3_read() (i.e. in_read_app_data
		 * is set) and it makes sense to read application data
		 * at this point (session renegotiation not yet started),
		 * we will indulge it.
		 */
		if (s->s3->in_read_app_data &&
			(s->s3->total_renegotiations != 0) &&
			((
				(s->state & SSL_ST_CONNECT) &&
				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
				(s->state <= SSL3_ST_CR_SRVR_HELLO_A)
				) || (
					(s->state & SSL_ST_ACCEPT) &&
					(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
					(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
					)
				))
			{
			s->s3->in_read_app_data=2;
			return(-1);
			}
		else
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
			goto f_err;
			}
		}
	/* not reached */

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
	return(-1);
	}