Search in sources :

Example 51 with SSLEngineResult

use of javax.net.ssl.SSLEngineResult in project voltdb by VoltDB.

the class TLSHandshaker method getRemnant.

/**
     * The JDK caches SSL sessions when the participants are the same (i.e.
     * multiple connection requests from the same peer). Once a session is cached
     * the client side ends its handshake session quickly, and is able to send
     * the login Volt message before the server finishes its handshake. This message
     * is caught in the servers last handshake network read. This method returns the
     * login message unencrypted
     *
     * @return potentially a byte buffer containing the client login message
     * @throws IOException if the decryption operation fails
     */
public ByteBuffer getRemnant() throws IOException {
    ByteBuffer bb = ((ByteBuffer) m_rxNetData.duplicate().flip()).slice();
    if (!bb.hasRemaining()) {
        return bb;
    }
    ByteBuffer remnant = ByteBuffer.allocate(m_eng.getSession().getApplicationBufferSize());
    SSLEngineResult result = m_eng.unwrap(bb, remnant);
    switch(result.getStatus()) {
        case OK:
            assert !bb.hasRemaining() : "there are unexpected additional remnants";
            return ((ByteBuffer) remnant.flip()).slice().asReadOnlyBuffer();
        case BUFFER_OVERFLOW:
            throw new IOException("buffer underflow while decrypting handshake remnant");
        case BUFFER_UNDERFLOW:
            throw new IOException("buffer overflow while decrypting handshake remnant");
        case CLOSED:
            throw new IOException("ssl engine closed while decrypting handshake remnant");
    }
    // unreachable
    return null;
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Example 52 with SSLEngineResult

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

the class Link method doWrite.

/**
     * No user, so comment it out.
     * 
     * Static methods for reading from a channel in case
     * you need to add a client that doesn't require nio.
     * @param ch channel to read from.
     * @param bytebuffer to use.
     * @return bytes read
     * @throws IOException if not read to completion.
    public static byte[] read(SocketChannel ch, ByteBuffer buff) throws IOException {
    	synchronized(buff) {
	    	buff.clear();
	    	buff.limit(4);
	    	
	    	while (buff.hasRemaining()) {
		    	if (ch.read(buff) == -1) {
		    		throw new IOException("Connection closed with -1 on reading size.");
		    	}
	    	}
	    	
	    	buff.flip();
	    	
	    	int length = buff.getInt();
	    	ByteArrayOutputStream output = new ByteArrayOutputStream(length);
	    	WritableByteChannel outCh = Channels.newChannel(output);
	    	
	    	int count = 0;
	    	while (count < length) {
	        	buff.clear();
	    		int read = ch.read(buff);
	    		if (read < 0) {
	    			throw new IOException("Connection closed with -1 on reading data.");
	    		}
	    		count += read;
	    		buff.flip();
	    		outCh.write(buff);
	    	}
	    	
	        return output.toByteArray();
    	}
    }
    */
private static void doWrite(SocketChannel ch, ByteBuffer[] buffers, SSLEngine sslEngine) throws IOException {
    SSLSession sslSession = sslEngine.getSession();
    ByteBuffer pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
    SSLEngineResult engResult;
    ByteBuffer headBuf = ByteBuffer.allocate(4);
    int totalLen = 0;
    for (ByteBuffer buffer : buffers) {
        totalLen += buffer.limit();
    }
    int processedLen = 0;
    while (processedLen < totalLen) {
        headBuf.clear();
        pkgBuf.clear();
        engResult = sslEngine.wrap(buffers, pkgBuf);
        if (engResult.getHandshakeStatus() != HandshakeStatus.FINISHED && engResult.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING && engResult.getStatus() != SSLEngineResult.Status.OK) {
            throw new IOException("SSL: SSLEngine return bad result! " + engResult);
        }
        processedLen = 0;
        for (ByteBuffer buffer : buffers) {
            processedLen += buffer.position();
        }
        int dataRemaining = pkgBuf.position();
        int header = dataRemaining;
        int headRemaining = 4;
        pkgBuf.flip();
        if (processedLen < totalLen) {
            header = header | HEADER_FLAG_FOLLOWING;
        }
        headBuf.putInt(header);
        headBuf.flip();
        while (headRemaining > 0) {
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("Writing Header " + headRemaining);
            }
            long count = ch.write(headBuf);
            headRemaining -= count;
        }
        while (dataRemaining > 0) {
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("Writing Data " + dataRemaining);
            }
            long count = ch.write(pkgBuf);
            dataRemaining -= count;
        }
    }
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLSession(javax.net.ssl.SSLSession) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Example 53 with SSLEngineResult

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

the class Link method read.

public byte[] read(SocketChannel ch) throws IOException {
    if (_readHeader) {
        // Start of a packet
        if (_readBuffer.position() == 0) {
            _readBuffer.limit(4);
        }
        if (ch.read(_readBuffer) == -1) {
            throw new IOException("Connection closed with -1 on reading size.");
        }
        if (_readBuffer.hasRemaining()) {
            s_logger.trace("Need to read the rest of the packet length");
            return null;
        }
        _readBuffer.flip();
        int header = _readBuffer.getInt();
        int readSize = (short) header;
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Packet length is " + readSize);
        }
        if (readSize > MAX_SIZE_PER_PACKET) {
            throw new IOException("Wrong packet size: " + readSize);
        }
        if (!_gotFollowingPacket) {
            _plaintextBuffer = ByteBuffer.allocate(2000);
        }
        if ((header & HEADER_FLAG_FOLLOWING) != 0) {
            _gotFollowingPacket = true;
        } else {
            _gotFollowingPacket = false;
        }
        _readBuffer.clear();
        _readHeader = false;
        if (_readBuffer.capacity() < readSize) {
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("Resizing the byte buffer from " + _readBuffer.capacity());
            }
            _readBuffer = ByteBuffer.allocate(readSize);
        }
        _readBuffer.limit(readSize);
    }
    if (ch.read(_readBuffer) == -1) {
        throw new IOException("Connection closed with -1 on read.");
    }
    if (_readBuffer.hasRemaining()) {
        // We're not done yet.
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Still has " + _readBuffer.remaining());
        }
        return null;
    }
    _readBuffer.flip();
    ByteBuffer appBuf;
    SSLSession sslSession = _sslEngine.getSession();
    SSLEngineResult engResult;
    int remaining = 0;
    while (_readBuffer.hasRemaining()) {
        remaining = _readBuffer.remaining();
        appBuf = ByteBuffer.allocate(sslSession.getApplicationBufferSize() + 40);
        engResult = _sslEngine.unwrap(_readBuffer, appBuf);
        if (engResult.getHandshakeStatus() != HandshakeStatus.FINISHED && engResult.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING && engResult.getStatus() != SSLEngineResult.Status.OK) {
            throw new IOException("SSL: SSLEngine return bad result! " + engResult);
        }
        if (remaining == _readBuffer.remaining()) {
            throw new IOException("SSL: Unable to unwrap received data! still remaining " + remaining + "bytes!");
        }
        appBuf.flip();
        if (_plaintextBuffer.remaining() < appBuf.limit()) {
            // We need to expand _plaintextBuffer for more data
            ByteBuffer newBuffer = ByteBuffer.allocate(_plaintextBuffer.capacity() + appBuf.limit() * 5);
            _plaintextBuffer.flip();
            newBuffer.put(_plaintextBuffer);
            _plaintextBuffer = newBuffer;
        }
        _plaintextBuffer.put(appBuf);
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Done with packet: " + appBuf.limit());
        }
    }
    _readBuffer.clear();
    _readHeader = true;
    if (!_gotFollowingPacket) {
        _plaintextBuffer.flip();
        byte[] result = new byte[_plaintextBuffer.limit()];
        _plaintextBuffer.get(result);
        return result;
    } else {
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Waiting for more packets");
        }
        return null;
    }
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLSession(javax.net.ssl.SSLSession) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Example 54 with SSLEngineResult

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

the class Link method read.

public byte[] read(SocketChannel ch) throws IOException {
    if (_readHeader) {
        // Start of a packet
        if (_readBuffer.position() == 0) {
            _readBuffer.limit(4);
        }
        if (ch.read(_readBuffer) == -1) {
            throw new IOException("Connection closed with -1 on reading size.");
        }
        if (_readBuffer.hasRemaining()) {
            s_logger.trace("Need to read the rest of the packet length");
            return null;
        }
        _readBuffer.flip();
        int header = _readBuffer.getInt();
        int readSize = (short) header;
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Packet length is " + readSize);
        }
        if (readSize > MAX_SIZE_PER_PACKET) {
            throw new IOException("Wrong packet size: " + readSize);
        }
        if (!_gotFollowingPacket) {
            _plaintextBuffer = ByteBuffer.allocate(2000);
        }
        if ((header & HEADER_FLAG_FOLLOWING) != 0) {
            _gotFollowingPacket = true;
        } else {
            _gotFollowingPacket = false;
        }
        _readBuffer.clear();
        _readHeader = false;
        if (_readBuffer.capacity() < readSize) {
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("Resizing the byte buffer from " + _readBuffer.capacity());
            }
            _readBuffer = ByteBuffer.allocate(readSize);
        }
        _readBuffer.limit(readSize);
    }
    if (ch.read(_readBuffer) == -1) {
        throw new IOException("Connection closed with -1 on read.");
    }
    if (_readBuffer.hasRemaining()) {
        // We're not done yet.
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Still has " + _readBuffer.remaining());
        }
        return null;
    }
    _readBuffer.flip();
    ByteBuffer appBuf;
    SSLSession sslSession = _sslEngine.getSession();
    SSLEngineResult engResult;
    int remaining = 0;
    while (_readBuffer.hasRemaining()) {
        remaining = _readBuffer.remaining();
        appBuf = ByteBuffer.allocate(sslSession.getApplicationBufferSize() + 40);
        engResult = _sslEngine.unwrap(_readBuffer, appBuf);
        if (engResult.getHandshakeStatus() != HandshakeStatus.FINISHED && engResult.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING && engResult.getStatus() != SSLEngineResult.Status.OK) {
            throw new IOException("SSL: SSLEngine return bad result! " + engResult);
        }
        if (remaining == _readBuffer.remaining()) {
            throw new IOException("SSL: Unable to unwrap received data! still remaining " + remaining + "bytes!");
        }
        appBuf.flip();
        if (_plaintextBuffer.remaining() < appBuf.limit()) {
            // We need to expand _plaintextBuffer for more data
            ByteBuffer newBuffer = ByteBuffer.allocate(_plaintextBuffer.capacity() + appBuf.limit() * 5);
            _plaintextBuffer.flip();
            newBuffer.put(_plaintextBuffer);
            _plaintextBuffer = newBuffer;
        }
        _plaintextBuffer.put(appBuf);
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Done with packet: " + appBuf.limit());
        }
    }
    _readBuffer.clear();
    _readHeader = true;
    if (!_gotFollowingPacket) {
        _plaintextBuffer.flip();
        byte[] result = new byte[_plaintextBuffer.limit()];
        _plaintextBuffer.get(result);
        return result;
    } else {
        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Waiting for more packets");
        }
        return null;
    }
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLSession(javax.net.ssl.SSLSession) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Example 55 with SSLEngineResult

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

the class Link method doHandshakeUnwrap.

private static boolean doHandshakeUnwrap(final SocketChannel socketChannel, final SSLEngine sslEngine, ByteBuffer peerAppData, ByteBuffer peerNetData, final int appBufferSize) throws IOException {
    if (socketChannel == null || sslEngine == null || peerAppData == null || peerNetData == null || appBufferSize < 0) {
        return false;
    }
    if (socketChannel.read(peerNetData) < 0) {
        if (sslEngine.isInboundDone() && sslEngine.isOutboundDone()) {
            return false;
        }
        try {
            sslEngine.closeInbound();
        } catch (SSLException e) {
            s_logger.warn("This SSL engine was forced to close inbound due to end of stream.");
        }
        sslEngine.closeOutbound();
        // in order to try to send a close message to the client.
        return true;
    }
    peerNetData.flip();
    SSLEngineResult result = null;
    try {
        result = sslEngine.unwrap(peerNetData, peerAppData);
        peerNetData.compact();
    } catch (SSLException sslException) {
        s_logger.error("SSL error occurred while processing unwrap data: " + sslException.getMessage());
        sslEngine.closeOutbound();
        return true;
    }
    switch(result.getStatus()) {
        case OK:
            break;
        case BUFFER_OVERFLOW:
            // Will occur when peerAppData's capacity is smaller than the data derived from peerNetData's unwrap.
            peerAppData = enlargeBuffer(peerAppData, appBufferSize);
            break;
        case BUFFER_UNDERFLOW:
            // Will occur either when no data was read from the peer or when the peerNetData buffer
            // was too small to hold all peer's data.
            peerNetData = handleBufferUnderflow(sslEngine, peerNetData);
            break;
        case CLOSED:
            if (sslEngine.isOutboundDone()) {
                return false;
            } else {
                sslEngine.closeOutbound();
                break;
            }
        default:
            throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
    }
    return true;
}
Also used : SSLEngineResult(javax.net.ssl.SSLEngineResult) SSLException(javax.net.ssl.SSLException)

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