Search in sources :

Example 6 with HandshakeStatus

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

the class SslHandler method unwrap.

/**
     * Unwraps inbound SSL records.
     */
private boolean unwrap(ChannelHandlerContext ctx, ByteBuf packet, int offset, int length) throws SSLException {
    boolean decoded = false;
    boolean wrapLater = false;
    boolean notifyClosure = false;
    ByteBuf decodeOut = allocate(ctx, length);
    try {
        // See https://github.com/netty/netty/issues/5860
        unwrapLoop: while (!ctx.isRemoved()) {
            final SSLEngineResult result = engineType.unwrap(this, packet, offset, length, decodeOut);
            final Status status = result.getStatus();
            final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
            final int produced = result.bytesProduced();
            final int consumed = result.bytesConsumed();
            // Update indexes for the next iteration
            offset += consumed;
            length -= consumed;
            switch(status) {
                case BUFFER_OVERFLOW:
                    int readableBytes = decodeOut.readableBytes();
                    int bufferSize = engine.getSession().getApplicationBufferSize() - readableBytes;
                    if (readableBytes > 0) {
                        decoded = true;
                        ctx.fireChannelRead(decodeOut);
                        // This buffer was handled, null it out.
                        decodeOut = null;
                        if (bufferSize <= 0) {
                            // It may happen that readableBytes >= engine.getSession().getApplicationBufferSize()
                            // while there is still more to unwrap, in this case we will just allocate a new buffer
                            // with the capacity of engine.getSession().getApplicationBufferSize() and call unwrap
                            // again.
                            bufferSize = engine.getSession().getApplicationBufferSize();
                        }
                    } else {
                        // This buffer was handled, null it out.
                        decodeOut.release();
                        decodeOut = null;
                    }
                    // Allocate a new buffer which can hold all the rest data and loop again.
                    // TODO: We may want to reconsider how we calculate the length here as we may
                    // have more then one ssl message to decode.
                    decodeOut = allocate(ctx, bufferSize);
                    continue;
                case CLOSED:
                    // notify about the CLOSED state of the SSLEngine. See #137
                    notifyClosure = true;
                    break;
                default:
                    break;
            }
            switch(handshakeStatus) {
                case NEED_UNWRAP:
                    break;
                case NEED_WRAP:
                    // costly unwrap operation and break out of the loop.
                    if (wrapNonAppData(ctx, true) && length == 0) {
                        break unwrapLoop;
                    }
                    break;
                case NEED_TASK:
                    runDelegatedTasks();
                    break;
                case FINISHED:
                    setHandshakeSuccess();
                    wrapLater = true;
                    //  - https://code.google.com/p/android/issues/detail?id=198639&thanks=198639&ts=1452501203
                    break;
                case NOT_HANDSHAKING:
                    if (setHandshakeSuccessIfStillHandshaking()) {
                        wrapLater = true;
                        continue;
                    }
                    if (flushedBeforeHandshake) {
                        // We need to call wrap(...) in case there was a flush done before the handshake completed.
                        //
                        // See https://github.com/netty/netty/pull/2437
                        flushedBeforeHandshake = false;
                        wrapLater = true;
                    }
                    // out of the loop.
                    if (length == 0) {
                        break unwrapLoop;
                    }
                    break;
                default:
                    throw new IllegalStateException("unknown handshake status: " + handshakeStatus);
            }
            if (status == Status.BUFFER_UNDERFLOW || consumed == 0 && produced == 0) {
                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;
            }
        }
        if (wrapLater) {
            wrap(ctx, true);
        }
        if (notifyClosure) {
            notifyClosePromise(null);
        }
    } finally {
        if (decodeOut != null) {
            if (decodeOut.isReadable()) {
                decoded = true;
                ctx.fireChannelRead(decodeOut);
            } else {
                decodeOut.release();
            }
        }
    }
    return decoded;
}
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)

Example 7 with HandshakeStatus

use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project robovm by robovm.

the class TestSSLEnginePair method handshakeCompleted.

private static boolean handshakeCompleted(SSLEngine engine, ByteBuffer output, ByteBuffer input, ByteBuffer scratch) throws IOException {
    try {
        // make the other side's output into our input
        input.flip();
        HandshakeStatus status = engine.getHandshakeStatus();
        switch(status) {
            case NEED_TASK:
                boolean progress = false;
                while (true) {
                    Runnable runnable = engine.getDelegatedTask();
                    if (runnable == null) {
                        return progress;
                    }
                    runnable.run();
                    progress = true;
                }
            case NEED_UNWRAP:
                // avoid underflow
                if (input.remaining() == 0) {
                    return false;
                }
                SSLEngineResult unwrapResult = engine.unwrap(input, scratch);
                assertEquals(SSLEngineResult.Status.OK, unwrapResult.getStatus());
                assertEquals(0, scratch.position());
                return true;
            case NEED_WRAP:
                // avoid possible overflow
                if (output.remaining() != output.capacity()) {
                    return false;
                }
                SSLEngineResult wrapResult = engine.wrap(EMPTY_BYTE_BUFFER, output);
                assertEquals(SSLEngineResult.Status.OK, wrapResult.getStatus());
                return true;
            case NOT_HANDSHAKING:
            // should have been checked by caller before calling
            case FINISHED:
                // only returned by wrap/unrap status, not getHandshakeStatus
                throw new IllegalStateException("Unexpected HandshakeStatus = " + status);
            default:
                throw new IllegalStateException("Unknown HandshakeStatus = " + status);
        }
    } finally {
        // shift consumed input, restore to output mode
        input.compact();
    }
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 8 with HandshakeStatus

use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project CloudStack-archive by CloudStack-extras.

the class Link method doHandshake.

public static void doHandshake(SocketChannel ch, SSLEngine sslEngine, boolean isClient) throws IOException {
    if (s_logger.isTraceEnabled()) {
        s_logger.trace("SSL: begin Handshake, isClient: " + isClient);
    }
    SSLEngineResult engResult;
    SSLSession sslSession = sslEngine.getSession();
    HandshakeStatus hsStatus;
    ByteBuffer in_pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
    ByteBuffer in_appBuf = ByteBuffer.allocate(sslSession.getApplicationBufferSize() + 40);
    ByteBuffer out_pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
    ByteBuffer out_appBuf = ByteBuffer.allocate(sslSession.getApplicationBufferSize() + 40);
    int count;
    if (isClient) {
        hsStatus = SSLEngineResult.HandshakeStatus.NEED_WRAP;
    } else {
        hsStatus = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
    }
    while (hsStatus != SSLEngineResult.HandshakeStatus.FINISHED) {
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("SSL: Handshake status " + hsStatus);
        }
        engResult = null;
        if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
            out_pkgBuf.clear();
            out_appBuf.clear();
            out_appBuf.put("Hello".getBytes());
            engResult = sslEngine.wrap(out_appBuf, out_pkgBuf);
            out_pkgBuf.flip();
            int remain = out_pkgBuf.limit();
            while (remain != 0) {
                remain -= ch.write(out_pkgBuf);
                if (remain < 0) {
                    throw new IOException("Too much bytes sent?");
                }
            }
        } else if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
            in_appBuf.clear();
            // One packet may contained multiply operation
            if (in_pkgBuf.position() == 0 || !in_pkgBuf.hasRemaining()) {
                in_pkgBuf.clear();
                count = ch.read(in_pkgBuf);
                if (count == -1) {
                    throw new IOException("Connection closed with -1 on reading size.");
                }
                in_pkgBuf.flip();
            }
            engResult = sslEngine.unwrap(in_pkgBuf, in_appBuf);
            ByteBuffer tmp_pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
            int loop_count = 0;
            while (engResult.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
                // The client is too slow? Cut it and let it reconnect
                if (loop_count > 10) {
                    throw new IOException("Too many times in SSL BUFFER_UNDERFLOW, disconnect guest.");
                }
                // We need more packets to complete this operation
                if (s_logger.isTraceEnabled()) {
                    s_logger.trace("SSL: Buffer underflowed, getting more packets");
                }
                tmp_pkgBuf.clear();
                count = ch.read(tmp_pkgBuf);
                if (count == -1) {
                    throw new IOException("Connection closed with -1 on reading size.");
                }
                tmp_pkgBuf.flip();
                in_pkgBuf.mark();
                in_pkgBuf.position(in_pkgBuf.limit());
                in_pkgBuf.limit(in_pkgBuf.limit() + tmp_pkgBuf.limit());
                in_pkgBuf.put(tmp_pkgBuf);
                in_pkgBuf.reset();
                in_appBuf.clear();
                engResult = sslEngine.unwrap(in_pkgBuf, in_appBuf);
                loop_count++;
            }
        } else if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) {
            Runnable run;
            while ((run = sslEngine.getDelegatedTask()) != null) {
                if (s_logger.isTraceEnabled()) {
                    s_logger.trace("SSL: Running delegated task!");
                }
                run.run();
            }
        } else if (hsStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
            throw new IOException("NOT a handshaking!");
        }
        if (engResult != null && engResult.getStatus() != SSLEngineResult.Status.OK) {
            throw new IOException("Fail to handshake! " + engResult.getStatus());
        }
        if (engResult != null)
            hsStatus = engResult.getHandshakeStatus();
        else
            hsStatus = sslEngine.getHandshakeStatus();
    }
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLSession(javax.net.ssl.SSLSession) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 9 with HandshakeStatus

use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project cloudstack by apache.

the class Link method doHandshake.

public static boolean doHandshake(final SocketChannel socketChannel, final SSLEngine sslEngine, final boolean isClient) throws IOException {
    if (socketChannel == null || sslEngine == null) {
        return false;
    }
    final int appBufferSize = sslEngine.getSession().getApplicationBufferSize();
    final int netBufferSize = sslEngine.getSession().getPacketBufferSize();
    ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
    ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
    ByteBuffer myNetData = ByteBuffer.allocate(netBufferSize);
    ByteBuffer peerNetData = ByteBuffer.allocate(netBufferSize);
    final long startTimeMills = System.currentTimeMillis();
    HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
    while (handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED && handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
        final long timeTaken = System.currentTimeMillis() - startTimeMills;
        if (timeTaken > 15000L) {
            s_logger.warn("SSL Handshake has taken more than 15s to connect to: " + socketChannel.getRemoteAddress() + ". Please investigate this connection.");
            return false;
        }
        switch(handshakeStatus) {
            case NEED_UNWRAP:
                if (!doHandshakeUnwrap(socketChannel, sslEngine, peerAppData, peerNetData, appBufferSize)) {
                    return false;
                }
                break;
            case NEED_WRAP:
                if (!doHandshakeWrap(socketChannel, sslEngine, myAppData, myNetData, peerNetData, netBufferSize)) {
                    return false;
                }
                break;
            case NEED_TASK:
                Runnable task;
                while ((task = sslEngine.getDelegatedTask()) != null) {
                    if (s_logger.isTraceEnabled()) {
                        s_logger.trace("SSL: Running delegated task!");
                    }
                    task.run();
                }
                break;
            case FINISHED:
                break;
            case NOT_HANDSHAKING:
                break;
            default:
                throw new IllegalStateException("Invalid SSL status: " + handshakeStatus);
        }
        handshakeStatus = sslEngine.getHandshakeStatus();
    }
    return true;
}
Also used : ByteBuffer(java.nio.ByteBuffer) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Example 10 with HandshakeStatus

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

the class AsyncSSLEngine2Impl method close.

@Override
public void close() {
    clientInitiated = true;
    if (mem.getConnectionState() == ConnectionState.NOT_STARTED) {
        listener.closed(true);
        return;
    }
    mem.compareSet(ConnectionState.CONNECTED, ConnectionState.DISCONNECTING);
    SSLEngine engine = mem.getEngine();
    engine.closeOutbound();
    HandshakeStatus status = engine.getHandshakeStatus();
    switch(status) {
        case NEED_WRAP:
            sendHandshakeMessage();
            break;
        case NOT_HANDSHAKING:
            if (ConnectionState.DISCONNECTED != mem.getConnectionState())
                throw new IllegalStateException("state=" + mem.getConnectionState() + " hsStatus=" + status + " should not be able to occur");
            break;
        default:
            //we WILL hit this and need to fix if other end closes...try closing both ends!!!
            throw new RuntimeException(mem + "bug, status not handled in close=" + status);
    }
}
Also used : SSLEngine(javax.net.ssl.SSLEngine) AsyncSSLEngine(org.webpieces.ssl.api.AsyncSSLEngine) HandshakeStatus(javax.net.ssl.SSLEngineResult.HandshakeStatus)

Aggregations

HandshakeStatus (javax.net.ssl.SSLEngineResult.HandshakeStatus)11 ByteBuffer (java.nio.ByteBuffer)7 SSLEngineResult (javax.net.ssl.SSLEngineResult)7 SSLEngine (javax.net.ssl.SSLEngine)5 AsyncSSLEngine (org.webpieces.ssl.api.AsyncSSLEngine)5 Status (javax.net.ssl.SSLEngineResult.Status)4 SSLException (javax.net.ssl.SSLException)2 ByteBuf (io.netty.buffer.ByteBuf)1 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)1 IOException (java.io.IOException)1 SelectionKey (java.nio.channels.SelectionKey)1 Selector (java.nio.channels.Selector)1 ArrayList (java.util.ArrayList)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 SSLSession (javax.net.ssl.SSLSession)1 AsyncSSLEngineException (org.webpieces.ssl.api.AsyncSSLEngineException)1