diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 2000-11-20 04:41:45 +0000 | 
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 2000-11-20 04:41:45 +0000 | 
| commit | 0d497cf6e989f7498cf5036a29fe7003a89abf83 (patch) | |
| tree | 48a3225dfba4179815fb512c8ba7492fa4c83fbc /crypto/openssl/ssl/s2_srvr.c | |
| parent | 94bb9d581468116c659950d31288ce30f661f3d4 (diff) | |
Diffstat (limited to 'crypto/openssl/ssl/s2_srvr.c')
| -rw-r--r-- | crypto/openssl/ssl/s2_srvr.c | 977 | 
1 files changed, 0 insertions, 977 deletions
| diff --git a/crypto/openssl/ssl/s2_srvr.c b/crypto/openssl/ssl/s2_srvr.c deleted file mode 100644 index 51c70df96acf4..0000000000000 --- a/crypto/openssl/ssl/s2_srvr.c +++ /dev/null @@ -1,977 +0,0 @@ -/* ssl/s2_srvr.c */ -/* 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.] - * - * $FreeBSD$ - */ - -#include "ssl_locl.h" -#ifndef NO_SSL2 -#include <stdio.h> -#include <openssl/bio.h> -#include <openssl/rand.h> -#include <openssl/objects.h> -#include <openssl/evp.h> - -static SSL_METHOD *ssl2_get_server_method(int ver); -static int get_client_master_key(SSL *s); -static int get_client_hello(SSL *s); -static int server_hello(SSL *s);  -static int get_client_finished(SSL *s); -static int server_verify(SSL *s); -static int server_finish(SSL *s); -static int request_certificate(SSL *s); -static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from, -	unsigned char *to,int padding); -#define BREAK	break - -static SSL_METHOD *ssl2_get_server_method(int ver) -	{ -	if (ver == SSL2_VERSION) -		return(SSLv2_server_method()); -	else -		return(NULL); -	} - -SSL_METHOD *SSLv2_server_method(void) -	{ -	static int init=1; -	static SSL_METHOD SSLv2_server_data; - -	if (init) -		{ -		memcpy((char *)&SSLv2_server_data,(char *)sslv2_base_method(), -			sizeof(SSL_METHOD)); -		SSLv2_server_data.ssl_accept=ssl2_accept; -		SSLv2_server_data.get_ssl_method=ssl2_get_server_method; -		init=0; -		} -	return(&SSLv2_server_data); -	} - -int ssl2_accept(SSL *s) -	{ -	unsigned long l=time(NULL); -	BUF_MEM *buf=NULL; -	int ret= -1; -	long num1; -	void (*cb)()=NULL; -	int new_state,state; - -	RAND_add(&l,sizeof(l),0); -	ERR_clear_error(); -	clear_sys_error(); - -	if (s->info_callback != NULL) -		cb=s->info_callback; -	else if (s->ctx->info_callback != NULL) -		cb=s->ctx->info_callback; - -	/* init things to blank */ -	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); -	s->in_handshake++; - -	if (s->cert == NULL) -		{ -		SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET); -		return(-1); -		} - -	clear_sys_error(); -	for (;;) -		{ -		state=s->state; - -		switch (s->state) -			{ -		case SSL_ST_BEFORE: -		case SSL_ST_ACCEPT: -		case SSL_ST_BEFORE|SSL_ST_ACCEPT: -		case SSL_ST_OK|SSL_ST_ACCEPT: - -			s->server=1; -			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); - -			s->version=SSL2_VERSION; -			s->type=SSL_ST_ACCEPT; - -			buf=s->init_buf; -			if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL)) -				{ ret= -1; goto end; } -			if (!BUF_MEM_grow(buf,(int) -				SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) -				{ ret= -1; goto end; } -			s->init_buf=buf; -			s->init_num=0; -			s->ctx->stats.sess_accept++; -			s->handshake_func=ssl2_accept; -			s->state=SSL2_ST_GET_CLIENT_HELLO_A; -			BREAK; - -		case SSL2_ST_GET_CLIENT_HELLO_A: -		case SSL2_ST_GET_CLIENT_HELLO_B: -		case SSL2_ST_GET_CLIENT_HELLO_C: -			s->shutdown=0; -			ret=get_client_hello(s); -			if (ret <= 0) goto end; -			s->init_num=0; -			s->state=SSL2_ST_SEND_SERVER_HELLO_A; -			BREAK; - -		case SSL2_ST_SEND_SERVER_HELLO_A: -		case SSL2_ST_SEND_SERVER_HELLO_B: -			ret=server_hello(s); -			if (ret <= 0) goto end; -			s->init_num=0; -			if (!s->hit) -				{ -				s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_A; -				BREAK; -				} -			else -				{ -				s->state=SSL2_ST_SERVER_START_ENCRYPTION; -				BREAK; -				} -		case SSL2_ST_GET_CLIENT_MASTER_KEY_A: -		case SSL2_ST_GET_CLIENT_MASTER_KEY_B: -			ret=get_client_master_key(s); -			if (ret <= 0) goto end; -			s->init_num=0; -			s->state=SSL2_ST_SERVER_START_ENCRYPTION; -			BREAK; - -		case SSL2_ST_SERVER_START_ENCRYPTION: -			/* Ok we how have sent all the stuff needed to -			 * start encrypting, the next packet back will -			 * be encrypted. */ -			if (!ssl2_enc_init(s,0)) -				{ ret= -1; goto end; } -			s->s2->clear_text=0; -			s->state=SSL2_ST_SEND_SERVER_VERIFY_A; -			BREAK; - -		case SSL2_ST_SEND_SERVER_VERIFY_A: -		case SSL2_ST_SEND_SERVER_VERIFY_B: -			ret=server_verify(s); -			if (ret <= 0) goto end; -			s->init_num=0; -			if (s->hit) -				{ -				/* If we are in here, we have been -				 * buffering the output, so we need to -				 * flush it and remove buffering from -				 * future traffic */ -				s->state=SSL2_ST_SEND_SERVER_VERIFY_C; -				BREAK; -				} -			else -				{ -				s->state=SSL2_ST_GET_CLIENT_FINISHED_A; -				break; -				} - - 		case SSL2_ST_SEND_SERVER_VERIFY_C: - 			/* get the number of bytes to write */ - 			num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL); - 			if (num1 != 0) - 				{ -				s->rwstate=SSL_WRITING; - 				num1=BIO_flush(s->wbio); - 				if (num1 <= 0) { ret= -1; goto end; } -				s->rwstate=SSL_NOTHING; -				} - - 			/* flushed and now remove buffering */ - 			s->wbio=BIO_pop(s->wbio); - - 			s->state=SSL2_ST_GET_CLIENT_FINISHED_A; -  			BREAK; - -		case SSL2_ST_GET_CLIENT_FINISHED_A: -		case SSL2_ST_GET_CLIENT_FINISHED_B: -			ret=get_client_finished(s); -			if (ret <= 0) -				goto end; -			s->init_num=0; -			s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_A; -			BREAK; - -		case SSL2_ST_SEND_REQUEST_CERTIFICATE_A: -		case SSL2_ST_SEND_REQUEST_CERTIFICATE_B: -		case SSL2_ST_SEND_REQUEST_CERTIFICATE_C: -		case SSL2_ST_SEND_REQUEST_CERTIFICATE_D: -			/* don't do a 'request certificate' if we -			 * don't want to, or we already have one, and -			 * we only want to do it once. */ -			if (!(s->verify_mode & SSL_VERIFY_PEER) || -				((s->session->peer != NULL) && -				(s->verify_mode & SSL_VERIFY_CLIENT_ONCE))) -				{ -				s->state=SSL2_ST_SEND_SERVER_FINISHED_A; -				break; -				} -			else -				{ -				ret=request_certificate(s); -				if (ret <= 0) goto end; -				s->init_num=0; -				s->state=SSL2_ST_SEND_SERVER_FINISHED_A; -				} -			BREAK; - -		case SSL2_ST_SEND_SERVER_FINISHED_A: -		case SSL2_ST_SEND_SERVER_FINISHED_B: -			ret=server_finish(s); -			if (ret <= 0) goto end; -			s->init_num=0; -			s->state=SSL_ST_OK; -			break; - -		case SSL_ST_OK: -			BUF_MEM_free(s->init_buf); -			ssl_free_wbio_buffer(s); -			s->init_buf=NULL; -			s->init_num=0; -		/*	ERR_clear_error();*/ - -			ssl_update_cache(s,SSL_SESS_CACHE_SERVER); - -			s->ctx->stats.sess_accept_good++; -			/* s->server=1; */ -			ret=1; - -			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); - -			goto end; -			/* BREAK; */ - -		default: -			SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_UNKNOWN_STATE); -			ret= -1; -			goto end; -			/* BREAK; */ -			} -		 -		if ((cb != NULL) && (s->state != state)) -			{ -			new_state=s->state; -			s->state=state; -			cb(s,SSL_CB_ACCEPT_LOOP,1); -			s->state=new_state; -			} -		} -end: -	s->in_handshake--; -	if (cb != NULL) -		cb(s,SSL_CB_ACCEPT_EXIT,ret); -	return(ret); -	} - -static int get_client_master_key(SSL *s) -	{ -	int is_export,i,n,keya,ek; -	unsigned char *p; -	SSL_CIPHER *cp; -	const EVP_CIPHER *c; -	const EVP_MD *md; - -	p=(unsigned char *)s->init_buf->data; -	if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A) -		{ -		i=ssl2_read(s,(char *)&(p[s->init_num]),10-s->init_num); - -		if (i < (10-s->init_num)) -			return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i)); -		if (*(p++) != SSL2_MT_CLIENT_MASTER_KEY) -			{ -			if (p[-1] != SSL2_MT_ERROR) -				{ -				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); -				SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_READ_WRONG_PACKET_TYPE); -				} -			else -				SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, -					SSL_R_PEER_ERROR); -			return(-1); -			} - -		cp=ssl2_get_cipher_by_char(p); -		if (cp == NULL) -			{ -			ssl2_return_error(s,SSL2_PE_NO_CIPHER); -			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, -				SSL_R_NO_CIPHER_MATCH); -			return(-1); -			} -		s->session->cipher= cp; - -		p+=3; -		n2s(p,i); s->s2->tmp.clear=i; -		n2s(p,i); s->s2->tmp.enc=i; -		n2s(p,i); s->session->key_arg_length=i; -		s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B; -		s->init_num=0; -		} - -	/* SSL2_ST_GET_CLIENT_MASTER_KEY_B */ -	p=(unsigned char *)s->init_buf->data; -	keya=s->session->key_arg_length; -	n=s->s2->tmp.clear+s->s2->tmp.enc+keya - 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_MASTER_KEY,i)); - -	memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]), -		(unsigned int)keya); - -	if (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) -		{ -		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); -		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY); -		return(-1); -		} -	i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc, -		&(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]), -		(s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING); - -	is_export=SSL_C_IS_EXPORT(s->session->cipher); -	 -	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL)) -		{ -		ssl2_return_error(s,SSL2_PE_NO_CIPHER); -		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS); -		return(0); -		} - -	if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) -		{ -		is_export=1; -		ek=8; -		} -	else -		ek=5; - -	/* bad decrypt */ -#if 1 -	/* If a bad decrypt, continue with protocol but with a -	 * dud master secret */ -	if ((i < 0) || -		((!is_export && (i != EVP_CIPHER_key_length(c))) -		|| (is_export && ((i != ek) || (s->s2->tmp.clear+i != -			EVP_CIPHER_key_length(c)))))) -		{ -		if (is_export) -			i=ek; -		else -			i=EVP_CIPHER_key_length(c); -		RAND_pseudo_bytes(p,i); -		} -#else -	if (i < 0) -		{ -		error=1; -		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_RSA_DECRYPT); -		} -	/* incorrect number of key bytes for non export cipher */ -	else if ((!is_export && (i != EVP_CIPHER_key_length(c))) -		|| (is_export && ((i != ek) || (s->s2->tmp.clear+i != -			EVP_CIPHER_key_length(c))))) -		{ -		error=1; -		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_WRONG_NUMBER_OF_KEY_BITS); -		} -	if (error) -		{ -		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); -		return(-1); -		} -#endif - -	if (is_export) i+=s->s2->tmp.clear; -	s->session->master_key_length=i; -	memcpy(s->session->master_key,p,(unsigned int)i); -	return(1); -	} - -static int get_client_hello(SSL *s) -	{ -	int i,n; -	unsigned char *p; -	STACK_OF(SSL_CIPHER) *cs; /* a stack of SSL_CIPHERS */ -	STACK_OF(SSL_CIPHER) *cl; /* the ones we want to use */ -	int z; - -	/* This is a bit of a hack to check for the correct packet -	 * type the first time round. */ -	if (s->state == SSL2_ST_GET_CLIENT_HELLO_A) -		{ -		s->first_packet=1; -		s->state=SSL2_ST_GET_CLIENT_HELLO_B; -		} - -	p=(unsigned char *)s->init_buf->data; -	if (s->state == SSL2_ST_GET_CLIENT_HELLO_B) -		{ -		i=ssl2_read(s,(char *)&(p[s->init_num]),9-s->init_num); -		if (i < (9-s->init_num))  -			return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i)); -	 -		if (*(p++) != SSL2_MT_CLIENT_HELLO) -			{ -			if (p[-1] != SSL2_MT_ERROR) -				{ -				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); -				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_READ_WRONG_PACKET_TYPE); -				} -			else -				SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -			return(-1); -			} -		n2s(p,i); -		if (i < s->version) s->version=i; -		n2s(p,i); s->s2->tmp.cipher_spec_length=i; -		n2s(p,i); s->s2->tmp.session_id_length=i; -		n2s(p,i); s->s2->challenge_length=i; -		if (	(i < SSL2_MIN_CHALLENGE_LENGTH) || -			(i > SSL2_MAX_CHALLENGE_LENGTH)) -			{ -			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=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); -		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 PEDANTIC -static void *dummy=&dummy; -# endif - -#endif | 
