s->client_version=(((int)p[0])<<8)|(int)p[1];
static int ssl3_get_client_hello(SSL *s)	{	int i,j,ok,al,ret= -1;	long n;	unsigned long id;	unsigned char *p,*d,*q;	SSL_CIPHER *c;	SSL_COMP *comp=NULL;	STACK_OF(SSL_CIPHER) *ciphers=NULL;	/* We do this so that we will respond with our native type.	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,	 * This down switching should be handled by a different method.	 * If we are SSLv3, we will respond with SSLv3, even if prompted with	 * TLSv1.	 */	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)		{		s->first_packet=1;		s->state=SSL3_ST_SR_CLNT_HELLO_B;		}	n=ssl3_get_message(s,		SSL3_ST_SR_CLNT_HELLO_B,		SSL3_ST_SR_CLNT_HELLO_C,		SSL3_MT_CLIENT_HELLO,		SSL3_RT_MAX_PLAIN_LENGTH,		&ok);	if (!ok) return((int)n);	d=p=(unsigned char *)s->init_buf->data;	/* The version number has already been checked in ssl3_get_message.	 * I a native TLSv1/SSLv3 method, the match must be correct except	 * perhaps for the first message *//*	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		- sesson 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);	}