Search in sources :

Example 81 with SSLEngineResult

use of javax.net.ssl.SSLEngineResult in project h2o-3 by h2oai.

the class SSLSocketChannel method unwrap.

private synchronized int unwrap(ByteBuffer dst) throws IOException {
    int read = 0;
    // We have outstanding data in our incoming decrypted buffer, use that data first to fill dst
    if (!dst.hasRemaining()) {
        return 0;
    }
    if (peerAppData.position() != 0) {
        read += copy(peerAppData, dst);
        return read;
    }
    if (netInBuffer.position() == 0) {
        channel.read(netInBuffer);
    }
    while (netInBuffer.position() != 0) {
        netInBuffer.flip();
        // We still might have left data here if dst was smaller than the amount of data in peerAppData
        if (peerAppData.position() != 0) {
            peerAppData.compact();
        }
        SSLEngineResult unwrapResult = sslEngine.unwrap(netInBuffer, peerAppData);
        switch(unwrapResult.getStatus()) {
            case OK:
                {
                    unwrapResult.bytesProduced();
                    if (unwrapResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK)
                        tasks();
                    break;
                }
            case BUFFER_OVERFLOW:
                {
                    int applicationBufferSize = sslEngine.getSession().getApplicationBufferSize();
                    if (applicationBufferSize > peerAppData.capacity()) {
                        int appSize = applicationBufferSize;
                        ByteBuffer b = ByteBuffer.allocate(appSize + peerAppData.position());
                        peerAppData.flip();
                        b.put(peerAppData);
                        peerAppData = b;
                    } else {
                        // We tried to unwrap data into peerAppData which means there's leftover in netInBuffer
                        // the upcoming read should read int potential new data after the leftover
                        netInBuffer.position(netInBuffer.limit());
                        netInBuffer.limit(netInBuffer.capacity());
                        peerAppData.compact();
                        if (!dst.hasRemaining()) {
                            return read;
                        }
                    }
                    break;
                }
            case BUFFER_UNDERFLOW:
                {
                    int packetBufferSize = sslEngine.getSession().getPacketBufferSize();
                    if (packetBufferSize > netInBuffer.capacity()) {
                        int netSize = packetBufferSize;
                        if (netSize > netInBuffer.capacity()) {
                            ByteBuffer b = ByteBuffer.allocate(netSize);
                            netInBuffer.flip();
                            b.put(netInBuffer);
                            netInBuffer = b;
                        }
                    } else {
                        // We have some leftover data from unwrap but no enough.
                        // We need to read in more data from the socket AFTER the current data.
                        netInBuffer.position(netInBuffer.limit());
                        netInBuffer.limit(netInBuffer.capacity());
                        channel.read(netInBuffer);
                        continue;
                    }
                    break;
                }
            default:
                throw new IOException("Failed to SSL unwrap with status " + unwrapResult.getStatus());
        }
        if (peerAppData != dst && dst.hasRemaining()) {
            peerAppData.flip();
            read += copy(peerAppData, dst);
            if (!dst.hasRemaining()) {
                netInBuffer.compact();
                return read;
            }
        }
        netInBuffer.compact();
    }
    return read;
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Example 82 with SSLEngineResult

use of javax.net.ssl.SSLEngineResult in project tomcat by apache.

the class SecureNioChannel method close.

/**
     * Sends a SSL close message, will not physically close the connection here.
     * <br>To close the connection, you could do something like
     * <pre><code>
     *   close();
     *   while (isOpen() &amp;&amp; !myTimeoutFunction()) Thread.sleep(25);
     *   if ( isOpen() ) close(true); //forces a close if you timed out
     * </code></pre>
     * @throws IOException if an I/O error occurs
     * @throws IOException if there is data on the outgoing network buffer and
     *                     we are unable to flush it
     */
@Override
public void close() throws IOException {
    if (closing)
        return;
    closing = true;
    sslEngine.closeOutbound();
    if (!flush(netOutBuffer)) {
        throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose"));
    }
    //prep the buffer for the close message
    netOutBuffer.clear();
    //perform the close, since we called sslEngine.closeOutbound
    SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer);
    //we should be in a close state
    if (handshake.getStatus() != SSLEngineResult.Status.CLOSED) {
        throw new IOException(sm.getString("channel.nio.ssl.invalidCloseState"));
    }
    //prepare the buffer for writing
    netOutBuffer.flip();
    //if there is data to be written
    flush(netOutBuffer);
    //is the channel closed?
    closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP));
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) IOException(java.io.IOException)

Example 83 with SSLEngineResult

use of javax.net.ssl.SSLEngineResult in project tomcat by apache.

the class SecureNio2Channel method close.

/**
     * Sends a SSL close message, will not physically close the connection here.<br>
     * To close the connection, you could do something like
     * <pre><code>
     *   close();
     *   while (isOpen() &amp;&amp; !myTimeoutFunction()) Thread.sleep(25);
     *   if ( isOpen() ) close(true); //forces a close if you timed out
     * </code></pre>
     * @throws IOException if an I/O error occurs
     * @throws IOException if there is data on the outgoing network buffer and we are unable to flush it
     */
@Override
public void close() throws IOException {
    if (closing)
        return;
    closing = true;
    sslEngine.closeOutbound();
    try {
        if (!flush().get(endpoint.getConnectionTimeout(), TimeUnit.MILLISECONDS).booleanValue()) {
            throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose"));
        }
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose"), e);
    } catch (WritePendingException e) {
        throw new IOException(sm.getString("channel.nio.ssl.pendingWriteDuringClose"), e);
    }
    //prep the buffer for the close message
    netOutBuffer.clear();
    //perform the close, since we called sslEngine.closeOutbound
    SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer);
    //we should be in a close state
    if (handshake.getStatus() != SSLEngineResult.Status.CLOSED) {
        throw new IOException(sm.getString("channel.nio.ssl.invalidCloseState"));
    }
    //prepare the buffer for writing
    netOutBuffer.flip();
    //if there is data to be written
    try {
        if (!flush().get(endpoint.getConnectionTimeout(), TimeUnit.MILLISECONDS).booleanValue()) {
            throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose"));
        }
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose"), e);
    } catch (WritePendingException e) {
        throw new IOException(sm.getString("channel.nio.ssl.pendingWriteDuringClose"), e);
    }
    //is the channel closed?
    closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP));
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) WritePendingException(java.nio.channels.WritePendingException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException)

Example 84 with SSLEngineResult

use of javax.net.ssl.SSLEngineResult in project tomcat by apache.

the class SecureNio2Channel method read.

@Override
public <A> void read(final ByteBuffer[] dsts, final int offset, final int length, final long timeout, final TimeUnit unit, final A attachment, final CompletionHandler<Long, ? super A> handler) {
    if (offset < 0 || dsts == null || (offset + length) > dsts.length) {
        throw new IllegalArgumentException();
    }
    if (closing || closed) {
        handler.completed(Long.valueOf(-1), attachment);
        return;
    }
    if (!handshakeComplete) {
        throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake"));
    }
    CompletionHandler<Integer, A> readCompletionHandler = new CompletionHandler<Integer, A>() {

        @Override
        public void completed(Integer nBytes, A attach) {
            if (nBytes.intValue() < 0) {
                failed(new EOFException(), attach);
            } else {
                try {
                    //the data read
                    long read = 0;
                    //the SSL engine result
                    SSLEngineResult unwrap;
                    do {
                        //prepare the buffer
                        netInBuffer.flip();
                        //unwrap the data
                        unwrap = sslEngine.unwrap(netInBuffer, dsts, offset, length);
                        //compact the buffer
                        netInBuffer.compact();
                        if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
                            //we did receive some data, add it to our total
                            read += unwrap.bytesProduced();
                            //perform any tasks if needed
                            if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
                                tasks();
                            //if we need more network data, then bail out for now.
                            if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
                                if (read == 0) {
                                    sc.read(netInBuffer, timeout, unit, attachment, this);
                                    return;
                                } else {
                                    break;
                                }
                            }
                        } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW && read > 0) {
                            //empty out the dst buffer before we do another read
                            break;
                        } else {
                            //in the constructor
                            throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
                        }
                    } while (//continue to unwrapping as long as the input buffer has stuff
                    netInBuffer.position() != 0);
                    int capacity = 0;
                    final int endOffset = offset + length;
                    for (int i = offset; i < endOffset; i++) {
                        capacity += dsts[i].remaining();
                    }
                    if (capacity == 0) {
                        unwrapBeforeRead = true;
                    } else {
                        unwrapBeforeRead = false;
                    }
                    // If everything is OK, so complete
                    handler.completed(Long.valueOf(read), attach);
                } catch (Exception e) {
                    failed(e, attach);
                }
            }
        }

        @Override
        public void failed(Throwable exc, A attach) {
            handler.failed(exc, attach);
        }
    };
    if (unwrapBeforeRead || netInBuffer.position() > 0) {
        readCompletionHandler.completed(Integer.valueOf(netInBuffer.position()), attachment);
    } else {
        sc.read(netInBuffer, timeout, unit, attachment, readCompletionHandler);
    }
}
Also used : IOException(java.io.IOException) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) EOFException(java.io.EOFException) ExecutionException(java.util.concurrent.ExecutionException) SSLException(javax.net.ssl.SSLException) WritePendingException(java.nio.channels.WritePendingException) SSLEngineResult(javax.net.ssl.SSLEngineResult) EOFException(java.io.EOFException) CompletionHandler(java.nio.channels.CompletionHandler)

Example 85 with SSLEngineResult

use of javax.net.ssl.SSLEngineResult in project tomcat by apache.

the class SecureNio2Channel method write.

@Override
public <A> void write(final ByteBuffer[] srcs, final int offset, final int length, final long timeout, final TimeUnit unit, final A attachment, final CompletionHandler<Long, ? super A> handler) {
    if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) {
        throw new IndexOutOfBoundsException();
    }
    // Check state
    if (closing || closed) {
        handler.failed(new IOException(sm.getString("channel.nio.ssl.closing")), attachment);
        return;
    }
    try {
        // Prepare the output buffer
        netOutBuffer.clear();
        // Wrap the source data into the internal buffer
        SSLEngineResult result = sslEngine.wrap(srcs, offset, length, netOutBuffer);
        final int written = result.bytesConsumed();
        netOutBuffer.flip();
        if (result.getStatus() == Status.OK) {
            if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                tasks();
            }
            // Write data to the channel
            sc.write(netOutBuffer, timeout, unit, attachment, new CompletionHandler<Integer, A>() {

                @Override
                public void completed(Integer nBytes, A attach) {
                    if (nBytes.intValue() < 0) {
                        failed(new EOFException(), attach);
                    } else if (netOutBuffer.hasRemaining()) {
                        sc.write(netOutBuffer, timeout, unit, attachment, this);
                    } else if (written == 0) {
                        // Special case, start over to avoid code duplication
                        write(srcs, offset, length, timeout, unit, attachment, handler);
                    } else {
                        // Call the handler completed method with the
                        // consumed bytes number
                        handler.completed(Long.valueOf(written), attach);
                    }
                }

                @Override
                public void failed(Throwable exc, A attach) {
                    handler.failed(exc, attach);
                }
            });
        } else {
            throw new IOException(sm.getString("channel.nio.ssl.wrapFail", result.getStatus()));
        }
    } catch (Exception e) {
        handler.failed(e, attachment);
    }
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) EOFException(java.io.EOFException) IOException(java.io.IOException) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) EOFException(java.io.EOFException) ExecutionException(java.util.concurrent.ExecutionException) SSLException(javax.net.ssl.SSLException) WritePendingException(java.nio.channels.WritePendingException)

Aggregations

SSLEngineResult (javax.net.ssl.SSLEngineResult)139 ByteBuffer (java.nio.ByteBuffer)53 IOException (java.io.IOException)32 SSLException (javax.net.ssl.SSLException)32 SSLEngine (javax.net.ssl.SSLEngine)25 Test (org.junit.Test)13 ReadOnlyBufferException (java.nio.ReadOnlyBufferException)12 SelfSignedCertificate (io.netty.handler.ssl.util.SelfSignedCertificate)10 HandshakeStatus (javax.net.ssl.SSLEngineResult.HandshakeStatus)9 EOFException (java.io.EOFException)7 ByteBuf (io.netty.buffer.ByteBuf)6 SSLSession (javax.net.ssl.SSLSession)6 WritePendingException (java.nio.channels.WritePendingException)5 KeyManagementException (java.security.KeyManagementException)5 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)5 ExecutionException (java.util.concurrent.ExecutionException)5 TimeoutException (java.util.concurrent.TimeoutException)5 Status (javax.net.ssl.SSLEngineResult.Status)5 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)4 BufferUnderflowException (java.nio.BufferUnderflowException)3