ssl_lib.c

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

C
2,062
字号
/*! \file ssl/ssl_lib.c *  \brief Version independent SSL functions. *//* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. *  * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to.  The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code.  The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). *  * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *    "This product includes cryptographic software written by *     Eric Young (eay@cryptsoft.com)" *    The word 'cryptographic' can be left out if the rouines from the library *    being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from  *    the apps directory (application code) you must include an acknowledgement: *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" *  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *  * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed.  i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */#include <assert.h>#include <stdio.h>#include <openssl/objects.h>#include <openssl/lhash.h>#include <openssl/x509v3.h>#include "ssl_locl.h"const char *SSL_version_str=OPENSSL_VERSION_TEXT;static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_meth=NULL;static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_ctx_meth=NULL;static int ssl_meth_num=0;static int ssl_ctx_meth_num=0;OPENSSL_GLOBAL SSL3_ENC_METHOD ssl3_undef_enc_method={	/* evil casts, but these functions are only called if there's a library bug */	(int (*)(SSL *,int))ssl_undefined_function,	(int (*)(SSL *, unsigned char *, int))ssl_undefined_function,	ssl_undefined_function,	(int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function,	(int (*)(SSL*, int))ssl_undefined_function,	(int (*)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char*, int, unsigned char *))ssl_undefined_function	};int SSL_clear(SSL *s)	{	int state;	if (s->method == NULL)		{		SSLerr(SSL_F_SSL_CLEAR,SSL_R_NO_METHOD_SPECIFIED);		return(0);		}	s->error=0;	s->hit=0;	s->shutdown=0;#if 0 /* Disabled since version 1.10 of this file (early return not       * needed because SSL_clear is not called when doing renegotiation) */	/* This is set if we are doing dynamic renegotiation so keep	 * the old cipher.  It is sort of a SSL_clear_lite :-) */	if (s->new_session) return(1);#else	if (s->new_session)		{		SSLerr(SSL_F_SSL_CLEAR,SSL_R_INTERNAL_ERROR);		return 0;		}#endif	state=s->state; /* Keep to check if we throw away the session-id */	s->type=0;	s->state=SSL_ST_BEFORE|((s->server)?SSL_ST_ACCEPT:SSL_ST_CONNECT);	s->version=s->method->version;	s->client_version=s->version;	s->rwstate=SSL_NOTHING;	s->rstate=SSL_ST_READ_HEADER;	s->read_ahead=s->ctx->read_ahead;	if (s->init_buf != NULL)		{		BUF_MEM_free(s->init_buf);		s->init_buf=NULL;		}	ssl_clear_cipher_ctx(s);	if (ssl_clear_bad_session(s))		{		SSL_SESSION_free(s->session);		s->session=NULL;		}	s->first_packet=0;#if 1	/* Check to see if we were changed into a different method, if	 * so, revert back if we are not doing session-id reuse. */	if ((s->session == NULL) && (s->method != s->ctx->method))		{		s->method->ssl_free(s);		s->method=s->ctx->method;		if (!s->method->ssl_new(s))			return(0);		}	else#endif		s->method->ssl_clear(s);	return(1);	}/** Used to change an SSL_CTXs default SSL method type */int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth)	{	STACK_OF(SSL_CIPHER) *sk;	ctx->method=meth;	sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),		&(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST);	if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))		{		SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);		return(0);		}	return(1);	}SSL *SSL_new(SSL_CTX *ctx)	{	SSL *s;	if (ctx == NULL)		{		SSLerr(SSL_F_SSL_NEW,SSL_R_NULL_SSL_CTX);		return(NULL);		}	if (ctx->method == NULL)		{		SSLerr(SSL_F_SSL_NEW,SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);		return(NULL);		}	s=(SSL *)OPENSSL_malloc(sizeof(SSL));	if (s == NULL) goto err;	memset(s,0,sizeof(SSL));	if (ctx->cert != NULL)		{		/* Earlier library versions used to copy the pointer to		 * the CERT, not its contents; only when setting new		 * parameters for the per-SSL copy, ssl_cert_new would be		 * called (and the direct reference to the per-SSL_CTX		 * settings would be lost, but those still were indirectly		 * accessed for various purposes, and for that reason they		 * used to be known as s->ctx->default_cert).		 * Now we don't look at the SSL_CTX's CERT after having		 * duplicated it once. */		s->cert = ssl_cert_dup(ctx->cert);		if (s->cert == NULL)			goto err;		}	else		s->cert=NULL; /* Cannot really happen (see SSL_CTX_new) */	s->sid_ctx_length=ctx->sid_ctx_length;	memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));	s->verify_mode=ctx->verify_mode;	s->verify_depth=ctx->verify_depth;	s->verify_callback=ctx->default_verify_callback;	s->purpose = ctx->purpose;	s->trust = ctx->trust;	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);	s->ctx=ctx;	s->verify_result=X509_V_OK;	s->method=ctx->method;	if (!s->method->ssl_new(s))		goto err;	s->quiet_shutdown=ctx->quiet_shutdown;	s->references=1;	s->server=(ctx->method->ssl_accept == ssl_undefined_function)?0:1;	s->options=ctx->options;	s->mode=ctx->mode;	SSL_clear(s);	CRYPTO_new_ex_data(ssl_meth,s,&s->ex_data);	return(s);err:	if (s != NULL)		{		if (s->cert != NULL)			ssl_cert_free(s->cert);		if (s->ctx != NULL)			SSL_CTX_free(s->ctx); /* decrement reference count */		OPENSSL_free(s);		}	SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE);	return(NULL);	}int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,				   unsigned int sid_ctx_len)    {    if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)	{	SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);	return 0;	}    ctx->sid_ctx_length=sid_ctx_len;    memcpy(ctx->sid_ctx,sid_ctx,sid_ctx_len);    return 1;    }int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,			       unsigned int sid_ctx_len)    {    if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)	{	SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);	return 0;	}    ssl->sid_ctx_length=sid_ctx_len;    memcpy(ssl->sid_ctx,sid_ctx,sid_ctx_len);    return 1;    }int SSL_CTX_set_purpose(SSL_CTX *s, int purpose){	if(X509_PURPOSE_get_by_id(purpose) == -1) {		SSLerr(SSL_F_SSL_CTX_SET_PURPOSE, SSL_R_INVALID_PURPOSE);		return 0;	}	s->purpose = purpose;	return 1;}int SSL_set_purpose(SSL *s, int purpose){	if(X509_PURPOSE_get_by_id(purpose) == -1) {		SSLerr(SSL_F_SSL_SET_PURPOSE, SSL_R_INVALID_PURPOSE);		return 0;	}	s->purpose = purpose;	return 1;}	int SSL_CTX_set_trust(SSL_CTX *s, int trust){	if(X509_TRUST_get_by_id(trust) == -1) {		SSLerr(SSL_F_SSL_CTX_SET_TRUST, SSL_R_INVALID_TRUST);		return 0;	}	s->trust = trust;	return 1;}int SSL_set_trust(SSL *s, int trust){	if(X509_TRUST_get_by_id(trust) == -1) {		SSLerr(SSL_F_SSL_SET_TRUST, SSL_R_INVALID_TRUST);		return 0;	}	s->trust = trust;	return 1;}void SSL_free(SSL *s)	{	int i;	if(s == NULL)	    return;	i=CRYPTO_add(&s->references,-1,CRYPTO_LOCK_SSL);#ifdef REF_PRINT	REF_PRINT("SSL",s);#endif	if (i > 0) return;#ifdef REF_CHECK	if (i < 0)		{		fprintf(stderr,"SSL_free, bad reference count\n");		abort(); /* ok */		}#endif	CRYPTO_free_ex_data(ssl_meth,(char *)s,&s->ex_data);	if (s->bbio != NULL)		{		/* If the buffering BIO is in place, pop it off */		if (s->bbio == s->wbio)			{			s->wbio=BIO_pop(s->wbio);			}		BIO_free(s->bbio);		s->bbio=NULL;		}	if (s->rbio != NULL)		BIO_free_all(s->rbio);	if ((s->wbio != NULL) && (s->wbio != s->rbio))		BIO_free_all(s->wbio);	if (s->init_buf != NULL) BUF_MEM_free(s->init_buf);	/* add extra stuff */	if (s->cipher_list != NULL) sk_SSL_CIPHER_free(s->cipher_list);	if (s->cipher_list_by_id != NULL) sk_SSL_CIPHER_free(s->cipher_list_by_id);	/* Make the next call work :-) */	if (s->session != NULL)		{		ssl_clear_bad_session(s);		SSL_SESSION_free(s->session);		}	ssl_clear_cipher_ctx(s);	if (s->cert != NULL) ssl_cert_free(s->cert);	/* Free up if allocated */	if (s->ctx) SSL_CTX_free(s->ctx);	if (s->client_CA != NULL)		sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);	if (s->method != NULL) s->method->ssl_free(s);	OPENSSL_free(s);	}void SSL_set_bio(SSL *s,BIO *rbio,BIO *wbio)	{	/* If the output buffering BIO is still in place, remove it	 */	if (s->bbio != NULL)		{		if (s->wbio == s->bbio)			{			s->wbio=s->wbio->next_bio;			s->bbio->next_bio=NULL;			}		}	if ((s->rbio != NULL) && (s->rbio != rbio))		BIO_free_all(s->rbio);	if ((s->wbio != NULL) && (s->wbio != wbio) && (s->rbio != s->wbio))		BIO_free_all(s->wbio);	s->rbio=rbio;	s->wbio=wbio;	}BIO *SSL_get_rbio(SSL *s)	{ return(s->rbio); }BIO *SSL_get_wbio(SSL *s)	{ return(s->wbio); }int SSL_get_fd(SSL *s)	{	int ret= -1;	BIO *b,*r;	b=SSL_get_rbio(s);	r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR);	if (r != NULL)		BIO_get_fd(r,&ret);	return(ret);	}#ifndef NO_SOCKint SSL_set_fd(SSL *s,int fd)	{	int ret=0;	BIO *bio=NULL;	bio=BIO_new(BIO_s_socket());	if (bio == NULL)		{		SSLerr(SSL_F_SSL_SET_FD,ERR_R_BUF_LIB);		goto err;		}	BIO_set_fd(bio,fd,BIO_NOCLOSE);	SSL_set_bio(s,bio,bio);	ret=1;err:	return(ret);	}int SSL_set_wfd(SSL *s,int fd)	{	int ret=0;	BIO *bio=NULL;	if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_SOCKET)		|| ((int)BIO_get_fd(s->rbio,NULL) != fd))		{		bio=BIO_new(BIO_s_socket());		if (bio == NULL)			{ SSLerr(SSL_F_SSL_SET_WFD,ERR_R_BUF_LIB); goto err; }		BIO_set_fd(bio,fd,BIO_NOCLOSE);		SSL_set_bio(s,SSL_get_rbio(s),bio);		}	else		SSL_set_bio(s,SSL_get_rbio(s),SSL_get_rbio(s));	ret=1;err:	return(ret);	}int SSL_set_rfd(SSL *s,int fd)	{	int ret=0;	BIO *bio=NULL;	if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_SOCKET)		|| ((int)BIO_get_fd(s->wbio,NULL) != fd))		{		bio=BIO_new(BIO_s_socket());		if (bio == NULL)			{			SSLerr(SSL_F_SSL_SET_RFD,ERR_R_BUF_LIB);			goto err;			}		BIO_set_fd(bio,fd,BIO_NOCLOSE);		SSL_set_bio(s,bio,SSL_get_wbio(s));		}	else		SSL_set_bio(s,SSL_get_wbio(s),SSL_get_wbio(s));	ret=1;err:	return(ret);	}#endif/* return length of latest Finished message we sent, copy to 'buf' */size_t SSL_get_finished(SSL *s, void *buf, size_t count)	{	size_t ret = 0;		if (s->s3 != NULL)		{		ret = s->s3->tmp.finish_md_len;		if (count > ret)			count = ret;		memcpy(buf, s->s3->tmp.finish_md, count);		}	return ret;	}/* return length of latest Finished message we expected, copy to 'buf' */size_t SSL_get_peer_finished(SSL *s, void *buf, size_t count)	{	size_t ret = 0;		if (s->s3 != NULL)		{		ret = s->s3->tmp.peer_finish_md_len;		if (count > ret)			count = ret;		memcpy(buf, s->s3->tmp.peer_finish_md, count);		}

⌨️ 快捷键说明

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