Search in sources :

Example 1 with Status

use of javax.net.ssl.SSLEngineResult.Status in project baseio by generallycloud.

the class SslHandler method wrap.

public ByteBuf wrap(SocketChannel channel, ByteBuf src) throws IOException {
    SSLEngine engine = channel.getSSLEngine();
    ByteBuf dst = getTempDst(engine);
    ByteBuf out = null;
    try {
        for (; ; ) {
            dst.clear();
            SSLEngineResult result = engine.wrap(src.nioBuffer(), dst.nioBuffer());
            Status status = result.getStatus();
            HandshakeStatus handshakeStatus = result.getHandshakeStatus();
            synchByteBuf(result, src, dst);
            if (status == Status.CLOSED) {
                return gc(channel, dst.flip());
            }
            if (handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) {
                if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
                    if (out != null) {
                        out.read(dst.flip());
                        return out.flip();
                    }
                    return gc(channel, dst.flip());
                } else if (handshakeStatus == HandshakeStatus.NEED_WRAP) {
                    if (out == null) {
                        out = allocate(channel, 256);
                    }
                    out.read(dst.flip());
                    continue;
                } else if (handshakeStatus == HandshakeStatus.FINISHED) {
                    channel.finishHandshake(null);
                    out.read(dst.flip());
                    return out.flip();
                } else if (handshakeStatus == HandshakeStatus.NEED_TASK) {
                    runDelegatedTasks(engine);
                    continue;
                }
            }
            if (src.hasRemaining()) {
                if (out == null) {
                    int outLength = ((src.limit() / src.position()) + 1) * (dst.position() - src.position()) + src.limit();
                    out = allocate(channel, outLength);
                }
                out.read(dst.flip());
                continue;
            }
            if (out != null) {
                out.read(dst.flip());
                return out.flip();
            }
            return gc(channel, dst.flip());
        }
    } catch (Throwable e) {
        ReleaseUtil.release(out);
        if (e instanceof IOException) {
            throw (IOException) e;
        }
        throw new IOException(e);
    }
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLEngine(javax.net.ssl.SSLEngine) IOException(java.io.IOException) ByteBuf(com.generallycloud.baseio.buffer.ByteBuf) EmptyByteBuf(com.generallycloud.baseio.buffer.EmptyByteBuf) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 2 with Status

use of javax.net.ssl.SSLEngineResult.Status in project webpieces by deanhiller.

the class AsyncSSLEngine3Impl method sendHandshakeMessageImpl.

private XFuture<Void> sendHandshakeMessageImpl(SSLEngine engine) throws SSLException {
    SSLEngine sslEngine = mem.getEngine();
    if (log.isTraceEnabled())
        log.trace(mem + "sending handshake message");
    ByteBuffer engineToSocketData = pool.nextBuffer(sslEngine.getSession().getPacketBufferSize());
    // CLOSE and all the threads that call feedPlainPacket can have contention on wrapping to encrypt and
    // must synchronize on sslEngine.wrap
    Status lastStatus;
    HandshakeStatus hsStatus;
    HandshakeStatus beforeWrapHandshakeStatus;
    synchronized (wrapLock) {
        // this is in the sync block, so we are synchronized with the engine state!!! and get the actual
        // state before calling wrap so we know the engine can't be switching states on us in another thread.
        beforeWrapHandshakeStatus = sslEngine.getHandshakeStatus();
        HandshakeStatus otherStatus = engine.getHandshakeStatus();
        if (beforeWrapHandshakeStatus != HandshakeStatus.NEED_WRAP)
            throw new IllegalStateException("we should only be calling this method when hsStatus=NEED_WRAP.  hsStatus=" + beforeWrapHandshakeStatus + " connectionState=" + mem.getConnectionState() + " otherStat=" + otherStatus + " eng1=" + sslEngine + " eng2=" + engine);
        circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.WRAP2_START, sslEngine));
        // KEEEEEP This very small.  wrap and then listener.packetEncrypted
        SSLEngineResult result = sslEngine.wrap(SslMementoImpl.EMPTY, engineToSocketData);
        circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.WRAP2_END, sslEngine));
        lastStatus = result.getStatus();
        hsStatus = result.getHandshakeStatus();
    }
    if (log.isTraceEnabled())
        log.trace(mem + "write packet pos=" + engineToSocketData.position() + " lim=" + engineToSocketData.limit() + " status=" + lastStatus + " hs=" + hsStatus);
    if (lastStatus == Status.BUFFER_OVERFLOW || lastStatus == Status.BUFFER_UNDERFLOW)
        throw new RuntimeException("status not right, status=" + lastStatus + " even though we sized the buffer to consume all?");
    boolean readNoData = engineToSocketData.position() == 0;
    engineToSocketData.flip();
    try {
        XFuture<Void> sentMsgFuture;
        if (readNoData) {
            if (log.isTraceEnabled())
                log.trace("ssl engine is farting. READ 0 data.  hsStatus=" + hsStatus + " status=" + lastStatus + " previous=" + beforeWrapHandshakeStatus);
            // Ok, I updated this thread https://stackoverflow.com/questions/56707024/java-sslengine-says-need-wrap-call-wrap-and-still-need-wrap/56822673#56822673
            // but basicaly, turning on -Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack
            // REALLY REALLY helps and you see that clients send a warning close_notify but I put logs before and after the call to
            // sslEngine.wrap and between those logs, the sslEngine logged ZERO debug information and did NOT generate it's
            // response close_notify :(.  crappy sslEngine.  This was in jdk 11.0.3 :(.
            // On top of this, downgrading to jdk1.8.0_111 which uses TLSv1.2 instead of TLSv1.3 works
            // just fine and sends back the close messages while jdk 11 is not doing that
            // so this sslEngineIsFarting is covering up their bug.
            // ADDITIONAL(different day):  Every time in docker opening client to remote server caused the ssl engine to fart(ie. come into this whacky
            // location).  This location is specifically SSLEngine tells us to WRAP, and THEN decides to wrap NOTHING!! wtf.
            sslEngineIsFarting = true;
            sentMsgFuture = XFuture.completedFuture(null);
        } else {
            metrics.recordEncryptedToSocket(engineToSocketData.remaining());
            sentMsgFuture = listener.sendEncryptedHandshakeData(engineToSocketData);
        }
        if (lastStatus == Status.CLOSED && !clientInitiated) {
            fireClose();
        } else if (hsStatus == HandshakeStatus.FINISHED) {
            fireLinkEstablished();
        }
        return sentMsgFuture;
    } catch (IllegalArgumentException e) {
        throw new IllegalArgumentException(e);
    }
}
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) ByteBuffer(java.nio.ByteBuffer) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 3 with Status

use of javax.net.ssl.SSLEngineResult.Status 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 4 with Status

use of javax.net.ssl.SSLEngineResult.Status in project webpieces by deanhiller.

the class AsyncSSLEngine3Impl method feedPlainPacketImpl.

private XFuture<Void> feedPlainPacketImpl(ByteBuffer buffer) throws SSLException {
    if (mem.getConnectionState() != ConnectionState.CONNECTED)
        throw new NioClosedChannelException(mem + " SSLEngine is not connected right now");
    else if (!buffer.hasRemaining())
        throw new IllegalArgumentException("your buffer has no readable data");
    SSLEngine sslEngine = mem.getEngine();
    if (log.isTraceEnabled())
        log.trace(mem + "feedPlainPacket [in-buffer] pos=" + buffer.position() + " lim=" + buffer.limit());
    XFuture<Void> future = encryptionTracker.addBytesToTrack(buffer.remaining());
    while (buffer.hasRemaining()) {
        ByteBuffer engineToSocketData = pool.nextBuffer(sslEngine.getSession().getPacketBufferSize());
        int remainBefore = buffer.remaining();
        int numEncrypted;
        SSLEngineResult result;
        synchronized (wrapLock) {
            circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.WRAP_START, sslEngine));
            result = sslEngine.wrap(buffer, engineToSocketData);
            circularBuffer.add(new Action(Thread.currentThread().getName(), ActionEnum.WRAP_END, sslEngine));
            numEncrypted = remainBefore - buffer.remaining();
        }
        Status status = result.getStatus();
        HandshakeStatus hsStatus = result.getHandshakeStatus();
        if (status != Status.OK)
            throw new RuntimeException("Bug, status=" + status + " instead of OK.  hsStatus=" + hsStatus + " Something went wrong and we could not encrypt the data");
        if (log.isTraceEnabled())
            log.trace(mem + "SSLListener.packetEncrypted pos=" + engineToSocketData.position() + " lim=" + engineToSocketData.limit() + " hsStatus=" + hsStatus + " status=" + status);
        engineToSocketData.flip();
        metrics.recordEncryptedToSocket(engineToSocketData.remaining());
        listener.packetEncrypted(engineToSocketData).handle((v, t) -> {
            if (t != null) {
                future.completeExceptionally(t);
            }
            encryptionTracker.ackBytes(numEncrypted);
            return null;
        });
    }
    pool.releaseBuffer(buffer);
    return future;
}
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) NioClosedChannelException(org.webpieces.util.exceptions.NioClosedChannelException) ByteBuffer(java.nio.ByteBuffer) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 5 with Status

use of javax.net.ssl.SSLEngineResult.Status in project webpieces by deanhiller.

the class AsyncSSLEngine2Impl method sendHandshakeMessageImpl.

private XFuture<Void> sendHandshakeMessageImpl() throws SSLException {
    SSLEngine sslEngine = mem.getEngine();
    if (log.isTraceEnabled())
        log.trace(mem + "sending handshake message");
    // HELPER.eraseBuffer(empty);
    HandshakeStatus hsStatus = sslEngine.getHandshakeStatus();
    if (hsStatus != HandshakeStatus.NEED_WRAP)
        throw new IllegalStateException("we should only be calling this method when hsStatus=NEED_WRAP.  hsStatus=" + hsStatus);
    List<XFuture<Void>> futures = new ArrayList<>();
    while (hsStatus == HandshakeStatus.NEED_WRAP) {
        ByteBuffer engineToSocketData = pool.nextBuffer(sslEngine.getSession().getPacketBufferSize());
        Status lastStatus = null;
        synchronized (wrapLock) {
            // KEEEEEP This very small.  wrap and then listener.packetEncrypted
            SSLEngineResult result = sslEngine.wrap(EMPTY, engineToSocketData);
            lastStatus = result.getStatus();
            hsStatus = result.getHandshakeStatus();
            final Status lastStatus2 = lastStatus;
            final HandshakeStatus hsStatus2 = hsStatus;
            if (log.isTraceEnabled())
                log.trace(mem + "write packet pos=" + engineToSocketData.position() + " lim=" + engineToSocketData.limit() + " status=" + lastStatus2 + " hs=" + hsStatus2);
            if (lastStatus == Status.BUFFER_OVERFLOW || lastStatus == Status.BUFFER_UNDERFLOW)
                throw new RuntimeException("status not right, status=" + lastStatus + " even though we sized the buffer to consume all?");
            engineToSocketData.flip();
            XFuture<Void> fut = listener.sendEncryptedHandshakeData(engineToSocketData);
            futures.add(fut);
        }
        if (lastStatus == Status.CLOSED && !clientInitiated) {
            fireClose();
        }
    }
    if (hsStatus == HandshakeStatus.NEED_WRAP || hsStatus == HandshakeStatus.NEED_TASK)
        throw new RuntimeException(mem + "BUG, need to implement more here status=" + hsStatus);
    final HandshakeStatus hsStatus2 = hsStatus;
    if (log.isTraceEnabled())
        log.trace(mem + "status=" + hsStatus2 + " isConn=" + mem.getConnectionState());
    if (hsStatus == HandshakeStatus.FINISHED) {
        fireLinkEstablished();
    }
    XFuture<Void> futureAll = XFuture.allOf(futures.toArray(new XFuture[futures.size()]));
    return futureAll;
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) SSLEngineResult(javax.net.ssl.SSLEngineResult) XFuture(org.webpieces.util.futures.XFuture) SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) ArrayList(java.util.ArrayList) ByteBuffer(java.nio.ByteBuffer) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Aggregations

Status (javax.net.ssl.SSLEngineResult.Status)12 SSLEngineResult (javax.net.ssl.SSLEngineResult)11 HandshakeStatus (javax.net.ssl.SSLEngineResult.HandshakeStatus)11 SSLEngine (javax.net.ssl.SSLEngine)9 ByteBuffer (java.nio.ByteBuffer)8 AsyncSSLEngine (org.webpieces.ssl.api.AsyncSSLEngine)7 IOException (java.io.IOException)3 SSLException (javax.net.ssl.SSLException)3 AsyncSSLEngineException (org.webpieces.ssl.api.AsyncSSLEngineException)3 ArrayList (java.util.ArrayList)2 XFuture (org.webpieces.util.futures.XFuture)2 ByteBuf (com.firenio.buffer.ByteBuf)1 ByteBufAllocator (com.firenio.buffer.ByteBufAllocator)1 ByteBuf (com.generallycloud.baseio.buffer.ByteBuf)1 EmptyByteBuf (com.generallycloud.baseio.buffer.EmptyByteBuf)1 ByteBuf (io.netty.buffer.ByteBuf)1 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)1 List (java.util.List)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 BufferStateManager (org.apache.nifi.remote.io.socket.BufferStateManager)1