Search in sources :

Example 1 with AsyncSSLEngineException

use of org.webpieces.ssl.api.AsyncSSLEngineException in project webpieces by deanhiller.

the class AsyncSSLEngine3Impl method beginHandshake.

@Override
public XFuture<Void> beginHandshake() {
    SSLEngine sslEngine = mem.getEngine();
    circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.BEGIN_HANDSHAKE_START, sslEngine));
    try {
        mem.compareSet(ConnectionState.NOT_STARTED, ConnectionState.CONNECTING);
        if (log.isTraceEnabled())
            log.trace(mem + "start handshake");
        try {
            sslEngine.beginHandshake();
        } catch (SSLException e) {
            throw new AsyncSSLEngineException(e);
        }
        if (sslEngine.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)
            throw new IllegalStateException("Dude, WTF, after beginHandshake, SSLEngine has to be NEED WRAP to send first hello message");
        return doHandshakeLoop();
    } finally {
        circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.BEGIN_HANDSHAKE_END, sslEngine));
    }
}
Also used : SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) AsyncSSLEngineException(org.webpieces.ssl.api.AsyncSSLEngineException) SSLException(javax.net.ssl.SSLException)

Example 2 with AsyncSSLEngineException

use of org.webpieces.ssl.api.AsyncSSLEngineException in project webpieces by deanhiller.

the class AsyncSSLEngine3Impl method unwrapPacket.

private boolean unwrapPacket() {
    SSLEngine sslEngine = mem.getEngine();
    HandshakeStatus hsStatus = sslEngine.getHandshakeStatus();
    Status status = null;
    logTrace1(mem.getCachedToProcess(), hsStatus);
    ByteBuffer encryptedData = mem.getCachedToProcess();
    SSLEngineResult result;
    ByteBuffer cachedOutBuffer = pool.nextBuffer(sslEngine.getSession().getApplicationBufferSize());
    int remainBeforeDecrypt = encryptedData.remaining();
    try {
        circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.UNWRAP_START, sslEngine));
        result = sslEngine.unwrap(encryptedData, cachedOutBuffer);
        mem.incrementCallToUnwrap();
    } catch (SSLException e) {
        // read before the buffer is cleared released
        // record bytes consumed...
        int consumedBytes = remainBeforeDecrypt - encryptedData.remaining();
        int numCallToUnwrap = mem.getNumCallToUnwrap();
        String extraInfo = createExtraInfo(encryptedData, e);
        release(encryptedData, cachedOutBuffer);
        mem.setCachedEncryptedData(ByteBuffer.allocate(0));
        String message = e.getMessage();
        if (message.contains("Received fatal alert: certificate_unknown")) {
            // This is normal for self signed certs, so just return.  Chrome closes the connection with
            // a reason and SSLEngine throws an exception :(
            mem.compareSet(ConnectionState.CONNECTING, ConnectionState.DISCONNECTED);
            decryptionTracker.ackBytes(consumedBytes);
            return true;
        }
        AsyncSSLEngineException ee = createExc(hsStatus, status, encryptedData, remainBeforeDecrypt, e, consumedBytes, numCallToUnwrap, extraInfo);
        throw ee;
    } finally {
        circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.UNWRAP_END, sslEngine));
    }
    status = result.getStatus();
    hsStatus = result.getHandshakeStatus();
    if (status == Status.CLOSED) {
        // If we are connected, then the close was remotely initiated
        mem.compareSet(ConnectionState.CONNECTED, ConnectionState.DISCONNECTING);
        // If we are NOT connected and are in Disconnecting state, then fireClose
        if (mem.getConnectionState() == ConnectionState.DISCONNECTING)
            fireClose();
    }
    // If we are in a state of NOT_HANDSHAKING, sometimes the bytes coming off are not enough for a FULL packet so BUFFER_UNDERFLOW will occur
    // This is normal
    logTrace(encryptedData, status, hsStatus);
    int totalBytesToAck = remainBeforeDecrypt - encryptedData.remaining();
    if (cachedOutBuffer.position() != 0) {
        firePlainPacketToListener(cachedOutBuffer, totalBytesToAck);
    } else {
        // pretend like all data is consumed
        cachedOutBuffer.position(cachedOutBuffer.limit());
        // buffer not needed since we did not use it and fill it with data
        pool.releaseBuffer(cachedOutBuffer);
        if (hsStatus == HandshakeStatus.NEED_WRAP || hsStatus == HandshakeStatus.NEED_TASK) {
            // THIS IS COMPLEX HERE.  In this case, we need to run a task and/or wrap data and need to
            // ack the bytes we just processed ONLY if those things get sent out.  If the NIC is putting backpressure
            // this then backpressures the incoming side until the peer can consumer our data first
            doHandshakeLoop().handle((v, t) -> {
                if (t != null)
                    log.error("Exception in ssl listener", t);
                decryptionTracker.ackBytes(totalBytesToAck);
                return null;
            });
        } else {
            // The engine consumed the bytes so we are done with them, ack that payload as consumed.
            decryptionTracker.ackBytes(totalBytesToAck);
        }
    }
    if (encryptedData.hasRemaining()) {
        mem.setCachedEncryptedData(encryptedData);
    } else {
        mem.setCachedEncryptedData(SslMementoImpl.EMPTY);
        pool.releaseBuffer(encryptedData);
    }
    if (hsStatus == HandshakeStatus.FINISHED)
        fireLinkEstablished();
    if (status == Status.BUFFER_UNDERFLOW)
        return true;
    return false;
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) AsyncSSLEngineException(org.webpieces.ssl.api.AsyncSSLEngineException) ByteBuffer(java.nio.ByteBuffer) SSLException(javax.net.ssl.SSLException) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 3 with AsyncSSLEngineException

use of org.webpieces.ssl.api.AsyncSSLEngineException in project webpieces by deanhiller.

the class AsyncSSLEngine2Impl method feedEncryptedPacketImpl.

private XFuture<Void> feedEncryptedPacketImpl(ByteBuffer encryptedInData, XFuture<Void> byteAcker) {
    SSLEngine sslEngine = mem.getEngine();
    HandshakeStatus hsStatus = sslEngine.getHandshakeStatus();
    Status status = null;
    logTrace1(encryptedInData, hsStatus);
    ByteBuffer encryptedData = encryptedInData;
    ByteBuffer cached = mem.getCachedToProcess();
    if (cached != null) {
        encryptedData = combine(cached, encryptedData);
        mem.setCachedEncryptedData(null);
    }
    int i = 0;
    // stay in loop while we
    // 1. need unwrap or not_handshaking or need_task AND
    // 2. have data in buffer
    // 3. have enough data in buffer(ie. not underflow)
    int totalToAck = 0;
    while (encryptedData.hasRemaining() && status != Status.BUFFER_UNDERFLOW && status != Status.CLOSED) {
        i++;
        SSLEngineResult result;
        ByteBuffer outBuffer = mem.getCachedOut();
        int remainBeforeDecrypt = encryptedData.remaining();
        try {
            result = sslEngine.unwrap(encryptedData, outBuffer);
            status = result.getStatus();
        } catch (SSLException e) {
            AsyncSSLEngineException ee = new AsyncSSLEngineException("status=" + status + " hsStatus=" + hsStatus + " b=" + encryptedData, e);
            throw ee;
        } finally {
            int totalBytesToAck = remainBeforeDecrypt - encryptedData.remaining();
            if (outBuffer.position() != 0) {
                outBuffer.flip();
                listener.packetUnencrypted(outBuffer).handle((v, t) -> {
                    if (t != null)
                        log.error("Exception in ssl listener", t);
                    decryptionTracker.ackBytes(totalBytesToAck);
                    return null;
                });
                // frequently the out buffer is not used so we only ask the pool for buffers AFTER it has been consumed/used
                ByteBuffer newCachedOut = pool.nextBuffer(sslEngine.getSession().getApplicationBufferSize());
                mem.setCachedOut(newCachedOut);
            } else {
                totalToAck += totalBytesToAck;
            }
        }
        status = result.getStatus();
        hsStatus = result.getHandshakeStatus();
        if (hsStatus == HandshakeStatus.NEED_TASK || hsStatus == HandshakeStatus.NEED_WRAP) {
            // handshake as well
            break;
        }
        logAndCheck(encryptedData, result, outBuffer, status, hsStatus, i);
    }
    if (encryptedData.hasRemaining()) {
        mem.setCachedEncryptedData(encryptedData);
    }
    logTrace(encryptedData, status, hsStatus);
    if (!encryptedData.hasRemaining())
        pool.releaseBuffer(encryptedData);
    int bytesToAck = totalToAck;
    return cleanAndFire(hsStatus, status).thenApply(v -> {
        decryptionTracker.ackBytes(bytesToAck);
        return null;
    }).thenCompose(v -> byteAcker);
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) BufferPool(org.webpieces.data.api.BufferPool) Logger(org.slf4j.Logger) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Status(javax.net.ssl.SSLEngineResult.Status) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) ByteAckTracker(org.webpieces.util.acking.ByteAckTracker) List(java.util.List) SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLException(javax.net.ssl.SSLException) XFuture(org.webpieces.util.futures.XFuture) AsyncSSLEngineException(org.webpieces.ssl.api.AsyncSSLEngineException) SslListener(org.webpieces.ssl.api.SslListener) ConnectionState(org.webpieces.ssl.api.ConnectionState) SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) AsyncSSLEngineException(org.webpieces.ssl.api.AsyncSSLEngineException) ByteBuffer(java.nio.ByteBuffer) SSLException(javax.net.ssl.SSLException) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 4 with AsyncSSLEngineException

use of org.webpieces.ssl.api.AsyncSSLEngineException in project webpieces by deanhiller.

the class AsyncSSLEngine2Impl method feedEncryptedPacketImpl.

private void feedEncryptedPacketImpl(ByteBuffer encryptedInData) {
    SSLEngine sslEngine = mem.getEngine();
    HandshakeStatus hsStatus = sslEngine.getHandshakeStatus();
    Status status = null;
    final HandshakeStatus hsStatus2 = hsStatus;
    log.trace(() -> mem + "[sockToEngine] going to unwrap pos=" + encryptedInData.position() + " lim=" + encryptedInData.limit() + " hsStatus=" + hsStatus2 + " cached=" + mem.getCachedToProcess());
    ByteBuffer encryptedData = encryptedInData;
    ByteBuffer cached = mem.getCachedToProcess();
    if (cached != null) {
        encryptedData = combine(cached, encryptedData);
        mem.setCachedEncryptedData(null);
    }
    int i = 0;
    //3. have enough data in buffer(ie. not underflow)
    while (encryptedData.hasRemaining() && status != Status.BUFFER_UNDERFLOW && status != Status.CLOSED) {
        i++;
        SSLEngineResult result;
        ByteBuffer outBuffer = mem.getCachedOut();
        try {
            result = sslEngine.unwrap(encryptedData, outBuffer);
        } catch (SSLException e) {
            AsyncSSLEngineException ee = new AsyncSSLEngineException("status=" + status + " hsStatus=" + hsStatus + " b=" + encryptedData, e);
            throw ee;
        } finally {
            if (outBuffer.position() != 0) {
                outBuffer.flip();
                listener.packetUnencrypted(outBuffer);
                //frequently the out buffer is not used so we only ask the pool for buffers AFTER it has been consumed/used
                ByteBuffer newCachedOut = pool.nextBuffer(sslEngine.getSession().getApplicationBufferSize());
                mem.setCachedOut(newCachedOut);
            }
        }
        status = result.getStatus();
        hsStatus = result.getHandshakeStatus();
        final ByteBuffer data = encryptedData;
        final Status status2 = status;
        final HandshakeStatus hsStatus3 = hsStatus;
        log.trace(() -> mem + "[sockToEngine] unwrap done pos=" + data.position() + " lim=" + data.limit() + " status=" + status2 + " hs=" + hsStatus3);
        if (i > 1000)
            throw new RuntimeException(this + "Bug, stuck in loop, bufIn=" + encryptedData + " bufOut=" + outBuffer + " hsStatus=" + hsStatus + " status=" + status);
        else if (hsStatus == HandshakeStatus.NEED_TASK) {
            //messages?
            break;
        } else if (status == Status.BUFFER_UNDERFLOW) {
            final ByteBuffer data1 = encryptedData;
            log.trace(() -> "buffer underflow. data=" + data1.remaining());
        }
    }
    if (encryptedData.hasRemaining()) {
        mem.setCachedEncryptedData(encryptedData);
    }
    final ByteBuffer data2 = encryptedData;
    final Status status2 = status;
    final HandshakeStatus hsStatus3 = hsStatus;
    log.trace(() -> mem + "[sockToEngine] reset pos=" + data2.position() + " lim=" + data2.limit() + " status=" + status2 + " hs=" + hsStatus3);
    cleanAndFire(hsStatus, status, encryptedData);
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) AsyncSSLEngineException(org.webpieces.ssl.api.AsyncSSLEngineException) ByteBuffer(java.nio.ByteBuffer) SSLException(javax.net.ssl.SSLException) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 5 with AsyncSSLEngineException

use of org.webpieces.ssl.api.AsyncSSLEngineException in project webpieces by deanhiller.

the class AsyncSSLEngine3Impl method createExc.

private AsyncSSLEngineException createExc(HandshakeStatus hsStatus, Status status, ByteBuffer encryptedData, int remainBeforeDecrypt, SSLException e, int consumedBytes, int numCallToUnwrap, String extraInfo) {
    List<String> s = createActionStr();
    // Add a ton of info for this one for debug purposes...
    AsyncSSLEngineException ee = new AsyncSSLEngineException("Number of call to unwrap=" + numCallToUnwrap + "before exception status=" + status + " consumedBytes=" + consumedBytes + " hsStatus=" + hsStatus + " b=" + encryptedData + " remaining before dycrypt=" + remainBeforeDecrypt + " extraInfo=" + extraInfo + "\n" + s, e);
    return ee;
}
Also used : AsyncSSLEngineException(org.webpieces.ssl.api.AsyncSSLEngineException)

Aggregations

AsyncSSLEngineException (org.webpieces.ssl.api.AsyncSSLEngineException)7 SSLEngine (javax.net.ssl.SSLEngine)6 SSLException (javax.net.ssl.SSLException)6 AsyncSSLEngine (org.webpieces.ssl.api.AsyncSSLEngine)6 ByteBuffer (java.nio.ByteBuffer)3 SSLEngineResult (javax.net.ssl.SSLEngineResult)3 HandshakeStatus (javax.net.ssl.SSLEngineResult.HandshakeStatus)3 Status (javax.net.ssl.SSLEngineResult.Status)3 ArrayList (java.util.ArrayList)1 List (java.util.List)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Logger (org.slf4j.Logger)1 LoggerFactory (org.slf4j.LoggerFactory)1 BufferPool (org.webpieces.data.api.BufferPool)1 ConnectionState (org.webpieces.ssl.api.ConnectionState)1 SslListener (org.webpieces.ssl.api.SslListener)1 ByteAckTracker (org.webpieces.util.acking.ByteAckTracker)1 XFuture (org.webpieces.util.futures.XFuture)1