s3_srvr.c

来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 1,755 行 · 第 1/3 页

C
1,755
字号
		SSL3_MT_CLIENT_HELLO,		SSL3_RT_MAX_PLAIN_LENGTH,		&ok);	if (!ok) return((int)n);	d=p=(unsigned char *)s->init_buf->data;	/* use version from inside client hello, not from record header	 * (may differ: see RFC 2246, Appendix E, second paragraph) */	s->client_version=(((int)p[0])<<8)|(int)p[1];	p+=2;	/* load the client random */	memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);	p+=SSL3_RANDOM_SIZE;	/* get the session-id */	j= *(p++);	s->hit=0;	if (j == 0)		{		if (!ssl_get_new_session(s,1))			goto err;		}	else		{		i=ssl_get_prev_session(s,p,j);		if (i == 1)			{ /* previous session */			s->hit=1;			}		else if (i == -1)			goto err;		else /* i == 0 */			{			if (!ssl_get_new_session(s,1))				goto err;			}		}	p+=j;	n2s(p,i);	if ((i == 0) && (j != 0))		{		/* we need a cipher if we are not resuming a session */		al=SSL_AD_ILLEGAL_PARAMETER;		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED);		goto f_err;		}	if ((i+p) > (d+n))		{		/* not enough data */		al=SSL_AD_DECODE_ERROR;		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);		goto f_err;		}	if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers))		== NULL))		{		goto err;		}	p+=i;	/* If it is a hit, check that the cipher is in the list */	if ((s->hit) && (i > 0))		{		j=0;		id=s->session->cipher->id;#ifdef CIPHER_DEBUG		printf("client sent %d ciphers\n",sk_num(ciphers));#endif		for (i=0; i<sk_SSL_CIPHER_num(ciphers); i++)			{			c=sk_SSL_CIPHER_value(ciphers,i);#ifdef CIPHER_DEBUG			printf("client [%2d of %2d]:%s\n",				i,sk_num(ciphers),SSL_CIPHER_get_name(c));#endif			if (c->id == id)				{				j=1;				break;				}			}		if (j == 0)			{			if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))				{				/* Very bad for multi-threading.... */				s->session->cipher=sk_SSL_CIPHER_value(ciphers,								       0);				}			else				{				/* we need to have the cipher in the cipher				 * list if we are asked to reuse it */				al=SSL_AD_ILLEGAL_PARAMETER;				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);				goto f_err;				}			}		}	/* compression */	i= *(p++);	q=p;	for (j=0; j<i; j++)		{		if (p[j] == 0) break;		}	p+=i;	if (j >= i)		{		/* no compress */		al=SSL_AD_DECODE_ERROR;		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);		goto f_err;		}	/* Worst case, we will use the NULL compression, but if we have other	 * options, we will now look for them.  We have i-1 compression	 * algorithms from the client, starting at q. */	s->s3->tmp.new_compression=NULL;	if (s->ctx->comp_methods != NULL)		{ /* See if we have a match */		int m,nn,o,v,done=0;		nn=sk_SSL_COMP_num(s->ctx->comp_methods);		for (m=0; m<nn; m++)			{			comp=sk_SSL_COMP_value(s->ctx->comp_methods,m);			v=comp->id;			for (o=0; o<i; o++)				{				if (v == q[o])					{					done=1;					break;					}				}			if (done) break;			}		if (done)			s->s3->tmp.new_compression=comp;		else			comp=NULL;		}	/* TLS does not mind if there is extra stuff */	if (s->version == SSL3_VERSION)		{		if (p > (d+n))			{			/* wrong number of bytes,			 * there could be more to follow */			al=SSL_AD_DECODE_ERROR;			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);			goto f_err;			}		}	/* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must	 * pick a cipher */	if (!s->hit)		{		s->session->compress_meth=(comp == NULL)?0:comp->id;		if (s->session->ciphers != NULL)			sk_SSL_CIPHER_free(s->session->ciphers);		s->session->ciphers=ciphers;		if (ciphers == NULL)			{			al=SSL_AD_ILLEGAL_PARAMETER;			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED);			goto f_err;			}		ciphers=NULL;		c=ssl3_choose_cipher(s,s->session->ciphers,				     ssl_get_ciphers_by_id(s));		if (c == NULL)			{			al=SSL_AD_HANDSHAKE_FAILURE;			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);			goto f_err;			}		s->s3->tmp.new_cipher=c;		}	else		{		/* Session-id reuse */#ifdef REUSE_CIPHER_BUG		STACK_OF(SSL_CIPHER) *sk;		SSL_CIPHER *nc=NULL;		SSL_CIPHER *ec=NULL;		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)			{			sk=s->session->ciphers;			for (i=0; i<sk_SSL_CIPHER_num(sk); i++)				{				c=sk_SSL_CIPHER_value(sk,i);				if (c->algorithms & SSL_eNULL)					nc=c;				if (SSL_C_IS_EXPORT(c))					ec=c;				}			if (nc != NULL)				s->s3->tmp.new_cipher=nc;			else if (ec != NULL)				s->s3->tmp.new_cipher=ec;			else				s->s3->tmp.new_cipher=s->session->cipher;			}		else#endif		s->s3->tmp.new_cipher=s->session->cipher;		}		/* we now have the following setup. 	 * client_random	 * cipher_list 		- our prefered list of ciphers	 * ciphers 		- the clients prefered list of ciphers	 * compression		- basically ignored right now	 * ssl version is set	- sslv3	 * s->session		- The ssl session has been setup.	 * s->hit		- session reuse flag	 * s->tmp.new_cipher	- the new cipher to use.	 */	ret=1;	if (0)		{f_err:		ssl3_send_alert(s,SSL3_AL_FATAL,al);		}err:	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);	return(ret);	}static int ssl3_send_server_hello(SSL *s)	{	unsigned char *buf;	unsigned char *p,*d;	int i,sl;	unsigned long l,Time;	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)		{		buf=(unsigned char *)s->init_buf->data;		p=s->s3->server_random;		Time=time(NULL);			/* Time */		l2n(Time,p);		RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));		/* Do the message type and length last */		d=p= &(buf[4]);		*(p++)=s->version>>8;		*(p++)=s->version&0xff;		/* Random stuff */		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);		p+=SSL3_RANDOM_SIZE;		/* now in theory we have 3 options to sending back the		 * session id.  If it is a re-use, we send back the		 * old session-id, if it is a new session, we send		 * back the new session-id or we send back a 0 length		 * session-id if we want it to be single use.		 * Currently I will not implement the '0' length session-id		 * 12-Jan-98 - I'll now support the '0' length stuff.		 */		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER))			s->session->session_id_length=0;		sl=s->session->session_id_length;		*(p++)=sl;		memcpy(p,s->session->session_id,sl);		p+=sl;		/* put the cipher */		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);		p+=i;		/* put the compression method */		if (s->s3->tmp.new_compression == NULL)			*(p++)=0;		else			*(p++)=s->s3->tmp.new_compression->id;		/* do the header */		l=(p-d);		d=buf;		*(d++)=SSL3_MT_SERVER_HELLO;		l2n3(l,d);		s->state=SSL3_ST_CW_CLNT_HELLO_B;		/* number of bytes to write */		s->init_num=p-buf;		s->init_off=0;		}	/* SSL3_ST_CW_CLNT_HELLO_B */	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));	}static int ssl3_send_server_done(SSL *s)	{	unsigned char *p;	if (s->state == SSL3_ST_SW_SRVR_DONE_A)		{		p=(unsigned char *)s->init_buf->data;		/* do the header */		*(p++)=SSL3_MT_SERVER_DONE;		*(p++)=0;		*(p++)=0;		*(p++)=0;		s->state=SSL3_ST_SW_SRVR_DONE_B;		/* number of bytes to write */		s->init_num=4;		s->init_off=0;		}	/* SSL3_ST_CW_CLNT_HELLO_B */	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));	}static int ssl3_send_server_key_exchange(SSL *s)	{#ifndef NO_RSA	unsigned char *q;	int j,num;	RSA *rsa;	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];	unsigned int u;#endif#ifndef NO_DH	DH *dh=NULL,*dhp;#endif	EVP_PKEY *pkey;	unsigned char *p,*d;	int al,i;	unsigned long type;	int n;	CERT *cert;	BIGNUM *r[4];	int nr[4],kn;	BUF_MEM *buf;	EVP_MD_CTX md_ctx;	if (s->state == SSL3_ST_SW_KEY_EXCH_A)		{		type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK;		cert=s->cert;		buf=s->init_buf;		r[0]=r[1]=r[2]=r[3]=NULL;		n=0;#ifndef NO_RSA		if (type & SSL_kRSA)			{			rsa=cert->rsa_tmp;			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))				{				rsa=s->cert->rsa_tmp_cb(s,				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));				if(rsa == NULL)				{					al=SSL_AD_HANDSHAKE_FAILURE;					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);					goto f_err;				}				CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);				cert->rsa_tmp=rsa;				}			if (rsa == NULL)				{				al=SSL_AD_HANDSHAKE_FAILURE;				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);				goto f_err;				}			r[0]=rsa->n;			r[1]=rsa->e;			s->s3->tmp.use_rsa_tmp=1;			}		else#endif#ifndef NO_DH			if (type & SSL_kEDH)			{			dhp=cert->dh_tmp;			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))				dhp=s->cert->dh_tmp_cb(s,				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));			if (dhp == NULL)				{				al=SSL_AD_HANDSHAKE_FAILURE;				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);				goto f_err;				}			if (s->s3->tmp.dh != NULL)				{				DH_free(dh);				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, SSL_R_INTERNAL_ERROR);				goto err;				}			if ((dh=DHparams_dup(dhp)) == NULL)				{				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);				goto err;				}			s->s3->tmp.dh=dh;			if ((dhp->pub_key == NULL ||			     dhp->priv_key == NULL ||			     (s->options & SSL_OP_SINGLE_DH_USE)))				{				if(!DH_generate_key(dh))				    {				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,					   ERR_R_DH_LIB);				    goto err;				    }				}			else				{				dh->pub_key=BN_dup(dhp->pub_key);				dh->priv_key=BN_dup(dhp->priv_key);				if ((dh->pub_key == NULL) ||					(dh->priv_key == NULL))					{					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);					goto err;					}				}			r[0]=dh->p;			r[1]=dh->g;			r[2]=dh->pub_key;			}		else #endif			{			al=SSL_AD_HANDSHAKE_FAILURE;			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);			goto f_err;			}		for (i=0; r[i] != NULL; i++)			{			nr[i]=BN_num_bytes(r[i]);			n+=2+nr[i];			}		if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))			{			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))				== NULL)				{				al=SSL_AD_DECODE_ERROR;				goto f_err;				}			kn=EVP_PKEY_size(pkey);			}		else			{			pkey=NULL;			kn=0;			}		if (!BUF_MEM_grow(buf,n+4+kn))			{			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);			goto err;			}		d=(unsigned char *)s->init_buf->data;		p= &(d[4]);		for (i=0; r[i] != NULL; i++)			{			s2n(nr[i],p);			BN_bn2bin(r[i],p);			p+=nr[i];			}		/* not anonymous */		if (pkey != NULL)			{			/* n is the length of the params, they start at &(d[4])			 * and p points to the space at the end. */#ifndef NO_RSA			if (pkey->type == EVP_PKEY_RSA)				{				q=md_buf;				j=0;				for (num=2; num > 0; num--)					{					EVP_DigestInit(&md_ctx,(num == 2)						?s->ctx->md5:s->ctx->sha1);					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);					EVP_DigestUpdate(&md_ctx,&(d[4]),n);					EVP_DigestFinal(&md_ctx,q,						(unsigned int *)&i);					q+=i;					j+=i;					}				if (RSA_sign(NID_md5_sha1, md_buf, j,					&(p[2]), &u, pkey->pkey.rsa) <= 0)					{					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);					goto err;					}				s2n(u,p);				n+=u+2;				}			else#endif#if !defined(NO_DSA)				if (pkey->type == EVP_PKEY_DSA)				{				/* lets do DSS */				EVP_SignInit(&md_ctx,EVP_dss1());				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);				EVP_SignUpdate(&md_ctx,&(d[4]),n);				if (!EVP_SignFinal(&md_ctx,&(p[2]),					(unsigned int *)&i,pkey))					{					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);					goto err;					}				s2n(i,p);				n+=i+2;				}			else#endif				{				/* Is this error check actually needed? */				al=SSL_AD_HANDSHAKE_FAILURE;				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);				goto f_err;				}			}		*(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;		l2n3(n,d);		/* we should now have things packed up, so lets send		 * it off */		s->init_num=n+4;		s->init_off=0;		}	s->state = SSL3_ST_SW_KEY_EXCH_B;	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));f_err:	ssl3_send_alert(s,SSL3_AL_FATAL,al);err:	return(-1);	}static int ssl3_send_certificate_request(SSL *s)	{	unsigned char *p,*d;	int i,j,nl,off,n;	STACK_OF(X509_NAME) *sk=NULL;	X509_NAME *name;	BUF_MEM *buf;	if (s->state == SSL3_ST_SW_CERT_REQ_A)		{		buf=s->init_buf;		d=p=(unsigned char *)&(buf->data[4]);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?