/** * Adds the ssl handler * * @param pipeline - channel pipeline */ protected void addSslHandler(ChannelPipeline pipeline) { if (sslContext != null) { SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(false); pipeline.addLast(SSL_HANDLER, new SslHandler(engine)); } }
@Override @Nullable protected SslInfo initSslInfo() { SslHandler sslHandler = ((Connection) this.request).channel().pipeline().get(SslHandler.class); if (sslHandler != null) { SSLSession session = sslHandler.engine().getSession(); return new DefaultSslInfo(session); } return null; }
private SSLEngine createSslEngine(SSLContext sslContext, String peerHost, int peerPort) { SSLEngine sslEngine = sslContext.createSSLEngine(peerHost, peerPort); if (cipherSuites != null) sslEngine.setEnabledCipherSuites(cipherSuites); if (enabledProtocols != null) sslEngine.setEnabledProtocols(enabledProtocols); // SSLParameters#setEndpointIdentificationAlgorithm enables endpoint validation // only in client mode. Hence, validation is enabled only for clients. if (mode == Mode.SERVER) { sslEngine.setUseClientMode(false); if (needClientAuth) sslEngine.setNeedClientAuth(needClientAuth); else sslEngine.setWantClientAuth(wantClientAuth); } else { sslEngine.setUseClientMode(true); SSLParameters sslParams = sslEngine.getSSLParameters(); sslParams.setEndpointIdentificationAlgorithm(endpointIdentification); sslEngine.setSSLParameters(sslParams); } return sslEngine; }
/** * Apply engine modifications that will exist in any use-case of TLS * * @param sslEngine the ssl engine that will be used for the connections. Is mutated. * @return the updated sslEngine (should be the same as the original, but don't rely on that) */ @Override public SSLEngine apply( SSLEngine sslEngine ) { if ( tlsVersions != null ) { sslEngine.setEnabledProtocols( tlsVersions ); } sslEngine.setUseClientMode( isClient ); return sslEngine; } }
private SSLConfigValidatorEngine(SslFactory sslFactory, SSLContext sslContext, Mode mode) { this.sslEngine = sslFactory.createSslEngine(sslContext, "localhost", 0); // these hints are not used for validation sslEngine.setUseClientMode(mode == Mode.CLIENT); appBuffer = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize()); netBuffer = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize()); }
if (sslEvent.isSuccess()) { CurrentPassport.fromChannel(ctx.channel()).add(PassportState.SERVER_CH_SSL_HANDSHAKE_COMPLETE); SslHandler sslhandler = (SslHandler) ctx.channel().pipeline().get("ssl"); SSLSession session = sslhandler.engine().getSession(); && session.getPeerCertificateChain() != null && session.getPeerCertificateChain().length > 0) { peerCert = session.getPeerCertificateChain()[0]; if (session.getLocalCertificates() != null && session.getLocalCertificates().length > 0) { SslHandshakeInfo info = new SslHandshakeInfo(isSSlFromIntermediary, session.getProtocol(), session.getCipherSuite(), clientAuth, serverCert, peerCert); ctx.channel().attr(ATTR_SSL_INFO).set(info); String clientIP = ctx.channel().attr(SourceAddressChannelHandler.ATTR_SOURCE_ADDRESS).get(); Throwable cause = sslEvent.cause(); ctx.pipeline().remove(this);
public SSLSocketChannel(final SSLContext sslContext, final SocketChannel socketChannel, final boolean client) throws IOException { if (!socketChannel.isConnected()) { throw new IllegalArgumentException("Cannot pass an un-connected SocketChannel"); } this.channel = socketChannel; this.socketAddress = socketChannel.getRemoteAddress(); final Socket socket = socketChannel.socket(); this.hostname = socket.getInetAddress().getHostName(); this.port = socket.getPort(); this.engine = sslContext.createSSLEngine(); this.engine.setUseClientMode(client); this.engine.setNeedClientAuth(true); streamInManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getPacketBufferSize())); streamOutManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getPacketBufferSize())); appDataManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getApplicationBufferSize())); }
public SSLSocketChannel(final SSLContext sslContext, final String hostname, final int port, final InetAddress localAddress, final boolean client) throws IOException { this.socketAddress = new InetSocketAddress(hostname, port); this.channel = SocketChannel.open(); if (localAddress != null) { final SocketAddress localSocketAddress = new InetSocketAddress(localAddress, 0); this.channel.bind(localSocketAddress); } this.hostname = hostname; this.port = port; this.engine = sslContext.createSSLEngine(); this.engine.setUseClientMode(client); engine.setNeedClientAuth(true); streamInManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getPacketBufferSize())); streamOutManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getPacketBufferSize())); appDataManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getApplicationBufferSize())); }
@Override protected void initChannel(Channel ch) throws Exception { SslHandler sslHandler = sslContext.newHandler(ch.alloc()); sslHandler.engine().setEnabledProtocols(sslContextFactory.getProtocols()); // Configure our pipeline of ChannelHandlerS. ChannelPipeline pipeline = ch.pipeline(); storeChannel(ch); addTimeoutHandlers(pipeline); addPassportHandler(pipeline); addTcpRelatedHandlers(pipeline); pipeline.addLast("ssl", sslHandler); addSslInfoHandlers(pipeline, isSSlFromIntermediary); addSslClientCertChecks(pipeline); addHttp1Handlers(pipeline); addHttpRelatedHandlers(pipeline); addZuulHandlers(pipeline); } }
ChannelHandler sslHandler = ctx.channel().pipeline().get("tls"); sslSession = ((SslHandler) sslHandler).engine().getSession(); if (log.isDebugEnabled()) { log.debug("Verifying HostName for {}, Cipher {}, Protocols {}", hostname, sslSession.getCipherSuite(), sslSession.getProtocol());
@Test public void closeWhenUnwrapError() throws Exception { SocketChannel mockChannel = mock(SocketChannel.class); Socket mockSocket = mock(Socket.class); when(mockChannel.socket()).thenReturn(mockSocket); when(mockSocket.isClosed()).thenReturn(true); when(mockEngine.isOutboundDone()).thenReturn(Boolean.FALSE); when(mockEngine.wrap(any(ByteBuffer.class), any(ByteBuffer.class))).thenReturn( new SSLEngineResult(BUFFER_OVERFLOW, FINISHED, 0, 0)); assertThatThrownBy(() -> nioSslEngine.close(mockChannel)).isInstanceOf(GemFireIOException.class) .hasMessageContaining("exception closing SSL session") .hasCauseInstanceOf(SSLException.class); }
void handshake(SSLConfigValidatorEngine peerEngine) throws SSLException { SSLEngineResult.HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus(); while (true) { switch (handshakeStatus) { case NEED_WRAP: handshakeResult = sslEngine.wrap(EMPTY_BUF, netBuffer); switch (handshakeResult.getStatus()) { case OK: break; case BUFFER_OVERFLOW: netBuffer.compact(); netBuffer = Utils.ensureCapacity(netBuffer, sslEngine.getSession().getPacketBufferSize()); netBuffer.flip(); break; handshakeResult = sslEngine.unwrap(peerEngine.netBuffer, appBuffer); peerEngine.netBuffer.compact(); handshakeStatus = handshakeResult.getHandshakeStatus(); case BUFFER_OVERFLOW: appBuffer = Utils.ensureCapacity(appBuffer, sslEngine.getSession().getApplicationBufferSize()); break; case BUFFER_UNDERFLOW: netBuffer = Utils.ensureCapacity(netBuffer, sslEngine.getSession().getPacketBufferSize()); break; case CLOSED: default: throw new SSLException("Unexpected handshake status: " + handshakeResult.getStatus()); sslEngine.getDelegatedTask().run(); handshakeStatus = sslEngine.getHandshakeStatus();
engine.closeOutbound(); final ByteBuffer outboundBuffer = streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize()); final SSLEngineResult handshakeResult = engine.wrap(appDataOut, outboundBuffer); if (handshakeResult.getStatus() != Status.CLOSED) { throw new IOException("Invalid close state - will not send network data"); int bytesDiscarded = channel.read(discardBuffer); while (bytesDiscarded > 0) { discardBuffer.clear(); bytesDiscarded = channel.read(discardBuffer); closeQuietly(channel.socket()); closeQuietly(channel); closed = true;
public void close() throws IOException { sslEngine.closeOutbound(); sslEngine.getSession().invalidate(); if( socketChannel.isOpen() ) socketChannel.write( wrap( emptybuffer ) );// FIXME what if not all bytes can be written socketChannel.close(); }
if (state == State.CLOSING) return; state = State.CLOSING; sslEngine.closeOutbound(); try { if (prevState != State.NOT_INITALIZED && isConnected()) { SSLEngineResult wrapResult = sslEngine.wrap(emptyBuf, netWriteBuffer); if (wrapResult.getStatus() != SSLEngineResult.Status.CLOSED) { throw new IOException("Unexpected status returned by SSLEngine.wrap, expected CLOSED, received " + wrapResult.getStatus() + ". Will not send close message to peer."); log.debug("Failed to send SSL Close message", ie); } finally { socketChannel.socket().close(); socketChannel.close(); netReadBuffer = null; netWriteBuffer = null;
private Optional<SSLEngine> getSslEngine(boolean useClientMode) { return getSslContext().map(sslContext -> { SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(useClientMode); sslEngine.setEnabledProtocols( getFilteredProtocols(sslEngine.getEnabledProtocols())); sslEngine.setEnabledCipherSuites( getFilteredCipherSuites(sslEngine.getEnabledCipherSuites())); return sslEngine; }); }
@Test public void handshakeDoesNotTerminateWithFinished() throws Exception { SocketChannel mockChannel = mock(SocketChannel.class); when(mockChannel.read(any(ByteBuffer.class))).thenReturn(100, 100, 100, 0); Socket mockSocket = mock(Socket.class); when(mockChannel.socket()).thenReturn(mockSocket); when(mockSocket.isClosed()).thenReturn(false); // initial read of handshake status followed by read of handshake status after task execution when(mockEngine.getHandshakeStatus()).thenReturn(NEED_UNWRAP); // interleaved wraps/unwraps/task-execution when(mockEngine.unwrap(any(ByteBuffer.class), any(ByteBuffer.class))).thenReturn( new SSLEngineResult(OK, NEED_WRAP, 100, 100)); when(mockEngine.wrap(any(ByteBuffer.class), any(ByteBuffer.class))).thenReturn( new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 100, 0)); ByteBuffer byteBuffer = ByteBuffer.allocate(netBufferSize); assertThatThrownBy(() -> spyNioSslEngine.handshake(mockChannel, 10000, byteBuffer)) .isInstanceOf( SSLHandshakeException.class) .hasMessageContaining("SSL Handshake terminated with status"); }
public SSLSocketChannel(final SSLEngine sslEngine, final SocketChannel socketChannel) throws IOException { if (!socketChannel.isConnected()) { throw new IllegalArgumentException("Cannot pass an un-connected SocketChannel"); } this.channel = socketChannel; this.socketAddress = socketChannel.getRemoteAddress(); final Socket socket = socketChannel.socket(); this.hostname = socket.getInetAddress().getHostName(); this.port = socket.getPort(); // don't set useClientMode or needClientAuth, use the engine as is and let the caller configure it this.engine = sslEngine; streamInManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getPacketBufferSize())); streamOutManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getPacketBufferSize())); appDataManager = new BufferStateManager(ByteBuffer.allocate(engine.getSession().getApplicationBufferSize())); }
private void createIoFilter(SocketChannel channel, boolean clientSocket) throws IOException { if (getConduit().useSSL() && channel != null) { InetSocketAddress address = (InetSocketAddress) channel.getRemoteAddress(); SSLEngine engine = getConduit().getSocketCreator().createSSLEngine(address.getHostName(), address.getPort()); if (!clientSocket) { engine.setWantClientAuth(true); engine.setNeedClientAuth(true); } int packetBufferSize = engine.getSession().getPacketBufferSize(); if (inputBuffer == null || (inputBuffer.capacity() < packetBufferSize)) { // TLS has a minimum input buffer size constraint if (inputBuffer != null) { Buffers.releaseReceiveBuffer(inputBuffer, getConduit().getStats()); } inputBuffer = Buffers.acquireReceiveBuffer(packetBufferSize, getConduit().getStats()); } if (channel.socket().getReceiveBufferSize() < packetBufferSize) { channel.socket().setReceiveBufferSize(packetBufferSize); } if (channel.socket().getSendBufferSize() < packetBufferSize) { channel.socket().setSendBufferSize(packetBufferSize); } ioFilter = getConduit().getSocketCreator().handshakeSSLSocketChannel(channel, engine, getConduit().idleConnectionTimeout, clientSocket, inputBuffer, getConduit().getStats()); } else { ioFilter = new NioPlainEngine(); } }
@Override public ByteChannel wrapChannel(SocketChannel channel, SelectionKey key) throws IOException { SSLEngine e = sslcontext.createSSLEngine(); if (enabledProtocols != null) { e.setEnabledProtocols(enabledProtocols); } if (enabledCiphersuites != null) { e.setEnabledCipherSuites(enabledCiphersuites); } e.setUseClientMode(false); return new SSLSocketChannel2(channel, e, exec, key); }