Search in sources :

Example 11 with Status

use of javax.net.ssl.SSLEngineResult.Status in project spring-integration by spring-projects.

the class TcpNioSSLConnection method decode.

/**
 * Performs the actual decryption of a received packet - which may be real
 * data, or handshaking data. Appropriate action is taken with the data.
 * If this side did not initiate the handshake, any handshaking data sent out
 * is handled by the thread running in the {@link SSLChannelOutputStream#doWrite(ByteBuffer)}
 * method, which is awoken here, as a result of reaching that stage in the handshaking.
 */
@SuppressWarnings("fallthrough")
private SSLEngineResult decode(ByteBuffer networkBuffer) throws IOException {
    SSLEngineResult result = new SSLEngineResult(Status.OK, this.sslEngine.getHandshakeStatus(), 0, 0);
    HandshakeStatus handshakeStatus = this.sslEngine.getHandshakeStatus();
    switch(handshakeStatus) {
        case NEED_TASK:
            runTasks();
            break;
        case NEED_UNWRAP:
        case FINISHED:
        case NOT_HANDSHAKING:
            this.decoded.clear();
            result = this.sslEngine.unwrap(networkBuffer, this.decoded);
            if (logger.isDebugEnabled()) {
                logger.debug("After unwrap: " + resultToString(result));
            }
            Status status = result.getStatus();
            if (status == Status.BUFFER_OVERFLOW) {
                this.decoded = this.allocateEncryptionBuffer(this.sslEngine.getSession().getApplicationBufferSize());
            }
            if (result.bytesProduced() > 0) {
                this.decoded.flip();
                super.sendToPipe(this.decoded);
            }
            break;
        case NEED_WRAP:
            if (!resumeWriterIfNeeded()) {
                this.encoded.clear();
                result = this.sslEngine.wrap(networkBuffer, this.encoded);
                if (logger.isDebugEnabled()) {
                    logger.debug("After wrap: " + resultToString(result));
                }
                if (result.getStatus() == Status.BUFFER_OVERFLOW) {
                    this.encoded = this.allocateEncryptionBuffer(this.sslEngine.getSession().getPacketBufferSize());
                } else {
                    this.encoded.flip();
                    getSSLChannelOutputStream().writeEncoded(this.encoded);
                }
            }
            break;
        default:
    }
    switch(result.getHandshakeStatus()) {
        case FINISHED:
            // NOSONAR - fall-through intended
            resumeWriterIfNeeded();
        // switch fall-through intended
        case NOT_HANDSHAKING:
        case NEED_UNWRAP:
            this.needMoreNetworkData = result.getStatus() == Status.BUFFER_UNDERFLOW || networkBuffer.remaining() == 0;
            break;
        default:
    }
    return result;
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) SSLEngineResult(javax.net.ssl.SSLEngineResult) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 12 with Status

use of javax.net.ssl.SSLEngineResult.Status in project netty by netty.

the class SslHandler method unwrap.

/**
 * Unwraps inbound SSL records.
 */
private int unwrap(ChannelHandlerContext ctx, ByteBuf packet, int length) throws SSLException {
    final int originalLength = length;
    boolean wrapLater = false;
    boolean notifyClosure = false;
    boolean executedRead = false;
    ByteBuf decodeOut = allocate(ctx, length);
    try {
        // See https://github.com/netty/netty/issues/5860
        do {
            final SSLEngineResult result = engineType.unwrap(this, packet, length, decodeOut);
            final Status status = result.getStatus();
            final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
            final int produced = result.bytesProduced();
            final int consumed = result.bytesConsumed();
            // Skip bytes now in case unwrap is called in a re-entry scenario. For example LocalChannel.read()
            // may entry this method in a re-entry fashion and if the peer is writing into a shared buffer we may
            // unwrap the same data multiple times.
            packet.skipBytes(consumed);
            length -= consumed;
            // 2. fireChannelRead for unwrapped data
            if (handshakeStatus == HandshakeStatus.FINISHED || handshakeStatus == HandshakeStatus.NOT_HANDSHAKING) {
                wrapLater |= (decodeOut.isReadable() ? setHandshakeSuccessUnwrapMarkReentry() : setHandshakeSuccess()) || handshakeStatus == HandshakeStatus.FINISHED;
            }
            // to preserve order of events.
            if (decodeOut.isReadable()) {
                setState(STATE_FIRE_CHANNEL_READ);
                if (isStateSet(STATE_UNWRAP_REENTRY)) {
                    executedRead = true;
                    executeChannelRead(ctx, decodeOut);
                } else {
                    ctx.fireChannelRead(decodeOut);
                }
                decodeOut = null;
            }
            if (status == Status.CLOSED) {
                // notify about the CLOSED state of the SSLEngine. See #137
                notifyClosure = true;
            } else if (status == Status.BUFFER_OVERFLOW) {
                if (decodeOut != null) {
                    decodeOut.release();
                }
                final int applicationBufferSize = engine.getSession().getApplicationBufferSize();
                // Allocate a new buffer which can hold all the rest data and loop again.
                // It may happen that applicationBufferSize < produced while there is still more to unwrap, in this
                // case we will just allocate a new buffer with the capacity of applicationBufferSize and call
                // unwrap again.
                decodeOut = allocate(ctx, engineType.calculatePendingData(this, applicationBufferSize < produced ? applicationBufferSize : applicationBufferSize - produced));
                continue;
            }
            if (handshakeStatus == HandshakeStatus.NEED_TASK) {
                boolean pending = runDelegatedTasks(true);
                if (!pending) {
                    // We scheduled a task on the delegatingTaskExecutor, so stop processing as we will
                    // resume once the task completes.
                    // 
                    // We break out of the loop only and do NOT return here as we still may need to notify
                    // about the closure of the SSLEngine.
                    wrapLater = false;
                    break;
                }
            } else if (handshakeStatus == HandshakeStatus.NEED_WRAP) {
                // costly unwrap operation and break out of the loop.
                if (wrapNonAppData(ctx, true) && length == 0) {
                    break;
                }
            }
            if (status == Status.BUFFER_UNDERFLOW || // If we processed NEED_TASK we should try again even we did not consume or produce anything.
            handshakeStatus != HandshakeStatus.NEED_TASK && (consumed == 0 && produced == 0 || (length == 0 && handshakeStatus == HandshakeStatus.NOT_HANDSHAKING))) {
                if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
                    // The underlying engine is starving so we need to feed it with more data.
                    // See https://github.com/netty/netty/pull/5039
                    readIfNeeded(ctx);
                }
                break;
            } else if (decodeOut == null) {
                decodeOut = allocate(ctx, length);
            }
        } while (!ctx.isRemoved());
        if (isStateSet(STATE_FLUSHED_BEFORE_HANDSHAKE) && handshakePromise.isDone()) {
            // We need to call wrap(...) in case there was a flush done before the handshake completed to ensure
            // we do not stale.
            // 
            // See https://github.com/netty/netty/pull/2437
            clearState(STATE_FLUSHED_BEFORE_HANDSHAKE);
            wrapLater = true;
        }
        if (wrapLater) {
            wrap(ctx, true);
        }
    } finally {
        if (decodeOut != null) {
            decodeOut.release();
        }
        if (notifyClosure) {
            if (executedRead) {
                executeNotifyClosePromise(ctx);
            } else {
                notifyClosePromise(null);
            }
        }
    }
    return originalLength - length;
}
Also used : HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus) Status(javax.net.ssl.SSLEngineResult.Status) SSLEngineResult(javax.net.ssl.SSLEngineResult) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) ByteBuf(io.netty.buffer.ByteBuf) 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