示例#1
0
/* Acquires and releases HandshakeLock.
*/
SECStatus
SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
{
    sslSocket *ss;
    SECStatus status;
    PRNetAddr addr;

    ss = ssl_FindSocket(s);
    if (!ss) {
	SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s));
	return SECFailure;
    }

    /* Don't waste my time */
    if (!ss->opt.useSecurity)
	return SECSuccess;

    SSL_LOCK_READER(ss);
    SSL_LOCK_WRITER(ss);

    /* Reset handshake state */
    ssl_Get1stHandshakeLock(ss);

    ss->firstHsDone = PR_FALSE;
    if ( asServer ) {
	ss->handshake = ssl2_BeginServerHandshake;
	ss->handshaking = sslHandshakingAsServer;
    } else {
	ss->handshake = ssl2_BeginClientHandshake;
	ss->handshaking = sslHandshakingAsClient;
    }
    ss->nextHandshake       = 0;
    ss->securityHandshake   = 0;

    ssl_GetRecvBufLock(ss);
    status = ssl_InitGather(&ss->gs);
    ssl_ReleaseRecvBufLock(ss);

    ssl_GetSSL3HandshakeLock(ss);

    /*
    ** Blow away old security state and get a fresh setup.
    */
    ssl_GetXmitBufLock(ss); 
    ssl_ResetSecurityInfo(&ss->sec, PR_TRUE);
    status = ssl_CreateSecurityInfo(ss);
    ssl_ReleaseXmitBufLock(ss); 

    ssl_ReleaseSSL3HandshakeLock(ss);
    ssl_Release1stHandshakeLock(ss);

    if (!ss->TCPconnected)
	ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));

    SSL_UNLOCK_WRITER(ss);
    SSL_UNLOCK_READER(ss);

    return status;
}
示例#2
0
/* 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 
** read the next handshake from the underlying socket.
** For SSLv2, returns when handshake is complete or fatal error occurs.
** For SSLv3, returns when handshake is complete, or application data has
** arrived that must be taken by application before handshake can continue, 
** or a fatal error occurs.
** Application should use handshake completion callback to tell which. 
*/
SECStatus
SSL_ForceHandshake(PRFileDesc *fd)
{
    sslSocket *ss;
    SECStatus  rv = SECFailure;

    ss = ssl_FindSocket(fd);
    if (!ss) {
	SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake",
		 SSL_GETPID(), fd));
	return rv;
    }

    /* Don't waste my time */
    if (!ss->opt.useSecurity) 
    	return SECSuccess;

    if (!ssl_SocketIsBlocking(ss)) {
	ssl_GetXmitBufLock(ss);
	if (ss->pendingBuf.len != 0) {
	    int sent = ssl_SendSavedWriteData(ss);
	    if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
		ssl_ReleaseXmitBufLock(ss);
		return SECFailure;
	    }
	}
	ssl_ReleaseXmitBufLock(ss);
    }

    ssl_Get1stHandshakeLock(ss);

    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
	int gatherResult;

    	ssl_GetRecvBufLock(ss);
	gatherResult = ssl3_GatherCompleteHandshake(ss, 0);
	ssl_ReleaseRecvBufLock(ss);
	if (gatherResult > 0) {
	    rv = SECSuccess;
	} else if (gatherResult == 0) {
	    PORT_SetError(PR_END_OF_FILE_ERROR);
	} else if (gatherResult == SECWouldBlock) {
	    PORT_SetError(PR_WOULD_BLOCK_ERROR);
	}
    } else if (!ss->firstHsDone) {
	rv = ssl_Do1stHandshake(ss);
    } else {
	/* tried to force handshake on an SSL 2 socket that has 
	** already completed the handshake. */
    	rv = SECSuccess;	/* just pretend we did it. */
    }

    ssl_Release1stHandshakeLock(ss);

    return rv;
}
示例#3
0
SECStatus
ssl_CreateSecurityInfo(sslSocket *ss)
{
    SECStatus status;

    ssl_GetXmitBufLock(ss);
    status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
    ssl_ReleaseXmitBufLock(ss);

    return status;
}
示例#4
0
int
ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
{
    int rv = 0;

    if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
        PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
        return PR_FAILURE;
    }
    if (flags & ~PR_MSG_PEEK) {
        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
        return PR_FAILURE;
    }

    if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
        ssl_GetXmitBufLock(ss);
        if (ss->pendingBuf.len != 0) {
            rv = ssl_SendSavedWriteData(ss);
            if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
                ssl_ReleaseXmitBufLock(ss);
                return SECFailure;
            }
        }
        ssl_ReleaseXmitBufLock(ss);
    }

    rv = 0;
    if (!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)) {
        PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
        return tls13_Read0RttData(ss, buf, len);
    }

    /* If any of these is non-zero, the initial handshake is not done. */
    if (!ss->firstHsDone) {
        ssl_Get1stHandshakeLock(ss);
        if (ss->handshake) {
            rv = ssl_Do1stHandshake(ss);
        }
        ssl_Release1stHandshakeLock(ss);
    }
    if (rv < 0) {
        return rv;
    }

    if (len == 0)
        return 0;

    rv = DoRecv(ss, (unsigned char *)buf, len, flags);
    SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
                SSL_GETPID(), ss->fd, rv, PORT_GetError()));
    return rv;
}
示例#5
0
int
ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
{
    sslSecurityInfo *sec;
    int              rv   = 0;

    sec = &ss->sec;

    if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
	PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
    	return PR_FAILURE;
    }
    if (flags & ~PR_MSG_PEEK) {
	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    	return PR_FAILURE;
    }

    if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
	ssl_GetXmitBufLock(ss);
	if (ss->pendingBuf.len != 0) {
	    rv = ssl_SendSavedWriteData(ss);
	    if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
		ssl_ReleaseXmitBufLock(ss);
		return SECFailure;
	    }
	    /* XXX short write? */
	}
	ssl_ReleaseXmitBufLock(ss);
    }
    
    rv = 0;
    /* If any of these is non-zero, the initial handshake is not done. */
    if (!ss->firstHsDone) {
	ssl_Get1stHandshakeLock(ss);
	if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
	    rv = ssl_Do1stHandshake(ss);
	}
	ssl_Release1stHandshakeLock(ss);
    }
    if (rv < 0) {
	return rv;
    }

    if (len == 0) return 0;

    rv = DoRecv(ss, (unsigned char*) buf, len, flags);
    SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
		SSL_GETPID(), ss->fd, rv, PORT_GetError()));
    return rv;
}
示例#6
0
SECStatus
ssl_CreateSecurityInfo(sslSocket *ss)
{
    SECStatus status;

    /* initialize sslv2 socket to send data in the clear. */
    ssl2_UseClearSendFunc(ss);

    ss->sec.blockSize  = 1;
    ss->sec.blockShift = 0;

    ssl_GetXmitBufLock(ss); 
    status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
    ssl_ReleaseXmitBufLock(ss); 

    return status;
}
示例#7
0
SECStatus
ssl_CreateSecurityInfo(sslSocket *ss)
{
    SECStatus status;

    
    ssl2_UseClearSendFunc(ss);

    ss->sec.blockSize  = 1;
    ss->sec.blockShift = 0;

    ssl_GetXmitBufLock(ss); 
    status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
    ssl_ReleaseXmitBufLock(ss); 

    return status;
}
示例#8
0
PRBool SSLInt_SendNewSessionTicket(PRFileDesc *fd) {
  sslSocket *ss = ssl_FindSocket(fd);
  if (!ss) {
    return PR_FALSE;
  }

  ssl_GetSSL3HandshakeLock(ss);
  ssl_GetXmitBufLock(ss);

  SECStatus rv = tls13_SendNewSessionTicket(ss);
  if (rv == SECSuccess) {
    rv = ssl3_FlushHandshake(ss, 0);
  }

  ssl_ReleaseXmitBufLock(ss);
  ssl_ReleaseSSL3HandshakeLock(ss);

  return rv == SECSuccess;
}
示例#9
0
/* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */
int
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
    int rv = 0;
    PRBool falseStart = PR_FALSE;

    SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
		SSL_GETPID(), ss->fd, len));

    if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
	PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
    	rv = PR_FAILURE;
	goto done;
    }
    if (flags) {
	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    	rv = PR_FAILURE;
	goto done;
    }

    ssl_GetXmitBufLock(ss);
    if (ss->pendingBuf.len != 0) {
	PORT_Assert(ss->pendingBuf.len > 0);
	rv = ssl_SendSavedWriteData(ss);
	if (rv >= 0 && ss->pendingBuf.len != 0) {
	    PORT_Assert(ss->pendingBuf.len > 0);
	    PORT_SetError(PR_WOULD_BLOCK_ERROR);
	    rv = SECFailure;
	}
    }
    ssl_ReleaseXmitBufLock(ss);
    if (rv < 0) {
	goto done;
    }

    if (len > 0) 
    	ss->writerThread = PR_GetCurrentThread();
    /* If any of these is non-zero, the initial handshake is not done. */
    if (!ss->firstHsDone) {
	ssl_Get1stHandshakeLock(ss);
	if (ss->opt.enableFalseStart &&
	    ss->version >= SSL_LIBRARY_VERSION_3_0) {
	    ssl_GetSSL3HandshakeLock(ss);
	    falseStart = ss->ssl3.hs.canFalseStart;
	    ssl_ReleaseSSL3HandshakeLock(ss);
	}
	if (!falseStart &&
	    (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
	    rv = ssl_Do1stHandshake(ss);
	}
	ssl_Release1stHandshakeLock(ss);
    }
    if (rv < 0) {
    	ss->writerThread = NULL;
	goto done;
    }

    /* Check for zero length writes after we do housekeeping so we make forward
     * progress.
     */
    if (len == 0) {
    	rv = 0;
	goto done;
    }
    PORT_Assert(buf != NULL);
    if (!buf) {
	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    	rv = PR_FAILURE;
	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
     */
    ssl_GetXmitBufLock(ss);
    rv = (*ss->sec.send)(ss, buf, len, flags);
    ssl_ReleaseXmitBufLock(ss);
    ss->writerThread = NULL;
done:
    if (rv < 0) {
	SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
		    SSL_GETPID(), ss->fd, rv, PORT_GetError()));
    } else {
	SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
		    SSL_GETPID(), ss->fd, rv));
    }
    return rv;
}
示例#10
0
int
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
    int rv = 0;
    PRBool falseStart = PR_FALSE;

    SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
		SSL_GETPID(), ss->fd, len));

    if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
	PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
    	rv = PR_FAILURE;
	goto done;
    }
    if (flags) {
	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    	rv = PR_FAILURE;
	goto done;
    }

    ssl_GetXmitBufLock(ss);
    if (ss->pendingBuf.len != 0) {
	PORT_Assert(ss->pendingBuf.len > 0);
	rv = ssl_SendSavedWriteData(ss);
	if (rv >= 0 && ss->pendingBuf.len != 0) {
	    PORT_Assert(ss->pendingBuf.len > 0);
	    PORT_SetError(PR_WOULD_BLOCK_ERROR);
	    rv = SECFailure;
	}
    }
    ssl_ReleaseXmitBufLock(ss);
    if (rv < 0) {
	goto done;
    }

    if (len > 0) 
    	ss->writerThread = PR_GetCurrentThread();
    
    if (!ss->firstHsDone) {
	ssl_Get1stHandshakeLock(ss);
	if (ss->opt.enableFalseStart &&
	    ss->version >= SSL_LIBRARY_VERSION_3_0) {
	    ssl_GetSSL3HandshakeLock(ss);
	    falseStart = ss->ssl3.hs.canFalseStart;
	    ssl_ReleaseSSL3HandshakeLock(ss);
	}
	if (!falseStart &&
	    (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
	    rv = ssl_Do1stHandshake(ss);
	}
	ssl_Release1stHandshakeLock(ss);
    }
    if (rv < 0) {
    	ss->writerThread = NULL;
	goto done;
    }

    if (len == 0) {
    	rv = 0;
	goto done;
    }
    PORT_Assert(buf != NULL);
    if (!buf) {
	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    	rv = PR_FAILURE;
	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));
    }

    ssl_GetXmitBufLock(ss);
    rv = (*ss->sec.send)(ss, buf, len, flags);
    ssl_ReleaseXmitBufLock(ss);
    ss->writerThread = NULL;
done:
    if (rv < 0) {
	SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
		    SSL_GETPID(), ss->fd, rv, PORT_GetError()));
    } else {
	SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
		    SSL_GETPID(), ss->fd, rv));
    }
    return rv;
}
示例#11
0
/* Sends out the initial client Hello message on the connection.
 * Acquires and releases the socket's xmitBufLock.
 */
SECStatus
ssl_BeginClientHandshake(sslSocket *ss)
{
    sslSessionID *sid;
    SECStatus rv;

    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));

    ss->sec.isServer = PR_FALSE;
    ssl_ChooseSessionIDProcs(&ss->sec);

    rv = ssl_CheckConfigSanity(ss);
    if (rv != SECSuccess)
        goto loser;

    /* Get peer name of server */
    rv = ssl_GetPeerInfo(ss);
    if (rv < 0) {
#ifdef HPUX11
        /*
         * On some HP-UX B.11.00 systems, getpeername() occasionally
         * fails with ENOTCONN after a successful completion of
         * non-blocking connect.  I found that if we do a write()
         * and then retry getpeername(), it will work.
         */
        if (PR_GetError() == PR_NOT_CONNECTED_ERROR) {
            char dummy;
            (void)PR_Write(ss->fd->lower, &dummy, 0);
            rv = ssl_GetPeerInfo(ss);
            if (rv < 0) {
                goto loser;
            }
        }
#else
        goto loser;
#endif
    }

    SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd));

    /* Try to find server in our session-id cache */
    if (ss->opt.noCache) {
        sid = NULL;
    } else {
        sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
                            ss->url);
    }
    if (sid) {
        if (sid->version >= ss->vrange.min && sid->version <= ss->vrange.max) {
            PORT_Assert(!ss->sec.localCert);
            ss->sec.localCert = CERT_DupCertificate(sid->localCert);
        } else {
            ss->sec.uncache(sid);
            ssl_FreeSID(sid);
            sid = NULL;
        }
    }
    if (!sid) {
        sid = PORT_ZNew(sslSessionID);
        if (!sid) {
            goto loser;
        }
        sid->references = 1;
        sid->cached = never_cached;
        sid->addr = ss->sec.ci.peer;
        sid->port = ss->sec.ci.port;
        if (ss->peerID != NULL) {
            sid->peerID = PORT_Strdup(ss->peerID);
        }
        if (ss->url != NULL) {
            sid->urlSvrName = PORT_Strdup(ss->url);
        }
    }
    ss->sec.ci.sid = sid;

    PORT_Assert(sid != NULL);

    ss->gs.state = GS_INIT;
    ss->handshake = ssl_GatherRecord1stHandshake;

    /* ssl3_SendClientHello will override this if it succeeds. */
    ss->version = SSL_LIBRARY_VERSION_3_0;

    ssl_GetSSL3HandshakeLock(ss);
    ssl_GetXmitBufLock(ss);
    rv = ssl3_SendClientHello(ss, client_hello_initial);
    ssl_ReleaseXmitBufLock(ss);
    ssl_ReleaseSSL3HandshakeLock(ss);

    return rv;

loser:
    return SECFailure;
}
示例#12
0
/* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */
int
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
    int rv = 0;

    SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
                SSL_GETPID(), ss->fd, len));

    if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
        PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
        rv = PR_FAILURE;
        goto done;
    }
    if (flags) {
        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
        rv = PR_FAILURE;
        goto done;
    }

    ssl_GetXmitBufLock(ss);
    if (ss->pendingBuf.len != 0) {
        PORT_Assert(ss->pendingBuf.len > 0);
        rv = ssl_SendSavedWriteData(ss);
        if (rv >= 0 && ss->pendingBuf.len != 0) {
            PORT_Assert(ss->pendingBuf.len > 0);
            PORT_SetError(PR_WOULD_BLOCK_ERROR);
            rv = SECFailure;
        }
    }
    ssl_ReleaseXmitBufLock(ss);
    if (rv < 0) {
        goto done;
    }

    if (len > 0)
        ss->writerThread = PR_GetCurrentThread();

    /* Check to see if we can write even though we're not finished.
     *
     * Case 1: False start
     * Case 2: TLS 1.3 0-RTT
     */
    if (!ss->firstHsDone) {
        PRBool falseStart = PR_FALSE;
        ssl_Get1stHandshakeLock(ss);
        if (ss->opt.enableFalseStart ||
            (ss->opt.enable0RttData && !ss->sec.isServer)) {
            ssl_GetSSL3HandshakeLock(ss);
            /* The client can sometimes send before the handshake is fully
             * complete. In TLS 1.2: false start; in TLS 1.3: 0-RTT. */
            falseStart = ss->ssl3.hs.canFalseStart ||
                         ss->ssl3.hs.zeroRttState == ssl_0rtt_sent ||
                         ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted;
            ssl_ReleaseSSL3HandshakeLock(ss);
        }
        if (!falseStart && ss->handshake) {
            rv = ssl_Do1stHandshake(ss);
        }
        ssl_Release1stHandshakeLock(ss);
    }
    if (rv < 0) {
        ss->writerThread = NULL;
        goto done;
    }

    /* Check for zero length writes after we do housekeeping so we make forward
     * progress.
     */
    if (len == 0) {
        rv = 0;
        goto done;
    }
    PORT_Assert(buf != NULL);
    if (!buf) {
        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
        rv = PR_FAILURE;
        goto done;
    }

    if (!ss->firstHsDone) {
#ifdef DEBUG
        ssl_GetSSL3HandshakeLock(ss);
        PORT_Assert(!ss->sec.isServer &&
                    (ss->ssl3.hs.canFalseStart ||
                     ss->ssl3.hs.zeroRttState == ssl_0rtt_sent ||
                     ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted));
        ssl_ReleaseSSL3HandshakeLock(ss);
#endif
        SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
                    SSL_GETPID(), ss->fd));
    }

    ssl_GetXmitBufLock(ss);
    rv = ssl3_SendApplicationData(ss, buf, len, flags);
    ssl_ReleaseXmitBufLock(ss);
    ss->writerThread = NULL;
done:
    if (rv < 0) {
        SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
                    SSL_GETPID(), ss->fd, rv, PORT_GetError()));
    } else {
        SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
                    SSL_GETPID(), ss->fd, rv));
    }
    return rv;
}