case SSL3_ST_SR_MS_SGC:
int ssl3_accept(SSL *s)	{	BUF_MEM *buf;	unsigned long l,Time=time(NULL);	void (*cb)()=NULL;	long num1;	int ret= -1;	int new_state,state,skip=0;	RAND_add(&Time,sizeof(Time),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_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET);		return(-1);		}	for (;;)		{		state=s->state;		switch (s->state)			{		case SSL_ST_RENEGOTIATE:			s->new_session=1;			/* s->state=SSL_ST_ACCEPT; */		case SSL3_ST_SR_MS_SGC:		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);			if ((s->version>>8) != 3)				abort();			/* s->version=SSL3_VERSION; */			s->type=SSL_ST_ACCEPT;			if (s->init_buf == NULL)				{				if ((buf=BUF_MEM_new()) == NULL)					{					ret= -1;					goto end;					}				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))					{					ret= -1;					goto end;					}				s->init_buf=buf;				}			if (!ssl3_setup_buffers(s))				{				ret= -1;				goto end;				}			/* Ok, we now need to push on a buffering BIO so that			 * the output is sent in a way that TCP likes :-)			 */			if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }			s->init_num=0;			if (s->state != SSL_ST_RENEGOTIATE)				{				if(s->state != SSL3_ST_SR_MS_SGC) ssl3_init_finished_mac(s);				s->state=SSL3_ST_SR_CLNT_HELLO_A;				s->ctx->stats.sess_accept++;				}			else				{				s->ctx->stats.sess_accept_renegotiate++;				s->state=SSL3_ST_SW_HELLO_REQ_A;				}			break;		case SSL3_ST_SW_HELLO_REQ_A:		case SSL3_ST_SW_HELLO_REQ_B:			s->shutdown=0;			ret=ssl3_send_hello_request(s);			if (ret <= 0) goto end;			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;			s->state=SSL3_ST_SW_FLUSH;			s->init_num=0;			ssl3_init_finished_mac(s);			break;		case SSL3_ST_SW_HELLO_REQ_C:			s->state=SSL_ST_OK;			ret=1;			goto end;			/* break; */		case SSL3_ST_SR_CLNT_HELLO_A:		case SSL3_ST_SR_CLNT_HELLO_B:		case SSL3_ST_SR_CLNT_HELLO_C:			s->shutdown=0;			ret=ssl3_get_client_hello(s);			if (ret <= 0) goto end;			s->state=SSL3_ST_SW_SRVR_HELLO_A;			s->init_num=0;			break;		case SSL3_ST_SW_SRVR_HELLO_A:		case SSL3_ST_SW_SRVR_HELLO_B:			ret=ssl3_send_server_hello(s);			if (ret <= 0) goto end;			if (s->hit)				s->state=SSL3_ST_SW_CHANGE_A;			else				s->state=SSL3_ST_SW_CERT_A;			s->init_num=0;			break;		case SSL3_ST_SW_CERT_A:		case SSL3_ST_SW_CERT_B:			/* Check if it is anon DH */			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))				{				ret=ssl3_send_server_certificate(s);				if (ret <= 0) goto end;				}			else				skip=1;			s->state=SSL3_ST_SW_KEY_EXCH_A;			s->init_num=0;			break;		case SSL3_ST_SW_KEY_EXCH_A:		case SSL3_ST_SW_KEY_EXCH_B:			l=s->s3->tmp.new_cipher->algorithms;			/* clear this, it may get reset by			 * send_server_key_exchange */			if (s->options & SSL_OP_EPHEMERAL_RSA)				s->s3->tmp.use_rsa_tmp=1;			else				s->s3->tmp.use_rsa_tmp=0;			/* only send if a DH key exchange, fortezza or			 * RSA but we have a sign only certificate */			if (s->s3->tmp.use_rsa_tmp			    || (l & (SSL_DH|SSL_kFZA))			    || ((l & SSL_kRSA)				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)					)				    )				)			    )				{				ret=ssl3_send_server_key_exchange(s);				if (ret <= 0) goto end;				}			else				skip=1;			s->state=SSL3_ST_SW_CERT_REQ_A;			s->init_num=0;			break;		case SSL3_ST_SW_CERT_REQ_A:		case SSL3_ST_SW_CERT_REQ_B:			if (/* don't request cert unless asked for it: */				!(s->verify_mode & SSL_VERIFY_PEER) ||				/* if SSL_VERIFY_CLIENT_ONCE is set,				 * don't request cert during re-negotiation: */				((s->session->peer != NULL) &&				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||				/* never request cert in anonymous ciphersuites				 * (see section "Certificate request" in SSL 3 drafts				 * and in RFC 2246): */				((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) &&				 /* ... except when the application insists on verification				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))				{				/* no cert request */				skip=1;				s->s3->tmp.cert_request=0;				s->state=SSL3_ST_SW_SRVR_DONE_A;				}			else				{				s->s3->tmp.cert_request=1;				ret=ssl3_send_certificate_request(s);				if (ret <= 0) goto end;#ifndef NETSCAPE_HANG_BUG				s->state=SSL3_ST_SW_SRVR_DONE_A;#else				s->state=SSL3_ST_SW_FLUSH;				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;#endif				s->init_num=0;				}			break;		case SSL3_ST_SW_SRVR_DONE_A:		case SSL3_ST_SW_SRVR_DONE_B:			ret=ssl3_send_server_done(s);			if (ret <= 0) goto end;			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;			s->state=SSL3_ST_SW_FLUSH;			s->init_num=0;			break;				case SSL3_ST_SW_FLUSH:			/* number of bytes to be flushed */			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;				}			s->state=s->s3->tmp.next_state;			break;		case SSL3_ST_SR_CERT_A:		case SSL3_ST_SR_CERT_B:			/* Check for second client hello if MS SGC */			ret = ssl3_check_client_hello(s);			if(ret <= 0) goto end;			if(ret == 2) s->state = SSL3_ST_SR_MS_SGC;			else {				/* could be sent for a DH cert, even if we				 * have not asked for it :-) */				ret=ssl3_get_client_certificate(s);				if (ret <= 0) goto end;				s->init_num=0;				s->state=SSL3_ST_SR_KEY_EXCH_A;			}			break;		case SSL3_ST_SR_KEY_EXCH_A:		case SSL3_ST_SR_KEY_EXCH_B:			ret=ssl3_get_client_key_exchange(s);			if (ret <= 0) goto end;			s->state=SSL3_ST_SR_CERT_VRFY_A;			s->init_num=0;			/* We need to get hashes here so if there is			 * a client cert, it can be verified */ 			s->method->ssl3_enc->cert_verify_mac(s,				&(s->s3->finish_dgst1),				&(s->s3->tmp.cert_verify_md[0]));			s->method->ssl3_enc->cert_verify_mac(s,				&(s->s3->finish_dgst2),				&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));			break;		case SSL3_ST_SR_CERT_VRFY_A:		case SSL3_ST_SR_CERT_VRFY_B:			/* we should decide if we expected this one */			ret=ssl3_get_cert_verify(s);			if (ret <= 0) goto end;			s->state=SSL3_ST_SR_FINISHED_A;			s->init_num=0;			break;		case SSL3_ST_SR_FINISHED_A:		case SSL3_ST_SR_FINISHED_B:			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,				SSL3_ST_SR_FINISHED_B);			if (ret <= 0) goto end;			if (s->hit)				s->state=SSL_ST_OK;			else				s->state=SSL3_ST_SW_CHANGE_A;			s->init_num=0;			break;		case SSL3_ST_SW_CHANGE_A:		case SSL3_ST_SW_CHANGE_B:			s->session->cipher=s->s3->tmp.new_cipher;			if (!s->method->ssl3_enc->setup_key_block(s))				{ ret= -1; goto end; }			ret=ssl3_send_change_cipher_spec(s,				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);			if (ret <= 0) goto end;			s->state=SSL3_ST_SW_FINISHED_A;			s->init_num=0;			if (!s->method->ssl3_enc->change_cipher_state(s,				SSL3_CHANGE_CIPHER_SERVER_WRITE))				{				ret= -1;				goto end;				}			break;		case SSL3_ST_SW_FINISHED_A:		case SSL3_ST_SW_FINISHED_B:			ret=ssl3_send_finished(s,				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,				s->method->ssl3_enc->server_finished_label,				s->method->ssl3_enc->server_finished_label_len);			if (ret <= 0) goto end;			s->state=SSL3_ST_SW_FLUSH;			if (s->hit)				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;			else				s->s3->tmp.next_state=SSL_ST_OK;			s->init_num=0;			break;		case SSL_ST_OK:			/* clean a few things up */			ssl3_cleanup_key_block(s);			BUF_MEM_free(s->init_buf);			s->init_buf=NULL;			/* remove buffering on output */			ssl_free_wbio_buffer(s);			s->new_session=0;			s->init_num=0;			ssl_update_cache(s,SSL_SESS_CACHE_SERVER);			s->ctx->stats.sess_accept_good++;			/* s->server=1; */			s->handshake_func=ssl3_accept;			ret=1;			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);			goto end;			/* break; */		default:			SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE);			ret= -1;			goto end;			/* break; */			}				if (!s->s3->tmp.reuse_message && !skip)			{			if (s->debug)				{				if ((ret=BIO_flush(s->wbio)) <= 0)					goto end;				}			if ((cb != NULL) && (s->state != state))				{				new_state=s->state;				s->state=state;				cb(s,SSL_CB_ACCEPT_LOOP,1);				s->state=new_state;				}			}		skip=0;		}end:	/* BIO_flush(s->wbio); */	if (cb != NULL)		cb(s,SSL_CB_ACCEPT_EXIT,ret);	s->in_handshake--;	return(ret);	}