static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st *msg_hdr, int *ok)
    {
    int i;
    unsigned char *p;

    /* make sure there's enough room to read this fragment */
    if ( (int)msg_hdr->frag_len && !BUF_MEM_grow_clean(s->init_buf, 
             (int)msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH + s->init_num))
        {
        SSLerr(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE,ERR_R_BUF_LIB);
        goto err;
        }

    p = (unsigned char *)s->init_buf->data;

    /* read the body of the fragment (header has already been read */
    if ( msg_hdr->frag_len > 0)
		{
		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
            &p[s->init_num], 
            msg_hdr->frag_len,0);
		if (i <= 0)
			{
			*ok = 0;
			return i;
			}
		}

    if ( msg_hdr->seq > s->d1->handshake_read_seq)
        dtls1_buffer_handshake_fragment(s, msg_hdr);
    else
        OPENSSL_assert(msg_hdr->seq < s->d1->handshake_read_seq);

    return DTLS1_HM_FRAGMENT_RETRY;
err:
    *ok = 0;
    return -1;
    }
Example #2
0
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
    BUF_MEM *b;
    unsigned char *p;
    int i;
    size_t want = HEADER_SIZE;
    int eos = 0;
    size_t off = 0;
    size_t len = 0;

    const unsigned char *q;
    long slen;
    int inf, tag, xclass;

    b = BUF_MEM_new();
    if (b == NULL) {
        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
        return -1;
    }

    ERR_clear_error();
    for (;;) {
        if (want >= (len - off)) {
            want -= (len - off);

            if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            i = BIO_read(in, &(b->data[len]), want);
            if ((i < 0) && ((len - off) == 0)) {
                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA);
                goto err;
            }
            if (i > 0) {
                if (len + i < len) {
                    ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
                    goto err;
                }
                len += i;
            }
        }
        /* else data already loaded */

        p = (unsigned char *)&(b->data[off]);
        q = p;
        inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
        if (inf & 0x80) {
            unsigned long e;

            e = ERR_GET_REASON(ERR_peek_error());
            if (e != ASN1_R_TOO_LONG)
                goto err;
            else
                ERR_clear_error(); /* clear error */
        }
        i = q - p;            /* header length */
        off += i;               /* end of data */

        if (inf & 1) {
            /* no data body so go round again */
            eos++;
            if (eos < 0) {
                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
                goto err;
            }
            want = HEADER_SIZE;
        } else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) {
            /* eos value, so go back and read another header */
            eos--;
            if (eos <= 0)
                break;
            else
                want = HEADER_SIZE;
        } else {
            /* suck in slen bytes of data */
            want = slen;
            if (want > (len - off)) {
                size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;

                want -= (len - off);
                if (want > INT_MAX /* BIO_read takes an int length */  ||
                    len + want < len) {
                    ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
                    goto err;
                }
                while (want > 0) {
                    /*
                     * Read content in chunks of increasing size
                     * so we can return an error for EOF without
                     * having to allocate the entire content length
                     * in one go.
                     */
                    size_t chunk = want > chunk_max ? chunk_max : want;

                    if (!BUF_MEM_grow_clean(b, len + chunk)) {
                        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
                        goto err;
                    }
                    want -= chunk;
                    while (chunk > 0) {
                        i = BIO_read(in, &(b->data[len]), chunk);
                        if (i <= 0) {
                            ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
                                    ASN1_R_NOT_ENOUGH_DATA);
                            goto err;
                        }
                    /*
                     * This can't overflow because |len+want| didn't
                     * overflow.
                     */
                        len += i;
                        chunk -= i;
                    }
                    if (chunk_max < INT_MAX/2)
                        chunk_max *= 2;
                }
            }
            if (off + slen < off) {
                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
                goto err;
            }
            off += slen;
            if (eos <= 0) {
                break;
            } else
                want = HEADER_SIZE;
        }
    }

    if (off > INT_MAX) {
        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
        goto err;
    }

    *pb = b;
    return off;
 err:
    BUF_MEM_free(b);
    return -1;
}
Example #3
0
TXT_DB *TXT_DB_read(BIO *in, int num)
{
    TXT_DB *ret = NULL;
    int er = 1;
    int esc = 0;
    long ln = 0;
    int i, add, n;
    int size = BUFSIZE;
    int offset = 0;
    char *p, **pp, *f;
    BUF_MEM *buf = NULL;

    if ((buf = BUF_MEM_new()) == NULL)
        goto err;
    if (!BUF_MEM_grow(buf, size))
        goto err;

    if ((ret = (TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL)
        goto err;
    ret->num_fields = num;
    ret->index = NULL;
    ret->qual = NULL;
    if ((ret->data = sk_new_null()) == NULL)
        goto err;
    if ((ret->index =
         (LHASH **)OPENSSL_malloc(sizeof(LHASH *) * num)) == NULL)
        goto err;
    if ((ret->qual =
         (int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **)) *
                                           num)) == NULL)
        goto err;
    for (i = 0; i < num; i++) {
        ret->index[i] = NULL;
        ret->qual[i] = NULL;
    }

    add = (num + 1) * sizeof(char *);
    buf->data[size - 1] = '\0';
    offset = 0;
    for (;;) {
        if (offset != 0) {
            size += BUFSIZE;
            if (!BUF_MEM_grow_clean(buf, size))
                goto err;
        }
        buf->data[offset] = '\0';
        BIO_gets(in, &(buf->data[offset]), size - offset);
        ln++;
        if (buf->data[offset] == '\0')
            break;
        if ((offset == 0) && (buf->data[0] == '#'))
            continue;
        i = strlen(&(buf->data[offset]));
        offset += i;
        if (buf->data[offset - 1] != '\n')
            continue;
        else {
            buf->data[offset - 1] = '\0'; /* blat the '\n' */
            if (!(p = (char *)OPENSSL_malloc(add + offset)))
                goto err;
            offset = 0;
        }
        pp = (char **)p;
        p += add;
        n = 0;
        pp[n++] = p;
        i = 0;
        f = buf->data;

        esc = 0;
        for (;;) {
            if (*f == '\0')
                break;
            if (*f == '\t') {
                if (esc)
                    p--;
                else {
                    *(p++) = '\0';
                    f++;
                    if (n >= num)
                        break;
                    pp[n++] = p;
                    continue;
                }
            }
            esc = (*f == '\\');
            *(p++) = *(f++);
        }
        *(p++) = '\0';
        if ((n != num) || (*f != '\0')) {
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty
                                                               * fix :-( */
            fprintf(stderr,
                    "wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",
                    ln, num, n, f);
#endif
            er = 2;
            goto err;
        }
        pp[n] = p;
        if (!sk_push(ret->data, (char *)pp)) {
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty
                                                               * fix :-( */
            fprintf(stderr, "failure in sk_push\n");
#endif
            er = 2;
            goto err;
        }
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
	{
	int ret=0;
	int i,j;
	BIO *btmp;
	BUF_MEM *buf_mem=NULL;
	BUF_MEM *buf=NULL;
	PKCS7_SIGNER_INFO *si;
	EVP_MD_CTX *mdc,ctx_tmp;
	STACK_OF(X509_ATTRIBUTE) *sk;
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
	ASN1_OCTET_STRING *os=NULL;

	EVP_MD_CTX_init(&ctx_tmp);
	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signedAndEnveloped:
		/* XXXXXXXXXXXXXXXX */
		si_sk=p7->d.signed_and_enveloped->signer_info;
		if (!(os=M_ASN1_OCTET_STRING_new()))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
		if (!(os=M_ASN1_OCTET_STRING_new()))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		p7->d.enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_signed:
		si_sk=p7->d.sign->signer_info;
		os=PKCS7_get_octet_string(p7->d.sign->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
			M_ASN1_OCTET_STRING_free(os);
			p7->d.sign->contents->d.data = NULL;
		}
		break;

	case NID_pkcs7_digest:
		os=PKCS7_get_octet_string(p7->d.digest->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
			{
			M_ASN1_OCTET_STRING_free(os);
			p7->d.digest->contents->d.data = NULL;
			}
		break;

		}

	if (si_sk != NULL)
		{
		if ((buf=BUF_MEM_new()) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
			goto err;
			}
		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
			{
			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
			if (si->pkey == NULL) continue;

			j=OBJ_obj2nid(si->digest_alg->algorithm);

			btmp=bio;

			btmp = PKCS7_find_digest(&mdc, btmp, j);

			if (btmp == NULL)
				goto err;

			/* We now have the EVP_MD_CTX, lets do the
			 * signing. */
			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
				goto err;
				}

			sk=si->auth_attr;

			/* If there are attributes, we add the digest
			 * attribute and only sign the attributes */
			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
				{
				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
				unsigned int md_len, alen;
				ASN1_OCTET_STRING *digest;
				ASN1_UTCTIME *sign_time;
				const EVP_MD *md_tmp;

				/* Add signing time if not already present */
				if (!PKCS7_get_signed_attribute(si,
							NID_pkcs9_signingTime))
					{
					if (!(sign_time=X509_gmtime_adj(NULL,0)))
						{
						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
							ERR_R_MALLOC_FAILURE);
						goto err;
						}
					PKCS7_add_signed_attribute(si,
						NID_pkcs9_signingTime,
						V_ASN1_UTCTIME,sign_time);
					}

				/* Add digest */
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
				if (!(digest=M_ASN1_OCTET_STRING_new()))
					{
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
						ERR_R_MALLOC_FAILURE);
					goto err;
					}
				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
								md_len))
					{
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
						ERR_R_MALLOC_FAILURE);
					goto err;
					}
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_messageDigest,
					V_ASN1_OCTET_STRING,digest);

				/* Now sign the attributes */
				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
				if(!abuf) goto err;
				EVP_SignUpdate(&ctx_tmp,abuf,alen);
				OPENSSL_free(abuf);
				}

#ifndef OPENSSL_NO_DSA
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();
#endif
#ifndef OPENSSL_NO_ECDSA
 			if (si->pkey->type == EVP_PKEY_EC)
 				ctx_tmp.digest=EVP_ecdsa();
#endif

			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
				(unsigned int *)&buf->length,si->pkey))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
				goto err;
				}
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
				goto err;
				}
			}
		}
	else if (i == NID_pkcs7_digest)
		{
		unsigned char md_data[EVP_MAX_MD_SIZE];
		unsigned int md_len;
		if (!PKCS7_find_digest(&mdc, bio,
				OBJ_obj2nid(p7->d.digest->md->algorithm)))
			goto err;
		EVP_DigestFinal_ex(mdc,md_data,&md_len);
		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
		}

	if (!PKCS7_is_detached(p7))
		{
		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
		if (btmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
			goto err;
			}
		BIO_get_mem_ptr(btmp,&buf_mem);
		/* Mark the BIO read only then we can use its copy of the data
		 * instead of making an extra copy.
		 */
		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
		BIO_set_mem_eof_return(btmp, 0);
		os->data = (unsigned char *)buf_mem->data;
		os->length = buf_mem->length;
#if 0
		M_ASN1_OCTET_STRING_set(os,
			(unsigned char *)buf_mem->data,buf_mem->length);
#endif
		}
	ret=1;
err:
	EVP_MD_CTX_cleanup(&ctx_tmp);
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}
Example #5
0
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
	{
	BUF_MEM *b;
	unsigned char *p;
	int i;
	int ret=-1;
	ASN1_const_CTX c;
	int want=HEADER_SIZE;
	int eos=0;
#if defined(__GNUC__) && defined(__ia64)
	/* pathetic compiler bug in all known versions as of Nov. 2002 */
	long off=0;
#else
	int off=0;
#endif
	int len=0;

	b=BUF_MEM_new();
	if (b == NULL)
		{
		ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
		return -1;
		}

	ERR_clear_error();
	for (;;)
		{
		if (want >= (len-off))
			{
			want-=(len-off);

			if (!BUF_MEM_grow_clean(b,len+want))
				{
				ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
				goto err;
				}
			i=BIO_read(in,&(b->data[len]),want);
			if ((i < 0) && ((len-off) == 0))
				{
				ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_NOT_ENOUGH_DATA);
				goto err;
				}
			if (i > 0)
				len+=i;
			}
		/* else data already loaded */

		p=(unsigned char *)&(b->data[off]);
		c.p=p;
		c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
			len-off);
		if (c.inf & 0x80)
			{
			unsigned long e;

			e=ERR_GET_REASON(ERR_peek_error());
			if (e != ASN1_R_TOO_LONG)
				goto err;
			else
				ERR_clear_error(); /* clear error */
			}
		i=(int)(c.p-p);/* header length */
		off+=i;	/* end of data */

		if (c.inf & 1)
			{
			/* no data body so go round again */
			eos++;
			want=HEADER_SIZE;
			}
		else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
			{
			/* eos value, so go back and read another header */
			eos--;
			if (eos <= 0)
				break;
			else
				want=HEADER_SIZE;
			}
		else 
			{
			/* suck in c.slen bytes of data */
			want=(int)c.slen;
			if (want > (len-off))
				{
				want-=(len-off);
				if (!BUF_MEM_grow_clean(b,len+want))
					{
					ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
					goto err;
					}
				while (want > 0)
					{
					i=BIO_read(in,&(b->data[len]),want);
					if (i <= 0)
						{
						ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
						    ASN1_R_NOT_ENOUGH_DATA);
						goto err;
						}
					len+=i;
					want -= i;
					}
				}
			off+=(int)c.slen;
			if (eos <= 0)
				{
				break;
				}
			else
				want=HEADER_SIZE;
			}
		}

	*pb = b;
	return off;
err:
	if (b != NULL) BUF_MEM_free(b);
	return(ret);
	}
Example #6
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
				}
			/* 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....
			 */
			else 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 (!(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;
			}
		}

#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];

/* The SSL2 protocol allows n to be larger, just pick
 * a reasonable buffer size. */
#if SSL3_RT_DEFAULT_PACKET_SIZE < 1024*4 - SSL3_RT_DEFAULT_WRITE_OVERHEAD
#error "SSL3_RT_DEFAULT_PACKET_SIZE is too small."
#endif
		n=((p[0]&0x7f)<<8)|p[1];
		if (n > SSL3_RT_DEFAULT_PACKET_SIZE - 2)
			{
			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);
	return(SSL_accept(s));
err:
	if (buf != buf_space) OPENSSL_free(buf);
	return(-1);
	}
Example #7
0
static int str_copy(CONF *conf, char *section, char **pto, char *from)
{
    int q, r, rr = 0, to = 0, len = 0;
    char *s, *e, *rp, *p, *rrp, *np, *cp, v;
    BUF_MEM *buf;

    if ((buf = BUF_MEM_new()) == NULL)
        return 0;

    len = strlen(from) + 1;
    if (!BUF_MEM_grow(buf, len))
        goto err;

    for (;;) {
        if (IS_QUOTE(conf, *from)) {
            q = *from;
            from++;
            while (!IS_EOF(conf, *from) && (*from != q)) {
                if (IS_ESC(conf, *from)) {
                    from++;
                    if (IS_EOF(conf, *from))
                        break;
                }
                buf->data[to++] = *(from++);
            }
            if (*from == q)
                from++;
        } else if (IS_DQUOTE(conf, *from)) {
            q = *from;
            from++;
            while (!IS_EOF(conf, *from)) {
                if (*from == q) {
                    if (*(from + 1) == q) {
                        from++;
                    } else {
                        break;
                    }
                }
                buf->data[to++] = *(from++);
            }
            if (*from == q)
                from++;
        } else if (IS_ESC(conf, *from)) {
            from++;
            v = *(from++);
            if (IS_EOF(conf, v))
                break;
            else if (v == 'r')
                v = '\r';
            else if (v == 'n')
                v = '\n';
            else if (v == 'b')
                v = '\b';
            else if (v == 't')
                v = '\t';
            buf->data[to++] = v;
        } else if (IS_EOF(conf, *from))
            break;
        else if (*from == '$') {
            size_t newsize;

            /* try to expand it */
            rrp = NULL;
            s = &(from[1]);
            if (*s == '{')
                q = '}';
            else if (*s == '(')
                q = ')';
            else
                q = 0;

            if (q)
                s++;
            cp = section;
            e = np = s;
            while (IS_ALNUM(conf, *e))
                e++;
            if ((e[0] == ':') && (e[1] == ':')) {
                cp = np;
                rrp = e;
                rr = *e;
                *rrp = '\0';
                e += 2;
                np = e;
                while (IS_ALNUM(conf, *e))
                    e++;
            }
            r = *e;
            *e = '\0';
            rp = e;
            if (q) {
                if (r != q) {
                    CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE);
                    goto err;
                }
                e++;
            }
            /*-
             * So at this point we have
             * np which is the start of the name string which is
             *   '\0' terminated.
             * cp which is the start of the section string which is
             *   '\0' terminated.
             * e is the 'next point after'.
             * r and rr are the chars replaced by the '\0'
             * rp and rrp is where 'r' and 'rr' came from.
             */
            p = _CONF_get_string(conf, cp, np);
            if (rrp != NULL)
                *rrp = rr;
            *rp = r;
            if (p == NULL) {
                CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE);
                goto err;
            }
            newsize = strlen(p) + buf->length - (e - from);
            if (newsize > MAX_CONF_VALUE_LENGTH) {
                CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
                goto err;
            }
            if (!BUF_MEM_grow_clean(buf, newsize)) {
                CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            while (*p)
                buf->data[to++] = *(p++);

            /*
             * Since we change the pointer 'from', we also have to change the
             * perceived length of the string it points at.  /RL
             */
            len -= e - from;
            from = e;

            /*
             * In case there were no braces or parenthesis around the
             * variable reference, we have to put back the character that was
             * replaced with a '\0'.  /RL
             */
            *rp = r;
        } else
            buf->data[to++] = *(from++);
    }
    buf->data[to] = '\0';
    OPENSSL_free(*pto);
    *pto = buf->data;
    OPENSSL_free(buf);
    return 1;
 err:
    BUF_MEM_free(buf);
    return 0;
}
Example #8
0
int tls_get_message_header(SSL *s, int *mt)
{
    /* s->init_num < SSL3_HM_HEADER_LENGTH */
    int skip_message, i, recvd_type, al;
    unsigned char *p;
    unsigned long l;

    p = (unsigned char *)s->init_buf->data;

    do {
        while (s->init_num < SSL3_HM_HEADER_LENGTH) {
            i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
                &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0);
            if (i <= 0) {
                s->rwstate = SSL_READING;
                return 0;
            }
            if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
                s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
                s->init_num = i - 1;
                s->s3->tmp.message_size = i;
                return 1;
            } else if (recvd_type != SSL3_RT_HANDSHAKE) {
                al = SSL_AD_UNEXPECTED_MESSAGE;
                SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY);
                goto f_err;
            }
            s->init_num += i;
        }

        skip_message = 0;
        if (!s->server)
            if (p[0] == SSL3_MT_HELLO_REQUEST)
                /*
                 * The server may always send 'Hello Request' messages --
                 * we are doing a handshake anyway now, so ignore them if
                 * their format is correct. Does not count for 'Finished'
                 * MAC.
                 */
                if (p[1] == 0 && p[2] == 0 && p[3] == 0) {
                    s->init_num = 0;
                    skip_message = 1;

                    if (s->msg_callback)
                        s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
                                        p, SSL3_HM_HEADER_LENGTH, s,
                                        s->msg_callback_arg);
                }
    } while (skip_message);
    /* s->init_num == SSL3_HM_HEADER_LENGTH */

    *mt = *p;
    s->s3->tmp.message_type = *(p++);

    if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
        /*
         * Only happens with SSLv3+ in an SSLv2 backward compatible
         * ClientHello
         */
         /*
          * Total message size is the remaining record bytes to read
          * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
          */
        l = RECORD_LAYER_get_rrec_length(&s->rlayer)
            + SSL3_HM_HEADER_LENGTH;
        if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) {
            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
            goto err;
        }
        s->s3->tmp.message_size = l;

        s->init_msg = s->init_buf->data;
        s->init_num = SSL3_HM_HEADER_LENGTH;
    } else {
        n2l3(p, l);
        /* BUF_MEM_grow takes an 'int' parameter */
        if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
            al = SSL_AD_ILLEGAL_PARAMETER;
            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
            goto f_err;
        }
        if (l && !BUF_MEM_grow_clean(s->init_buf,
                                    (int)l + SSL3_HM_HEADER_LENGTH)) {
            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
            goto err;
        }
        s->s3->tmp.message_size = l;

        s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
        s->init_num = 0;
    }

    return 1;
 f_err:
    ssl3_send_alert(s, SSL3_AL_FATAL, al);
 err:
    return 0;
}
Example #9
0
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
				const unsigned char **in, long inlen, 
				const ASN1_ITEM *it,
				int tag, int aclass, char opt, ASN1_TLC *ctx)
	{
	int ret = 0, utype;
	long plen;
	char cst, inf, free_cont = 0;
	const unsigned char *p;
	BUF_MEM buf;
	const unsigned char *cont = NULL;
	long len; 
	if (!pval)
		{
		ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL);
		return 0; /* Should never happen */
		}

	if (it->itype == ASN1_ITYPE_MSTRING)
		{
		utype = tag;
		tag = -1;
		}
	else
		utype = it->utype;

	if (utype == V_ASN1_ANY)
		{
		/* If type is ANY need to figure out type from tag */
		unsigned char oclass;
		if (tag >= 0)
			{
			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
					ASN1_R_ILLEGAL_TAGGED_ANY);
			return 0;
			}
		if (opt)
			{
			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
					ASN1_R_ILLEGAL_OPTIONAL_ANY);
			return 0;
			}
		p = *in;
		ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
					&p, inlen, -1, 0, 0, ctx);
		if (!ret)
			{
			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
					ERR_R_NESTED_ASN1_ERROR);
			return 0;
			}
		if (oclass != V_ASN1_UNIVERSAL)
			utype = V_ASN1_OTHER;
		}
	if (tag == -1)
		{
		tag = utype;
		aclass = V_ASN1_UNIVERSAL;
		}
	p = *in;
	/* Check header */
	ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
				&p, inlen, tag, aclass, opt, ctx);
	if (!ret)
		{
		ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
		return 0;
		}
	else if (ret == -1)
		return -1;
        ret = 0;
	/* SEQUENCE, SET and "OTHER" are left in encoded form */
	if ((utype == V_ASN1_SEQUENCE)
		|| (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER))
		{
		/* Clear context cache for type OTHER because the auto clear
		 * when we have a exact match wont work
		 */
		if (utype == V_ASN1_OTHER)
			{
			asn1_tlc_clear(ctx);
			}
		/* SEQUENCE and SET must be constructed */
		else if (!cst)
			{
			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
				ASN1_R_TYPE_NOT_CONSTRUCTED);
			return 0;
			}

		cont = *in;
		/* If indefinite length constructed find the real end */
		if (inf)
			{
			if (!asn1_find_end(&p, plen, inf))
				 goto err;
			len = p - cont;
			}
		else
			{
			len = p - cont + plen;
			p += plen;
			buf.data = NULL;
			}
		}
	else if (cst)
		{
		buf.length = 0;
		buf.max = 0;
		buf.data = NULL;
		/* Should really check the internal tags are correct but
		 * some things may get this wrong. The relevant specs
		 * say that constructed string types should be OCTET STRINGs
		 * internally irrespective of the type. So instead just check
		 * for UNIVERSAL class and ignore the tag.
		 */
		if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
			{
			free_cont = 1;
			goto err;
			}
		len = buf.length;
		/* Append a final null to string */
		if (!BUF_MEM_grow_clean(&buf, len + 1))
			{
			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
						ERR_R_MALLOC_FAILURE);
			return 0;
			}
		buf.data[len] = 0;
		cont = (const unsigned char *)buf.data;
		free_cont = 1;
		}
	else
		{
		cont = p;
		len = plen;
		p += plen;
		}

	/* We now have content length and type: translate into a structure */
	if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
		goto err;

	*in = p;
	ret = 1;
	err:
	if (free_cont && buf.data) OPENSSL_free(buf.data);
	return ret;
	}
unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)
	{
	unsigned char *p;
	int n,i;
	unsigned long l=7;
	BUF_MEM *buf;
	X509_STORE_CTX xs_ctx;
	X509_OBJECT obj;

	int no_chain;

	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
		no_chain = 1;
	else
		no_chain = 0;

	/* TLSv1 sends a chain with nothing in it, instead of an alert */
	buf=s->init_buf;
	if (!BUF_MEM_grow_clean(buf,10))
		{
		SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
		return(0);
		}
	if (x != NULL)
		{
		if(!no_chain && !X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL))
			{
			SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
			return(0);
			}

		for (;;)
			{
			n=i2d_X509(x,NULL);
			if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
				{
				SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
				return(0);
				}
			p=(unsigned char *)&(buf->data[l]);
			l2n3(n,p);
			i2d_X509(x,&p);
			l+=n+3;

			if (no_chain)
				break;

			if (X509_NAME_cmp(X509_get_subject_name(x),
				X509_get_issuer_name(x)) == 0) break;

			i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509,
				X509_get_issuer_name(x),&obj);
			if (i <= 0) break;
			x=obj.data.x509;
			/* Count is one too high since the X509_STORE_get uped the
			 * ref count */
			X509_free(x);
			}
		if (!no_chain)
			X509_STORE_CTX_cleanup(&xs_ctx);
		}

	/* Thawte special :-) */
	if (s->ctx->extra_certs != NULL)
	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
		{
		x=sk_X509_value(s->ctx->extra_certs,i);
		n=i2d_X509(x,NULL);
		if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
			{
			SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
			return(0);
			}
		p=(unsigned char *)&(buf->data[l]);
		l2n3(n,p);
		i2d_X509(x,&p);
		l+=n+3;
		}

	l-=7;
	p=(unsigned char *)&(buf->data[4]);
	l2n3(l,p);
	l+=3;
	p=(unsigned char *)&(buf->data[0]);
	*(p++)=SSL3_MT_CERTIFICATE;
	l2n3(l,p);
	l+=4;
	return(l);
	}
Example #11
0
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
	{
	unsigned char *p;
	int n,i;
	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH;
	BUF_MEM *buf;
	X509_STORE_CTX xs_ctx;
	X509_OBJECT obj;

	/* TLSv1 sends a chain with nothing in it, instead of an alert */
	buf=s->init_buf;
	if (!BUF_MEM_grow_clean(buf,10))
		{
		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
		return(0);
		}
	if (x != NULL)
		{
		if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL))
			{
			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
			return(0);
			}

		for (;;)
			{
			n=i2d_X509(x,NULL);
			if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
				{
				SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
				return(0);
				}
			p=(unsigned char *)&(buf->data[l]);
			l2n3(n,p);
			i2d_X509(x,&p);
			l+=n+3;
			if (X509_NAME_cmp(X509_get_subject_name(x),
				X509_get_issuer_name(x)) == 0) break;

			i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509,
				X509_get_issuer_name(x),&obj);
			if (i <= 0) break;
			x=obj.data.x509;
			/* Count is one too high since the X509_STORE_get uped the
			 * ref count */
			X509_free(x);
			}

		X509_STORE_CTX_cleanup(&xs_ctx);
		}

	/* Thawte special :-) */
	if (s->ctx->extra_certs != NULL)
	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
		{
		x=sk_X509_value(s->ctx->extra_certs,i);
		n=i2d_X509(x,NULL);
		if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
			{
			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
			return(0);
			}
		p=(unsigned char *)&(buf->data[l]);
		l2n3(n,p);
		i2d_X509(x,&p);
		l+=n+3;
		}

	l-= (3 + DTLS1_HM_HEADER_LENGTH);

	p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
	l2n3(l,p);
	l+=3;
	p=(unsigned char *)&(buf->data[0]);
	p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l);

	l+=DTLS1_HM_HEADER_LENGTH;
	return(l);
	}
Example #12
0
/* Obtain handshake message of message type 'mt' (any if mt == -1),
 * maximum acceptable body length 'max'.
 * The first four bytes (msg_type and length) are read in state 'st1',
 * the body is read in state 'stn'.
 */
long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
{
    uint8_t *p;
    uint32_t l;
    long n;
    int i, al;
    CBS cbs;
    uint8_t message_type;

    if (s->s3->tmp.reuse_message) {
        s->s3->tmp.reuse_message = 0;
        if ((mt >= 0) && (s->s3->tmp.message_type != mt)) {
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
            goto f_err;
        }
        *ok = 1;
        s->state = stn;
        s->init_msg = s->init_buf->data + 4;
        s->init_num = (int)s->s3->tmp.message_size;
        return s->init_num;
    }

    p = (uint8_t *)s->init_buf->data;

    if (s->state == st1) /* s->init_num < 4 */
    {
        int skip_message;

        do {
            while (s->init_num < 4) {
                i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num],
                                              4 - s->init_num, 0);
                if (i <= 0) {
                    s->rwstate = SSL_READING;
                    *ok = 0;
                    return i;
                }
                s->init_num += i;
            }

            skip_message = 0;
            if (!s->server && p[0] == SSL3_MT_HELLO_REQUEST) {
                /*
                 * The server may always send 'Hello Request'
                 * messages -- we are doing a handshake anyway
                 * now, so ignore them if their format is
                 * correct.  Does not count for 'Finished' MAC.
                 */
                if (p[1] == 0 && p[2] == 0 && p[3] == 0) {
                    s->init_num = 0;
                    skip_message = 1;

                    if (s->msg_callback)
                        s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s,
                                        s->msg_callback_arg);
                }
            }
        } while (skip_message);

        /* s->init_num == 4 */

        if ((mt >= 0) && (*p != mt)) {
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
            goto f_err;
        }

        /* XXX remove call to n2l3 */
        CBS_init(&cbs, p, 4);
        if (!CBS_get_u8(&cbs, &message_type) ||
            !CBS_get_u24(&cbs, &l)) {
            SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB);
            goto err;
        }
        s->s3->tmp.message_type = message_type;

        if (l > (unsigned long)max) {
            al = SSL_AD_ILLEGAL_PARAMETER;
            SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
            goto f_err;
        }
        if (l && !BUF_MEM_grow_clean(s->init_buf, l + 4)) {
            SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB);
            goto err;
        }
        s->s3->tmp.message_size = l;
        s->state = stn;

        s->init_msg = s->init_buf->data + 4;
        s->init_num = 0;
    }

    /* next state (stn) */
    p = s->init_msg;
    n = s->s3->tmp.message_size - s->init_num;
    while (n > 0) {
        i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num], n, 0);
        if (i <= 0) {
            s->rwstate = SSL_READING;
            *ok = 0;
            return i;
        }
        s->init_num += i;
        n -= i;
    }

    /* If receiving Finished, record MAC of prior handshake messages for
     * Finished verification. */
    if (*s->init_buf->data == SSL3_MT_FINISHED)
        ssl3_take_mac(s);

    /* Feed this message into MAC computation. */
    tls1_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num + 4);
    if (s->msg_callback)
        s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
                        (size_t)s->init_num + 4, s, s->msg_callback_arg);
    *ok = 1;
    return s->init_num;
f_err:
    ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
    *ok = 0;
    return (-1);
}
Example #13
0
/* There have been a few bug fixes for this function from
 * Paul Keogh <*****@*****.**>, many thanks to him */
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
	{
	ASN1_STRING *os=NULL;
	BUF_MEM b;
	int num;

	b.length=0;
	b.max=0;
	b.data=NULL;

	if (a == NULL)
		{
		c->error=ERR_R_PASSED_NULL_PARAMETER;
		goto err;
		}

	num=0;
	for (;;)
		{
		if (c->inf & 1)
			{
			c->eos=ASN1_const_check_infinite_end(&c->p,
				(long)(c->max-c->p));
			if (c->eos) break;
			}
		else
			{
			if (c->slen <= 0) break;
			}

		c->q=c->p;
		if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
			== NULL)
			{
			c->error=ERR_R_ASN1_LIB;
			goto err;
			}

		if (!BUF_MEM_grow_clean(&b,num+os->length))
			{
			c->error=ERR_R_BUF_LIB;
			goto err;
			}
		memcpy(&(b.data[num]),os->data,os->length);
		if (!(c->inf & 1))
			c->slen-=(c->p-c->q);
		num+=os->length;
		}

	if (!asn1_const_Finish(c)) goto err;

	a->length=num;
	if (a->data != NULL) OPENSSL_free(a->data);
	a->data=(unsigned char *)b.data;
	if (os != NULL) ASN1_STRING_free(os);
	return(1);
err:
	OPENSSL_PUT_ERROR(ASN1, asn1_collate_primitive, c->error);
	if (os != NULL) ASN1_STRING_free(os);
	if (b.data != NULL) OPENSSL_free(b.data);
	return(0);
	}
static long
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
	{
	unsigned char *p;
	unsigned long l, frag_off, frag_len;
	int i,al;
	struct hm_header_st msg_hdr;
    unsigned long overlap;
    
    /* see if we have the required fragment already */
    if (dtls1_retrieve_buffered_fragment(s, &l))
    {
        /* compute MAC, remove fragment headers */
        dtls1_process_handshake_fragment(s, l);
        s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
        s->state = stn;
        return 1;
    }

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

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

	OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);

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

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

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

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

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

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

    s->init_num += i;

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

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

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

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

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

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

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

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

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

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

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

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

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

    dtls1_process_handshake_fragment(s, frag_len - overlap);

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

	return s->init_num;

f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
    s->init_num = 0;
err:
	*ok=0;
	return(-1);
	}
Example #15
0
static int
asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
	BUF_MEM *b;
	unsigned char *p;
	int i;
	ASN1_const_CTX c;
	size_t want = HEADER_SIZE;
	int eos = 0;
	size_t off = 0;
	size_t len = 0;

	b = BUF_MEM_new();
	if (b == NULL) {
		ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
		return -1;
	}

	ERR_clear_error();
	for (;;) {
		if (want >= (len - off)) {
			want -= (len - off);

			if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
				ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
				goto err;
			}
			i = BIO_read(in, &(b->data[len]), want);
			if ((i < 0) && ((len - off) == 0)) {
				ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA);
				goto err;
			}
			if (i > 0) {
				if (len + i < len) {
					ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
					goto err;
				}
				len += i;
			}
		}
		/* else data already loaded */

		p = (unsigned char *) & (b->data[off]);
		c.p = p;
		c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag),
		    &(c.xclass), len - off);
		if (c.inf & 0x80) {
			unsigned long e;

			e = ERR_GET_REASON(ERR_peek_error());
			if (e != ASN1_R_TOO_LONG)
				goto err;
			else
				ERR_clear_error(); /* clear error */
		}
		i = c.p - p;	/* header length */
		off += i;	/* end of data */

		if (c.inf & 1) {
			/* no data body so go round again */
			eos++;
			if (eos < 0) {
				ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
				goto err;
			}
			want = HEADER_SIZE;
		} else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) {
			/* eos value, so go back and read another header */
			eos--;
			if (eos <= 0)
				break;
			else
				want = HEADER_SIZE;
		} else {
			/* suck in c.slen bytes of data */
			want = c.slen;
			if (want > (len - off)) {
				want -= (len - off);
				if (want > INT_MAX /* BIO_read takes an int length */ ||
				    len+want < len) {
					ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
					goto err;
				}
				if (!BUF_MEM_grow_clean(b, len + want)) {
					ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
					goto err;
				}
				while (want > 0) {
					i = BIO_read(in, &(b->data[len]), want);
					if (i <= 0) {
						ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
						    ASN1_R_NOT_ENOUGH_DATA);
						goto err;
					}
					/* This can't overflow because
					 * |len+want| didn't overflow. */
					len += i;
					want -= i;
				}
			}
			if (off + c.slen < off) {
				ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
				goto err;
			}
			off += c.slen;
			if (eos <= 0) {
				break;
			} else
				want = HEADER_SIZE;
		}
	}

	if (off > INT_MAX) {
		ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
		goto err;
	}

	*pb = b;
	return off;

err:
	if (b != NULL)
		BUF_MEM_free(b);
	return -1;
}
Example #16
0
/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1),
 * maximum acceptable body length |max|. The first four bytes (msg_type and
 * length) are read in state |header_state|, the body is read in state
 * |body_state|. */
long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type,
                      long max, enum ssl_hash_message_t hash_message, int *ok) {
  uint8_t *p;
  unsigned long l;
  long n;
  int al;

  if (ssl->s3->tmp.reuse_message) {
    /* A ssl_dont_hash_message call cannot be combined with reuse_message; the
     * ssl_dont_hash_message would have to have been applied to the previous
     * call. */
    assert(hash_message == ssl_hash_message);
    ssl->s3->tmp.reuse_message = 0;
    if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
      al = SSL_AD_UNEXPECTED_MESSAGE;
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
      goto f_err;
    }
    *ok = 1;
    ssl->state = body_state;
    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
    ssl->init_num = (int)ssl->s3->tmp.message_size;
    return ssl->init_num;
  }

  p = (uint8_t *)ssl->init_buf->data;

  if (ssl->state == header_state) {
    assert(ssl->init_num < 4);

    for (;;) {
      while (ssl->init_num < 4) {
        int bytes_read = ssl3_read_bytes(
            ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], 4 - ssl->init_num, 0);
        if (bytes_read <= 0) {
          *ok = 0;
          return bytes_read;
        }
        ssl->init_num += bytes_read;
      }

      static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
      if (ssl->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) {
        break;
      }

      /* The server may always send 'Hello Request' messages -- we are doing
       * a handshake anyway now, so ignore them if their format is correct.
       * Does not count for 'Finished' MAC. */
      ssl->init_num = 0;

      if (ssl->msg_callback) {
        ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, p, 4, ssl,
                        ssl->msg_callback_arg);
      }
    }

    /* ssl->init_num == 4 */

    if (msg_type >= 0 && *p != msg_type) {
      al = SSL_AD_UNEXPECTED_MESSAGE;
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
      goto f_err;
    }
    ssl->s3->tmp.message_type = *(p++);

    n2l3(p, l);
    if (l > (unsigned long)max) {
      al = SSL_AD_ILLEGAL_PARAMETER;
      OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
      goto f_err;
    }

    if (l && !BUF_MEM_grow_clean(ssl->init_buf, l + 4)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
      goto err;
    }
    ssl->s3->tmp.message_size = l;
    ssl->state = body_state;

    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
    ssl->init_num = 0;
  }

  /* next state (body_state) */
  p = ssl->init_msg;
  n = ssl->s3->tmp.message_size - ssl->init_num;
  while (n > 0) {
    int bytes_read =
        ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], n, 0);
    if (bytes_read <= 0) {
      ssl->rwstate = SSL_READING;
      *ok = 0;
      return bytes_read;
    }
    ssl->init_num += bytes_read;
    n -= bytes_read;
  }

  /* Feed this message into MAC computation. */
  if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
    goto err;
  }
  if (ssl->msg_callback) {
    ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
                    (size_t)ssl->init_num + 4, ssl, ssl->msg_callback_arg);
  }
  *ok = 1;
  return ssl->init_num;

f_err:
  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);

err:
  *ok = 0;
  return -1;
}
Example #17
0
/* Obtain handshake message of message type 'mt' (any if mt == -1),
 * maximum acceptable body length 'max'.
 * The first four bytes (msg_type and length) are read in state 'st1',
 * the body is read in state 'stn'.
 */
long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
	{
	unsigned char *p;
	unsigned long l;
	long n;
	int i,al;

	if (s->s3->tmp.reuse_message)
		{
		s->s3->tmp.reuse_message=0;
		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		*ok=1;
		s->init_msg = s->init_buf->data + 4;
		s->init_num = (int)s->s3->tmp.message_size;
		return s->init_num;
		}

	p=(unsigned char *)s->init_buf->data;

	if (s->state == st1) /* s->init_num < 4 */
		{
		int skip_message;

		do
			{
			while (s->init_num < 4)
				{
				i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
					&p[s->init_num],4 - s->init_num, 0);
				if (i <= 0)
					{
					s->rwstate=SSL_READING;
					*ok = 0;
					return i;
					}
				s->init_num+=i;
				}
			
			skip_message = 0;
			if (!s->server)
				if (p[0] == SSL3_MT_HELLO_REQUEST)
					/* The server may always send 'Hello Request' messages --
					 * we are doing a handshake anyway now, so ignore them
					 * if their format is correct. Does not count for
					 * 'Finished' MAC. */
					if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
						{
						s->init_num = 0;
						skip_message = 1;

						if (s->msg_callback)
							s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg);
						}
			}
		while (skip_message);

		/* s->init_num == 4 */

		if ((mt >= 0) && (*p != mt))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
			goto f_err;
			}
		if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) &&
					(st1 == SSL3_ST_SR_CERT_A) &&
					(stn == SSL3_ST_SR_CERT_B))
			{
			/* At this point we have got an MS SGC second client
			 * hello (maybe we should always allow the client to
			 * start a new handshake?). We need to restart the mac.
			 * Don't increment {num,total}_renegotiations because
			 * we have not completed the handshake. */
			ssl3_init_finished_mac(s);
			}

		s->s3->tmp.message_type= *(p++);

		n2l3(p,l);
		if (l > (unsigned long)max)
			{
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE);
			goto f_err;
			}
		if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */
			{
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE);
			goto f_err;
			}
		if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l+4))
			{
			SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB);
			goto err;
			}
		s->s3->tmp.message_size=l;
		s->state=stn;

		s->init_msg = s->init_buf->data + 4;
		s->init_num = 0;
		}

	/* next state (stn) */
	p = s->init_msg;
	n = s->s3->tmp.message_size - s->init_num;
	while (n > 0)
		{
		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0);
		if (i <= 0)
			{
			s->rwstate=SSL_READING;
			*ok = 0;
			return i;
			}
		s->init_num += i;
		n -= i;
		}

#ifndef OPENSSL_NO_NEXTPROTONEG
	/* If receiving Finished, record MAC of prior handshake messages for
	 * Finished verification. */
	if (*s->init_buf->data == SSL3_MT_FINISHED)
		ssl3_take_mac(s);
#endif

	/* Feed this message into MAC computation. */
	ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4);
	if (s->msg_callback)
		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg);
	*ok=1;
	return s->init_num;
f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
	*ok=0;
	return(-1);
	}
Example #18
0
unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)
{
    unsigned char *p;
    int i;
    unsigned long l = 7;
    BUF_MEM *buf;
    int no_chain;

    if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
        no_chain = 1;
    else
        no_chain = 0;

    /* TLSv1 sends a chain with nothing in it, instead of an alert */
    buf = s->init_buf;
    if (!BUF_MEM_grow_clean(buf, 10)) {
        SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_BUF_LIB);
        return (0);
    }
    if (x != NULL) {
        if (no_chain) {
            if (ssl3_add_cert_to_buf(buf, &l, x))
                return (0);
        } else {
            X509_STORE_CTX xs_ctx;

            if (!X509_STORE_CTX_init(&xs_ctx, s->ctx->cert_store, x, NULL)) {
                SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_X509_LIB);
                return (0);
            }
            X509_verify_cert(&xs_ctx);
            /* Don't leave errors in the queue */
            ERR_clear_error();
            for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
                x = sk_X509_value(xs_ctx.chain, i);

                if (ssl3_add_cert_to_buf(buf, &l, x)) {
                    X509_STORE_CTX_cleanup(&xs_ctx);
                    return 0;
                }
            }
            X509_STORE_CTX_cleanup(&xs_ctx);
        }
    }
    /* Thawte special :-) */
    for (i = 0; i < sk_X509_num(s->ctx->extra_certs); i++) {
        x = sk_X509_value(s->ctx->extra_certs, i);
        if (ssl3_add_cert_to_buf(buf, &l, x))
            return (0);
    }

    l -= 7;
    p = (unsigned char *)&(buf->data[4]);
    l2n3(l, p);
    l += 3;
    p = (unsigned char *)&(buf->data[0]);
    *(p++) = SSL3_MT_CERTIFICATE;
    l2n3(l, p);
    l += 4;
    return (l);
}
Example #19
0
int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
       long *len)
  {
  EVP_ENCODE_CTX ctx;
  int end=0,i,k,bl=0,hl=0,nohead=0;
  char buf[256];
  BUF_MEM *nameB;
  BUF_MEM *headerB;
  BUF_MEM *dataB,*tmpB;
  
  nameB=BUF_MEM_new();
  headerB=BUF_MEM_new();
  dataB=BUF_MEM_new();
  if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
    {
    BUF_MEM_free(nameB);
    BUF_MEM_free(headerB);
    BUF_MEM_free(dataB);
    PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
    return(0);
    }

  buf[254]='\0';
  for (;;)
    {
    i=BIO_gets(bp,buf,254);

    if (i <= 0)
      {
      PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
      goto err;
      }

    while ((i >= 0) && (buf[i] <= ' ')) i--;
    buf[++i]='\n'; buf[++i]='\0';

    if (strncmp(buf,"-----BEGIN ",11) == 0)
      {
      i=strlen(&(buf[11]));

      if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
        continue;
      if (!BUF_MEM_grow(nameB,i+9))
        {
        PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
        goto err;
        }
      memcpy(nameB->data,&(buf[11]),i-6);
      nameB->data[i-6]='\0';
      break;
      }
    }
  hl=0;
  if (!BUF_MEM_grow(headerB,256))
    { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
  headerB->data[0]='\0';
  for (;;)
    {
    i=BIO_gets(bp,buf,254);
    if (i <= 0) break;

    while ((i >= 0) && (buf[i] <= ' ')) i--;
    buf[++i]='\n'; buf[++i]='\0';

    if (buf[0] == '\n') break;
    if (!BUF_MEM_grow(headerB,hl+i+9))
      { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
    if (strncmp(buf,"-----END ",9) == 0)
      {
      nohead=1;
      break;
      }
    memcpy(&(headerB->data[hl]),buf,i);
    headerB->data[hl+i]='\0';
    hl+=i;
    }

  bl=0;
  if (!BUF_MEM_grow(dataB,1024))
    { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
  dataB->data[0]='\0';
  if (!nohead)
    {
    for (;;)
      {
      i=BIO_gets(bp,buf,254);
      if (i <= 0) break;

      while ((i >= 0) && (buf[i] <= ' ')) i--;
      buf[++i]='\n'; buf[++i]='\0';

      if (i != 65) end=1;
      if (strncmp(buf,"-----END ",9) == 0)
        break;
      if (i > 65) break;
      if (!BUF_MEM_grow_clean(dataB,i+bl+9))
        {
        PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
        goto err;
        }
      memcpy(&(dataB->data[bl]),buf,i);
      dataB->data[bl+i]='\0';
      bl+=i;
      if (end)
        {
        buf[0]='\0';
        i=BIO_gets(bp,buf,254);
        if (i <= 0) break;

        while ((i >= 0) && (buf[i] <= ' ')) i--;
        buf[++i]='\n'; buf[++i]='\0';

        break;
        }
      }
    }
  else
    {
    tmpB=headerB;
    headerB=dataB;
    dataB=tmpB;
    bl=hl;
    }
  i=strlen(nameB->data);
  if (  (strncmp(buf,"-----END ",9) != 0) ||
    (strncmp(nameB->data,&(buf[9]),i) != 0) ||
    (strncmp(&(buf[9+i]),"-----\n",6) != 0))
    {
    PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
    goto err;
    }

  EVP_DecodeInit(&ctx);
  i=EVP_DecodeUpdate(&ctx,
    (unsigned char *)dataB->data,&bl,
    (unsigned char *)dataB->data,bl);
  if (i < 0)
    {
    PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
    goto err;
    }
  i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
  if (i < 0)
    {
    PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
    goto err;
    }
  bl+=k;

  if (bl == 0) goto err;
  *name=nameB->data;
  *header=headerB->data;
  *data=(unsigned char *)dataB->data;
  *len=bl;
  OPENSSL_free(nameB);
  OPENSSL_free(headerB);
  OPENSSL_free(dataB);
  return(1);
err:
  BUF_MEM_free(nameB);
  BUF_MEM_free(headerB);
  BUF_MEM_free(dataB);
  return(0);
  }
Example #20
0
/*
 * Obtain handshake message of message type 'mt' (any if mt == -1), maximum
 * acceptable body length 'max'. The first four bytes (msg_type and length)
 * are read in state 'st1', the body is read in state 'stn'.
 */
long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
{
    unsigned char *p;
    unsigned long l;
    long n;
    int i, al, recvd_type;

    if (s->s3->tmp.reuse_message) {
        s->s3->tmp.reuse_message = 0;
        if ((mt >= 0) && (s->s3->tmp.message_type != mt)) {
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
            goto f_err;
        }
        *ok = 1;
        s->state = stn;
        s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
        s->init_num = (int)s->s3->tmp.message_size;
        return s->init_num;
    }

    p = (unsigned char *)s->init_buf->data;

    if (s->state == st1) {
        /* s->init_num < SSL3_HM_HEADER_LENGTH */
        int skip_message;

        do {
            while (s->init_num < SSL3_HM_HEADER_LENGTH) {
                i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
                    &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0);
                if (i <= 0) {
                    s->rwstate = SSL_READING;
                    *ok = 0;
                    return i;
                }
                if (s->init_num == 0
                        && recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC
                        && (mt < 0 || mt == SSL3_MT_CHANGE_CIPHER_SPEC)) {
                    if (*p != SSL3_MT_CCS) {
                        al = SSL_AD_UNEXPECTED_MESSAGE;
                        SSLerr(SSL_F_SSL3_GET_MESSAGE,
                               SSL_R_UNEXPECTED_MESSAGE);
                        goto f_err;
                    }
                    s->init_num = i - 1;
                    s->init_msg = p + 1;
                    s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
                    s->s3->tmp.message_size = i - 1;
                    s->state = stn;
                    *ok = 1;
                    if (s->msg_callback)
                        s->msg_callback(0, s->version,
                                        SSL3_RT_CHANGE_CIPHER_SPEC, p, 1, s,
                                        s->msg_callback_arg);
                    return i - 1;
                } else if (recvd_type != SSL3_RT_HANDSHAKE) {
                    al = SSL_AD_UNEXPECTED_MESSAGE;
                    SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_CCS_RECEIVED_EARLY);
                    goto f_err;
                }
                s->init_num += i;
            }

            skip_message = 0;
            if (!s->server)
                if (p[0] == SSL3_MT_HELLO_REQUEST)
                    /*
                     * The server may always send 'Hello Request' messages --
                     * we are doing a handshake anyway now, so ignore them if
                     * their format is correct. Does not count for 'Finished'
                     * MAC.
                     */
                    if (p[1] == 0 && p[2] == 0 && p[3] == 0) {
                        s->init_num = 0;
                        skip_message = 1;

                        if (s->msg_callback)
                            s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
                                            p, SSL3_HM_HEADER_LENGTH, s,
                                            s->msg_callback_arg);
                    }
        } while (skip_message);
        /* s->init_num == SSL3_HM_HEADER_LENGTH */

        if ((mt >= 0) && (*p != mt)) {
            al = SSL_AD_UNEXPECTED_MESSAGE;
            SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
            goto f_err;
        }

        s->s3->tmp.message_type = *(p++);

        if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
            /*
             * Only happens with SSLv3+ in an SSLv2 backward compatible
             * ClientHello
             */
             /*
              * Total message size is the remaining record bytes to read
              * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
              */
            l = RECORD_LAYER_get_rrec_length(&s->rlayer)
                + SSL3_HM_HEADER_LENGTH;
            if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) {
                SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB);
                goto err;
            }
            s->s3->tmp.message_size = l;
            s->state = stn;

            s->init_msg = s->init_buf->data;
            s->init_num = SSL3_HM_HEADER_LENGTH;
        } else {
            n2l3(p, l);
            if (l > (unsigned long)max) {
                al = SSL_AD_ILLEGAL_PARAMETER;
                SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
                goto f_err;
            }
            /* BUF_MEM_grow takes an 'int' parameter */
            if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
                al = SSL_AD_ILLEGAL_PARAMETER;
                SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
                goto f_err;
            }
            if (l && !BUF_MEM_grow_clean(s->init_buf,
                                        (int)l + SSL3_HM_HEADER_LENGTH)) {
                SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB);
                goto err;
            }
            s->s3->tmp.message_size = l;
            s->state = stn;

            s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
            s->init_num = 0;
        }
    }

    /* next state (stn) */
    p = s->init_msg;
    n = s->s3->tmp.message_size - s->init_num;
    while (n > 0) {
        i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
                                      &p[s->init_num], n, 0);
        if (i <= 0) {
            s->rwstate = SSL_READING;
            *ok = 0;
            return i;
        }
        s->init_num += i;
        n -= i;
    }

#ifndef OPENSSL_NO_NEXTPROTONEG
    /*
     * If receiving Finished, record MAC of prior handshake messages for
     * Finished verification.
     */
    if (*s->init_buf->data == SSL3_MT_FINISHED)
        ssl3_take_mac(s);
#endif

    /* Feed this message into MAC computation. */
    if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
        ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num);
        if (s->msg_callback)
            s->msg_callback(0, SSL2_VERSION, 0,  s->init_buf->data,
                            (size_t)s->init_num, s, s->msg_callback_arg);
    } else {
        ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
            s->init_num + SSL3_HM_HEADER_LENGTH);
        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
                            (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
                            s->msg_callback_arg);
    }

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