Search in sources :

Example 6 with SSLEngineResult

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

the class OpenSSLEngine method unwrap.

@Override
public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
    // Check to make sure the engine has not been closed
    if (destroyed) {
        return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
    }
    // Throw required runtime exceptions
    if (src == null || dsts == null) {
        throw new IllegalArgumentException(sm.getString("engine.nullBuffer"));
    }
    if (offset >= dsts.length || offset + length > dsts.length) {
        throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), Integer.toString(length), Integer.toString(dsts.length)));
    }
    int capacity = 0;
    final int endOffset = offset + length;
    for (int i = offset; i < endOffset; i++) {
        ByteBuffer dst = dsts[i];
        if (dst == null) {
            throw new IllegalArgumentException(sm.getString("engine.nullBufferInArray"));
        }
        if (dst.isReadOnly()) {
            throw new ReadOnlyBufferException();
        }
        capacity += dst.remaining();
    }
    // Prepare OpenSSL to work in server mode and receive handshake
    if (accepted == 0) {
        beginHandshakeImplicitly();
    }
    // In handshake or close_notify stages, check if call to unwrap was made
    // without regard to the handshake status.
    SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
    if ((!handshakeFinished || engineClosed) && handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
        return new SSLEngineResult(getEngineStatus(), SSLEngineResult.HandshakeStatus.NEED_WRAP, 0, 0);
    }
    int len = src.remaining();
    // protect against protocol overflow attack vector
    if (len > MAX_ENCRYPTED_PACKET_LENGTH) {
        isInboundDone = true;
        isOutboundDone = true;
        engineClosed = true;
        shutdown();
        throw new SSLException(sm.getString("engine.oversizedPacket"));
    }
    // Write encrypted data to network BIO
    int written = -1;
    try {
        written = writeEncryptedData(src);
    } catch (Exception e) {
        throw new SSLException(e);
    }
    // OpenSSL can return 0 or -1 to these calls if nothing was written
    if (written < 0) {
        written = 0;
    }
    // There won't be any application data until we're done handshaking
    //
    // We first check handshakeFinished to eliminate the overhead of extra JNI call if possible.
    int pendingApp = pendingReadableBytesInSSL();
    if (!handshakeFinished) {
        pendingApp = 0;
    }
    int bytesProduced = 0;
    int idx = offset;
    // Do we have enough room in dsts to write decrypted data?
    if (capacity < pendingApp) {
        return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), written, 0);
    }
    while (pendingApp > 0) {
        // Write decrypted data to dsts buffers
        while (idx < endOffset) {
            ByteBuffer dst = dsts[idx];
            if (!dst.hasRemaining()) {
                idx++;
                continue;
            }
            if (pendingApp <= 0) {
                break;
            }
            int bytesRead;
            try {
                bytesRead = readPlaintextData(dst);
            } catch (Exception e) {
                throw new SSLException(e);
            }
            if (bytesRead == 0) {
                break;
            }
            bytesProduced += bytesRead;
            pendingApp -= bytesRead;
            capacity -= bytesRead;
            if (!dst.hasRemaining()) {
                idx++;
            }
        }
        if (capacity == 0) {
            break;
        } else if (pendingApp == 0) {
            pendingApp = pendingReadableBytesInSSL();
        }
    }
    // Check to see if we received a close_notify message from the peer
    if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
        receivedShutdown = true;
        closeOutbound();
        closeInbound();
    }
    if (bytesProduced == 0 && written == 0) {
        return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
    } else {
        return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(), written, bytesProduced);
    }
}
Also used : ReadOnlyBufferException(java.nio.ReadOnlyBufferException) SSLEngineResult(javax.net.ssl.SSLEngineResult) ByteBuffer(java.nio.ByteBuffer) SSLException(javax.net.ssl.SSLException) SSLException(javax.net.ssl.SSLException) CertificateException(javax.security.cert.CertificateException) ReadOnlyBufferException(java.nio.ReadOnlyBufferException) SSLPeerUnverifiedException(javax.net.ssl.SSLPeerUnverifiedException)

Example 7 with SSLEngineResult

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

the class SecureNio2Channel method handshakeWrap.

/**
     * Performs the WRAP function
     * @return the result
     * @throws IOException An IO error occurred
     */
protected SSLEngineResult handshakeWrap() throws IOException {
    //this should never be called with a network buffer that contains data
    //so we can clear it here.
    netOutBuffer.clear();
    //perform the wrap
    getBufHandler().configureWriteBufferForRead();
    SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer);
    //prepare the results to be written
    netOutBuffer.flip();
    //set the status
    handshakeStatus = result.getHandshakeStatus();
    return result;
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult)

Example 8 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 dst, final long timeout, final TimeUnit unit, final A attachment, final CompletionHandler<Integer, ? super A> handler) {
    // Check state
    if (closing || closed) {
        handler.completed(Integer.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 {
                    ByteBuffer dst2 = dst;
                    //the data read
                    int read = 0;
                    //the SSL engine result
                    SSLEngineResult unwrap;
                    do {
                        //prepare the buffer
                        netInBuffer.flip();
                        //unwrap the data
                        unwrap = sslEngine.unwrap(netInBuffer, dst2);
                        //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) {
                            if (read > 0) {
                                // read is attempted
                                break;
                            } else {
                                // since the buffer was created.
                                if (dst2 == getBufHandler().getReadBuffer()) {
                                    // This is the normal case for this code
                                    getBufHandler().expand(sslEngine.getSession().getApplicationBufferSize());
                                    dst2 = getBufHandler().getReadBuffer();
                                } else {
                                    // to the caller that the buffer has been replaced.
                                    throw new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()));
                                }
                            }
                        } else {
                            // Something else went wrong
                            throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
                        }
                    // continue to unwrap as long as the input buffer has stuff
                    } while (netInBuffer.position() != 0);
                    if (!dst2.hasRemaining()) {
                        unwrapBeforeRead = true;
                    } else {
                        unwrapBeforeRead = false;
                    }
                    // If everything is OK, so complete
                    handler.completed(Integer.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 : SSLEngineResult(javax.net.ssl.SSLEngineResult) EOFException(java.io.EOFException) CompletionHandler(java.nio.channels.CompletionHandler) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) 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)

Example 9 with SSLEngineResult

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

the class SecureNio2Channel method handshakeUnwrap.

/**
     * Perform handshake unwrap
     * @return the result
     * @throws IOException An IO error occurred
     */
protected SSLEngineResult handshakeUnwrap() throws IOException {
    if (netInBuffer.position() == netInBuffer.limit()) {
        //clear the buffer if we have emptied it out on data
        netInBuffer.clear();
    }
    SSLEngineResult result;
    boolean cont = false;
    //loop while we can perform pure SSLEngine data
    do {
        //prepare the buffer with the incoming data
        netInBuffer.flip();
        //call unwrap
        getBufHandler().configureReadBufferForWrite();
        result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer());
        //compact the buffer, this is an optional method, wonder what would happen if we didn't
        netInBuffer.compact();
        //read in the status
        handshakeStatus = result.getHandshakeStatus();
        if (result.getStatus() == SSLEngineResult.Status.OK && result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
            //execute tasks if we need to
            handshakeStatus = tasks();
        }
        //perform another unwrap?
        cont = result.getStatus() == SSLEngineResult.Status.OK && handshakeStatus == HandshakeStatus.NEED_UNWRAP;
    } while (cont);
    return result;
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult)

Example 10 with SSLEngineResult

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

the class SecureNioChannel method read.

/**
     * Reads a sequence of bytes from this channel into the given buffer.
     *
     * @param dst The buffer into which bytes are to be transferred
     * @return The number of bytes read, possibly zero, or <tt>-1</tt> if the
     *         channel has reached end-of-stream
     * @throws IOException If some other I/O error occurs
     * @throws IllegalArgumentException if the destination buffer is different
     *                                  than getBufHandler().getReadBuffer()
     */
@Override
public int read(ByteBuffer dst) throws IOException {
    // Make sure we only use the ApplicationBufferHandler's buffers
    if (dst != getBufHandler().getReadBuffer() && (getAppReadBufHandler() == null || dst != getAppReadBufHandler().getByteBuffer())) {
        throw new IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer"));
    }
    //are we in the middle of closing or closed?
    if (closing || closed)
        return -1;
    //did we finish our handshake?
    if (!handshakeComplete)
        throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake"));
    //read from the network
    int netread = sc.read(netInBuffer);
    //did we reach EOF? if so send EOF up one layer.
    if (netread == -1)
        return -1;
    //the data read
    int read = 0;
    //the SSL engine result
    SSLEngineResult unwrap;
    do {
        //prepare the buffer
        netInBuffer.flip();
        //unwrap the data
        unwrap = sslEngine.unwrap(netInBuffer, dst);
        //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) {
                break;
            }
        } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) {
            if (read > 0) {
                // read is attempted
                break;
            } else {
                // since the buffer was created.
                if (dst == getBufHandler().getReadBuffer()) {
                    // This is the normal case for this code
                    getBufHandler().expand(sslEngine.getSession().getApplicationBufferSize());
                    dst = getBufHandler().getReadBuffer();
                } else if (dst == getAppReadBufHandler().getByteBuffer()) {
                    getAppReadBufHandler().expand(sslEngine.getSession().getApplicationBufferSize());
                    dst = getAppReadBufHandler().getByteBuffer();
                } else {
                    // to the caller that the buffer has been replaced.
                    throw new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()));
                }
            }
        } else {
            // Something else went wrong
            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);
    return read;
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) IOException(java.io.IOException)

Aggregations

SSLEngineResult (javax.net.ssl.SSLEngineResult)131 ByteBuffer (java.nio.ByteBuffer)53 IOException (java.io.IOException)31 SSLException (javax.net.ssl.SSLException)29 SSLEngine (javax.net.ssl.SSLEngine)23 Test (org.junit.Test)13 ReadOnlyBufferException (java.nio.ReadOnlyBufferException)12 SelfSignedCertificate (io.netty.handler.ssl.util.SelfSignedCertificate)10 EOFException (java.io.EOFException)7 HandshakeStatus (javax.net.ssl.SSLEngineResult.HandshakeStatus)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 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)4 Status (javax.net.ssl.SSLEngineResult.Status)4 BufferUnderflowException (java.nio.BufferUnderflowException)3