Exemple #1
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();
    /* If any of these is non-zero, the initial handshake is not done. */
    if (!ss->firstHsDone) {
        PRBool falseStart = PR_FALSE;
        ssl_Get1stHandshakeLock(ss);
        if (ss->opt.enableFalseStart) {
            ssl_GetSSL3HandshakeLock(ss);
            falseStart = ss->ssl3.hs.canFalseStart;
            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->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 = 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;
}
Exemple #2
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;
}