Reinterpret the READ and WRITE poll flags depending on the state of the

socket and the SSL handshake.  Rename the badly named "connected" flag.
Bugzilla bugs 56924, 56926, 66706.
Modified Files:
    ssl3con.c sslauth.c sslcon.c ssldef.c sslgathr.c sslimpl.h
    sslsecur.c sslsock.c
This commit is contained in:
nelsonb%netscape.com 2001-03-16 23:26:06 +00:00
Родитель 0fa0b3f419
Коммит 46c15355d3
8 изменённых файлов: 169 добавлений и 80 удалений

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: ssl3con.c,v 1.16 2001/02/07 00:34:54 nelsonb%netscape.com Exp $ * $Id: ssl3con.c,v 1.17 2001/03/16 23:25:59 nelsonb%netscape.com Exp $
*/ */
#include "nssrenam.h" #include "nssrenam.h"
@ -1327,6 +1327,7 @@ spec_locked_loser:
if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
ss->handshakeBegun = 1;
count = ssl_SendSavedWriteData(ss, &ss->pendingBuf, count = ssl_SendSavedWriteData(ss, &ss->pendingBuf,
&ssl_DefSend); &ssl_DefSend);
if (count < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) { if (count < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) {
@ -1335,6 +1336,7 @@ spec_locked_loser:
} }
} }
} else if (write->len > 0) { } else if (write->len > 0) {
ss->handshakeBegun = 1;
count = ssl_DefSend(ss, write->buf, write->len, count = ssl_DefSend(ss, write->buf, write->len,
flags & ~ssl_SEND_FLAG_MASK); flags & ~ssl_SEND_FLAG_MASK);
if (count < 0) { if (count < 0) {
@ -1455,12 +1457,12 @@ ssl3_HandleNoCertificate(sslSocket *ss)
/* If the server has required client-auth blindly but doesn't /* If the server has required client-auth blindly but doesn't
* actually look at the certificate it won't know that no * actually look at the certificate it won't know that no
* certificate was presented so we shutdown the socket to ensure * certificate was presented so we shutdown the socket to ensure
* an error. We only do this if we aren't connected because * an error. We only do this if we haven't already completed the
* if we're redoing the handshake we know the server is paying * first handshake because if we're redoing the handshake we
* attention to the certificate. * know the server is paying attention to the certificate.
*/ */
if ((ss->requireCertificate == 1) || if ((ss->requireCertificate == 1) ||
(!ss->connected && (ss->requireCertificate > 1))) { (!ss->firstHsDone && (ss->requireCertificate > 1))) {
PRFileDesc * lower; PRFileDesc * lower;
ss->sec->uncache(ss->sec->ci.sid); ss->sec->uncache(ss->sec->ci.sid);
@ -4616,7 +4618,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
*/ */
if ((sid->peerCert == NULL) && ss->requestCertificate && if ((sid->peerCert == NULL) && ss->requestCertificate &&
((ss->requireCertificate == 1) || ((ss->requireCertificate == 1) ||
((ss->requireCertificate == 2) && !ss->connected))) { ((ss->requireCertificate == 2) && !ss->firstHsDone))) {
++ssl3stats.hch_sid_cache_not_ok; ++ssl3stats.hch_sid_cache_not_ok;
ss->sec->uncache(sid); ss->sec->uncache(sid);
@ -6494,9 +6496,9 @@ xmit_loser:
ssl_ReleaseXmitBufLock(ss); /*************************************/ ssl_ReleaseXmitBufLock(ss); /*************************************/
/* we're connected now. */ /* The first handshake is now completed. */
ss->handshake = NULL; ss->handshake = NULL;
ss->connected = PR_TRUE; ss->firstHsDone = PR_TRUE;
ss->gather->writeOffset = 0; ss->gather->writeOffset = 0;
ss->gather->readOffset = 0; ss->gather->readOffset = 0;
@ -7445,7 +7447,8 @@ ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size)
} }
/* /*
** If ssl3 socket is connected and in idle state, then start a new handshake. ** If ssl3 socket has completed the first handshake, and is in idle state,
** then start a new handshake.
** If flushCache is true, the SID cache will be flushed first, forcing a ** If flushCache is true, the SID cache will be flushed first, forcing a
** "Full" handshake (not a session restart handshake), to be done. ** "Full" handshake (not a session restart handshake), to be done.
** **
@ -7460,7 +7463,7 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache)
PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );
if (!ss->connected || if (!ss->firstHsDone ||
((ss->version >= SSL_LIBRARY_VERSION_3_0) && ((ss->version >= SSL_LIBRARY_VERSION_3_0) &&
ss->ssl3 && (ss->ssl3->hs.ws != idle_handshake))) { ss->ssl3 && (ss->ssl3->hs.ws != idle_handshake))) {
PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);

Просмотреть файл

@ -30,7 +30,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: sslauth.c,v 1.4 2001/02/09 02:11:30 nelsonb%netscape.com Exp $ * $Id: sslauth.c,v 1.5 2001/03/16 23:26:02 nelsonb%netscape.com Exp $
*/ */
#include "cert.h" #include "cert.h"
#include "secitem.h" #include "secitem.h"
@ -84,7 +84,7 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
*op = SSL_SECURITY_STATUS_OFF; *op = SSL_SECURITY_STATUS_OFF;
} }
if (ss->useSecurity && ss->connected) { if (ss->useSecurity && ss->firstHsDone) {
PORT_Assert(ss->sec != 0); PORT_Assert(ss->sec != 0);
sec = ss->sec; sec = ss->sec;

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: sslcon.c,v 1.6 2001/01/30 21:02:24 wtc%netscape.com Exp $ * $Id: sslcon.c,v 1.7 2001/03/16 23:26:02 nelsonb%netscape.com Exp $
*/ */
#include "nssrenam.h" #include "nssrenam.h"
@ -546,6 +546,7 @@ ssl2_SendErrorMessage(sslSocket *ss, int error)
SSL_TRC(3, ("%d: SSL[%d]: sending error %d", SSL_GETPID(), ss->fd, error)); SSL_TRC(3, ("%d: SSL[%d]: sending error %d", SSL_GETPID(), ss->fd, error));
ss->handshakeBegun = 1;
rv = (*sec->send)(ss, msg, sizeof(msg), 0); rv = (*sec->send)(ss, msg, sizeof(msg), 0);
if (rv >= 0) { if (rv >= 0) {
rv = SECSuccess; rv = SECSuccess;
@ -3102,6 +3103,7 @@ invalid:
/* Send it to the server */ /* Send it to the server */
DUMP_MSG(29, (ss, msg, sendLen)); DUMP_MSG(29, (ss, msg, sendLen));
ss->handshakeBegun = 1;
rv = (*sec->send)(ss, msg, sendLen, 0); rv = (*sec->send)(ss, msg, sendLen, 0);
ssl_ReleaseXmitBufLock(ss); /***************************************/ ssl_ReleaseXmitBufLock(ss); /***************************************/
@ -3595,6 +3597,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
DUMP_MSG(29, (ss, msg, sendLen)); DUMP_MSG(29, (ss, msg, sendLen));
ss->handshakeBegun = 1;
sent = (*sec->send)(ss, msg, sendLen, 0); sent = (*sec->send)(ss, msg, sendLen, 0);
if (sent < 0) { if (sent < 0) {
goto loser; goto loser;

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: ssldef.c,v 1.2 2000/10/07 02:22:22 nelsonb%netscape.com Exp $ * $Id: ssldef.c,v 1.3 2001/03/16 23:26:03 nelsonb%netscape.com Exp $
*/ */
#include "cert.h" #include "cert.h"
@ -115,8 +115,10 @@ int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
if (rv < 0) { if (rv < 0) {
PRErrorCode err = PR_GetError(); PRErrorCode err = PR_GetError();
if (err == PR_WOULD_BLOCK_ERROR) { if (err == PR_WOULD_BLOCK_ERROR) {
ss->lastWriteBlocked = 1;
return count ? count : rv; return count ? count : rv;
} }
ss->lastWriteBlocked = 0;
MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR) MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
/* Loser */ /* Loser */
return rv; return rv;
@ -130,6 +132,7 @@ int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
} }
break; break;
} }
ss->lastWriteBlocked = 0;
return count; return count;
} }
@ -157,8 +160,10 @@ int ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
if (rv < 0) { if (rv < 0) {
PRErrorCode err = PR_GetError(); PRErrorCode err = PR_GetError();
if (err == PR_WOULD_BLOCK_ERROR) { if (err == PR_WOULD_BLOCK_ERROR) {
ss->lastWriteBlocked = 1;
return count ? count : rv; return count ? count : rv;
} }
ss->lastWriteBlocked = 0;
MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR) MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
/* Loser */ /* Loser */
return rv; return rv;
@ -172,6 +177,7 @@ int ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
} }
break; break;
} }
ss->lastWriteBlocked = 0;
return count; return count;
} }

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: sslgathr.c,v 1.2 2000/12/02 00:54:01 nelsonb%netscape.com Exp $ * $Id: sslgathr.c,v 1.3 2001/03/16 23:26:04 nelsonb%netscape.com Exp $
*/ */
#include "cert.h" #include "cert.h"
#include "ssl.h" #include "ssl.h"
@ -139,7 +139,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
/* Probably finished this piece */ /* Probably finished this piece */
switch (gs->state) { switch (gs->state) {
case GS_HEADER: case GS_HEADER:
if ((ss->enableSSL3 || ss->enableTLS) && !ss->connected) { if ((ss->enableSSL3 || ss->enableTLS) && !ss->firstHsDone) {
PORT_Assert( ssl_Have1stHandshakeLock(ss) ); PORT_Assert( ssl_Have1stHandshakeLock(ss) );
@ -183,7 +183,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
return SECFailure; return SECFailure;
} }
} }
} /* ((ss->enableSSL3 || ss->enableTLS) && !ss->connected) */ } /* ((ss->enableSSL3 || ss->enableTLS) && !ss->firstHsDone) */
/* we've got the first 3 bytes. The header may be two or three. */ /* we've got the first 3 bytes. The header may be two or three. */
if (gs->hdr[0] & 0x80) { if (gs->hdr[0] & 0x80) {

Просмотреть файл

@ -33,7 +33,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: sslimpl.h,v 1.10 2001/02/07 17:50:43 wtc%netscape.com Exp $ * $Id: sslimpl.h,v 1.11 2001/03/16 23:26:04 nelsonb%netscape.com Exp $
*/ */
#ifndef __sslimpl_h_ #ifndef __sslimpl_h_
@ -238,6 +238,11 @@ typedef struct sslOptionsStr {
unsigned int detectRollBack : 1; /* 14 */ unsigned int detectRollBack : 1; /* 14 */
} sslOptions; } sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
sslHandshakingAsClient,
sslHandshakingAsServer
} sslHandshakingType;
/* /*
** SSL Socket struct ** SSL Socket struct
** **
@ -254,20 +259,23 @@ struct sslSocketStr {
unsigned int useSecurity : 1; unsigned int useSecurity : 1;
unsigned int requestCertificate : 1; unsigned int requestCertificate : 1;
unsigned int requireCertificate : 2; unsigned int requireCertificate : 2;
unsigned int handshakeAsClient : 1; unsigned int handshakeAsClient : 1;
unsigned int handshakeAsServer : 1; unsigned int handshakeAsServer : 1;
unsigned int enableSSL2 : 1; unsigned int enableSSL2 : 1;
unsigned int enableSSL3 : 1; unsigned int enableSSL3 : 1;
unsigned int enableTLS : 1; unsigned int enableTLS : 1;
unsigned int clientAuthRequested: 1; unsigned int clientAuthRequested: 1;
unsigned int noCache : 1; unsigned int noCache : 1;
unsigned int fdx : 1; /* simultaneous read/write threads */ unsigned int fdx : 1; /* simultaneous read/write threads */
unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */ unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */
unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */ unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */
unsigned int connected : 1; /* initial handshake is complete. */ unsigned int firstHsDone : 1; /* first handshake is complete. */
unsigned int recvdCloseNotify : 1; /* received SSL EOF. */ unsigned int recvdCloseNotify : 1; /* received SSL EOF. */
unsigned int lastWriteBlocked : 1;
unsigned int TCPconnected : 1;
unsigned int handshakeBegun : 1;
/* version of the protocol to use */ /* version of the protocol to use */
SSL3ProtocolVersion version; SSL3ProtocolVersion version;
@ -353,6 +361,8 @@ const unsigned char * preferredCipher;
PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */ PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */
PRUint16 chosenPreference; /* SSL2 cipher preferences. */ PRUint16 chosenPreference; /* SSL2 cipher preferences. */
sslHandshakingType handshaking;
ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED]; ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
}; };

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: sslsecur.c,v 1.7 2001/02/09 02:11:30 nelsonb%netscape.com Exp $ * $Id: sslsecur.c,v 1.8 2001/03/16 23:26:05 nelsonb%netscape.com Exp $
*/ */
#include "cert.h" #include "cert.h"
#include "secitem.h" #include "secitem.h"
@ -143,12 +143,12 @@ ssl_Do1stHandshake(sslSocket *ss)
/* for v3 this is done in ssl3_HandleFinished() */ /* for v3 this is done in ssl3_HandleFinished() */
if ((ss->sec != NULL) && /* used SSL */ if ((ss->sec != NULL) && /* used SSL */
(ss->handshakeCallback != NULL) && /* has callback */ (ss->handshakeCallback != NULL) && /* has callback */
(!ss->connected) && /* only first time */ (!ss->firstHsDone) && /* only first time */
(ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */ (ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */
ss->connected = PR_TRUE; ss->firstHsDone = PR_TRUE;
(ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
} }
ss->connected = PR_TRUE; ss->firstHsDone = PR_TRUE;
ss->gather->writeOffset = 0; ss->gather->writeOffset = 0;
ss->gather->readOffset = 0; ss->gather->readOffset = 0;
break; break;
@ -187,7 +187,7 @@ AlwaysBlock(sslSocket *ss)
void void
ssl_SetAlwaysBlock(sslSocket *ss) ssl_SetAlwaysBlock(sslSocket *ss)
{ {
if (!ss->connected) { if (!ss->firstHsDone) {
ss->handshake = AlwaysBlock; ss->handshake = AlwaysBlock;
ss->nextHandshake = 0; ss->nextHandshake = 0;
} }
@ -200,6 +200,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
{ {
sslSocket *ss; sslSocket *ss;
SECStatus rv; SECStatus rv;
PRNetAddr addr;
ss = ssl_FindSocket(s); ss = ssl_FindSocket(s);
if (!ss) { if (!ss) {
@ -218,9 +219,14 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
ssl_Get1stHandshakeLock(ss); ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss);
ss->connected = PR_FALSE; ss->firstHsDone = PR_FALSE;
ss->handshake = asServer ? ssl2_BeginServerHandshake if ( asServer ) {
: ssl2_BeginClientHandshake; ss->securityHandshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
} else {
ss->securityHandshake = ssl2_BeginClientHandshake;
ss->handshaking = sslHandshakingAsClient;
}
ss->nextHandshake = 0; ss->nextHandshake = 0;
ss->securityHandshake = 0; ss->securityHandshake = 0;
@ -244,6 +250,9 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
ssl_ReleaseSSL3HandshakeLock(ss); ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss); ssl_Release1stHandshakeLock(ss);
if (!ss->TCPconnected)
ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
SSL_UNLOCK_WRITER(ss); SSL_UNLOCK_WRITER(ss);
SSL_UNLOCK_READER(ss); SSL_UNLOCK_READER(ss);
@ -369,10 +378,11 @@ SSL_ForceHandshake(PRFileDesc *fd)
} else if (gatherResult == SECWouldBlock) { } else if (gatherResult == SECWouldBlock) {
PORT_SetError(PR_WOULD_BLOCK_ERROR); PORT_SetError(PR_WOULD_BLOCK_ERROR);
} }
} else if (!ss->connected) { } else if (!ss->firstHsDone) {
rv = ssl_Do1stHandshake(ss); rv = ssl_Do1stHandshake(ss);
} else { } else {
/* tried to force handshake on a connected SSL 2 socket. */ /* tried to force handshake on an SSL 2 socket that has
** already completed the handshake. */
rv = SECSuccess; /* just pretend we did it. */ rv = SECSuccess; /* just pretend we did it. */
} }
@ -882,32 +892,29 @@ ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
PORT_Assert(ss->sec != 0); PORT_Assert(ss->sec != 0);
/* First connect to server */
rv = osfd->methods->connect(osfd, sa, ss->cTimeout);
if (rv < 0) {
int olderrno = PR_GetError();
SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
SSL_GETPID(), ss->fd, olderrno));
if ((olderrno == PR_IS_CONNECTED_ERROR) ||
(olderrno == PR_IN_PROGRESS_ERROR)) {
/*
** Connected or trying to connect. Caller is Using a non-blocking
** connect. Go ahead and set things up.
*/
} else {
return rv;
}
}
SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, setting up handshake",
SSL_GETPID(), ss->fd));
if ( ss->handshakeAsServer ) { if ( ss->handshakeAsServer ) {
ss->securityHandshake = ssl2_BeginServerHandshake; ss->securityHandshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
} else { } else {
ss->securityHandshake = ssl2_BeginClientHandshake; ss->securityHandshake = ssl2_BeginClientHandshake;
ss->handshaking = sslHandshakingAsClient;
} }
/* connect to server */
rv = osfd->methods->connect(osfd, sa, ss->cTimeout);
if (rv == PR_SUCCESS) {
ss->TCPconnected = 1;
} else {
int err = PR_GetError();
SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
SSL_GETPID(), ss->fd, err));
if (err == PR_IS_CONNECTED_ERROR) {
ss->TCPconnected = 1;
}
}
SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, rv == %d",
SSL_GETPID(), ss->fd, rv));
return rv; return rv;
} }
@ -917,8 +924,9 @@ ssl_SecureClose(sslSocket *ss)
int rv; int rv;
if (ss->version >= SSL_LIBRARY_VERSION_3_0 && if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
ss->connected && ss->firstHsDone &&
!(ss->shutdownHow & ssl_SHUTDOWN_SEND) && !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
!ss->recvdCloseNotify &&
(ss->ssl3 != NULL)) { (ss->ssl3 != NULL)) {
(void) SSL3_SendAlert(ss, alert_warning, close_notify); (void) SSL3_SendAlert(ss, alert_warning, close_notify);
@ -943,7 +951,8 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow)
if ((sslHow & ssl_SHUTDOWN_SEND) != 0 && if ((sslHow & ssl_SHUTDOWN_SEND) != 0 &&
!(ss->shutdownHow & ssl_SHUTDOWN_SEND) && !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
(ss->version >= SSL_LIBRARY_VERSION_3_0) && (ss->version >= SSL_LIBRARY_VERSION_3_0) &&
ss->connected && ss->firstHsDone &&
!ss->recvdCloseNotify &&
(ss->ssl3 != NULL)) { (ss->ssl3 != NULL)) {
(void) SSL3_SendAlert(ss, alert_warning, close_notify); (void) SSL3_SendAlert(ss, alert_warning, close_notify);
@ -992,7 +1001,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
rv = 0; rv = 0;
/* If any of these is non-zero, the initial handshake is not done. */ /* If any of these is non-zero, the initial handshake is not done. */
if (!ss->connected) { if (!ss->firstHsDone) {
ssl_Get1stHandshakeLock(ss); ssl_Get1stHandshakeLock(ss);
if (ss->handshake || ss->nextHandshake || ss->securityHandshake) { if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
rv = ssl_Do1stHandshake(ss); rv = ssl_Do1stHandshake(ss);
@ -1054,7 +1063,7 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
if (len > 0) if (len > 0)
ss->writerThread = PR_GetCurrentThread(); ss->writerThread = PR_GetCurrentThread();
/* If any of these is non-zero, the initial handshake is not done. */ /* If any of these is non-zero, the initial handshake is not done. */
if (!ss->connected) { if (!ss->firstHsDone) {
ssl_Get1stHandshakeLock(ss); ssl_Get1stHandshakeLock(ss);
if (ss->handshake || ss->nextHandshake || ss->securityHandshake) { if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
rv = ssl_Do1stHandshake(ss); rv = ssl_Do1stHandshake(ss);
@ -1214,7 +1223,7 @@ SSL_GetSessionID(PRFileDesc *fd)
ssl_Get1stHandshakeLock(ss); ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss);
if (ss->useSecurity && ss->connected && ss->sec && ss->sec->ci.sid) { if (ss->useSecurity && ss->firstHsDone && ss->sec && ss->sec->ci.sid) {
sid = ss->sec->ci.sid; sid = ss->sec->ci.sid;
item = (SECItem *)PORT_Alloc(sizeof(SECItem)); item = (SECItem *)PORT_Alloc(sizeof(SECItem));
if (sid->version < SSL_LIBRARY_VERSION_3_0) { if (sid->version < SSL_LIBRARY_VERSION_3_0) {

Просмотреть файл

@ -34,7 +34,7 @@
* may use your version of this file under either the MPL or the * may use your version of this file under either the MPL or the
* GPL. * GPL.
* *
* $Id: sslsock.c,v 1.13 2001/02/09 02:11:31 nelsonb%netscape.com Exp $ * $Id: sslsock.c,v 1.14 2001/03/16 23:26:06 nelsonb%netscape.com Exp $
*/ */
#include "seccomon.h" #include "seccomon.h"
#include "cert.h" #include "cert.h"
@ -897,6 +897,7 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
{ {
sslSocket * ns = NULL; sslSocket * ns = NULL;
PRStatus rv; PRStatus rv;
PRNetAddr addr;
if (model == NULL) { if (model == NULL) {
/* Just create a default socket if we're given NULL for the model */ /* Just create a default socket if we're given NULL for the model */
@ -922,6 +923,10 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
#ifdef _WIN32 #ifdef _WIN32
PR_Sleep(PR_INTERVAL_NO_WAIT); /* workaround NT winsock connect bug. */ PR_Sleep(PR_INTERVAL_NO_WAIT); /* workaround NT winsock connect bug. */
#endif #endif
ns = ssl_FindSocket(fd);
PORT_Assert(ns);
if (ns)
ns->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ns, &addr));
return fd; return fd;
} }
@ -984,10 +989,13 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout)
if ( ns->useSecurity ) { if ( ns->useSecurity ) {
if ( ns->handshakeAsClient ) { if ( ns->handshakeAsClient ) {
ns->handshake = ssl2_BeginClientHandshake; ns->handshake = ssl2_BeginClientHandshake;
ss->handshaking = sslHandshakingAsClient;
} else { } else {
ns->handshake = ssl2_BeginServerHandshake; ns->handshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
} }
} }
ns->TCPconnected = 1;
return newfd; return newfd;
loser: loser:
@ -1236,6 +1244,7 @@ ssl_GetPeerInfo(sslSocket *ss)
if (rv < 0) { if (rv < 0) {
return SECFailure; return SECFailure;
} }
ss->TCPconnected = 1;
/* we have to mask off the high byte because AIX is lame */ /* we have to mask off the high byte because AIX is lame */
if ((sin.inet.family & 0xff) == PR_AF_INET) { if ((sin.inet.family & 0xff) == PR_AF_INET) {
PR_ConvertIPv4AddrToIPv6(sin.inet.ip, &ci->peer); PR_ConvertIPv4AddrToIPv6(sin.inet.ip, &ci->peer);
@ -1277,13 +1286,16 @@ SSL_SetSockPeerID(PRFileDesc *fd, char *peerID)
return SECSuccess; return SECSuccess;
} }
#define PR_POLL_RW (PR_POLL_WRITE | PR_POLL_READ)
static PRInt16 PR_CALLBACK static PRInt16 PR_CALLBACK
ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *out_flags) ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
{ {
sslSocket *ss; sslSocket *ss;
PRInt16 ret_flags = how_flags; /* should select on these flags. */ PRInt16 new_flags = how_flags; /* should select on these flags. */
PRNetAddr addr;
*out_flags = 0; *p_out_flags = 0;
ss = ssl_GetPrivate(fd); ss = ssl_GetPrivate(fd);
if (!ss) { if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in SSL_Poll", SSL_DBG(("%d: SSL[%d]: bad socket in SSL_Poll",
@ -1291,27 +1303,73 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *out_flags)
return 0; /* don't poll on this socket */ return 0; /* don't poll on this socket */
} }
if ((ret_flags & PR_POLL_WRITE) && if (ss->useSecurity &&
ss->useSecurity && ss->handshaking != sslHandshakingUndetermined &&
!ss->connected && !ss->firstHsDone &&
/* XXX There needs to be a better test than the following. */ (how_flags & PR_POLL_RW)) {
/* Don't check ss->securityHandshake. */ if (!ss->TCPconnected) {
(ss->handshake || ss->nextHandshake)) { ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
/* The user is trying to write, but the handshake is blocked waiting }
* to read, so tell NSPR NOT to poll on write. /* If it's not connected, then presumably the application is polling
** on read or write appropriately, so don't change it.
*/ */
ret_flags ^= PR_POLL_WRITE; /* don't select on write. */ if (ss->TCPconnected) {
ret_flags |= PR_POLL_READ; /* do select on read. */ if (!ss->handshakeBegun) {
/* If the handshake has not begun, poll on read or write
** based on the local application's role in the handshake,
** not based on what the application requested.
*/
new_flags &= ~PR_POLL_RW;
if (ss->handshaking == sslHandshakingAsClient) {
new_flags |= PR_POLL_WRITE;
} else { /* handshaking as server */
new_flags |= PR_POLL_READ;
}
} else
/* First handshake is in progress */
if (ss->lastWriteBlocked) {
if (new_flags & PR_POLL_READ) {
/* The caller is waiting for data to be received,
** but the initial handshake is blocked on write, or the
** client's first handshake record has not been written.
** The code should select on write, not read.
*/
new_flags ^= PR_POLL_READ; /* don't select on read. */
new_flags |= PR_POLL_WRITE; /* do select on write. */
}
} else if (new_flags & PR_POLL_WRITE) {
/* The caller is trying to write, but the handshake is
** blocked waiting for data to read, and the first
** handshake has been sent. so do NOT to poll on write.
*/
new_flags ^= PR_POLL_WRITE; /* don't select on write. */
new_flags |= PR_POLL_READ; /* do select on read. */
}
}
} else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
*p_out_flags = PR_POLL_READ; /* it's ready already. */
return new_flags;
}
if (new_flags && (fd->lower->methods->poll != NULL)) {
PRInt16 lower_out_flags = 0;
PRInt16 lower_new_flags;
lower_new_flags = fd->lower->methods->poll(fd->lower, new_flags,
&lower_out_flags);
if ((lower_new_flags & lower_out_flags) && (how_flags != new_flags)) {
PRInt16 out_flags = lower_out_flags & ~PR_POLL_RW;
if (lower_out_flags & PR_POLL_READ)
out_flags |= PR_POLL_WRITE;
if (lower_out_flags & PR_POLL_WRITE)
out_flags |= PR_POLL_READ;
*p_out_flags = out_flags;
new_flags = how_flags;
} else {
*p_out_flags = lower_out_flags;
new_flags = lower_new_flags;
}
} }
if ((ret_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) { return new_flags;
*out_flags = PR_POLL_READ; /* it's ready already. */
} else if (ret_flags && (fd->lower->methods->poll != NULL)) {
ret_flags = fd->lower->methods->poll(fd->lower, ret_flags, out_flags);
}
return ret_flags;
} }