Beispiel #1
0
/* Obtain handshake message of message type 'mt' (any if mt == -1),
 * maximum acceptable body length 'max'.
 * Read an entire handshake message.  Handshake messages arrive in
 * fragments.
 */
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
	{
	int i, al;
	struct hm_header_st *msg_hdr;
	unsigned char *p;
	unsigned long msg_len;

	/* s3->tmp is used to store messages that are unexpected, caused
	 * by the absence of an optional handshake message */
	if (s->s3->tmp.reuse_message)
		{
		s->s3->tmp.reuse_message=0;
		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		*ok=1;
		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
		s->init_num = (int)s->s3->tmp.message_size;
		return s->init_num;
		}

	msg_hdr = &s->d1->r_msg_hdr;
	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));

again:
	i = dtls1_get_message_fragment(s, st1, stn, max, ok);
	if ( i == DTLS1_HM_BAD_FRAGMENT ||
		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
		goto again;
	else if ( i <= 0 && !*ok)
		return i;

	p = (unsigned char *)s->init_buf->data;
	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, 0x00, sizeof(struct hm_header_st));

	/* Don't change sequence numbers while listening */
	if (!s->d1->listen)
		s->d1->handshake_read_seq++;

	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
	return s->init_num;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
	*ok = 0;
	return -1;
	}
Beispiel #2
0
static long
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
	{
	unsigned char wire[DTLS1_HM_HEADER_LENGTH];
	unsigned long len, frag_off, frag_len;
	int i,al;
	struct hm_header_st msg_hdr;

	/* see if we have the required fragment already */
	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
		{
		if (*ok)	s->init_num = frag_len;
		return frag_len;
		}

	/* read handshake message header */
	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
		DTLS1_HM_HEADER_LENGTH, 0);
	if (i <= 0) 	/* nbio, or an error */
		{
		s->rwstate=SSL_READING;
		*ok = 0;
		return i;
		}
	/* 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);
		goto f_err;
		}

	/* parse the message fragment header */
	dtls1_get_message_header(wire, &msg_hdr);

	/* 
	 * if this is a future (or stale) message it gets buffered
	 * (or dropped)--no further processing at this time
	 * 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 && !(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);

	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
		wire[0] == SSL3_MT_HELLO_REQUEST)
		{
		/* The server may always send 'Hello Request' messages --
		 * we are doing a handshake anyway now, so ignore them
		 * if their format is correct. Does not count for
		 * 'Finished' MAC. */
		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
			{
			if (s->msg_callback)
				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
					wire, DTLS1_HM_HEADER_LENGTH, s, 
					s->msg_callback_arg);
			
			s->init_num = 0;
			return dtls1_get_message_fragment(s, st1, stn,
				max, ok);
			}
		else /* Incorrectly formated Hello request */
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		}

	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 */
		if (i <= 0)
			{
			s->rwstate=SSL_READING;
			*ok = 0;
			return i;
			}
		}
	else
		i = 0;

	/* XDTLS:  an incorrectly formatted fragment should cause the 
	 * handshake to fail */
	if (i != (int)frag_len)
		{
		al=SSL3_AD_ILLEGAL_PARAMETER;
		SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL3_AD_ILLEGAL_PARAMETER);
		goto f_err;
		}

	*ok = 1;

	/* 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;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
	s->init_num = 0;

	*ok=0;
	return(-1);
	}
Beispiel #3
0
/* Obtain handshake message of message type 'mt' (any if mt == -1),
 * maximum acceptable body length 'max'.
 * Read an entire handshake message.  Handshake messages arrive in
 * fragments.
 */
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
	{
	int i, al;
	struct hm_header_st *msg_hdr;

	/* s3->tmp is used to store messages that are unexpected, caused
	 * by the absence of an optional handshake message */
	if (s->s3->tmp.reuse_message)
		{
		s->s3->tmp.reuse_message=0;
		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		*ok=1;
		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
		s->init_num = (int)s->s3->tmp.message_size;
		return s->init_num;
		}

	msg_hdr = &s->d1->r_msg_hdr;
	do
		{
		if ( msg_hdr->frag_off == 0)
			{
			/* s->d1->r_message_header.msg_len = 0; */
			memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
			}

		i = dtls1_get_message_fragment(s, st1, stn, max, ok);
		if ( i == DTLS1_HM_BAD_FRAGMENT ||
			i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
			continue;
		else if ( i <= 0 && !*ok)
			return i;

		/* Note that s->init_sum is used 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. Overlapping fragments would cause
		 * premature termination, so we don't expect overlaps.
		 * Well, handling overlaps would require something more
		 * drastic. Indeed, as it is now there is no way to
		 * tell if out-of-order fragment from the middle was
		 * the last. '>=' is the best/least we can do to control
		 * the potential damage caused by malformed overlaps. */
		if ((unsigned int)s->init_num >= msg_hdr->msg_len)
			{
			unsigned char *p = (unsigned char *)s->init_buf->data;
			unsigned long msg_len = msg_hdr->msg_len;

			/* reconstruct message header as if it was
			 * sent in single fragment */
			*(p++) = msg_hdr->type;
			l2n3(msg_len,p);
			s2n (msg_hdr->seq,p);
			l2n3(0,p);
			l2n3(msg_len,p);
			if (s->client_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, 0x00, sizeof(struct hm_header_st));

			s->d1->handshake_read_seq++;
			/* we just read a handshake message from the other side:
			 * this means that we don't need to retransmit of the
			 * buffered messages.  
			 * XDTLS: may be able clear out this
			 * buffer a little sooner (i.e if an out-of-order
			 * handshake message/record is received at the record
			 * layer.  
			 * XDTLS: exception is that the server needs to
			 * know that change cipher spec and finished messages
			 * have been received by the client before clearing this
			 * buffer.  this can simply be done by waiting for the
			 * first data  segment, but is there a better way?  */
			dtls1_clear_record_buffer(s);

			s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
			return s->init_num;
			}
		else
			msg_hdr->frag_off = i;
		} while(1) ;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
	*ok = 0;
	return -1;
	}
/* Obtain handshake message of message type 'mt' (any if mt == -1),
 * maximum acceptable body length 'max'.
 * Read an entire handshake message.  Handshake messages arrive in
 * fragments.
 */
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
	{
	int i, al;
	struct hm_header_st *msg_hdr;
	unsigned char *p;
	unsigned long msg_len;

	/* s3->tmp is used to store messages that are unexpected, caused
	 * by the absence of an optional handshake message */
	if (s->s3->tmp.reuse_message)
		{
		s->s3->tmp.reuse_message=0;
		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		*ok=1;
		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
		s->init_num = (int)s->s3->tmp.message_size;
		return s->init_num;
		}

	msg_hdr = &s->d1->r_msg_hdr;
	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));

again:
	i = dtls1_get_message_fragment(s, st1, stn, max, ok);
	if ( i == DTLS1_HM_BAD_FRAGMENT ||
		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
		goto again;
	else if ( i <= 0 && !*ok)
		return i;

	p = (unsigned char *)s->init_buf->data;
	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, 0x00, sizeof(struct hm_header_st));

	s->d1->handshake_read_seq++;
	/* we just read a handshake message from the other side:
	 * this means that we don't need to retransmit of the
	 * buffered messages.  
	 * XDTLS: may be able clear out this
	 * buffer a little sooner (i.e if an out-of-order
	 * handshake message/record is received at the record
	 * layer.  
	 * XDTLS: exception is that the server needs to
	 * know that change cipher spec and finished messages
	 * have been received by the client before clearing this
	 * buffer.  this can simply be done by waiting for the
	 * first data  segment, but is there a better way?  */
	dtls1_clear_record_buffer(s);

	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
	return s->init_num;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
	*ok = 0;
	return -1;
	}
static long
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
	{
	unsigned char *p;
	unsigned long l, frag_off, frag_len;
	int i,al;
	struct hm_header_st msg_hdr;
    unsigned long overlap;
    
    /* see if we have the required fragment already */
    if (dtls1_retrieve_buffered_fragment(s, &l))
    {
        /* compute MAC, remove fragment headers */
        dtls1_process_handshake_fragment(s, l);
        s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
        s->state = stn;
        return 1;
    }

    /* get a handshake fragment from the record layer */
	p = (unsigned char *)s->init_buf->data;

    /* read handshake message header */
	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],
		DTLS1_HM_HEADER_LENGTH, 0);
	if (i <= 0) 	/* nbio, or an error */
		{
		s->rwstate=SSL_READING;
		*ok = 0;
		return i;
		}

	OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);

	p += s->init_num;
    /* parse the message fragment header */
    
    dtls1_get_message_header(p, &msg_hdr);

    /* 
     * if this is a future (or stale) message it gets buffered
     * (or dropped)--no further processing at this time 
     */
    if ( msg_hdr.seq != s->d1->handshake_read_seq)
        return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);

    l = msg_hdr.msg_len;
    frag_off = msg_hdr.frag_off;
	frag_len = msg_hdr.frag_len;

    /* sanity checking */
    if ( frag_off + frag_len > l)
        {
        al=SSL_AD_ILLEGAL_PARAMETER;
        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
        goto f_err;
        }

	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
        p[0] == SSL3_MT_HELLO_REQUEST)
        {
        /* The server may always send 'Hello Request' messages --
         * we are doing a handshake anyway now, so ignore them
         * if their format is correct. Does not count for
         * 'Finished' MAC. */
        if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
            {
            if (s->msg_callback)
                s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
                    p, DTLS1_HM_HEADER_LENGTH, s, 
                    s->msg_callback_arg);
            
            s->init_num = 0;
            return dtls1_get_message_fragment(s, st1, stn,
                max, ok);
            }
        else /* Incorrectly formated Hello request */
            {
            al=SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
            goto f_err;
            }
        }

    /* XDTLS: do a sanity check on the fragment */

    s->init_num += i;

	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
		{
		/* BUF_MEM_grow takes an 'int' parameter */
		if (l > (INT_MAX-DTLS1_HM_HEADER_LENGTH)) 
			{
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
			goto f_err;
			}
		if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l
			+ DTLS1_HM_HEADER_LENGTH))
			{
			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
			goto err;
			}
        /* Only do this test when we're reading the expected message.
         * Stale messages will be dropped and future messages will be buffered */
        if ( l > (unsigned long)max)
			{
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
			goto f_err;
			}

		s->s3->tmp.message_size=l;
		}

    if ( frag_len > (unsigned long)max)
        {
        al=SSL_AD_ILLEGAL_PARAMETER;
        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
        goto f_err;
        }
    if ( frag_len + s->init_num > (INT_MAX - DTLS1_HM_HEADER_LENGTH))
        {
        al=SSL_AD_ILLEGAL_PARAMETER;
        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
        goto f_err;
        }

    if ( frag_len & !BUF_MEM_grow_clean(s->init_buf, (int)frag_len 
             + DTLS1_HM_HEADER_LENGTH + s->init_num))
        {
        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
        goto err;
        }

	if ( s->d1->r_msg_hdr.frag_off == 0)
		{
		s->s3->tmp.message_type = msg_hdr.type;
		s->d1->r_msg_hdr.type = msg_hdr.type;
		s->d1->r_msg_hdr.msg_len = l;
		/* s->d1->r_msg_hdr.seq = seq_num; */
		}

	/* XDTLS:  ressurect this when restart is in place */
	s->state=stn;
	
	/* next state (stn) */
	p = (unsigned char *)s->init_buf->data;

	if ( frag_len > 0)
		{
		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
            &p[s->init_num], 
            frag_len,0);
        /* XDTLS:  fix this--message fragments cannot span multiple packets */
		if (i <= 0)
			{
			s->rwstate=SSL_READING;
			*ok = 0;
			return i;
			}
		}
	else
		i = 0;

    /* XDTLS:  an incorrectly formatted fragment should cause the 
     * handshake to fail */
	OPENSSL_assert(i == (int)frag_len);

#if 0
    /* Successfully read a fragment.
     * It may be (1) out of order, or
     *           (2) it's a repeat, in which case we dump it
     *           (3) the one we are expecting next (maybe with overlap)
     * If it is next one, it may overlap with previously read bytes
     */

    /* case (1): buffer the future fragment 
     * (we can treat fragments from a future message the same
     * as future fragments from the message being currently read, since
     * they are sematically simply out of order.
     */
    if ( msg_hdr.seq > s->d1->handshake_read_seq ||
        frag_off > s->init_num - DTLS1_HM_HEADER_LENGTH)
    {
        dtls1_buffer_handshake_fragment(s, &msg_hdr);
        return DTLS1_HM_FRAGMENT_RETRY;
    }

    /* case (2):  drop the entire fragment, and try again */
    if ( msg_hdr.seq < s->d1->handshake_read_seq ||
        frag_off + frag_len < s->init_num - DTLS1_HM_HEADER_LENGTH)
        {
        s->init_num -= DTLS1_HM_HEADER_LENGTH;
        return DTLS1_HM_FRAGMENT_RETRY;
        }
#endif

    /* case (3): received a immediately useful fragment.  Determine the 
     * possible overlap and copy the fragment.
     */
    overlap = (s->init_num - DTLS1_HM_HEADER_LENGTH) - frag_off;
        
    /* retain the header for the first fragment */
    if ( s->init_num > DTLS1_HM_HEADER_LENGTH)
        {
        memmove(&(s->init_buf->data[s->init_num]),
            &(s->init_buf->data[s->init_num + DTLS1_HM_HEADER_LENGTH + overlap]),
            frag_len - overlap);

        s->init_num += frag_len - overlap;
        }
    else
        s->init_num += frag_len;

    dtls1_process_handshake_fragment(s, frag_len - overlap);

	if (s->msg_callback)
		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, 
			(size_t)s->init_num, s, 
			s->msg_callback_arg);
	*ok=1;

	return s->init_num;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
    s->init_num = 0;
err:
	*ok=0;
	return(-1);
	}
/* Obtain handshake message of message type 'mt' (any if mt == -1),
 * maximum acceptable body length 'max'.
 * Read an entire handshake message.  Handshake messages arrive in
 * fragments.
 */
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
	{
	int i, al;

	/* s3->tmp is used to store messages that are unexpected, caused
	 * by the absence of an optional handshake message */
	if (s->s3->tmp.reuse_message)
		{
		s->s3->tmp.reuse_message=0;
		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		*ok=1;
		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
		s->init_num = (int)s->s3->tmp.message_size;
		return s->init_num;
		}
	
	do
		{
		if ( s->d1->r_msg_hdr.frag_off == 0)
			{
			/* s->d1->r_message_header.msg_len = 0; */
			memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
			}

		i = dtls1_get_message_fragment(s, st1, stn, max, ok);
		if ( i == DTLS1_HM_BAD_FRAGMENT ||
            i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
			continue;
		else if ( i <= 0 && !*ok)
			return i;

		if (s->d1->r_msg_hdr.msg_len == (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
			{
			memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));

			s->d1->handshake_read_seq++;
			/* we just read a handshake message from the other side:
			 * this means that we don't need to retransmit of the
			 * buffered messages.  
			 * XDTLS: may be able clear out this
			 * buffer a little sooner (i.e if an out-of-order
			 * handshake message/record is received at the record
			 * layer.  
			 * XDTLS: exception is that the server needs to
			 * know that change cipher spec and finished messages
			 * have been received by the client before clearing this
			 * buffer.  this can simply be done by waiting for the
			 * first data  segment, but is there a better way?  */
			dtls1_clear_record_buffer(s);

            s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
			return s->init_num - DTLS1_HM_HEADER_LENGTH;
			}
		else
			s->d1->r_msg_hdr.frag_off = i;
		} while(1) ;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
	*ok = 0;
	return -1;
	}