| Index: net/third_party/nss/ssl/sslsecur.c
|
| ===================================================================
|
| --- net/third_party/nss/ssl/sslsecur.c (revision 227672)
|
| +++ net/third_party/nss/ssl/sslsecur.c (working copy)
|
| @@ -97,23 +97,13 @@
|
| ss->securityHandshake = 0;
|
| }
|
| if (ss->handshake == 0) {
|
| - ssl_GetRecvBufLock(ss);
|
| - ss->gs.recordLen = 0;
|
| - ssl_ReleaseRecvBufLock(ss);
|
| -
|
| - SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
|
| - SSL_GETPID(), ss->fd));
|
| - /* call handshake callback for ssl v2 */
|
| - /* for v3 this is done in ssl3_HandleFinished() */
|
| - if ((ss->handshakeCallback != NULL) && /* has callback */
|
| - (!ss->firstHsDone) && /* only first time */
|
| - (ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */
|
| - ss->firstHsDone = PR_TRUE;
|
| - (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
| + /* 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);
|
| }
|
| - ss->firstHsDone = PR_TRUE;
|
| - ss->gs.writeOffset = 0;
|
| - ss->gs.readOffset = 0;
|
| break;
|
| }
|
| rv = (*ss->handshake)(ss);
|
| @@ -134,6 +124,24 @@
|
| return rv;
|
| }
|
|
|
| +void
|
| +ssl_FinishHandshake(sslSocket *ss)
|
| +{
|
| + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
| +
|
| + SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
|
| +
|
| + ss->firstHsDone = PR_TRUE;
|
| + ss->enoughFirstHsDone = PR_TRUE;
|
| + ss->gs.writeOffset = 0;
|
| + ss->gs.readOffset = 0;
|
| +
|
| + if (ss->handshakeCallback) {
|
| + (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
| + }
|
| +}
|
| +
|
| /*
|
| * Handshake function that blocks. Used to force a
|
| * retry on a connection on the next read/write.
|
| @@ -206,6 +214,7 @@
|
| ssl_Get1stHandshakeLock(ss);
|
|
|
| ss->firstHsDone = PR_FALSE;
|
| + ss->enoughFirstHsDone = PR_FALSE;
|
| if ( asServer ) {
|
| ss->handshake = ssl2_BeginServerHandshake;
|
| ss->handshaking = sslHandshakingAsServer;
|
| @@ -221,6 +230,8 @@
|
| ssl_ReleaseRecvBufLock(ss);
|
|
|
| ssl_GetSSL3HandshakeLock(ss);
|
| + ss->ssl3.hs.canFalseStart = PR_FALSE;
|
| + ss->ssl3.hs.restartTarget = NULL;
|
|
|
| /*
|
| ** Blow away old security state and get a fresh setup.
|
| @@ -331,6 +342,71 @@
|
| return SECSuccess;
|
| }
|
|
|
| +/* Register an application callback to be called when false start may happen.
|
| +** Acquires and releases HandshakeLock.
|
| +*/
|
| +SECStatus
|
| +SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
|
| + void *arg)
|
| +{
|
| + sslSocket *ss;
|
| +
|
| + ss = ssl_FindSocket(fd);
|
| + if (!ss) {
|
| + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback",
|
| + SSL_GETPID(), fd));
|
| + return SECFailure;
|
| + }
|
| +
|
| + if (!ss->opt.useSecurity) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return SECFailure;
|
| + }
|
| +
|
| + ssl_Get1stHandshakeLock(ss);
|
| + ssl_GetSSL3HandshakeLock(ss);
|
| +
|
| + ss->canFalseStartCallback = cb;
|
| + ss->canFalseStartCallbackData = arg;
|
| +
|
| + ssl_ReleaseSSL3HandshakeLock(ss);
|
| + ssl_Release1stHandshakeLock(ss);
|
| +
|
| + return SECSuccess;
|
| +}
|
| +
|
| +SECStatus
|
| +SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
|
| +{
|
| + sslSocket *ss;
|
| +
|
| + *canFalseStart = PR_FALSE;
|
| + ss = ssl_FindSocket(fd);
|
| + if (!ss) {
|
| + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
|
| + SSL_GETPID(), fd));
|
| + return SECFailure;
|
| + }
|
| +
|
| + if (!ss->ssl3.initialized) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return SECFailure;
|
| + }
|
| +
|
| + if (ss->version < SSL_LIBRARY_VERSION_3_0) {
|
| + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
|
| + return SECFailure;
|
| + }
|
| +
|
| + /* Require a forward-secret key exchange. */
|
| + *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
|
| + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
|
| + ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
|
| + ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa;
|
| +
|
| + return SECSuccess;
|
| +}
|
| +
|
| /* Try to make progress on an SSL handshake by attempting to read the
|
| ** next handshake from the peer, and sending any responses.
|
| ** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot
|
| @@ -524,6 +600,9 @@
|
| int amount;
|
| int available;
|
|
|
| + /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
|
| + * 1stHandshakeLock. */
|
| + ssl_Get1stHandshakeLock(ss);
|
| ssl_GetRecvBufLock(ss);
|
|
|
| available = ss->gs.writeOffset - ss->gs.readOffset;
|
| @@ -590,6 +669,7 @@
|
|
|
| done:
|
| ssl_ReleaseRecvBufLock(ss);
|
| + ssl_Release1stHandshakeLock(ss);
|
| return rv;
|
| }
|
|
|
| @@ -1156,7 +1236,8 @@
|
| int
|
| ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
|
| {
|
| - int rv = 0;
|
| + int rv = 0;
|
| + PRBool falseStart = PR_FALSE;
|
|
|
| SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
|
| SSL_GETPID(), ss->fd, len));
|
| @@ -1191,19 +1272,14 @@
|
| ss->writerThread = PR_GetCurrentThread();
|
| /* If any of these is non-zero, the initial handshake is not done. */
|
| if (!ss->firstHsDone) {
|
| - PRBool canFalseStart = PR_FALSE;
|
| ssl_Get1stHandshakeLock(ss);
|
| - if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
|
| + if (ss->opt.enableFalseStart &&
|
| + ss->version >= SSL_LIBRARY_VERSION_3_0) {
|
| ssl_GetSSL3HandshakeLock(ss);
|
| - if ((ss->ssl3.hs.ws == wait_change_cipher ||
|
| - ss->ssl3.hs.ws == wait_finished ||
|
| - ss->ssl3.hs.ws == wait_new_session_ticket) &&
|
| - ssl3_CanFalseStart(ss)) {
|
| - canFalseStart = PR_TRUE;
|
| - }
|
| + falseStart = ss->ssl3.hs.canFalseStart;
|
| ssl_ReleaseSSL3HandshakeLock(ss);
|
| }
|
| - if (!canFalseStart &&
|
| + if (!falseStart &&
|
| (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
|
| rv = ssl_Do1stHandshake(ss);
|
| }
|
| @@ -1228,6 +1304,17 @@
|
| goto done;
|
| }
|
|
|
| + if (!ss->firstHsDone) {
|
| + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
|
| +#ifdef DEBUG
|
| + ssl_GetSSL3HandshakeLock(ss);
|
| + PORT_Assert(ss->ssl3.hs.canFalseStart);
|
| + ssl_ReleaseSSL3HandshakeLock(ss);
|
| +#endif
|
| + SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
|
| + SSL_GETPID(), ss->fd));
|
| + }
|
| +
|
| /* Send out the data using one of these functions:
|
| * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
|
| * ssl3_SendApplicationData
|
|
|