/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock. * * Currently, the list of functions called through ss->handshake is: * * In sslsocks.c: * SocksGatherRecord * SocksHandleReply * SocksStartGather * * In sslcon.c: * ssl_GatherRecord1stHandshake * ssl2_HandleClientSessionKeyMessage * ssl2_HandleMessage * ssl2_HandleVerifyMessage * ssl2_BeginClientHandshake * ssl2_BeginServerHandshake * ssl2_HandleClientHelloMessage * ssl2_HandleServerHelloMessage * * The ss->handshake function returns SECWouldBlock under these conditions: * 1. ssl_GatherRecord1stHandshake called ssl2_GatherData which read in * the beginning of an SSL v3 hello message and returned SECWouldBlock * to switch to SSL v3 handshake processing. * * 2. ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming * v2 client hello msg, and called ssl3_HandleV2ClientHello which * returned SECWouldBlock. * * 3. SECWouldBlock was returned by one of the callback functions, via * one of these paths: * - ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() -> * ss->getClientAuthData() * * - ssl2_HandleServerHelloMessage() -> ss->handleBadCert() * * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> * ssl3_HandleRecord() -> ssl3_HandleHandshake() -> * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() -> * ss->handleBadCert() * * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> * ssl3_HandleRecord() -> ssl3_HandleHandshake() -> * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() -> * ss->getClientAuthData() * * Called from: SSL_ForceHandshake (below), * ssl_SecureRecv (below) and * ssl_SecureSend (below) * from: WaitForResponse in sslsocks.c * ssl_SocksRecv in sslsocks.c * ssl_SocksSend in sslsocks.c * * Caller must hold the (write) handshakeLock. */ int ssl_Do1stHandshake(sslSocket *ss) { int rv = SECSuccess; int loopCount = 0; do { PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); if (ss->handshake == 0) { /* Previous handshake finished. Switch to next one */ ss->handshake = ss->nextHandshake; ss->nextHandshake = 0; } if (ss->handshake == 0) { /* Previous handshake finished. Switch to security handshake */ ss->handshake = ss->securityHandshake; ss->securityHandshake = 0; } if (ss->handshake == 0) { /* for v3 this is done in ssl3_FinishHandshake */ if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) { ssl_GetRecvBufLock(ss); ss->gs.recordLen = 0; ssl_FinishHandshake(ss); ssl_ReleaseRecvBufLock(ss); } break; } rv = (*ss->handshake)(ss); ++loopCount; /* This code must continue to loop on SECWouldBlock, * or any positive value. See XXX_1 comments. */ } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */ PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); if (rv == SECWouldBlock) { PORT_SetError(PR_WOULD_BLOCK_ERROR); rv = SECFailure; } return rv; }
int ssl_Do1stHandshake(sslSocket *ss) { int rv = SECSuccess; int loopCount = 0; do { PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); if (ss->handshake == 0) { ss->handshake = ss->nextHandshake; ss->nextHandshake = 0; } if (ss->handshake == 0) { ss->handshake = ss->securityHandshake; ss->securityHandshake = 0; } if (ss->handshake == 0) { if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) { ssl_GetRecvBufLock(ss); ss->gs.recordLen = 0; ssl_FinishHandshake(ss); ssl_ReleaseRecvBufLock(ss); } break; } rv = (*ss->handshake)(ss); ++loopCount; } while (rv != SECFailure); PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); if (rv == SECWouldBlock) { PORT_SetError(PR_WOULD_BLOCK_ERROR); rv = SECFailure; } return rv; }