ssl_lib.c

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

C
2,062
字号
	if ((num%n) != 0)		{		SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);		return(NULL);		}	if ((skp == NULL) || (*skp == NULL))		sk=sk_SSL_CIPHER_new_null(); /* change perhaps later */	else		{		sk= *skp;		sk_SSL_CIPHER_zero(sk);		}	for (i=0; i<num; i+=n)		{		c=ssl_get_cipher_by_char(s,p);		p+=n;		if (c != NULL)			{			if (!sk_SSL_CIPHER_push(sk,c))				{				SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,ERR_R_MALLOC_FAILURE);				goto err;				}			}		}	if (skp != NULL)		*skp=sk;	return(sk);err:	if ((skp == NULL) || (*skp == NULL))		sk_SSL_CIPHER_free(sk);	return(NULL);	}unsigned long SSL_SESSION_hash(SSL_SESSION *a)	{	unsigned long l;	l=(unsigned long)		((unsigned int) a->session_id[0]     )|		((unsigned int) a->session_id[1]<< 8L)|		((unsigned long)a->session_id[2]<<16L)|		((unsigned long)a->session_id[3]<<24L);	return(l);	}int SSL_SESSION_cmp(SSL_SESSION *a,SSL_SESSION *b)	{	if (a->ssl_version != b->ssl_version)		return(1);	if (a->session_id_length != b->session_id_length)		return(1);	return(memcmp(a->session_id,b->session_id,a->session_id_length));	}SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)	{	SSL_CTX *ret=NULL;		if (meth == NULL)		{		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED);		return(NULL);		}	if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0)		{		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);		goto err;		}	ret=(SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX));	if (ret == NULL)		goto err;	memset(ret,0,sizeof(SSL_CTX));	ret->method=meth;	ret->cert_store=NULL;	ret->session_cache_mode=SSL_SESS_CACHE_SERVER;	ret->session_cache_size=SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;	ret->session_cache_head=NULL;	ret->session_cache_tail=NULL;	/* We take the system default */	ret->session_timeout=meth->get_timeout();	ret->new_session_cb=NULL;	ret->remove_session_cb=NULL;	ret->get_session_cb=NULL;	memset((char *)&ret->stats,0,sizeof(ret->stats));	ret->references=1;	ret->quiet_shutdown=0;/*	ret->cipher=NULL;*//*	ret->s2->challenge=NULL;	ret->master_key=NULL;	ret->key_arg=NULL;	ret->s2->conn_id=NULL; */	ret->info_callback=NULL;	ret->app_verify_callback=NULL;	ret->app_verify_arg=NULL;	ret->read_ahead=0;	ret->verify_mode=SSL_VERIFY_NONE;	ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */	ret->default_verify_callback=NULL;	if ((ret->cert=ssl_cert_new()) == NULL)		goto err;	ret->default_passwd_callback=NULL;	ret->default_passwd_callback_userdata=NULL;	ret->client_cert_cb=NULL;	ret->sessions=lh_new(SSL_SESSION_hash,SSL_SESSION_cmp);	if (ret->sessions == NULL) goto err;	ret->cert_store=X509_STORE_new();	if (ret->cert_store == NULL) goto err;	ssl_create_cipher_list(ret->method,		&ret->cipher_list,&ret->cipher_list_by_id,		SSL_DEFAULT_CIPHER_LIST);	if (ret->cipher_list == NULL	    || sk_SSL_CIPHER_num(ret->cipher_list) <= 0)		{		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS);		goto err2;		}	if ((ret->rsa_md5=EVP_get_digestbyname("ssl2-md5")) == NULL)		{		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES);		goto err2;		}	if ((ret->md5=EVP_get_digestbyname("ssl3-md5")) == NULL)		{		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES);		goto err2;		}	if ((ret->sha1=EVP_get_digestbyname("ssl3-sha1")) == NULL)		{		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES);		goto err2;		}	if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL)		goto err;	CRYPTO_new_ex_data(ssl_ctx_meth,(char *)ret,&ret->ex_data);	ret->extra_certs=NULL;	ret->comp_methods=SSL_COMP_get_compression_methods();	return(ret);err:	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);err2:	if (ret != NULL) SSL_CTX_free(ret);	return(NULL);	}static void SSL_COMP_free(SSL_COMP *comp)    { OPENSSL_free(comp); }void SSL_CTX_free(SSL_CTX *a)	{	int i;	if (a == NULL) return;	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX);#ifdef REF_PRINT	REF_PRINT("SSL_CTX",a);#endif	if (i > 0) return;#ifdef REF_CHECK	if (i < 0)		{		fprintf(stderr,"SSL_CTX_free, bad reference count\n");		abort(); /* ok */		}#endif	CRYPTO_free_ex_data(ssl_ctx_meth,(char *)a,&a->ex_data);	if (a->sessions != NULL)		{		SSL_CTX_flush_sessions(a,0);		lh_free(a->sessions);		}	if (a->cert_store != NULL)		X509_STORE_free(a->cert_store);	if (a->cipher_list != NULL)		sk_SSL_CIPHER_free(a->cipher_list);	if (a->cipher_list_by_id != NULL)		sk_SSL_CIPHER_free(a->cipher_list_by_id);	if (a->cert != NULL)		ssl_cert_free(a->cert);	if (a->client_CA != NULL)		sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free);	if (a->extra_certs != NULL)		sk_X509_pop_free(a->extra_certs,X509_free);	if (a->comp_methods != NULL)		sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free);	OPENSSL_free(a);	}void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb)	{	ctx->default_passwd_callback=cb;	}void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u)	{	ctx->default_passwd_callback_userdata=u;	}void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,int (*cb)(),char *arg)	{	/* now	 *     int (*cb)(X509_STORE_CTX *),	 * but should be	 *     int (*cb)(X509_STORE_CTX *, void *arg)	 */	ctx->app_verify_callback=cb;	ctx->app_verify_arg=arg; /* never used */	}void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *))	{	ctx->verify_mode=mode;	ctx->default_verify_callback=cb;	/* This needs cleaning up EAY EAY EAY */	X509_STORE_set_verify_cb_func(ctx->cert_store,cb);	}void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth)	{	ctx->verify_depth=depth;	}void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)	{	CERT_PKEY *cpk;	int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign;	int rsa_enc_export,dh_rsa_export,dh_dsa_export;	int rsa_tmp_export,dh_tmp_export,kl;	unsigned long mask,emask;	if (c == NULL) return;	kl=SSL_C_EXPORT_PKEYLENGTH(cipher);#ifndef NO_RSA	rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL);	rsa_tmp_export=(c->rsa_tmp_cb != NULL ||		(rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl));#else	rsa_tmp=rsa_tmp_export=0;#endif#ifndef NO_DH	dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL);	dh_tmp_export=(c->dh_tmp_cb != NULL ||		(dh_tmp && DH_size(c->dh_tmp)*8 <= kl));#else	dh_tmp=dh_tmp_export=0;#endif	cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);	rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL);	rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl);	cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]);	rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL);	cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]);	dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL);	cpk= &(c->pkeys[SSL_PKEY_DH_RSA]);	dh_rsa=  (cpk->x509 != NULL && cpk->privatekey != NULL);	dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);	cpk= &(c->pkeys[SSL_PKEY_DH_DSA]);/* FIX THIS EAY EAY EAY */	dh_dsa=  (cpk->x509 != NULL && cpk->privatekey != NULL);	dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);	mask=0;	emask=0;#ifdef CIPHER_DEBUG	printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",		rsa_tmp,rsa_tmp_export,dh_tmp,		rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);#endif	if (rsa_enc || (rsa_tmp && rsa_sign))		mask|=SSL_kRSA;	if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc)))		emask|=SSL_kRSA;#if 0	/* The match needs to be both kEDH and aRSA or aDSA, so don't worry */	if (	(dh_tmp || dh_rsa || dh_dsa) && 		(rsa_enc || rsa_sign || dsa_sign))		mask|=SSL_kEDH;	if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) &&		(rsa_enc || rsa_sign || dsa_sign))		emask|=SSL_kEDH;#endif	if (dh_tmp_export) 		emask|=SSL_kEDH;	if (dh_tmp)		mask|=SSL_kEDH;	if (dh_rsa) mask|=SSL_kDHr;	if (dh_rsa_export) emask|=SSL_kDHr;	if (dh_dsa) mask|=SSL_kDHd;	if (dh_dsa_export) emask|=SSL_kDHd;	if (rsa_enc || rsa_sign)		{		mask|=SSL_aRSA;		emask|=SSL_aRSA;		}	if (dsa_sign)		{		mask|=SSL_aDSS;		emask|=SSL_aDSS;		}	mask|=SSL_aNULL;	emask|=SSL_aNULL;	c->mask=mask;	c->export_mask=emask;	c->valid=1;	}/* THIS NEEDS CLEANING UP */X509 *ssl_get_server_send_cert(SSL *s)	{	unsigned long alg,mask,kalg;	CERT *c;	int i,is_export;	c=s->cert;	ssl_set_cert_masks(c, s->s3->tmp.new_cipher);	alg=s->s3->tmp.new_cipher->algorithms;	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);	mask=is_export?c->export_mask:c->mask;	kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK);	if 	(kalg & SSL_kDHr)		i=SSL_PKEY_DH_RSA;	else if (kalg & SSL_kDHd)		i=SSL_PKEY_DH_DSA;	else if (kalg & SSL_aDSS)		i=SSL_PKEY_DSA_SIGN;	else if (kalg & SSL_aRSA)		{		if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)			i=SSL_PKEY_RSA_SIGN;		else			i=SSL_PKEY_RSA_ENC;		}	else /* if (kalg & SSL_aNULL) */		{		SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,SSL_R_INTERNAL_ERROR);		return(NULL);		}	if (c->pkeys[i].x509 == NULL) return(NULL);	return(c->pkeys[i].x509);	}EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher)	{	unsigned long alg;	CERT *c;	alg=cipher->algorithms;	c=s->cert;	if ((alg & SSL_aDSS) &&		(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))		return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);	else if (alg & SSL_aRSA)		{		if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)			return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);		else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)			return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey);		else			return(NULL);		}	else /* if (alg & SSL_aNULL) */		{		SSLerr(SSL_F_SSL_GET_SIGN_PKEY,SSL_R_INTERNAL_ERROR);		return(NULL);		}	}void ssl_update_cache(SSL *s,int mode)	{	int i;	/* If the session_id_length is 0, we are not supposed to cache it,	 * and it would be rather hard to do anyway :-) */	if (s->session->session_id_length == 0) return;	if ((s->ctx->session_cache_mode & mode)		&& (!s->hit)		&& SSL_CTX_add_session(s->ctx,s->session)		&& (s->ctx->new_session_cb != NULL))		{		CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION);		if (!s->ctx->new_session_cb(s,s->session))			SSL_SESSION_free(s->session);		}	/* auto flush every 255 connections */	i=s->ctx->session_cache_mode;	if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) &&		((i & mode) == mode))		{		if (  (((mode & SSL_SESS_CACHE_CLIENT)			?s->ctx->stats.sess_connect_good			:s->ctx->stats.sess_accept_good) & 0xff) == 0xff)			{			SSL_CTX_flush_sessions(s->ctx,time(NULL));			}		}	}SSL_METHOD *SSL_get_ssl_method(SSL *s)	{	return(s->method);	}int SSL_set_ssl_method(SSL *s,SSL_METHOD *meth)	{	int conn= -1;	int ret=1;	if (s->method != meth)		{		if (s->handshake_func != NULL)			conn=(s->handshake_func == s->method->ssl_connect);		if (s->method->version == meth->version)			s->method=meth;		else			{			s->method->ssl_free(s);			s->method=meth;			ret=s->method->ssl_new(s);			}		if (conn == 1)			s->handshake_func=meth->ssl_connect;		else if (conn == 0)			s->handshake_func=meth->ssl_accept;		}	return(ret);	}int SSL_get_error(SSL *s,int i)	{	int reason;	unsigned long l;	BIO *bio;	if (i > 0) return(SSL_ERROR_NONE);	/* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake	 * etc, where we do encode the error */	if ((l=ERR_peek_error()) != 0)		{		if (ERR_GET_LIB(l) == ERR_LIB_SYS)			return(SSL_ERROR_SYSCALL);		else			return(SSL_ERROR_SSL);		}	if ((i < 0) && SSL_want_read(s))		{		bio=SSL_get_rbio(s);		if (BIO_should_read(bio))			return(SSL_ERROR_WANT_READ);		else if (BIO_should_write(bio))			/* This one doesn't make too much sense ... We never try			 * to write to the rbio, and an application program where			 * rbio and wbio are separate couldn't even know what it			 * should wait for.			 * However if we ever set s->rwstate incorrectly			 * (so that we have SSL_want_read(s) instead of			 * SSL_want_write(s)) and rbio and wbio *are* the same,			 * this test works around that bug; so it might be safer			 * to keep it. */			return(SSL_ERROR_WANT_WRITE);		else if (BIO_should_io_special(bio))			{			reason=BIO_get_retry_reason(bio);			if (reason == BIO_RR_CONNECT)				return(SSL_ERROR_WANT_CONNECT);			else				return(SSL_ERROR_SYSCALL); /* unknown */			}		}	if ((i < 0) && SSL_want_write(s))

⌨️ 快捷键说明

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