if (ssl3->hs.ws != wait_cert_request && ssl3->hs.ws != wait_server_key) {
if (ss->ssl3.hs.ws != wait_cert_request && ss->ssl3.hs.ws != wait_server_key) {
ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length){    ssl3State *          ssl3        = ss->ssl3;    PRArenaPool *        arena       = NULL;    dnameNode *          node;    PRInt32              remaining;    PRBool               isTLS       = PR_FALSE;    int                  i;    int                  errCode     = SSL_ERROR_RX_MALFORMED_CERT_REQUEST;    int                  nnames      = 0;    SECStatus            rv;    SSL3AlertDescription desc        = illegal_parameter;    SECItem              cert_types  = {siBuffer, NULL, 0};    CERTDistNames        ca_list;    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",		SSL_GETPID(), ss->fd));    PORT_Assert( ssl_HaveRecvBufLock(ss) );    PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );    if (ssl3->hs.ws != wait_cert_request &&    	ssl3->hs.ws != wait_server_key) {	desc    = unexpected_message;	errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;	goto alert_loser;    }    /* clean up anything left from previous handshake. */    if (ssl3->clientCertChain != NULL) {       CERT_DestroyCertificateList(ssl3->clientCertChain);       ssl3->clientCertChain = NULL;    }    isTLS = (PRBool)(ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0);    rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);    if (rv != SECSuccess)    	goto loser;		/* malformed, alert has been sent */    arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if (arena == NULL)    	goto no_mem;    remaining = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);    if (remaining < 0)    	goto loser;	 	/* malformed, alert has been sent */    if ((PRUint32)remaining > length)	goto alert_loser;    ca_list.head = node = PORT_ArenaZNew(arena, dnameNode);    if (node == NULL)    	goto no_mem;    while (remaining > 0) {	PRInt32 len;	if (remaining < 2)	    goto alert_loser;	/* malformed */	node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);	if (len <= 0)	    goto loser;		/* malformed, alert has been sent */	remaining -= 2;	if (remaining < len)	    goto alert_loser;	/* malformed */	node->name.data = b;	b         += len;	length    -= len;	remaining -= len;	nnames++;	if (remaining <= 0)	    break;		/* success */	node->next = PORT_ArenaZNew(arena, dnameNode);	node = node->next;	if (node == NULL)	    goto no_mem;    }    ca_list.nnames = nnames;    ca_list.names  = (SECItem*)PORT_ArenaAlloc(arena, nnames * sizeof(SECItem));    if (nnames > 0 && ca_list.names == NULL)        goto no_mem;    for(i = 0, node = (dnameNode*)ca_list.head;	i < nnames;	i++, node = node->next) {	ca_list.names[i] = node->name;    }    if (length != 0)        goto alert_loser;   	/* malformed */    desc = no_certificate;    ssl3->hs.ws = wait_hello_done;    if (ss->getClientAuthData == NULL) {	rv = SECFailure; /* force it to send a no_certificate alert */    } else {	/* XXX Should pass cert_types in this call!! */	rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,						 ss->fd, &ca_list,						 &ssl3->clientCertificate,						 &ssl3->clientPrivateKey);    }    switch (rv) {    case SECWouldBlock:	/* getClientAuthData has put up a dialog box. */	ssl_SetAlwaysBlock(ss);	break;	/* not an error */    case SECSuccess:        /* check what the callback function returned */        if ((!ssl3->clientCertificate) || (!ssl3->clientPrivateKey)) {            /* we are missing either the key or cert */            if (ssl3->clientCertificate) {                /* got a cert, but no key - free it */                CERT_DestroyCertificate(ssl3->clientCertificate);                ssl3->clientCertificate = NULL;            }            if (ssl3->clientPrivateKey) {                /* got a key, but no cert - free it */                SECKEY_DestroyPrivateKey(ssl3->clientPrivateKey);                ssl3->clientPrivateKey = NULL;            }            goto send_no_certificate;        }	/* Setting ssl3->clientCertChain non-NULL will cause	 * ssl3_HandleServerHelloDone to call SendCertificate.	 */	ssl3->clientCertChain = CERT_CertChainFromCert(ssl3->clientCertificate,			certUsageSSLClient, PR_FALSE);	if (ssl3->clientCertChain == NULL) {	    if (ssl3->clientCertificate != NULL) {		CERT_DestroyCertificate(ssl3->clientCertificate);		ssl3->clientCertificate = NULL;	    }	    if (ssl3->clientPrivateKey != NULL) {		SECKEY_DestroyPrivateKey(ssl3->clientPrivateKey);		ssl3->clientPrivateKey = NULL;	    }	    goto send_no_certificate;	}	break;	/* not an error */    case SECFailure:    default:send_no_certificate:	if (isTLS) {	    ssl3->sendEmptyCert = PR_TRUE;	} else {	    (void)SSL3_SendAlert(ss, alert_warning, no_certificate);	}	rv = SECSuccess;	break;    }    goto done;no_mem:    rv = SECFailure;    PORT_SetError(SEC_ERROR_NO_MEMORY);    goto done;alert_loser:    if (isTLS && desc == illegal_parameter)    	desc = decode_error;    (void)SSL3_SendAlert(ss, alert_fatal, desc);loser:    PORT_SetError(errCode);    rv = SECFailure;done:    if (arena != NULL)    	PORT_FreeArena(arena, PR_FALSE);    if (cert_types.data != NULL)    	SECITEM_FreeItem(&cert_types, PR_FALSE);    return rv;}