s2_srvr.c

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

C
976
字号
			SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_INVALID_CHALLENGE_LENGTH);			return(-1);			}		s->state=SSL2_ST_GET_CLIENT_HELLO_C;		s->init_num=0;		}	/* SSL2_ST_GET_CLIENT_HELLO_C */	p=(unsigned char *)s->init_buf->data;	n=s->s2->tmp.cipher_spec_length+s->s2->challenge_length+		s->s2->tmp.session_id_length-s->init_num;	i=ssl2_read(s,(char *)&(p[s->init_num]),n);	if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i));	/* get session-id before cipher stuff so we can get out session	 * structure if it is cached */	/* session-id */	if ((s->s2->tmp.session_id_length != 0) && 		(s->s2->tmp.session_id_length != SSL2_SSL_SESSION_ID_LENGTH))		{		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);		SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_BAD_SSL_SESSION_ID_LENGTH);		return(-1);		}	if (s->s2->tmp.session_id_length == 0)		{		if (!ssl_get_new_session(s,1))			{			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);			return(-1);			}		}	else		{		i=ssl_get_prev_session(s,&(p[s->s2->tmp.cipher_spec_length]),			s->s2->tmp.session_id_length);		if (i == 1)			{ /* previous session */			s->hit=1;			}		else if (i == -1)			{			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);			return(-1);			}		else			{			if (s->cert == NULL)				{				ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE);				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_NO_CERTIFICATE_SET);				return(-1);				}			if (!ssl_get_new_session(s,1))				{				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);				return(-1);				}			}		}	if (!s->hit)		{		cs=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.cipher_spec_length,			&s->session->ciphers);		if (cs == NULL) goto mem_err;		cl=ssl_get_ciphers_by_id(s);		for (z=0; z<sk_SSL_CIPHER_num(cs); z++)			{			if (sk_SSL_CIPHER_find(cl,sk_SSL_CIPHER_value(cs,z)) < 0)				{				sk_SSL_CIPHER_delete(cs,z);				z--;				}			}		/* s->session->ciphers should now have a list of		 * ciphers that are on both the client and server.		 * This list is ordered by the order the client sent		 * the ciphers.		 */		}	p+=s->s2->tmp.cipher_spec_length;	/* done cipher selection */	/* session id extracted already */	p+=s->s2->tmp.session_id_length;	/* challenge */	memcpy(s->s2->challenge,p,(unsigned int)s->s2->challenge_length);	return(1);mem_err:	SSLerr(SSL_F_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE);	return(0);	}static int server_hello(SSL *s)	{	unsigned char *p,*d;	int n,hit;	STACK_OF(SSL_CIPHER) *sk;	p=(unsigned char *)s->init_buf->data;	if (s->state == SSL2_ST_SEND_SERVER_HELLO_A)		{		d=p+11;		*(p++)=SSL2_MT_SERVER_HELLO;		/* type */		hit=s->hit;		*(p++)=(unsigned char)hit;#if 1		if (!hit)			{			if (s->session->sess_cert != NULL)				/* This can't really happen because get_client_hello				 * has called ssl_get_new_session, which does not set				 * sess_cert. */				ssl_sess_cert_free(s->session->sess_cert);			s->session->sess_cert = ssl_sess_cert_new();			if (s->session->sess_cert == NULL)				{				SSLerr(SSL_F_SERVER_HELLO, ERR_R_MALLOC_FAILURE);				return(-1);				}			}		/* If 'hit' is set, then s->sess_cert may be non-NULL or NULL,		 * depending on whether it survived in the internal cache		 * or was retrieved from an external cache.		 * If it is NULL, we cannot put any useful data in it anyway,		 * so we don't touch it.		 */#else /* That's what used to be done when cert_st and sess_cert_st were	   * the same. */		if (!hit)			{			/* else add cert to session */			CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT);			if (s->session->sess_cert != NULL)				ssl_cert_free(s->session->sess_cert);			s->session->sess_cert=s->cert;					}		else	/* We have a session id-cache hit, if the			 * session-id has no certificate listed against			 * the 'cert' structure, grab the 'old' one			 * listed against the SSL connection */			{			if (s->session->sess_cert == NULL)				{				CRYPTO_add(&s->cert->references,1,					CRYPTO_LOCK_SSL_CERT);				s->session->sess_cert=s->cert;				}			}#endif		if (s->cert == NULL)			{			ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE);			SSLerr(SSL_F_SERVER_HELLO,SSL_R_NO_CERTIFICATE_SPECIFIED);			return(-1);			}		if (hit)			{			*(p++)=0;		/* no certificate type */			s2n(s->version,p);	/* version */			s2n(0,p);		/* cert len */			s2n(0,p);		/* ciphers len */			}		else			{			/* EAY EAY */			/* put certificate type */			*(p++)=SSL2_CT_X509_CERTIFICATE;			s2n(s->version,p);	/* version */			n=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);			s2n(n,p);		/* certificate length */			i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&d);			n=0;						/* lets send out the ciphers we like in the			 * prefered order */			sk= s->session->ciphers;			n=ssl_cipher_list_to_bytes(s,s->session->ciphers,d);			d+=n;			s2n(n,p);		/* add cipher length */			}		/* make and send conn_id */		s2n(SSL2_CONNECTION_ID_LENGTH,p);	/* add conn_id length */		s->s2->conn_id_length=SSL2_CONNECTION_ID_LENGTH;		RAND_pseudo_bytes(s->s2->conn_id,(int)s->s2->conn_id_length);		memcpy(d,s->s2->conn_id,SSL2_CONNECTION_ID_LENGTH);		d+=SSL2_CONNECTION_ID_LENGTH;		s->state=SSL2_ST_SEND_SERVER_HELLO_B;		s->init_num=d-(unsigned char *)s->init_buf->data;		s->init_off=0;		}	/* SSL2_ST_SEND_SERVER_HELLO_B */ 	/* If we are using TCP/IP, the performance is bad if we do 2 	 * writes without a read between them.  This occurs when 	 * Session-id reuse is used, so I will put in a buffering module 	 */ 	if (s->hit) 		{		if (!ssl_init_wbio_buffer(s,1)) return(-1); 		} 	return(ssl2_do_write(s));	}static int get_client_finished(SSL *s)	{	unsigned char *p;	int i;	p=(unsigned char *)s->init_buf->data;	if (s->state == SSL2_ST_GET_CLIENT_FINISHED_A)		{		i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num);		if (i < 1-s->init_num)			return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));		if (*p != SSL2_MT_CLIENT_FINISHED)			{			if (*p != SSL2_MT_ERROR)				{				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);				SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE);				}			else				SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_PEER_ERROR);			return(-1);			}		s->init_num=0;		s->state=SSL2_ST_GET_CLIENT_FINISHED_B;		}	/* SSL2_ST_GET_CLIENT_FINISHED_B */	i=ssl2_read(s,(char *)&(p[s->init_num]),s->s2->conn_id_length-s->init_num);	if (i < (int)s->s2->conn_id_length-s->init_num)		{		return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i));		}	if (memcmp(p,s->s2->conn_id,(unsigned int)s->s2->conn_id_length) != 0)		{		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);		SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_CONNECTION_ID_IS_DIFFERENT);		return(-1);		}	return(1);	}static int server_verify(SSL *s)	{	unsigned char *p;	if (s->state == SSL2_ST_SEND_SERVER_VERIFY_A)		{		p=(unsigned char *)s->init_buf->data;		*(p++)=SSL2_MT_SERVER_VERIFY;		memcpy(p,s->s2->challenge,(unsigned int)s->s2->challenge_length);		/* p+=s->s2->challenge_length; */		s->state=SSL2_ST_SEND_SERVER_VERIFY_B;		s->init_num=s->s2->challenge_length+1;		s->init_off=0;		}	return(ssl2_do_write(s));	}static int server_finish(SSL *s)	{	unsigned char *p;	if (s->state == SSL2_ST_SEND_SERVER_FINISHED_A)		{		p=(unsigned char *)s->init_buf->data;		*(p++)=SSL2_MT_SERVER_FINISHED;		memcpy(p,s->session->session_id,			(unsigned int)s->session->session_id_length);		/* p+=s->session->session_id_length; */		s->state=SSL2_ST_SEND_SERVER_FINISHED_B;		s->init_num=s->session->session_id_length+1;		s->init_off=0;		}	/* SSL2_ST_SEND_SERVER_FINISHED_B */	return(ssl2_do_write(s));	}/* send the request and check the response */static int request_certificate(SSL *s)	{	unsigned char *p,*p2,*buf2;	unsigned char *ccd;	int i,j,ctype,ret= -1;	X509 *x509=NULL;	STACK_OF(X509) *sk=NULL;	ccd=s->s2->tmp.ccl;	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_A)		{		p=(unsigned char *)s->init_buf->data;		*(p++)=SSL2_MT_REQUEST_CERTIFICATE;		*(p++)=SSL2_AT_MD5_WITH_RSA_ENCRYPTION;		RAND_pseudo_bytes(ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);		memcpy(p,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_B;		s->init_num=SSL2_MIN_CERT_CHALLENGE_LENGTH+2;		s->init_off=0;		}	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_B)		{		i=ssl2_do_write(s);		if (i <= 0)			{			ret=i;			goto end;			}		s->init_num=0;		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_C;		}	if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_C)		{		p=(unsigned char *)s->init_buf->data;		i=ssl2_read(s,(char *)&(p[s->init_num]),6-s->init_num);		if (i < 3)			{			ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);			goto end;			}		if ((*p == SSL2_MT_ERROR) && (i >= 3))			{			n2s(p,i);			if (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)				{				ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);				SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);				goto end;				}			ret=1;			goto end;			}		if ((*(p++) != SSL2_MT_CLIENT_CERTIFICATE) || (i < 6))			{			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_SHORT_READ);			goto end;			}		/* ok we have a response */		/* certificate type, there is only one right now. */		ctype= *(p++);		if (ctype != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)			{			ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_RESPONSE_ARGUMENT);			goto end;			}		n2s(p,i); s->s2->tmp.clen=i;		n2s(p,i); s->s2->tmp.rlen=i;		s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_D;		s->init_num=0;		}	/* SSL2_ST_SEND_REQUEST_CERTIFICATE_D */	p=(unsigned char *)s->init_buf->data;	j=s->s2->tmp.clen+s->s2->tmp.rlen-s->init_num;	i=ssl2_read(s,(char *)&(p[s->init_num]),j);	if (i < j) 		{		ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i);		goto end;		}	x509=(X509 *)d2i_X509(NULL,&p,(long)s->s2->tmp.clen);	if (x509 == NULL)		{		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_X509_LIB);		goto msg_end;		}	if (((sk=sk_X509_new_null()) == NULL) || (!sk_X509_push(sk,x509)))		{		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);		goto msg_end;		}	i=ssl_verify_cert_chain(s,sk);	if (i)	/* we like the packet, now check the chksum */		{		EVP_MD_CTX ctx;		EVP_PKEY *pkey=NULL;		EVP_VerifyInit(&ctx,s->ctx->rsa_md5);		EVP_VerifyUpdate(&ctx,s->s2->key_material,			(unsigned int)s->s2->key_material_length);		EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);		buf2=OPENSSL_malloc((unsigned int)i);		if (buf2 == NULL)			{			SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);			goto msg_end;			}		p2=buf2;		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2);		EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i);		OPENSSL_free(buf2);		pkey=X509_get_pubkey(x509);		if (pkey == NULL) goto end;		i=EVP_VerifyFinal(&ctx,p,s->s2->tmp.rlen,pkey);		EVP_PKEY_free(pkey);		memset(&ctx,0,sizeof(ctx));		if (i) 			{			if (s->session->peer != NULL)				X509_free(s->session->peer);			s->session->peer=x509;			CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);			s->session->verify_result = s->verify_result;			ret=1;			goto end;			}		else			{			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_CHECKSUM);			goto msg_end;			}		}	else		{msg_end:		ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);		}end:	sk_X509_free(sk);	X509_free(x509);	return(ret);	}static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from,	     unsigned char *to, int padding)	{	RSA *rsa;	int i;	if ((c == NULL) || (c->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL))		{		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY);		return(-1);		}	if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey->type != EVP_PKEY_RSA)		{		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);		return(-1);		}	rsa=c->pkeys[SSL_PKEY_RSA_ENC].privatekey->pkey.rsa;	/* we have the public key */	i=RSA_private_decrypt(len,from,to,rsa,padding);	if (i < 0)		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,ERR_R_RSA_LIB);	return(i);	}#else /* !NO_SSL2 */# if PEDANTICstatic void *dummy=&dummy;# endif#endif

⌨️ 快捷键说明

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