ss->noCache = 1;
ss->opt.noCache = 1;
ssl2_HandleClientHelloMessage(sslSocket *ss){    sslSessionID    *sid;    sslServerCerts * sc;    CERTCertificate *serverCert;    PRUint8         *msg;    PRUint8         *data;    PRUint8         *cs;    PRUint8         *sd;    PRUint8         *cert = NULL;    PRUint8         *challenge;    unsigned int    challengeLen;    SECStatus       rv;     int             csLen;    int             sendLen;    int             sdLen;    int             certLen;    int             pid;    int             sent;    int             gotXmitBufLock = 0;#if defined(SOLARIS) && defined(i386)    volatile PRUint8 hit;#else    int             hit;#endif    PRUint8         csImpl[sizeof implementedCipherSuites];    PORT_Assert( ssl_Have1stHandshakeLock(ss) );    sc = ss->serverCerts + kt_rsa;    serverCert = sc->serverCert;    ssl_GetRecvBufLock(ss);    data = ss->gs.buf.buf + ss->gs.recordOffset;    DUMP_MSG(29, (ss, data, ss->gs.recordLen));    /* Make sure first message has some data and is the client hello message */    if ((ss->gs.recordLen < SSL_HL_CLIENT_HELLO_HBYTES)	|| (data[0] != SSL_MT_CLIENT_HELLO)) {	goto bad_client;    }    /* Get peer name of client */    rv = ssl_GetPeerInfo(ss);    if (rv != SECSuccess) {	goto loser;    }    /* Examine version information */    /*     * See if this might be a V2 client hello asking to use the V3 protocol     */    if ((data[0] == SSL_MT_CLIENT_HELLO) &&         (data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) && 	(ss->enableSSL3 || ss->enableTLS)) {	rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen);	if (rv != SECFailure) { /* Success */	    ss->handshake             = NULL;	    ss->nextHandshake         = ssl_GatherRecord1stHandshake;	    ss->securityHandshake     = NULL;	    ss->gs.state              = GS_INIT;	    /* ssl3_HandleV3ClientHello has set ss->version,	    ** and has gotten us a brand new sid.  	    */	    ss->sec.ci.sid->version  = ss->version;	}	ssl_ReleaseRecvBufLock(ss);	return rv;    }    /* Previously, there was a test here to see if SSL2 was enabled.    ** If not, an error code was set, and SECFailure was returned,    ** without sending any error code to the other end of the connection.    ** That test has been removed.  If SSL2 has been disabled, there    ** should be no SSL2 ciphers enabled, and consequently, the code    ** below should send the ssl2 error message SSL_PE_NO_CYPHERS.    ** We now believe this is the correct thing to do, even when SSL2    ** has been explicitly disabled by the application.    */    /* Extract info from message */    ss->version = (data[1] << 8) | data[2];    /* If some client thinks ssl v2 is 2.0 instead of 0.2, we'll allow it.  */    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {	ss->version = SSL_LIBRARY_VERSION_2;    }        csLen        = (data[3] << 8) | data[4];    sdLen        = (data[5] << 8) | data[6];    challengeLen = (data[7] << 8) | data[8];    cs           = data + SSL_HL_CLIENT_HELLO_HBYTES;    sd           = cs + csLen;    challenge    = sd + sdLen;    PRINT_BUF(7, (ss, "server, client session-id value:", sd, sdLen));    if (!csLen || (csLen % 3) != 0 ||         (sdLen != 0 && sdLen != SSL2_SESSIONID_BYTES) ||	challengeLen < SSL_MIN_CHALLENGE_BYTES || 	challengeLen > SSL_MAX_CHALLENGE_BYTES ||        (unsigned)ss->gs.recordLen !=             SSL_HL_CLIENT_HELLO_HBYTES + csLen + sdLen + challengeLen) {	SSL_DBG(("%d: SSL[%d]: bad client hello message, len=%d should=%d",		 SSL_GETPID(), ss->fd, ss->gs.recordLen,		 SSL_HL_CLIENT_HELLO_HBYTES+csLen+sdLen+challengeLen));	goto bad_client;    }    SSL_TRC(3, ("%d: SSL[%d]: client version is %x",		SSL_GETPID(), ss->fd, ss->version));    if (ss->version != SSL_LIBRARY_VERSION_2) {	if (ss->version > SSL_LIBRARY_VERSION_2) {	    /*	    ** Newer client than us. Things are ok because new clients	    ** are required to be backwards compatible with old servers.	    ** Change version number to our version number so that client	    ** knows whats up.	    */	    ss->version = SSL_LIBRARY_VERSION_2;	} else {	    SSL_TRC(1, ("%d: SSL[%d]: client version is %x (we are %x)",		SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));	    PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);	    goto loser;	}    }    /* Qualify cipher specs before returning them to client */    csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);    if (csLen == 0) {	/* no overlap, send client our list of supported SSL v2 ciphers. */        cs    = csImpl;	csLen = sizeof implementedCipherSuites;    	PORT_Memcpy(cs, implementedCipherSuites, csLen);	csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);	if (csLen == 0) {	  /* We don't support any SSL v2 ciphers! */	  ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);	  PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);	  goto loser;	}	/* Since this handhsake is going to fail, don't cache it. */	ss->noCache = 1;     }    /* Squirrel away the challenge for later */    PORT_Memcpy(ss->sec.ci.clientChallenge, challenge, challengeLen);    /* Examine message and see if session-id is good */    ss->sec.ci.elements = 0;    if (sdLen > 0 && !ss->noCache) {	SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",		    SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],		    ss->sec.ci.peer.pr_s6_addr32[1], 		    ss->sec.ci.peer.pr_s6_addr32[2],		    ss->sec.ci.peer.pr_s6_addr32[3]));	sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sd, sdLen, ss->dbHandle);    } else {	sid = NULL;    }    if (sid) {	/* Got a good session-id. Short cut! */	SSL_TRC(1, ("%d: SSL[%d]: server, using session-id for 0x%08x (age=%d)",		    SSL_GETPID(), ss->fd, ss->sec.ci.peer, 		    ssl_Time() - sid->creationTime));	PRINT_BUF(1, (ss, "session-id value:", sd, sdLen));	ss->sec.ci.sid = sid;	ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;	hit = 1;	certLen = 0;	csLen = 0;        ss->sec.authAlgorithm = sid->authAlgorithm;	ss->sec.authKeyBits   = sid->authKeyBits;	ss->sec.keaType       = sid->keaType;	ss->sec.keaKeyBits    = sid->keaKeyBits;	rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE);	if (rv != SECSuccess) {	    goto loser;	}    } else {	SECItem * derCert   = &serverCert->derCert;	SSL_TRC(7, ("%d: SSL[%d]: server, lookup nonce missed",		    SSL_GETPID(), ss->fd));	if (!serverCert) {	    SET_ERROR_CODE	    goto loser;	}	hit = 0;	sid = (sslSessionID*) PORT_ZAlloc(sizeof(sslSessionID));	if (!sid) {	    goto loser;	}	sid->references = 1;	sid->addr = ss->sec.ci.peer;	sid->port = ss->sec.ci.port;	/* Invent a session-id */	ss->sec.ci.sid = sid;	PK11_GenerateRandom(sid->u.ssl2.sessionID+2, SSL2_SESSIONID_BYTES-2);	pid = SSL_GETPID();	sid->u.ssl2.sessionID[0] = MSB(pid);	sid->u.ssl2.sessionID[1] = LSB(pid);	cert    = derCert->data;	certLen = derCert->len;	/* pretend that server sids remember the local cert. */	PORT_Assert(!sid->localCert);	if (sid->localCert) {	    CERT_DestroyCertificate(sid->localCert);	}	sid->localCert     = CERT_DupCertificate(serverCert);	ss->sec.authAlgorithm = ssl_sign_rsa;	ss->sec.keaType       = ssl_kea_rsa;	ss->sec.keaKeyBits    = \	ss->sec.authKeyBits   = ss->serverCerts[kt_rsa].serverKeyBits;    }    /* server sids don't remember the local cert, so whether we found    ** a sid or not, just "remember" we used the rsa server cert.    */    if (ss->sec.localCert) {	CERT_DestroyCertificate(ss->sec.localCert);    }    ss->sec.localCert     = CERT_DupCertificate(serverCert);    /* Build up final list of required elements */    ss->sec.ci.requiredElements = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED;    if (ss->requestCertificate) {	ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE;    }    ss->sec.ci.sentElements = 0;    /* Send hello message back to client */    sendLen = SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen	    + SSL_CONNECTIONID_BYTES;    ssl_GetXmitBufLock(ss); gotXmitBufLock = 1;    rv = ssl2_GetSendBuffer(ss, sendLen);    if (rv != SECSuccess) {	goto loser;    }    SSL_TRC(3, ("%d: SSL[%d]: sending server-hello (%d)",		SSL_GETPID(), ss->fd, sendLen));    msg = ss->sec.ci.sendBuf.buf;    msg[0] = SSL_MT_SERVER_HELLO;    msg[1] = hit;    msg[2] = SSL_CT_X509_CERTIFICATE;    msg[3] = MSB(ss->version);    msg[4] = LSB(ss->version);    msg[5] = MSB(certLen);    msg[6] = LSB(certLen);    msg[7] = MSB(csLen);    msg[8] = LSB(csLen);    msg[9] = MSB(SSL_CONNECTIONID_BYTES);    msg[10] = LSB(SSL_CONNECTIONID_BYTES);    if (certLen) {	PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES, cert, certLen);    }    if (csLen) {	PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES+certLen, cs, csLen);    }    PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES+certLen+csLen,                 ss->sec.ci.connectionID, SSL_CONNECTIONID_BYTES);    DUMP_MSG(29, (ss, msg, sendLen));    ss->handshakeBegun = 1;    sent = (*ss->sec.send)(ss, msg, sendLen, 0);    if (sent < 0) {	goto loser;    }    ssl_ReleaseXmitBufLock(ss); gotXmitBufLock = 0;    ss->gs.recordLen = 0;    ss->handshake = ssl_GatherRecord1stHandshake;    if (hit) {	/* Old SID Session key is good. Go encrypted */	ssl2_UseEncryptedSendFunc(ss);	/* Send server verify message now that keys are established */	rv = ssl2_SendServerVerifyMessage(ss);	if (rv != SECSuccess) 	    goto loser;	ss->nextHandshake = ssl2_HandleMessage;	ssl_ReleaseRecvBufLock(ss);	rv = ssl2_TriggerNextMessage(ss);	return rv;    }    ss->nextHandshake = ssl2_HandleClientSessionKeyMessage;    ssl_ReleaseRecvBufLock(ss);    return SECSuccess;  bad_client:    PORT_SetError(SSL_ERROR_BAD_CLIENT);    /* FALLTHROUGH */  loser:    if (gotXmitBufLock) {    	ssl_ReleaseXmitBufLock(ss); gotXmitBufLock = 0;    }    SSL_TRC(10, ("%d: SSL[%d]: server, wait for client-hello lossage",		 SSL_GETPID(), ss->fd));    ssl_ReleaseRecvBufLock(ss);    return SECFailure;}