Пример #1
0
int itr(long int n)
{
	char s[MAX]; int counter = 0 ;
	while(n!=4)(memset(s,'\0',MAX),n2s(n,s),printf("number:%ld, String format : %s , new Number = %ld\n",n,s,strlen(s)),n = strlen(s),counter++);
	return counter;
}
Пример #2
0
void numToChar(long int n , char s[])
{
if(n == 0) sc(s,db[0]); else while(n != 0)(n >= 0 && n <= 19)?(sc(s,db[n]),(n >9) ? (n = n/100) :(n = n /10)):(n >=20 && n <= 99)?(n%10 == 0 )?(sc(s,tens[n/10-2]),n = n /100):(sc(s,tens[n/10-2]),sc(s,db[n%10]),n = n /100 ):((n >= 100 && n <=999)?(n%100 == 0 )?(sc(s,db[n/100]),sc(s,"hundred"),n = n/1000 ):(sc(s,db[n/100]),sc(s,"hundred"),n = n %100 ):((n >= 1000 && n <=99999)?(n % 1000 == 0)?(n2s(n/1000,s),sc(s,"thousand"),n = n/100000):(n2s(n/1000,s),sc(s,"thousand"),n = n%1000):((n >= 100000 && n <= 9999999)?(n%100000 == 0)?(n2s(n/100000,s),sc(s,"lakh"),n = n/10000000):(n2s(n/100000,s),sc(s,"lakh"),n = n%100000):((n >=10000000)?(n % 10000000 == 0)?(n2s(n/10000000,s),sc(s,"crore"),n = n/1000000000):(n2s(n/10000000,s),sc(s,"crore"),n = n%10000000):1))));
}
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
{
    unsigned short type;
    unsigned short size;
    unsigned short len;
    unsigned char *data = *p;
    s->servername_done = 0;
    s->tlsext_status_type = -1;

    if (data >= (d+n-2))
        return 1;
    n2s(data,len);

    if (data > (d+n-len))
        return 1;

    while (data <= (d+n-4))
    {
        n2s(data,type);
        n2s(data,size);

        if (data+size > (d+n))
            return 1;

        if (s->tlsext_debug_cb)
            s->tlsext_debug_cb(s, 0, type, data, size,
                               s->tlsext_debug_arg);
        /* The servername extension is treated as follows:

           - Only the hostname type is supported with a maximum length of 255.
           - The servername is rejected if too long or if it contains zeros,
             in which case an fatal alert is generated.
           - The servername field is maintained together with the session cache.
           - When a session is resumed, the servername call back invoked in order
             to allow the application to position itself to the right context.
           - The servername is acknowledged if it is new for a session or when
             it is identical to a previously used for the same session.
             Applications can control the behaviour.  They can at any time
             set a 'desirable' servername for a new SSL object. This can be the
             case for example with HTTPS when a Host: header field is received and
             a renegotiation is requested. In this case, a possible servername
             presented in the new client hello is only acknowledged if it matches
             the value of the Host: field.
           - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
             if they provide for changing an explicit servername context for the session,
             i.e. when the session has been established with a servername extension.
           - On session reconnect, the servername extension may be absent.

        */

        if (type == TLSEXT_TYPE_server_name)
        {
            unsigned char *sdata;
            int servname_type;
            int dsize;

            if (size < 2)
            {
                *al = SSL_AD_DECODE_ERROR;
                return 0;
            }
            n2s(data,dsize);
            size -= 2;
            if (dsize > size  )
            {
                *al = SSL_AD_DECODE_ERROR;
                return 0;
            }

            sdata = data;
            while (dsize > 3)
            {
                servname_type = *(sdata++);
                n2s(sdata,len);
                dsize -= 3;

                if (len > dsize)
                {
                    *al = SSL_AD_DECODE_ERROR;
                    return 0;
                }
                if (s->servername_done == 0)
                    switch (servname_type)
                    {
                    case TLSEXT_NAMETYPE_host_name:
                        if (s->session->tlsext_hostname == NULL)
                        {
                            if (len > TLSEXT_MAXLEN_host_name ||
                                    ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
                            {
                                *al = TLS1_AD_UNRECOGNIZED_NAME;
                                return 0;
                            }
                            memcpy(s->session->tlsext_hostname, sdata, len);
                            s->session->tlsext_hostname[len]='\0';
                            if (strlen(s->session->tlsext_hostname) != len) {
                                OPENSSL_free(s->session->tlsext_hostname);
                                s->session->tlsext_hostname = NULL;
                                *al = TLS1_AD_UNRECOGNIZED_NAME;
                                return 0;
                            }
                            s->servername_done = 1;

                        }
                        else
                            s->servername_done = strlen(s->session->tlsext_hostname) == len
                                                 && strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;

                        break;

                    default:
                        break;
                    }

                dsize -= len;
            }
            if (dsize != 0)
            {
                *al = SSL_AD_DECODE_ERROR;
                return 0;
            }

        }
        else if (type == TLSEXT_TYPE_status_request
                 && s->ctx->tlsext_status_cb)
        {

            if (size < 5)
            {
                *al = SSL_AD_DECODE_ERROR;
                return 0;
            }

            s->tlsext_status_type = *data++;
            size--;
            if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
            {
                const unsigned char *sdata;
                int dsize;
                /* Read in responder_id_list */
                n2s(data,dsize);
                size -= 2;
                if (dsize > size  )
                {
                    *al = SSL_AD_DECODE_ERROR;
                    return 0;
                }
                while (dsize > 0)
                {
                    OCSP_RESPID *id;
                    int idsize;
                    if (dsize < 4)
                    {
                        *al = SSL_AD_DECODE_ERROR;
                        return 0;
                    }
                    n2s(data, idsize);
                    dsize -= 2 + idsize;
                    if (dsize < 0)
                    {
                        *al = SSL_AD_DECODE_ERROR;
                        return 0;
                    }
                    sdata = data;
                    data += idsize;
                    id = d2i_OCSP_RESPID(NULL,
                                         &sdata, idsize);
                    if (!id)
                    {
                        *al = SSL_AD_DECODE_ERROR;
                        return 0;
                    }
                    if (data != sdata)
                    {
                        OCSP_RESPID_free(id);
                        *al = SSL_AD_DECODE_ERROR;
                        return 0;
                    }
                    if (!s->tlsext_ocsp_ids
                            && !(s->tlsext_ocsp_ids =
                                     sk_OCSP_RESPID_new_null()))
                    {
                        OCSP_RESPID_free(id);
                        *al = SSL_AD_INTERNAL_ERROR;
                        return 0;
                    }
                    if (!sk_OCSP_RESPID_push(
                                s->tlsext_ocsp_ids, id))
                    {
                        OCSP_RESPID_free(id);
                        *al = SSL_AD_INTERNAL_ERROR;
                        return 0;
                    }
                }

                /* Read in request_extensions */
                n2s(data,dsize);
                size -= 2;
                if (dsize > size)
                {
                    *al = SSL_AD_DECODE_ERROR;
                    return 0;
                }
                sdata = data;
                if (dsize > 0)
                {
                    s->tlsext_ocsp_exts =
                        d2i_X509_EXTENSIONS(NULL,
                                            &sdata, dsize);
                    if (!s->tlsext_ocsp_exts
                            || (data + dsize != sdata))
                    {
                        *al = SSL_AD_DECODE_ERROR;
                        return 0;
                    }
                }
            }
            /* We don't know what to do with any other type
            * so ignore it.
            */
            else
                s->tlsext_status_type = -1;
        }
        /* session ticket processed earlier */

        data+=size;
    }

    *p = data;
    return 1;
}
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
{
    unsigned short type;
    unsigned short size;
    unsigned short len;
    unsigned char *data = *p;

    int tlsext_servername = 0;

    if (data >= (d+n-2))
        return 1;

    n2s(data,len);

    while(data <= (d+n-4))
    {
        n2s(data,type);
        n2s(data,size);

        if (data+size > (d+n))
            return 1;

        if (s->tlsext_debug_cb)
            s->tlsext_debug_cb(s, 1, type, data, size,
                               s->tlsext_debug_arg);

        if (type == TLSEXT_TYPE_server_name)
        {
            if (s->tlsext_hostname == NULL || size > 0)
            {
                *al = TLS1_AD_UNRECOGNIZED_NAME;
                return 0;
            }
            tlsext_servername = 1;
        }
        else if (type == TLSEXT_TYPE_session_ticket)
        {
            if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
                    || (size > 0))
            {
                *al = TLS1_AD_UNSUPPORTED_EXTENSION;
                return 0;
            }
            s->tlsext_ticket_expected = 1;
        }
        else if (type == TLSEXT_TYPE_status_request)
        {
            /* MUST be empty and only sent if we've requested
             * a status request message.
             */
            if ((s->tlsext_status_type == -1) || (size > 0))
            {
                *al = TLS1_AD_UNSUPPORTED_EXTENSION;
                return 0;
            }
            /* Set flag to expect CertificateStatus message */
            s->tlsext_status_expected = 1;
        }

        data+=size;
    }

    if (data != d+n)
    {
        *al = SSL_AD_DECODE_ERROR;
        return 0;
    }

    if (!s->hit && tlsext_servername == 1)
    {
        if (s->tlsext_hostname)
        {
            if (s->session->tlsext_hostname == NULL)
            {
                s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
                if (!s->session->tlsext_hostname)
                {
                    *al = SSL_AD_UNRECOGNIZED_NAME;
                    return 0;
                }
            }
            else
            {
                *al = SSL_AD_DECODE_ERROR;
                return 0;
            }
        }
    }

    *p = data;
    return 1;
}
Пример #5
0
unsigned char *set_zstatus(mstr *src, int arg, unsigned char **ctxtp, boolean_t need_rtsloc)
{
	unsigned char	*b_line;	/* beginning of line (used to restart line) */
	mval		val;		/* pointer to dollar_zstatus */
	unsigned char	zstatus_buff[2*OUT_BUFF_SIZE];
	unsigned char	*zstatus_bptr, *zstatus_iter;
	int		save_arg;
	size_t		util_len ;
	mval		*status_loc;
	boolean_t 	trans_frame;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	b_line = 0;
	if (!need_rtsloc)
	 	trans_frame = FALSE;
	else
	{	/* get the line address of the last "known" MUMPS code that was executed.  MUMPS
		 * indirection consitutes MUMPS code that is "unknown" is the sense that there is no
		 * line address for it.
		 */
		trans_frame = !(SFT_DM & frame_pointer->type) && ((!(frame_pointer->type & SFT_COUNT
			|| 0 == frame_pointer->type)) || (SFT_ZINTR & frame_pointer->type));
		if (trans_frame)
		{
			save_arg = arg;
			SET_ERR_CODE(frame_pointer, arg);
		}
		src->len = INTCAST(get_symb_line((unsigned char*)src->addr, &b_line, ctxtp) - (unsigned char*)src->addr);
	}
	MV_FORCE_MVAL(&val, arg);
	n2s(&val);
	memcpy(zstatus_buff, val.str.addr, val.str.len);
	zstatus_bptr = zstatus_buff + val.str.len;
	*zstatus_bptr++ = ',';
	if (0 != b_line)
	{
		memcpy(zstatus_bptr, src->addr, src->len);
		zstatus_bptr += src->len;
		*zstatus_bptr++ = ',';
	}
	zstatus_iter = zstatus_bptr;
	util_len = TREF(util_outptr)  - TREF(util_outbuff_ptr);
	if (trans_frame)
	{	/* currently no inserted message (arg) needs arguments.  The following code needs
		 * to be changed if any new parametered message is added.
		 */
		*(TREF(util_outbuff_ptr)) = '-';
		memcpy(&zstatus_buff[OUT_BUFF_SIZE], TREF(util_outbuff_ptr), util_len); /* save original message */
		util_out_print(NULL, RESET); /* clear any pending msgs and reset util_out_buff */
		gtm_putmsg_noflush(VARLSTCNT(1) arg);

		memcpy(zstatus_bptr, TREF(util_outbuff_ptr), TREF(util_outptr) - TREF(util_outbuff_ptr));
		zstatus_bptr += (TREF(util_outptr) - TREF(util_outbuff_ptr));
		*zstatus_bptr++ = ',';
		memcpy(zstatus_bptr, &zstatus_buff[OUT_BUFF_SIZE], util_len);

		/* restore original message into util_outbuf */
		memcpy(TREF(util_outbuff_ptr), &zstatus_buff[OUT_BUFF_SIZE], util_len);
		*(TREF(util_outbuff_ptr)) = '%';
		TREF(util_outptr) = TREF(util_outbuff_ptr) + util_len;
		arg = save_arg;
	} else
		memcpy(zstatus_bptr, TREF(util_outbuff_ptr), util_len);
	zstatus_bptr += util_len;
	for (; zstatus_iter < zstatus_bptr; zstatus_iter++)
	{
		if ('\n' == *zstatus_iter)
			*zstatus_iter = ',';
	}
	status_loc = (NULL == zyerr_frame) ? &dollar_zstatus : &dollar_zerror;
	status_loc->str.len = INTCAST(zstatus_bptr - zstatus_buff);
	status_loc->str.addr = (char *)zstatus_buff;
	s2pool(&status_loc->str);
	status_loc->mvtype = MV_STR;
        /* If this is a MEMORY issue, setting the ecode is of dubious worth since we are not going
         * to drive any handlers and it can definitely be expensive in terms of memory use as ecode_add()
         * (further down the pike) is likely to load the text of the module into storage if it can. So we bypass
         * ecode setting for these two fatal errors. 02/2008 se
	 */
	if (ERR_MEMORY != arg)
		ecode_set(arg);
	return (b_line);
}
Пример #6
0
SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
{
    SCT *sct = NULL;
    const unsigned char *p;

    if (len == 0 || len > MAX_SCT_SIZE) {
        CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
        goto err;
    }

    if ((sct = SCT_new()) == NULL)
        goto err;

    p = *in;

    sct->version = *p;
    if (sct->version == SCT_VERSION_V1) {
        int sig_len;
        size_t len2;
        /*-
         * Fixed-length header:
         *   struct {
         *     Version sct_version;     (1 byte)
         *     log_id id;               (32 bytes)
         *     uint64 timestamp;        (8 bytes)
         *     CtExtensions extensions; (2 bytes + ?)
         *   }
         */
        if (len < 43) {
            CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
            goto err;
        }
        len -= 43;
        p++;
        sct->log_id = BUF_memdup(p, CT_V1_HASHLEN);
        if (sct->log_id == NULL)
            goto err;
        sct->log_id_len = CT_V1_HASHLEN;
        p += CT_V1_HASHLEN;

        n2l8(p, sct->timestamp);

        n2s(p, len2);
        if (len < len2) {
            CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
            goto err;
        }
        if (len2 > 0) {
            sct->ext = BUF_memdup(p, len2);
            if (sct->ext == NULL)
                goto err;
        }
        sct->ext_len = len2;
        p += len2;
        len -= len2;

        sig_len = o2i_SCT_signature(sct, &p, len);
        if (sig_len <= 0) {
            CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
            goto err;
        }
        len -= sig_len;
        *in = p + len;
    } else {
        /* If not V1 just cache encoding */
        sct->sct = BUF_memdup(p, len);
        if (sct->sct == NULL)
            goto err;
        sct->sct_len = len;
        *in = p + len;
    }

    if (psct != NULL) {
        SCT_free(*psct);
        *psct = sct;
    }

    return sct;
err:
    SCT_free(sct);
    return NULL;
}
Пример #7
0
void op_fnztrnlnm(mval *name,mval *table,int4 ind,mval *mode,mval *case_blind,mval *item,mval *ret)
{
	struct dsc$descriptor	lname, ltable;
	uint4		attribute, status, retlen, mask, full_mask;
	char			acmode;
	short int		*item_code, pass, index;
	bool			full;
	char			buff[256], result[MAX_RESULT_SIZE];
	char			i, slot, last_slot;
	char			def_table[] = "LNM$DCL_LOGICAL";

	struct
	{
		item_list_3	item[3];
		int4		terminator;
	} item_list;
	error_def(ERR_BADTRNPARAM);

	if(!name->str.len || MAX_LOGNAM_LENGTH < name->str.len || MAX_LOGNAM_LENGTH < table->str.len)
		rts_error(VARLSTCNT(1) SS$_IVLOGNAM);
	memset(&item_list,0,SIZEOF(item_list));
	item_list.item[0].item_code = 0;
	item_list.item[0].buffer_address = result;
	item_list.item[0].buffer_length = MAX_RESULT_SIZE;
	item_list.item[0].return_length_address = &retlen;
	item_code = &item_list.item[0].item_code;

	lname.dsc$w_length = name->str.len;
	lname.dsc$a_pointer = name->str.addr;
	lname.dsc$b_dtype = DSC$K_DTYPE_T;
	lname.dsc$b_class = DSC$K_CLASS_S;

	if (table->str.len)
	{	ltable.dsc$w_length = table->str.len;
		ltable.dsc$a_pointer = table->str.addr;
	}else
	{	ltable.dsc$a_pointer = def_table;
		ltable.dsc$w_length = strlen(def_table);
	}
	ltable.dsc$b_dtype = DSC$K_DTYPE_T;
	ltable.dsc$b_class = DSC$K_CLASS_S;

	if(ind)
	{	item_list.item[0].item_code = LNM$_INDEX;
		item_list.item[0].buffer_address = &ind;
		item_list.item[1].item_code = 0;
		item_list.item[1].buffer_address = result;
		item_list.item[1].buffer_length = MAX_RESULT_SIZE;
		item_list.item[1].return_length_address = &retlen;
		item_code = &item_list.item[1].item_code;
	}

	attribute = LNM$M_CASE_BLIND;
	if (case_blind->str.len)
	{
		if (case_blind->str.len > 14)
			rts_error(VARLSTCNT(4) ERR_BADTRNPARAM, 2,
				MIN(SHRT_MAX, case_blind->str.len), case_blind->str.addr);
		lower_to_upper(buff,case_blind->str.addr,case_blind->str.len);
		if (case_blind->str.len == 14 && !memcmp(buff,"CASE_SENSITIVE",14))
			attribute = 0;
		else if (case_blind->str.len != 10 || memcmp(buff,"CASE_BLIND",10))
			rts_error(VARLSTCNT(4) ERR_BADTRNPARAM,2,case_blind->str.len,case_blind->str.addr);
	}

	acmode = NOVALUE;
	if (mode->str.len)
	{
		if (mode->str.len > 14)
			rts_error(VARLSTCNT(4) ERR_BADTRNPARAM, 2,
				MIN(SHRT_MAX, mode->str.len), mode->str.addr);
		lower_to_upper(buff,mode->str.addr,mode->str.len);
		switch (buff[0])
		{
		case 'U':
			if ( mode->str.len = 4 && !memcmp(buff, "USER", 4))
				acmode = PSL$C_USER;
		case 'S':
			if ( mode->str.len = 10 && !memcmp(buff, "SUPERVISOR", 10))
				acmode = PSL$C_SUPER;
		case 'K':
			if ( mode->str.len = 6 && !memcmp(buff, "KERNEL", 6))
				acmode = PSL$C_KERNEL;
		case 'E':
			if ( mode->str.len = 9 && !memcmp(buff, "EXECUTIVE", 9))
				acmode = PSL$C_EXEC;
		}
		if (acmode == NOVALUE)
			rts_error(VARLSTCNT(4) ERR_BADTRNPARAM,2,mode->str.len,mode->str.addr);
	}

	full = FALSE;
	*item_code = NOVALUE;
	if (item->str.len)
	{	if (item->str.len > 12)
			rts_error(VARLSTCNT(4) ERR_BADTRNPARAM, 2,
				MIN(SHRT_MAX, item->str.len), item->str.addr);
		lower_to_upper(buff,item->str.addr,item->str.len);
		if ((i = buff[0] - 'A') < MIN_INDEX || i > MAX_INDEX)
		{	rts_error(VARLSTCNT(4) ERR_BADTRNPARAM, 2, item->str.len, item->str.addr);
		}
		if ( trnlnm_index[i].len)
		{	slot = trnlnm_index[i].index;
			last_slot = trnlnm_index[i].len;
			for (; slot < last_slot; slot++)
			{	if (item->str.len == trnlnm_table[slot].len &&
					!memcmp(trnlnm_table[slot].name, buff, item->str.len))
				{	if (trnlnm_table[slot].item_code == FULL_VALUE)
					{	if (ind)
							index = 2;
						else
							index = 1;
						*item_code = LNM$_STRING;
						item_list.item[index].buffer_address = &full_mask;
						item_list.item[index].buffer_length = SIZEOF(full_mask);
						item_list.item[index].item_code = LNM$_ATTRIBUTES;
						item_code = &item_list.item[index].item_code;
						full = TRUE;
					}else
					{	*item_code = trnlnm_table[slot].item_code;
					}
					break;
				}
			}
		}
		if (*item_code == NOVALUE)
		{	rts_error(VARLSTCNT(4) ERR_BADTRNPARAM,2,item->str.len,item->str.addr);
		}
	}else
	{	*item_code = LNM$_STRING;
	}
	for ( pass = 0 ; ; pass++ )
	{	retlen = 0;
		status = sys$trnlnm(&attribute, &ltable, &lname, acmode == NOVALUE ? 0 : &acmode, &item_list);
		if (status & 1)
		{	if (*item_code == LNM$_STRING || *item_code == LNM$_TABLE)
			{	ret->mvtype = MV_STR;
				ENSURE_STP_FREE_SPACE(retlen);
				ret->str.addr = stringpool.free;
				ret->str.len = retlen;
				memcpy(ret->str.addr, result, retlen);
				stringpool.free += retlen;
				return;
			}else if (*item_code == LNM$_LENGTH || *item_code == LNM$_MAX_INDEX)
			{
				MV_FORCE_MVAL(ret,*(int4 *)result) ;
				n2s(ret);
				return;
			}else if (*item_code == LNM$_ACMODE)
			{	ret->mvtype = MV_STR;
				switch(*result)
				{	case PSL$C_USER:
						ENSURE_STP_FREE_SPACE(4);
						ret->str.addr = stringpool.free;
						ret->str.len = 4;
						memcpy(ret->str.addr, "USER", 4);
						stringpool.free += 4;
						return;
					case PSL$C_SUPER:
						ENSURE_STP_FREE_SPACE(5);
						ret->str.addr = stringpool.free;
						ret->str.len = 5;
						memcpy(ret->str.addr, "SUPER", 5);
						stringpool.free += 5;
						return;
					case PSL$C_EXEC:
						ENSURE_STP_FREE_SPACE(9);
						ret->str.addr = stringpool.free;
						ret->str.len = 9;
						memcpy(ret->str.addr, "EXECUTIVE", 9);
						stringpool.free += 9;
						return;
					case PSL$C_KERNEL:
						ENSURE_STP_FREE_SPACE(6);
						ret->str.addr = stringpool.free;
						ret->str.len = 6;
						memcpy(ret->str.addr, "KERNEL", 6);
						stringpool.free += 6;
						return;
					default:
						GTMASSERT;
				}
			}else
			{	assert(*item_code == LNM$_ATTRIBUTES);
				if (full)
				{	if (!retlen)	/* If the logical name exists, but has no entry for the specified index, */
					{		/* then the return status will be normal as the TERMINAL attribute will  */
							/* be filled in, but there will be no equivalence name, thus retlen == 0 */
						ret->mvtype = MV_STR;
						if (!pass)
						{	ret->str.len = 0;
							return;
						}
						ENSURE_STP_FREE_SPACE(lname.dsc$w_length);
						ret->str.addr = stringpool.free;
						ret->str.len = lname.dsc$w_length;
						memcpy(ret->str.addr, lname.dsc$a_pointer, lname.dsc$w_length);
						stringpool.free += lname.dsc$w_length;
						return;
					}
					if(full_mask & LNM$M_TERMINAL)
					{	ret->mvtype = MV_STR;
						ENSURE_STP_FREE_SPACE(retlen);
						ret->str.addr = stringpool.free;
						ret->str.len = retlen;
						memcpy(ret->str.addr, result, retlen);
						stringpool.free += retlen;
						return;
					}
					memcpy(buff,result,retlen);
					lname.dsc$w_length = retlen;
					lname.dsc$a_pointer = buff;
				}else
				{	mask = attr_tab[slot];
					if (mask == NOVALUE)
						GTMASSERT;
					MV_FORCE_MVAL(ret,( *((int4*)result) & mask ? 1 : 0 )) ;
					n2s(ret);
					return;
				}
			}
		}else if (status == SS$_NOLOGNAM)
		{	ret->mvtype = MV_STR;
			if (full && pass > 0)
			{
				ENSURE_STP_FREE_SPACE(lname.dsc$w_length);
				ret->str.addr = stringpool.free;
				ret->str.len = lname.dsc$w_length;
				memcpy(ret->str.addr, lname.dsc$a_pointer, lname.dsc$w_length);
				stringpool.free += lname.dsc$w_length;
			}else
			{	ret->str.len = 0;
			}
			return;
		}else
		{	rts_error(VARLSTCNT(1) status);
		}
	}
	MV_FORCE_MVAL(ret, 0) ;
	return;
}
Пример #8
0
static int get_server_hello(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p;
	int i,j;
	unsigned long len;
	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;

	buf=(unsigned char *)s->init_buf->data;
	p=buf;
	if (s->state == SSL2_ST_GET_SERVER_HELLO_A)
		{
		i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num);
		if (i < (11-s->init_num)) 
			return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
		s->init_num = 11;

		if (*(p++) != SSL2_MT_SERVER_HELLO)
			{
			if (p[-1] != SSL2_MT_ERROR)
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_READ_WRONG_PACKET_TYPE);
				}
			else
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_PEER_ERROR);
			return(-1);
			}
#ifdef __APPLE_CC__
		/* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug
		 * workaround. <*****@*****.**> */
		s->hit=(i=*(p++))?1:0;
#else
		s->hit=(*(p++))?1:0;
#endif
		s->s2->tmp.cert_type= *(p++);
		n2s(p,i);
		if (i < s->version) s->version=i;
		n2s(p,i); s->s2->tmp.cert_length=i;
		n2s(p,i); s->s2->tmp.csl=i;
		n2s(p,i); s->s2->tmp.conn_id_length=i;
		s->state=SSL2_ST_GET_SERVER_HELLO_B;
		}

	/* SSL2_ST_GET_SERVER_HELLO_B */
	len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length;
	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
		{
		SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG);
		return -1;
		}
	j = (int)len - s->init_num;
	i = ssl2_read(s,(char *)&(buf[s->init_num]),j);
	if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
	if (s->msg_callback)
		s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */

	/* things are looking good */

	p = buf + 11;
	if (s->hit)
		{
		if (s->s2->tmp.cert_length != 0) 
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO);
			return(-1);
			}
		if (s->s2->tmp.cert_type != 0)
			{
			if (!(s->options &
				SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
				{
				SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
				return(-1);
				}
			}
		if (s->s2->tmp.csl != 0)
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO);
			return(-1);
			}
		}
	else
		{
#ifdef undef
		/* very bad */
		memset(s->session->session_id,0,
			SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES);
		s->session->session_id_length=0;
		*/
#endif

		/* we need to do this in case we were trying to reuse a 
		 * client session but others are already reusing it.
		 * If this was a new 'blank' session ID, the session-id
		 * length will still be 0 */
		if (s->session->session_id_length > 0)
			{
			if (!ssl_get_new_session(s,0))
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				return(-1);
				}
			}

		if (ssl2_set_certificate(s,s->s2->tmp.cert_type,
			s->s2->tmp.cert_length,p) <= 0)
			{
			ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
			return(-1);
			}
		p+=s->s2->tmp.cert_length;

		if (s->s2->tmp.csl == 0)
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST);
			return(-1);
			}

		/* We have just received a list of ciphers back from the
		 * server.  We need to get the ones that match, then select
		 * the one we want the most :-). */

		/* load the ciphers */
		sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl,
					    &s->session->ciphers);
		p+=s->s2->tmp.csl;
		if (sk == NULL)
			{
			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
			return(-1);
			}

		(void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);

		/* get the array of ciphers we will accept */
		cl=SSL_get_ciphers(s);
		(void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);

		/*
		 * If server preference flag set, choose the first
		 * (highest priority) cipher the server sends, otherwise
		 * client preference has priority.
		 */
		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
		    prio = sk;
		    allow = cl;
		    }
		else
		    {
		    prio = cl;
		    allow = sk;
		    }
		/* In theory we could have ciphers sent back that we
		 * don't want to use but that does not matter since we
		 * will check against the list we originally sent and
		 * for performance reasons we should not bother to match
		 * the two lists up just to check. */
		for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
			{
			if (sk_SSL_CIPHER_find(allow,
					     sk_SSL_CIPHER_value(prio,i)) >= 0)
				break;
			}

		if (i >= sk_SSL_CIPHER_num(prio))
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
			return(-1);
			}
		s->session->cipher=sk_SSL_CIPHER_value(prio,i);


		if (s->session->peer != NULL) /* can't happen*/
			{
			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
			return(-1);
			}

		s->session->peer = s->session->sess_cert->peer_key->x509;
		/* peer_key->x509 has been set by ssl2_set_certificate. */
		CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
		}

	if (s->session->sess_cert == NULL 
      || s->session->peer != s->session->sess_cert->peer_key->x509)
		/* can't happen */
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
		return(-1);
		}
		
	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG);
		return -1;
		}
	memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
	return(1);
	}
Пример #9
0
static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
	{
	int result = 0;
	SSL* s = fixture.s;
	unsigned char *payload = fixture.payload;
	unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1];
	int return_value;
	unsigned const char *p;
	int actual_payload_len;

	s->s3->rrec.data = payload;
	s->s3->rrec.length = strlen((const char*)payload);
	*payload++ = TLS1_HB_REQUEST;
	s2n(fixture.sent_payload_len, payload);

	/* Make a local copy of the request, since it gets overwritten at some
	 * point */
	memcpy((char *)sent_buf, (const char*)payload, sizeof(sent_buf));

	return_value = fixture.process_heartbeat(s);

	if (return_value != fixture.expected_return_value)
		{
		printf("%s failed: expected return value %d, received %d\n",
					 fixture.test_case_name, fixture.expected_return_value,
					 return_value);
		result = 1;
		}

	/* If there is any byte alignment, it will be stored in wbuf.offset. */
	p = &(s->s3->wbuf.buf[
			fixture.return_payload_offset + s->s3->wbuf.offset]);
	actual_payload_len = 0;
	n2s(p, actual_payload_len);

	if (actual_payload_len != fixture.expected_payload_len)
		{
		printf("%s failed:\n  expected payload len: %d\n  received: %d\n",
					 fixture.test_case_name, fixture.expected_payload_len,
					 actual_payload_len);
		print_payload("sent", sent_buf, strlen((const char*)sent_buf));
		print_payload("received", p, actual_payload_len);
		result = 1;
		}
	else
		{
		char* actual_payload = BUF_strndup((const char*)p, actual_payload_len);
		if (strcmp(actual_payload, fixture.expected_return_payload) != 0)
			{
			printf("%s failed:\n  expected payload: \"%s\"\n  received: \"%s\"\n",
						 fixture.test_case_name, fixture.expected_return_payload,
						 actual_payload);
			result = 1;
			}
		OPENSSL_free(actual_payload);
		}

	if (result != 0)
		{
		printf("** %s failed **\n--------\n", fixture.test_case_name);
		}
	return result;
	}
Пример #10
0
/* ssl_check_for_safari attempts to fingerprint Safari using OS X
 * SecureTransport using the TLS extension block in |d|, of length |n|.
 * Safari, since 10.6, sends exactly these extensions, in this order:
 *   SNI,
 *   elliptic_curves
 *   ec_point_formats
 *
 * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
 * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
 * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
 * 10.8..10.8.3 (which don't work).
 */
static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsigned char *d, int n) {
	unsigned short type, size;
	static const unsigned char kSafariExtensionsBlock[] = {
		0x00, 0x0a,  /* elliptic_curves extension */
		0x00, 0x08,  /* 8 bytes */
		0x00, 0x06,  /* 6 bytes of curve ids */
		0x00, 0x17,  /* P-256 */
		0x00, 0x18,  /* P-384 */
		0x00, 0x19,  /* P-521 */

		0x00, 0x0b,  /* ec_point_formats */
		0x00, 0x02,  /* 2 bytes */
		0x01,        /* 1 point format */
		0x00,        /* uncompressed */
	};

	/* The following is only present in TLS 1.2 */
	static const unsigned char kSafariTLS12ExtensionsBlock[] = {
		0x00, 0x0d,  /* signature_algorithms */
		0x00, 0x0c,  /* 12 bytes */
		0x00, 0x0a,  /* 10 bytes */
		0x05, 0x01,  /* SHA-384/RSA */
		0x04, 0x01,  /* SHA-256/RSA */
		0x02, 0x01,  /* SHA-1/RSA */
		0x04, 0x03,  /* SHA-256/ECDSA */
		0x02, 0x03,  /* SHA-1/ECDSA */
	};

	if (data >= (d+n-2))
		return;
	data += 2;

	if (data > (d+n-4))
		return;
	n2s(data,type);
	n2s(data,size);

	if (type != TLSEXT_TYPE_server_name)
		return;

	if (data+size > d+n)
		return;
	data += size;

	if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
		{
		const size_t len1 = sizeof(kSafariExtensionsBlock);
		const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);

		if (data + len1 + len2 != d+n)
			return;
		if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
			return;
		if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
			return;
		}
	else
		{
		const size_t len = sizeof(kSafariExtensionsBlock);

		if (data + len != d+n)
			return;
		if (memcmp(data, kSafariExtensionsBlock, len) != 0)
			return;
		}

	s->s3->is_probably_safari = 1;
}
Пример #11
0
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short type;
	unsigned short size;
	unsigned short len;
	unsigned char *data = *p;
	int renegotiate_seen = 0;

	s->servername_done = 0;
	s->tlsext_status_type = -1;

	if (data >= (d+n-2))
		goto ri_check;
	n2s(data,len);

	if (data > (d+n-len)) 
		goto ri_check;

	while (data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		goto ri_check;
#if 0
		fprintf(stderr,"Received extension type %d size %d\n",type,size);
#endif
		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 0, type, data, size,
						s->tlsext_debug_arg);
/* The servername extension is treated as follows:

   - Only the hostname type is supported with a maximum length of 255.
   - The servername is rejected if too long or if it contains zeros,
     in which case an fatal alert is generated.
   - The servername field is maintained together with the session cache.
   - When a session is resumed, the servername call back invoked in order
     to allow the application to position itself to the right context. 
   - The servername is acknowledged if it is new for a session or when 
     it is identical to a previously used for the same session. 
     Applications can control the behaviour.  They can at any time
     set a 'desirable' servername for a new SSL object. This can be the
     case for example with HTTPS when a Host: header field is received and
     a renegotiation is requested. In this case, a possible servername
     presented in the new client hello is only acknowledged if it matches
     the value of the Host: field. 
   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
     if they provide for changing an explicit servername context for the session,
     i.e. when the session has been established with a servername extension. 
   - On session reconnect, the servername extension may be absent. 

*/      

		if (type == TLSEXT_TYPE_server_name)
			{
			unsigned char *sdata;
			int servname_type;
			int dsize; 
		
			if (size < 2) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			n2s(data,dsize);  
			size -= 2;
			if (dsize > size  ) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				} 

			sdata = data;
			while (dsize > 3) 
				{
	 			servname_type = *(sdata++); 
				n2s(sdata,len);
				dsize -= 3;

				if (len > dsize) 
					{
					*al = SSL_AD_DECODE_ERROR;
					return 0;
					}
				if (s->servername_done == 0)
				switch (servname_type)
					{
				case TLSEXT_NAMETYPE_host_name:
					if (!s->hit)
						{
						if(s->session->tlsext_hostname)
							{
							*al = SSL_AD_DECODE_ERROR;
							return 0;
							}
						if (len > TLSEXT_MAXLEN_host_name)
							{
							*al = TLS1_AD_UNRECOGNIZED_NAME;
							return 0;
							}
						if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)
							{
							*al = TLS1_AD_INTERNAL_ERROR;
							return 0;
							}
						memcpy(s->session->tlsext_hostname, sdata, len);
						s->session->tlsext_hostname[len]='\0';
						if (strlen(s->session->tlsext_hostname) != len) {
							OPENSSL_free(s->session->tlsext_hostname);
							s->session->tlsext_hostname = NULL;
							*al = TLS1_AD_UNRECOGNIZED_NAME;
							return 0;
						}
						s->servername_done = 1; 

						}
					else 
						s->servername_done = s->session->tlsext_hostname
							&& strlen(s->session->tlsext_hostname) == len 
							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
					
					break;

				default:
					break;
					}
				 
				dsize -= len;
				}
			if (dsize != 0) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}

			}

#ifndef OPENSSL_NO_EC
		else if (type == TLSEXT_TYPE_ec_point_formats &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;
			int ecpointformatlist_length = *(sdata++);

			if (ecpointformatlist_length != size - 1)
				{
				*al = TLS1_AD_DECODE_ERROR;
				return 0;
				}
			if (!s->hit)
				{
				if(s->session->tlsext_ecpointformatlist)
					{
					*al = TLS1_AD_DECODE_ERROR;
					return 0;
					}
				s->session->tlsext_ecpointformatlist_length = 0;
				if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
					{
					*al = TLS1_AD_INTERNAL_ERROR;
					return 0;
					}
				s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
				memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
				}
#if 0
			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ecpointformatlist (length=%i) ", s->session->tlsext_ecpointformatlist_length);
			sdata = s->session->tlsext_ecpointformatlist;
			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
				fprintf(stderr,"%i ",*(sdata++));
			fprintf(stderr,"\n");
#endif
			}
		else if (type == TLSEXT_TYPE_elliptic_curves &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;
			int ellipticcurvelist_length = (*(sdata++) << 8);
			ellipticcurvelist_length += (*(sdata++));

			if (ellipticcurvelist_length != size - 2)
				{
				*al = TLS1_AD_DECODE_ERROR;
				return 0;
				}
			if (!s->hit)
				{
				if(s->session->tlsext_ellipticcurvelist)
					{
					*al = TLS1_AD_DECODE_ERROR;
					return 0;
					}
				s->session->tlsext_ellipticcurvelist_length = 0;
				if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL)
					{
					*al = TLS1_AD_INTERNAL_ERROR;
					return 0;
					}
				s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
				memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
				}
#if 0
			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length);
			sdata = s->session->tlsext_ellipticcurvelist;
			for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++)
				fprintf(stderr,"%i ",*(sdata++));
			fprintf(stderr,"\n");
#endif
			}
#endif /* OPENSSL_NO_EC */
#ifdef TLSEXT_TYPE_opaque_prf_input
		else if (type == TLSEXT_TYPE_opaque_prf_input &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;

			if (size < 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			n2s(sdata, s->s3->client_opaque_prf_input_len);
			if (s->s3->client_opaque_prf_input_len != size - 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}

			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
				OPENSSL_free(s->s3->client_opaque_prf_input);
			if (s->s3->client_opaque_prf_input_len == 0)
				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
			else
				s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
			if (s->s3->client_opaque_prf_input == NULL)
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			}
#endif
		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if (s->tls_session_ticket_ext_cb &&
			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			}
		else if (type == TLSEXT_TYPE_renegotiate)
			{
			if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
				return 0;
			renegotiate_seen = 1;
			}
		else if (type == TLSEXT_TYPE_status_request &&
		         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
			{
		
			if (size < 5) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}

			s->tlsext_status_type = *data++;
			size--;
			if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
				{
				const unsigned char *sdata;
				int dsize;
				/* Read in responder_id_list */
				n2s(data,dsize);
				size -= 2;
				if (dsize > size  ) 
					{
					*al = SSL_AD_DECODE_ERROR;
					return 0;
					}
				while (dsize > 0)
					{
					OCSP_RESPID *id;
					int idsize;
					if (dsize < 4)
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					n2s(data, idsize);
					dsize -= 2 + idsize;
					if (dsize < 0)
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					sdata = data;
					data += idsize;
					id = d2i_OCSP_RESPID(NULL,
								&sdata, idsize);
					if (!id)
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					if (data != sdata)
						{
						OCSP_RESPID_free(id);
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					if (!s->tlsext_ocsp_ids
						&& !(s->tlsext_ocsp_ids =
						sk_OCSP_RESPID_new_null()))
						{
						OCSP_RESPID_free(id);
						*al = SSL_AD_INTERNAL_ERROR;
						return 0;
						}
					if (!sk_OCSP_RESPID_push(
							s->tlsext_ocsp_ids, id))
						{
						OCSP_RESPID_free(id);
						*al = SSL_AD_INTERNAL_ERROR;
						return 0;
						}
					}

				/* Read in request_extensions */
				n2s(data,dsize);
				size -= 2;
				if (dsize > size) 
					{
					*al = SSL_AD_DECODE_ERROR;
					return 0;
					}
				sdata = data;
				if (dsize > 0)
					{
					s->tlsext_ocsp_exts =
						d2i_X509_EXTENSIONS(NULL,
							&sdata, dsize);
					if (!s->tlsext_ocsp_exts
						|| (data + dsize != sdata))
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					}
				}
				/* We don't know what to do with any other type
 			 	* so ignore it.
 			 	*/
				else
					s->tlsext_status_type = -1;
			}

		/* session ticket processed earlier */
		data+=size;
		}
				
	*p = data;

	ri_check:

	/* Need RI if renegotiating */

	if (!renegotiate_seen && s->new_session &&
		!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
		{
		*al = SSL_AD_HANDSHAKE_FAILURE;
	 	SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,
				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
		return 0;
		}

	return 1;
	}
Пример #12
0
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short length;
	unsigned short type;
	unsigned short size;
	unsigned char *data = *p;
	int tlsext_servername = 0;
	int renegotiate_seen = 0;

	if (data >= (d+n-2))
		goto ri_check;

	n2s(data,length);
	if (data+length != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	while(data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		goto ri_check;

		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 1, type, data, size,
						s->tlsext_debug_arg);

		if (type == TLSEXT_TYPE_server_name)
			{
			if (s->tlsext_hostname == NULL || size > 0)
				{
				*al = TLS1_AD_UNRECOGNIZED_NAME;
				return 0;
				}
			tlsext_servername = 1;   
			}

#ifndef OPENSSL_NO_EC
		else if (type == TLSEXT_TYPE_ec_point_formats &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;
			int ecpointformatlist_length = *(sdata++);

			if (ecpointformatlist_length != size - 1)
				{
				*al = TLS1_AD_DECODE_ERROR;
				return 0;
				}
			s->session->tlsext_ecpointformatlist_length = 0;
			if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
			if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
			memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
#if 0
			fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
			sdata = s->session->tlsext_ecpointformatlist;
			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
				fprintf(stderr,"%i ",*(sdata++));
			fprintf(stderr,"\n");
#endif
			}
#endif /* OPENSSL_NO_EC */

		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if (s->tls_session_ticket_ext_cb &&
			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
				|| (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			s->tlsext_ticket_expected = 1;
			}
#ifdef TLSEXT_TYPE_opaque_prf_input
		else if (type == TLSEXT_TYPE_opaque_prf_input &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;

			if (size < 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			n2s(sdata, s->s3->server_opaque_prf_input_len);
			if (s->s3->server_opaque_prf_input_len != size - 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			
			if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
				OPENSSL_free(s->s3->server_opaque_prf_input);
			if (s->s3->server_opaque_prf_input_len == 0)
				s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
			else
				s->s3->server_opaque_prf_input = BUF_memdup(sdata, s->s3->server_opaque_prf_input_len);

			if (s->s3->server_opaque_prf_input == NULL)
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			}
#endif
		else if (type == TLSEXT_TYPE_status_request &&
		         s->version != DTLS1_VERSION)
			{
			/* MUST be empty and only sent if we've requested
			 * a status request message.
			 */ 
			if ((s->tlsext_status_type == -1) || (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			/* Set flag to expect CertificateStatus message */
			s->tlsext_status_expected = 1;
			}
		else if (type == TLSEXT_TYPE_renegotiate)
			{
			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
				return 0;
			renegotiate_seen = 1;
			}
		data+=size;		
		}

	if (data != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	if (!s->hit && tlsext_servername == 1)
		{
 		if (s->tlsext_hostname)
			{
			if (s->session->tlsext_hostname == NULL)
				{
				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
				if (!s->session->tlsext_hostname)
					{
					*al = SSL_AD_UNRECOGNIZED_NAME;
					return 0;
					}
				}
			else 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			}
		}

	*p = data;

	ri_check:

	/* Determine if we need to see RI. Strictly speaking if we want to
	 * avoid an attack we should *always* see RI even on initial server
	 * hello because the client doesn't see any renegotiation during an
	 * attack. However this would mean we could not connect to any server
	 * which doesn't support RI so for the immediate future tolerate RI
	 * absence on initial connect only.
	 */
	if (!renegotiate_seen
		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
		{
		*al = SSL_AD_HANDSHAKE_FAILURE;
		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
		return 0;
		}

	return 1;
	}
Пример #13
0
int ssl23_get_client_hello(SSL *s)
	{
	char buf_space[11]; /* Request this many bytes in initial read.
	                     * We can detect SSL 3.0/TLS 1.0 Client Hellos
	                     * ('type == 3') correctly only when the following
	                     * is in a single record, which is not guaranteed by
	                     * the protocol specification:
	                     * Byte  Content
	                     *  0     type            \
	                     *  1/2   version          > record header
	                     *  3/4   length          /
	                     *  5     msg_type        \
	                     *  6-8   length           > Client Hello message
	                     *  9/10  client_version  /
	                     */
	char *buf= &(buf_space[0]);
	unsigned char *p,*d,*d_len,*dd;
	unsigned int i;
	unsigned int csl,sil,cl;
	int n=0,j;
	int type=0;
	int v[2];

	if (s->state ==	SSL23_ST_SR_CLNT_HELLO_A)
		{
		/* read the initial header */
		v[0]=v[1]=0;

		if (!ssl3_setup_buffers(s)) goto err;

		n=ssl23_read_bytes(s, sizeof buf_space);
		if (n != sizeof buf_space) return(n); /* n == -1 || n == 0 */

		p=s->packet;

		memcpy(buf,p,n);

		if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO))
			{
			/*
			 * SSLv2 header
			 */
			if ((p[3] == 0x00) && (p[4] == 0x02))
				{
				v[0]=p[3]; v[1]=p[4];
				/* SSLv2 */
				if (!(s->options & SSL_OP_NO_SSLv2))
					type=1;
				}
			else if (p[3] == SSL3_VERSION_MAJOR)
				{
				v[0]=p[3]; v[1]=p[4];
				/* SSLv3/TLSv1 */
				if (p[4] >= TLS1_VERSION_MINOR)
					{
					if (!(s->options & SSL_OP_NO_TLSv1))
						{
						s->version=TLS1_VERSION;
						/* type=2; */ /* done later to survive restarts */
						s->state=SSL23_ST_SR_CLNT_HELLO_B;
						}
					else if (!(s->options & SSL_OP_NO_SSLv3))
						{
						s->version=SSL3_VERSION;
						/* type=2; */
						s->state=SSL23_ST_SR_CLNT_HELLO_B;
						}
					else if (!(s->options & SSL_OP_NO_SSLv2))
						{
						type=1;
						}
					}
				else if (!(s->options & SSL_OP_NO_SSLv3))
					{
					s->version=SSL3_VERSION;
					/* type=2; */
					s->state=SSL23_ST_SR_CLNT_HELLO_B;
					}
				else if (!(s->options & SSL_OP_NO_SSLv2))
					type=1;

				}
			}
		else if ((p[0] == SSL3_RT_HANDSHAKE) &&
			 (p[1] == SSL3_VERSION_MAJOR) &&
			 (p[5] == SSL3_MT_CLIENT_HELLO) &&
			 ((p[3] == 0 && p[4] < 5 /* silly record length? */)
				|| (p[9] == p[1])))
			{
			/*
			 * SSLv3 or tls1 header
			 */
			
			v[0]=p[1]; /* major version (= SSL3_VERSION_MAJOR) */
			/* We must look at client_version inside the Client Hello message
			 * to get the correct minor version.
			 * However if we have only a pathologically small fragment of the
			 * Client Hello message, this would be difficult, and we'd have
			 * to read more records to find out.
			 * No known SSL 3.0 client fragments ClientHello like this,
			 * so we simply assume TLS 1.0 to avoid protocol version downgrade
			 * attacks. */
			if (p[3] == 0 && p[4] < 6)
				{
#if 0
				SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL);
				goto err;
#else
				v[1] = TLS1_VERSION_MINOR;
#endif
				}
			else
				v[1]=p[10]; /* minor version according to client_version */
			if (v[1] >= TLS1_VERSION_MINOR)
				{
				if (!(s->options & SSL_OP_NO_TLSv1))
					{
					s->version=TLS1_VERSION;
					type=3;
					}
				else if (!(s->options & SSL_OP_NO_SSLv3))
					{
					s->version=SSL3_VERSION;
					type=3;
					}
				}
			else
				{
				/* client requests SSL 3.0 */
				if (!(s->options & SSL_OP_NO_SSLv3))
					{
					s->version=SSL3_VERSION;
					type=3;
					}
				else if (!(s->options & SSL_OP_NO_TLSv1))
					{
					/* we won't be able to use TLS of course,
					 * but this will send an appropriate alert */
					s->version=TLS1_VERSION;
					type=3;
					}
				}
			}
		else if ((strncmp("GET ", (char *)p,4) == 0) ||
			 (strncmp("POST ",(char *)p,5) == 0) ||
			 (strncmp("HEAD ",(char *)p,5) == 0) ||
			 (strncmp("PUT ", (char *)p,4) == 0))
			{
			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTP_REQUEST);
			goto err;
			}
		else if (strncmp("CONNECT",(char *)p,7) == 0)
			{
			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTPS_PROXY_REQUEST);
			goto err;
			}
		}

	if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
		{
		/* we have SSLv3/TLSv1 in an SSLv2 header
		 * (other cases skip this state) */

		type=2;
		p=s->packet;
		v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
		v[1] = p[4];

		n=((p[0]&0x7f)<<8)|p[1];
		if (n > (1024*4))
			{
			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
			goto err;
			}

		j=ssl23_read_bytes(s,n+2);
		if (j <= 0) return(j);

		ssl3_finish_mac(s, s->packet+2, s->packet_length-2);
		if (s->msg_callback)
			s->msg_callback(0, SSL2_VERSION, 0, s->packet+2, s->packet_length-2, s, s->msg_callback_arg); /* CLIENT-HELLO */

		p=s->packet;
		p+=5;
		n2s(p,csl);
		n2s(p,sil);
		n2s(p,cl);
		d=(unsigned char *)s->init_buf->data;
		if ((csl+sil+cl+11) != s->packet_length)
			{
			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
			goto err;
			}

		/* record header: msg_type ... */
		*(d++) = SSL3_MT_CLIENT_HELLO;
		/* ... and length (actual value will be written later) */
		d_len = d;
		d += 3;

		/* client_version */
		*(d++) = SSL3_VERSION_MAJOR; /* == v[0] */
		*(d++) = v[1];

		/* lets populate the random area */
		/* get the challenge_length */
		i=(cl > SSL3_RANDOM_SIZE)?SSL3_RANDOM_SIZE:cl;
		memset(d,0,SSL3_RANDOM_SIZE);
		memcpy(&(d[SSL3_RANDOM_SIZE-i]),&(p[csl+sil]),i);
		d+=SSL3_RANDOM_SIZE;

		/* no session-id reuse */
		*(d++)=0;

		/* ciphers */
		j=0;
		dd=d;
		d+=2;
		for (i=0; i<csl; i+=3)
			{
			if (p[i] != 0) continue;
			*(d++)=p[i+1];
			*(d++)=p[i+2];
			j+=2;
			}
		s2n(j,dd);

		/* COMPRESSION */
		*(d++)=1;
		*(d++)=0;
		
		i = (d-(unsigned char *)s->init_buf->data) - 4;
		l2n3((long)i, d_len);

		/* get the data reused from the init_buf */
		s->s3->tmp.reuse_message=1;
		s->s3->tmp.message_type=SSL3_MT_CLIENT_HELLO;
		s->s3->tmp.message_size=i;
		}

	/* imaginary new state (for program structure): */
	/* s->state = SSL23_SR_CLNT_HELLO_C */

	if (type == 1)
		{
#ifdef OPENSSL_NO_SSL2
		SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
		goto err;
#else
		/* we are talking sslv2 */
		/* we need to clean up the SSLv3/TLSv1 setup and put in the
		 * sslv2 stuff. */

		if (s->s2 == NULL)
			{
			if (!ssl2_new(s))
				goto err;
			}
		else
			ssl2_clear(s);

		if (s->s3 != NULL) ssl3_free(s);

		if (!BUF_MEM_grow_clean(s->init_buf,
			SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
			{
			goto err;
			}

		s->state=SSL2_ST_GET_CLIENT_HELLO_A;
		if (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3)
			s->s2->ssl2_rollback=0;
		else
			/* reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0
			 * (SSL 3.0 draft/RFC 2246, App. E.2) */
			s->s2->ssl2_rollback=1;

		/* setup the n bytes we have read so we get them from
		 * the sslv2 buffer */
		s->rstate=SSL_ST_READ_HEADER;
		s->packet_length=n;
		s->packet= &(s->s2->rbuf[0]);
		memcpy(s->packet,buf,n);
		s->s2->rbuf_left=n;
		s->s2->rbuf_offs=0;

		s->method=SSLv2_server_method();
		s->handshake_func=s->method->ssl_accept;
#endif
		}

	if ((type == 2) || (type == 3))
		{
		/* we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style) */

		if (!ssl_init_wbio_buffer(s,1)) goto err;

		/* we are in this state */
		s->state=SSL3_ST_SR_CLNT_HELLO_A;

		if (type == 3)
			{
			/* put the 'n' bytes we have read into the input buffer
			 * for SSLv3 */
			s->rstate=SSL_ST_READ_HEADER;
			s->packet_length=n;
			s->packet= &(s->s3->rbuf.buf[0]);
			memcpy(s->packet,buf,n);
			s->s3->rbuf.left=n;
			s->s3->rbuf.offset=0;
			}
		else
			{
			s->packet_length=0;
			s->s3->rbuf.left=0;
			s->s3->rbuf.offset=0;
			}

		if (s->version == TLS1_VERSION)
			s->method = TLSv1_server_method();
		else
			s->method = SSLv3_server_method();
#if 0 /* ssl3_get_client_hello does this */
		s->client_version=(v[0]<<8)|v[1];
#endif
		s->handshake_func=s->method->ssl_accept;
		}
	
	if ((type < 1) || (type > 3))
		{
		/* bad, very bad */
		SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNKNOWN_PROTOCOL);
		goto err;
		}
	s->init_num=0;

	if (buf != buf_space) OPENSSL_free(buf);
	s->first_packet=1;
	return(SSL_accept(s));
err:
	if (buf != buf_space) OPENSSL_free(buf);
	return(-1);
	}
Пример #14
0
/* Get a SERVER HELLO response from the server */
void get_server_hello(ssl_conn* ssl)
{
	unsigned char buf[BUFSIZE];
	unsigned char *p, *end;
	int len;
	int server_version, cert_length, cs_length, conn_id_length;
	int found;

	if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
		printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
		exit(1);
	}
	if (len < 11) {
		printf("get_server_hello: Packet too short (len = %d)\n", len);
		exit(1);
	}

	p = buf;

	if (*(p++) != SSL2_MT_SERVER_HELLO) {
		printf("get_server_hello: Expected SSL2 MT SERVER HELLO, got %x\n", (int)p[-1]);
		exit(1);
	}

	if (*(p++) != 0) {
		printf("get_server_hello: SESSION-ID-HIT is not 0\n");
		exit(1);
	}

	if (*(p++) != 1) {
		printf("get_server_hello: CERTIFICATE-TYPE is not SSL CT X509 CERTIFICATE\n");
		exit(1);
	}

	n2s(p, server_version);
	if (server_version != 2) {
		printf("get_server_hello: Unsupported server version %d\n", server_version);
		exit(1);
	}

	n2s(p, cert_length);
	n2s(p, cs_length);
	n2s(p, conn_id_length);

	if (len != 11 + cert_length + cs_length + conn_id_length) {
		printf("get_server_hello: Malformed packet size\n");
		exit(1);
	}

	/* read the server certificate */
	ssl->x509 = NULL;
	ssl->x509=d2i_X509(NULL,&p,(long)cert_length);
	if (ssl->x509 == NULL) {
		printf("get server hello: Cannot parse x509 certificate\n");
		exit(1);
	}

	if (cs_length % 3 != 0) {
		printf("get server hello: CIPHER-SPECS-LENGTH is not a multiple of 3\n");
		exit(1);
	}

	found = 0;
	for (end=p+cs_length; p < end; p += 3) {
		if ((p[0] == 0x01) && (p[1] == 0x00) && (p[2] == 0x80))
			found = 1;	/* SSL CK RC4 128 WITH MD5 */
	}

	if (!found) {
		printf("get server hello: Remote server does not support 128 bit RC4\n");
		exit(1);
	}

	if (conn_id_length > SSL2_MAX_CONNECTION_ID_LENGTH) {
		printf("get server hello: CONNECTION-ID-LENGTH is too long\n");
		exit(1);
	}

	/* The connection id is sent back to the server in the CLIENT FINISHED packet */
	ssl->conn_id_length = conn_id_length;
	memcpy(ssl->conn_id, p, conn_id_length);
}
Пример #15
0
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short length;
	unsigned short type;
	unsigned short size;
	unsigned char *data = *p;
	int tlsext_servername = 0;
	int renegotiate_seen = 0;

	if (data >= (d+n-2))
		goto ri_check;

	n2s(data,length);
	if (data+length != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	while(data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		goto ri_check;

		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 1, type, data, size,
						s->tlsext_debug_arg);

		if (type == TLSEXT_TYPE_server_name)
			{
			if (s->tlsext_hostname == NULL || size > 0)
				{
				*al = TLS1_AD_UNRECOGNIZED_NAME;
				return 0;
				}
			tlsext_servername = 1;   
			}
		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
				|| (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			s->tlsext_ticket_expected = 1;
			}
		else if (type == TLSEXT_TYPE_status_request &&
		         s->version != DTLS1_VERSION)
			{
			/* MUST be empty and only sent if we've requested
			 * a status request message.
			 */ 
			if ((s->tlsext_status_type == -1) || (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			/* Set flag to expect CertificateStatus message */
			s->tlsext_status_expected = 1;
			}
		else if (type == TLSEXT_TYPE_renegotiate)
			{
			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
				return 0;
			renegotiate_seen = 1;
			}
		data+=size;		
		}

	if (data != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	if (!s->hit && tlsext_servername == 1)
		{
 		if (s->tlsext_hostname)
			{
			if (s->session->tlsext_hostname == NULL)
				{
				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
				if (!s->session->tlsext_hostname)
					{
					*al = SSL_AD_UNRECOGNIZED_NAME;
					return 0;
					}
				}
			else 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			}
		}

	*p = data;

	ri_check:

	/* Determine if we need to see RI. Strictly speaking if we want to
	 * avoid an attack we should *always* see RI even on initial server
	 * hello because the client doesn't see any renegotiation during an
	 * attack. However this would mean we could not connect to any server
	 * which doesn't support RI so for the immediate future tolerate RI
	 * absence on initial connect only.
	 */
	if (!renegotiate_seen
		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
		{
		*al = SSL_AD_HANDSHAKE_FAILURE;
		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
		return 0;
		}

	return 1;
	}
Пример #16
0
int ssl23_get_client_hello(SSL *s)
{
    /*-
     * Request this many bytes in initial read.
     * We can detect SSL 3.0/TLS 1.0 Client Hellos
     * ('type == 3') correctly only when the following
     * is in a single record, which is not guaranteed by
     * the protocol specification:
     * Byte  Content
     *  0     type            \
     *  1/2   version          > record header
     *  3/4   length          /
     *  5     msg_type        \
     *  6-8   length           > Client Hello message
     *  9/10  client_version  /
     */
    char buf_space[11];
    char *buf = &(buf_space[0]);
    unsigned char *p, *d, *d_len, *dd;
    unsigned int i;
    unsigned int csl, sil, cl;
    int n = 0, j;
    int type = 0;
    int v[2];

    if (s->state == SSL23_ST_SR_CLNT_HELLO_A) {
        /* read the initial header */
        v[0] = v[1] = 0;

        if (!ssl3_setup_buffers(s))
            goto err;

        n = ssl23_read_bytes(s, sizeof buf_space);
        if (n != sizeof buf_space)
            return (n);         /* n == -1 || n == 0 */

        p = s->packet;

        memcpy(buf, p, n);

        if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) {
            /*
             * SSLv2 header
             */
            if ((p[3] == 0x00) && (p[4] == 0x02)) {
                v[0] = p[3];
                v[1] = p[4];
                /* SSLv2 */
                if (!(s->options & SSL_OP_NO_SSLv2))
                    type = 1;
            } else if (p[3] == SSL3_VERSION_MAJOR) {
                v[0] = p[3];
                v[1] = p[4];
                /* SSLv3/TLSv1 */
                if (p[4] >= TLS1_VERSION_MINOR) {
                    if (p[4] >= TLS1_2_VERSION_MINOR &&
                        !(s->options & SSL_OP_NO_TLSv1_2)) {
                        s->version = TLS1_2_VERSION;
                        s->state = SSL23_ST_SR_CLNT_HELLO_B;
                    } else if (p[4] >= TLS1_1_VERSION_MINOR &&
                               !(s->options & SSL_OP_NO_TLSv1_1)) {
                        s->version = TLS1_1_VERSION;
                        /*
                         * type=2;
                         *//*
                         * done later to survive restarts
                         */
                        s->state = SSL23_ST_SR_CLNT_HELLO_B;
                    } else if (!(s->options & SSL_OP_NO_TLSv1)) {
                        s->version = TLS1_VERSION;
                        /*
                         * type=2;
                         *//*
                         * done later to survive restarts
                         */
                        s->state = SSL23_ST_SR_CLNT_HELLO_B;
                    } else if (!(s->options & SSL_OP_NO_SSLv3)) {
                        s->version = SSL3_VERSION;
                        /* type=2; */
                        s->state = SSL23_ST_SR_CLNT_HELLO_B;
                    } else if (!(s->options & SSL_OP_NO_SSLv2)) {
                        type = 1;
                    }
                } else if (!(s->options & SSL_OP_NO_SSLv3)) {
                    s->version = SSL3_VERSION;
                    /* type=2; */
                    s->state = SSL23_ST_SR_CLNT_HELLO_B;
                } else if (!(s->options & SSL_OP_NO_SSLv2))
                    type = 1;

            }
        }
        /* p[4] < 5 ... silly record length? */
        else if ((p[0] == SSL3_RT_HANDSHAKE) &&
                 (p[1] == SSL3_VERSION_MAJOR) &&
                 (p[5] == SSL3_MT_CLIENT_HELLO) && ((p[3] == 0 && p[4] < 5)
                                                    || (p[9] >= p[1]))) {
            /*
             * SSLv3 or tls1 header
             */

            v[0] = p[1];        /* major version (= SSL3_VERSION_MAJOR) */
            /*
             * We must look at client_version inside the Client Hello message
             * to get the correct minor version. However if we have only a
             * pathologically small fragment of the Client Hello message, this
             * would be difficult, and we'd have to read more records to find
             * out. No known SSL 3.0 client fragments ClientHello like this,
             * so we simply reject such connections to avoid protocol version
             * downgrade attacks.
             */
            if (p[3] == 0 && p[4] < 6) {
                SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_RECORD_TOO_SMALL);
                goto err;
            }
            /*
             * if major version number > 3 set minor to a value which will
             * use the highest version 3 we support. If TLS 2.0 ever appears
             * we will need to revise this....
             */
            if (p[9] > SSL3_VERSION_MAJOR)
                v[1] = 0xff;
            else
                v[1] = p[10];   /* minor version according to client_version */
            if (v[1] >= TLS1_VERSION_MINOR) {
                if (v[1] >= TLS1_2_VERSION_MINOR &&
                    !(s->options & SSL_OP_NO_TLSv1_2)) {
                    s->version = TLS1_2_VERSION;
                    type = 3;
                } else if (v[1] >= TLS1_1_VERSION_MINOR &&
                           !(s->options & SSL_OP_NO_TLSv1_1)) {
                    s->version = TLS1_1_VERSION;
                    type = 3;
                } else if (!(s->options & SSL_OP_NO_TLSv1)) {
                    s->version = TLS1_VERSION;
                    type = 3;
                } else if (!(s->options & SSL_OP_NO_SSLv3)) {
                    s->version = SSL3_VERSION;
                    type = 3;
                }
            } else {
                /* client requests SSL 3.0 */
                if (!(s->options & SSL_OP_NO_SSLv3)) {
                    s->version = SSL3_VERSION;
                    type = 3;
                } else if (!(s->options & SSL_OP_NO_TLSv1)) {
                    /*
                     * we won't be able to use TLS of course, but this will
                     * send an appropriate alert
                     */
                    s->version = TLS1_VERSION;
                    type = 3;
                }
            }
        } else if ((strncmp("GET ", (char *)p, 4) == 0) ||
                   (strncmp("POST ", (char *)p, 5) == 0) ||
                   (strncmp("HEAD ", (char *)p, 5) == 0) ||
                   (strncmp("PUT ", (char *)p, 4) == 0)) {
            SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_HTTP_REQUEST);
            goto err;
        } else if (strncmp("CONNECT", (char *)p, 7) == 0) {
            SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_HTTPS_PROXY_REQUEST);
            goto err;
        }
    }

    /* ensure that TLS_MAX_VERSION is up-to-date */
    OPENSSL_assert(s->version <= TLS_MAX_VERSION);

    if (s->version < TLS1_2_VERSION && tls1_suiteb(s)) {
        SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
               SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
        goto err;
    }
#ifdef OPENSSL_FIPS
    if (FIPS_mode() && (s->version < TLS1_VERSION)) {
        SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
               SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
        goto err;
    }
#endif

    if (s->state == SSL23_ST_SR_CLNT_HELLO_B) {
        /*
         * we have SSLv3/TLSv1 in an SSLv2 header (other cases skip this
         * state)
         */

        type = 2;
        p = s->packet;
        v[0] = p[3];            /* == SSL3_VERSION_MAJOR */
        v[1] = p[4];

        /*-
         * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
         * header is sent directly on the wire, not wrapped as a TLS
         * record. It's format is:
         * Byte  Content
         * 0-1   msg_length
         * 2     msg_type
         * 3-4   version
         * 5-6   cipher_spec_length
         * 7-8   session_id_length
         * 9-10  challenge_length
         * ...   ...
         */
        n = ((p[0] & 0x7f) << 8) | p[1];
        if (n > (1024 * 4)) {
            SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_RECORD_TOO_LARGE);
            goto err;
        }
        if (n < 9) {
            SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
                   SSL_R_RECORD_LENGTH_MISMATCH);
            goto err;
        }

        j = ssl23_read_bytes(s, n + 2);
        /*
         * We previously read 11 bytes, so if j > 0, we must have j == n+2 ==
         * s->packet_length. We have at least 11 valid packet bytes.
         */
        if (j <= 0)
            return (j);

        ssl3_finish_mac(s, s->packet + 2, s->packet_length - 2);

        /* CLIENT-HELLO */
        if (s->msg_callback)
            s->msg_callback(0, SSL2_VERSION, 0, s->packet + 2,
                            s->packet_length - 2, s, s->msg_callback_arg);

        p = s->packet;
        p += 5;
        n2s(p, csl);
        n2s(p, sil);
        n2s(p, cl);
        d = (unsigned char *)s->init_buf->data;
        if ((csl + sil + cl + 11) != s->packet_length) { /* We can't have TLS
                                                          * extensions in SSL
                                                          * 2.0 format *
                                                          * Client Hello, can
                                                          * we? Error
                                                          * condition should
                                                          * be * '>'
                                                          * otherweise */
            SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
                   SSL_R_RECORD_LENGTH_MISMATCH);
            goto err;
        }

        /* record header: msg_type ... */
        *(d++) = SSL3_MT_CLIENT_HELLO;
        /* ... and length (actual value will be written later) */
        d_len = d;
        d += 3;

        /* client_version */
        *(d++) = SSL3_VERSION_MAJOR; /* == v[0] */
        *(d++) = v[1];

        /* lets populate the random area */
        /* get the challenge_length */
        i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
        memset(d, 0, SSL3_RANDOM_SIZE);
        memcpy(&(d[SSL3_RANDOM_SIZE - i]), &(p[csl + sil]), i);
        d += SSL3_RANDOM_SIZE;

        /* no session-id reuse */
        *(d++) = 0;

        /* ciphers */
        j = 0;
        dd = d;
        d += 2;
        for (i = 0; i < csl; i += 3) {
            if (p[i] != 0)
                continue;
            *(d++) = p[i + 1];
            *(d++) = p[i + 2];
            j += 2;
        }
        s2n(j, dd);

        /* COMPRESSION */
        *(d++) = 1;
        *(d++) = 0;

#if 0
        /* copy any remaining data with may be extensions */
        p = p + csl + sil + cl;
        while (p < s->packet + s->packet_length) {
            *(d++) = *(p++);
        }
#endif

        i = (d - (unsigned char *)s->init_buf->data) - 4;
        l2n3((long)i, d_len);

        /* get the data reused from the init_buf */
        s->s3->tmp.reuse_message = 1;
        s->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO;
        s->s3->tmp.message_size = i;
    }

    /* imaginary new state (for program structure): */
    /* s->state = SSL23_SR_CLNT_HELLO_C */

    if (type == 1) {
#ifdef OPENSSL_NO_SSL2
        SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_UNSUPPORTED_PROTOCOL);
        goto err;
#else
        /* we are talking sslv2 */
        /*
         * we need to clean up the SSLv3/TLSv1 setup and put in the sslv2
         * stuff.
         */

        if (s->s2 == NULL) {
            if (!ssl2_new(s))
                goto err;
        } else
            ssl2_clear(s);

        if (s->s3 != NULL)
            ssl3_free(s);

        if (!BUF_MEM_grow_clean(s->init_buf,
                                SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) {
            goto err;
        }

        s->state = SSL2_ST_GET_CLIENT_HELLO_A;
        if (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3)
            s->s2->ssl2_rollback = 0;
        else
            /*
             * reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0
             * (SSL 3.0 draft/RFC 2246, App. E.2)
             */
            s->s2->ssl2_rollback = 1;

        /*
         * setup the n bytes we have read so we get them from the sslv2
         * buffer
         */
        s->rstate = SSL_ST_READ_HEADER;
        s->packet_length = n;
        s->packet = &(s->s2->rbuf[0]);
        memcpy(s->packet, buf, n);
        s->s2->rbuf_left = n;
        s->s2->rbuf_offs = 0;

        s->method = SSLv2_server_method();
        s->handshake_func = s->method->ssl_accept;
#endif
    }

    if ((type == 2) || (type == 3)) {
        /*
         * we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style)
         */
        const SSL_METHOD *new_method;
        new_method = ssl23_get_server_method(s->version);
        if (new_method == NULL) {
            SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_UNSUPPORTED_PROTOCOL);
            goto err;
        }
        s->method = new_method;

        if (!ssl_init_wbio_buffer(s, 1))
            goto err;

        /* we are in this state */
        s->state = SSL3_ST_SR_CLNT_HELLO_A;

        if (type == 3) {
            /*
             * put the 'n' bytes we have read into the input buffer for SSLv3
             */
            s->rstate = SSL_ST_READ_HEADER;
            s->packet_length = n;
            if (s->s3->rbuf.buf == NULL)
                if (!ssl3_setup_read_buffer(s))
                    goto err;

            s->packet = &(s->s3->rbuf.buf[0]);
            memcpy(s->packet, buf, n);
            s->s3->rbuf.left = n;
            s->s3->rbuf.offset = 0;
        } else {
            s->packet_length = 0;
            s->s3->rbuf.left = 0;
            s->s3->rbuf.offset = 0;
        }
#if 0                           /* ssl3_get_client_hello does this */
        s->client_version = (v[0] << 8) | v[1];
#endif
        s->handshake_func = s->method->ssl_accept;
    }

    if ((type < 1) || (type > 3)) {
        /* bad, very bad */
        SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
        goto err;
    }
    s->init_num = 0;

    if (buf != buf_space)
        OPENSSL_free(buf);
    return (SSL_accept(s));
 err:
    if (buf != buf_space)
        OPENSSL_free(buf);
    return (-1);
}
Пример #17
0
int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
				const unsigned char *limit, SSL_SESSION **ret)
	{
	/* Point after session ID in client hello */
	const unsigned char *p = session_id + len;
	unsigned short i;

	/* If tickets disabled behave as if no ticket present
 	 * to permit stateful resumption.
 	 */
	if (SSL_get_options(s) & SSL_OP_NO_TICKET)
		return 1;

	if ((s->version <= SSL3_VERSION) || !limit)
		return 1;
	if (p >= limit)
		return -1;
	/* Skip past DTLS cookie */
	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
		{
		i = *(p++);
		p+= i;
		if (p >= limit)
			return -1;
		}
	/* Skip past cipher list */
	n2s(p, i);
	p+= i;
	if (p >= limit)
		return -1;
	/* Skip past compression algorithm list */
	i = *(p++);
	p += i;
	if (p > limit)
		return -1;
	/* Now at start of extensions */
	if ((p + 2) >= limit)
		return 1;
	n2s(p, i);
	while ((p + 4) <= limit)
		{
		unsigned short type, size;
		n2s(p, type);
		n2s(p, size);
		if (p + size > limit)
			return 1;
		if (type == TLSEXT_TYPE_session_ticket)
			{
			/* If zero length note client will accept a ticket
 			 * and indicate cache miss to trigger full handshake
 			 */
			if (size == 0)
				{
				s->tlsext_ticket_expected = 1;
				return 0;	/* Cache miss */
				}
			return tls_decrypt_ticket(s, p, size, session_id, len,
									ret);
			}
		p += size;
		}
	return 1;
	}
Пример #18
0
/*-
 * Return up to 'len' payload bytes received in 'type' records.
 * 'type' is one of the following:
 *
 *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
 *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
 *   -  0 (during a shutdown, no data has to be returned)
 *
 * If we don't have stored data to work from, read a SSL/TLS record first
 * (possibly multiple records if we still don't have anything to return).
 *
 * This function must handle any surprises the peer may have for us, such as
 * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
 * messages are treated as if they were handshake messages *if* the |recd_type|
 * argument is non NULL.
 * Also if record payloads contain fragments too small to process, we store
 * them until there is enough for the respective protocol (the record protocol
 * may use arbitrary fragmentation and even interleaving):
 *     Change cipher spec protocol
 *             just 1 byte needed, no need for keeping anything stored
 *     Alert protocol
 *             2 bytes needed (AlertLevel, AlertDescription)
 *     Handshake protocol
 *             4 bytes needed (HandshakeType, uint24 length) -- we just have
 *             to detect unexpected Client Hello and Hello Request messages
 *             here, anything else is handled by higher layers
 *     Application data protocol
 *             none of our business
 */
int dtls1_read_bytes(SSL *s, int type, int *recvd_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 (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
        /* 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)))
        return ret;

    /*
     * Now s->rlayer.d->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 ((!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) ||
        (BIO_dgram_is_sctp(SSL_get_rbio(s))
         && ossl_statem_in_sctp_read_sock(s)
         && s->s3->in_read_app_data != 2))
#else
    if (!ossl_statem_get_in_handshake(s) && 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->rlayer.rrec;

    /*
     * We are not handshaking and have no data yet, so process data buffered
     * during the last handshake in advance, if any.
     */
    if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) {
        pitem *item;
        item = pqueue_pop(s->rlayer.d->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 ((SSL3_RECORD_get_length(rr) == 0)
            || (s->rlayer.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;
        }
    }

    /* 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 */
        && (SSL3_RECORD_get_type(rr) != 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->rlayer.d->buffered_app_data),
            SSL3_RECORD_get_seq_num(rr)) < 0) {
            SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
            return -1;
        }
        SSL3_RECORD_set_length(rr, 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) {
        SSL3_RECORD_set_length(rr, 0);
        s->rwstate = SSL_NOTHING;
        return (0);
    }

    if (type == SSL3_RECORD_get_type(rr)
            || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
                && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
        /*
         * SSL3_RT_APPLICATION_DATA or
         * SSL3_RT_HANDSHAKE or
         * SSL3_RT_CHANGE_CIPHER_SPEC
         */
        /*
         * 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 (recvd_type != NULL)
            *recvd_type = SSL3_RECORD_get_type(rr);

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

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

        memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
        if (!peek) {
            SSL3_RECORD_sub_length(rr, n);
            SSL3_RECORD_add_off(rr, n);
            if (SSL3_RECORD_get_length(rr) == 0) {
                s->rlayer.rstate = SSL_ST_READ_HEADER;
                SSL3_RECORD_set_off(rr, 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)) &&
            SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA &&
            ossl_statem_in_sctp_read_sock(s)) {
            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 (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
            dest_maxlen = sizeof s->rlayer.d->handshake_fragment;
            dest = s->rlayer.d->handshake_fragment;
            dest_len = &s->rlayer.d->handshake_fragment_len;
        } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
            dest_maxlen = sizeof(s->rlayer.d->alert_fragment);
            dest = s->rlayer.d->alert_fragment;
            dest_len = &s->rlayer.d->alert_fragment_len;
        }
#ifndef OPENSSL_NO_HEARTBEATS
        else if (SSL3_RECORD_get_type(rr) == DTLS1_RT_HEARTBEAT) {
            /* We allow a 0 return */
            if (dtls1_process_heartbeat(s, SSL3_RECORD_get_data(rr),
                    SSL3_RECORD_get_length(rr)) < 0) {
                return -1;
            }
            /* Exit and notify application to read again */
            SSL3_RECORD_set_length(rr, 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 (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) {
            /*
             * Application data while renegotiating is allowed. Try again
             * reading.
             */
            if (SSL3_RECORD_get_type(rr)  == 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 pathological case, the Client Hello may be
             * fragmented--don't always expect dest_maxlen bytes
             */
            if (SSL3_RECORD_get_length(rr)  < 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->rlayer.rstate = SSL_ST_READ_HEADER;
                SSL3_RECORD_set_length(rr, 0);
                goto start;
            }

            /* now move 'n' bytes: */
            for (k = 0; k < dest_maxlen; k++) {
                dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
                SSL3_RECORD_add_off(rr, 1);
                SSL3_RECORD_add_length(rr, -1);
            }
            *dest_len = dest_maxlen;
        }
    }

    /*-
     * s->rlayer.d->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
     * s->rlayer.d->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->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
        (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
        (s->session != NULL) && (s->session->cipher != NULL)) {
        s->rlayer.d->handshake_fragment_len = 0;

        if ((s->rlayer.d->handshake_fragment[1] != 0) ||
            (s->rlayer.d->handshake_fragment[2] != 0) ||
            (s->rlayer.d->handshake_fragment[3] != 0)) {
            al = SSL_AD_DECODE_ERROR;
            SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
            goto f_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->rlayer.d->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 (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 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->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
        int alert_level = s->rlayer.d->alert_fragment[0];
        int alert_descr = s->rlayer.d->alert_fragment[1];

        s->rlayer.d->alert_fragment_len = 0;

        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_ALERT,
                            s->rlayer.d->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 == SSL3_AL_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->rlayer.d->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 == SSL3_AL_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;
        SSL3_RECORD_set_length(rr, 0);
        return (0);
    }

    if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
        /*
         * We can't process a CCS now, because previous handshake messages
         * are still missing, so just drop it.
         */
        SSL3_RECORD_set_length(rr, 0);
        goto start;
    }

    /*
     * Unexpected handshake message (Client Hello, or protocol violation)
     */
    if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
        !ossl_statem_get_in_handshake(s)) {
        struct hm_header_st msg_hdr;

        /* this may just be a stale retransmit */
        dtls1_get_message_header(rr->data, &msg_hdr);
        if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) {
            SSL3_RECORD_set_length(rr, 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);
            SSL3_RECORD_set_length(rr, 0);
            goto start;
        }

        if (SSL_is_init_finished(s) &&
            !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
            ossl_statem_set_in_init(s, 1);
            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 (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 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 (SSL3_RECORD_get_type(rr)) {
    default:
        /* TLS just ignores unknown message types */
        if (s->version == TLS1_VERSION) {
            SSL3_RECORD_set_length(rr, 0);
            goto start;
        }
        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 ossl_statem_get_in_handshake(s) is true, 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) &&
            ossl_statem_app_data_allowed(s)) {
            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);
    return (-1);
}
Пример #19
0
int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
{
    unsigned char *pl;
    unsigned short hbtype;
    unsigned int payload;
    unsigned int padding = 16;  /* Use minimum padding */

    if (s->msg_callback)
        s->msg_callback(0, s->version, DTLS1_RT_HEARTBEAT,
                        p, length, s, s->msg_callback_arg);

    /* Read type and payload length */
    if (HEARTBEAT_SIZE_STD(0) > length)
        return 0;               /* silently discard */
    if (length > SSL3_RT_MAX_PLAIN_LENGTH)
        return 0;               /* silently discard per RFC 6520 sec. 4 */

    hbtype = *p++;
    n2s(p, payload);
    if (HEARTBEAT_SIZE_STD(payload) > length)
        return 0;               /* silently discard per RFC 6520 sec. 4 */
    pl = p;

    if (hbtype == TLS1_HB_REQUEST) {
        unsigned char *buffer, *bp;
        unsigned int write_length = HEARTBEAT_SIZE(payload, padding);
        int r;

        if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
            return 0;

        /* Allocate memory for the response. */
        buffer = OPENSSL_malloc(write_length);
        if (buffer == NULL)
            return -1;
        bp = buffer;

        /* Enter response type, length and copy payload */
        *bp++ = TLS1_HB_RESPONSE;
        s2n(payload, bp);
        memcpy(bp, pl, payload);
        bp += payload;
        /* Random padding */
        if (RAND_bytes(bp, padding) <= 0) {
            OPENSSL_free(buffer);
            return -1;
        }

        r = dtls1_write_bytes(s, DTLS1_RT_HEARTBEAT, buffer, write_length);

        if (r >= 0 && s->msg_callback)
            s->msg_callback(1, s->version, DTLS1_RT_HEARTBEAT,
                            buffer, write_length, s, s->msg_callback_arg);

        OPENSSL_free(buffer);

        if (r < 0)
            return r;
    } else if (hbtype == TLS1_HB_RESPONSE) {
        unsigned int seq;

        /*
         * We only send sequence numbers (2 bytes unsigned int), and 16
         * random bytes, so we just try to read the sequence number
         */
        n2s(pl, seq);

        if (payload == 18 && seq == s->tlsext_hb_seq) {
            dtls1_stop_timer(s);
            s->tlsext_hb_seq++;
            s->tlsext_hb_pending = 0;
        }
    }

    return 0;
}