/* * Using the SSLContext created during object creation, * create/configure the SSLEngines we'll use for this test. */ private void createSSLEngines() throws Exception { /* * Configure the serverEngine to act as a server in the SSL/TLS * handshake. Also, require SSL client authentication. */ serverEngine = sslc.createSSLEngine(); serverEngine.setUseClientMode(false); serverEngine.setNeedClientAuth(true); /* * Similar to above, but using client mode instead. */ clientEngine = sslc.createSSLEngine("client", 80); clientEngine.setUseClientMode(true); }
public ChannelPipeline getPipeline() throws Exception { log.debug("Creating client channel pipeline"); ChannelPipeline pipeline = Channels.pipeline(); SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(true); SslHandler sslHandler = new SslHandler(engine); sslHandler.setCloseOnSSLException(true); pipeline.addLast("ssl", sslHandler); pipeline.addLast("chunker", new ChunkedWriteHandler()); pipeline.addLast( "framer", new DelimiterBasedFrameDecoder(protocol.maxHeaderLength(), protocol.headerDelimiter())); pipeline.addLast("stringDecoder", new StringDecoder(protocol.headerCharset())); pipeline.addLast("stringEncoder", new StringEncoder(protocol.headerCharset())); HeaderCodec headerCodec = new HeaderCodec(protocol); pipeline.addLast("headerDecoder", headerCodec.decoder()); pipeline.addLast("headerEncoder", headerCodec.encoder()); pipeline.addLast("client", new ClientHandler(store)); return pipeline; }
/** * Creates a new <code>TLSWrapper</code> instance. * * @param sslc * @param eventHandler * @param clientMode */ public TLSWrapper( SSLContext sslc, TLSEventHandler eventHandler, String[] sslProtocols, boolean clientMode) { tlsEngine = sslc.createSSLEngine(); tlsEngine.setUseClientMode(clientMode); if (tls_jdk_nss_workaround) { // Workaround for TLS/SSL bug in new JDK used with new version of // nss library see also: // http://stackoverflow.com/q/10687200/427545 // http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=b509d9cb5d8164d90e6731f5fc44?bug_id=6928796 tlsEngine.setEnabledCipherSuites(tls_workaround_ciphers); } if (sslProtocols != null) { tlsEngine.setEnabledProtocols(sslProtocols); } netBuffSize = tlsEngine.getSession().getPacketBufferSize(); appBuffSize = tlsEngine.getSession().getApplicationBufferSize(); this.eventHandler = eventHandler; if (!clientMode) { tlsEngine.setWantClientAuth(true); } }
/** * Create a new client mode SSL engine, configured from an option map. * * @param sslContext the SSL context * @param optionMap the SSL options * @param peerAddress the peer address of the connection * @return the configured SSL engine */ public static SSLEngine createSSLEngine( SSLContext sslContext, OptionMap optionMap, InetSocketAddress peerAddress) { final SSLEngine engine = sslContext.createSSLEngine( optionMap.get(Options.SSL_PEER_HOST_NAME, getHostNameNoResolve(peerAddress)), optionMap.get(Options.SSL_PEER_PORT, peerAddress.getPort())); engine.setUseClientMode(true); engine.setEnableSessionCreation(optionMap.get(Options.SSL_ENABLE_SESSION_CREATION, true)); final Sequence<String> cipherSuites = optionMap.get(Options.SSL_ENABLED_CIPHER_SUITES); if (cipherSuites != null) { final Set<String> supported = new HashSet<String>(Arrays.asList(engine.getSupportedCipherSuites())); final List<String> finalList = new ArrayList<String>(); for (String name : cipherSuites) { if (supported.contains(name)) { finalList.add(name); } } engine.setEnabledCipherSuites(finalList.toArray(new String[finalList.size()])); } final Sequence<String> protocols = optionMap.get(Options.SSL_ENABLED_PROTOCOLS); if (protocols != null) { final Set<String> supported = new HashSet<String>(Arrays.asList(engine.getSupportedProtocols())); final List<String> finalList = new ArrayList<String>(); for (String name : protocols) { if (supported.contains(name)) { finalList.add(name); } } engine.setEnabledProtocols(finalList.toArray(new String[finalList.size()])); } return engine; }
protected SSLEngine createSSLEngine(String sniHostName, List<Cipher> clientRequestedCiphers) { SSLHostConfig sslHostConfig = getSSLHostConfig(sniHostName); SSLHostConfigCertificate certificate = selectCertificate(sslHostConfig, clientRequestedCiphers); SSLContextWrapper sslContextWrapper = certificate.getSslContextWrapper(); if (sslContextWrapper == null) { throw new IllegalStateException(sm.getString("endpoint.jsse.noSslContext", sniHostName)); } SSLEngine engine = sslContextWrapper.getSSLContext().createSSLEngine(); switch (sslHostConfig.getCertificateVerification()) { case NONE: engine.setNeedClientAuth(false); engine.setWantClientAuth(false); break; case OPTIONAL: case OPTIONAL_NO_CA: engine.setWantClientAuth(true); break; case REQUIRED: engine.setNeedClientAuth(true); break; } engine.setUseClientMode(false); engine.setEnabledCipherSuites(sslContextWrapper.getEnabledCiphers()); engine.setEnabledProtocols(sslContextWrapper.getEnabledProtocols()); SSLParameters sslParameters = engine.getSSLParameters(); sslParameters.setUseCipherSuitesOrder(sslHostConfig.getHonorCipherOrder()); // In case the getter returns a defensive copy engine.setSSLParameters(sslParameters); return engine; }
public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = pipeline(); // Add SSL handler first to encrypt and decrypt everything. // In this example, we use a bogus certificate in the server side // and accept any invalid certificates in the client side. // You will need something more complicated to identify both // and server in the real world. // // Read SecureChatSslContextFactory // if you need client certificate authentication. SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); engine.setUseClientMode(false); pipeline.addLast("ssl", new SslHandler(engine)); // On top of the SSL handler, add the text line codec. pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); // and then business logic. pipeline.addLast("handler", new SecureChatServerHandler()); return pipeline; }
public Channel createChannel(SocketChannel sc, SelectorThread st, ChannelListener l) throws IOException, SSLException { log.info("Creating SecureChannel. Client mode: " + clientMode); SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(clientMode); engine.setNeedClientAuth(true); return new SSLChannel(st, sc, l, engine); }
@Test public void testGentleCloseDuringHandshake() throws Exception { InetSocketAddress address = startServer(version, null); SslContextFactory sslContextFactory = newSslContextFactory(); sslContextFactory.start(); SSLEngine sslEngine = sslContextFactory.newSSLEngine(address); sslEngine.setUseClientMode(true); NextProtoNego.put( sslEngine, new NextProtoNego.ClientProvider() { @Override public boolean supports() { return true; } @Override public void unsupported() {} @Override public String selectProtocol(List<String> protocols) { return null; } }); sslEngine.beginHandshake(); ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize()); sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted); encrypted.flip(); try (SocketChannel channel = SocketChannel.open(address)) { // Send ClientHello, immediately followed by TLS Close Alert and then by FIN channel.write(encrypted); sslEngine.closeOutbound(); encrypted.clear(); sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted); encrypted.flip(); channel.write(encrypted); channel.shutdownOutput(); // Read ServerHello from server encrypted.clear(); int read = channel.read(encrypted); encrypted.flip(); Assert.assertTrue(read > 0); // Cannot decrypt, as the SSLEngine has been already closed // Now if we read more, we should either read the TLS Close Alert, or directly -1 encrypted.clear(); read = channel.read(encrypted); // Sending a TLS Close Alert during handshake results in an exception when // unwrapping that the server react to by closing the connection abruptly. Assert.assertTrue(read < 0); } }
@Override protected Connection newConnection(SelectableChannel channel, EndPoint endpoint) { SSLEngine engine = __sslCtxFactory.newSSLEngine(); engine.setUseClientMode(false); SslConnection sslConnection = new SslConnection(__byteBufferPool, _threadPool, endpoint, engine); sslConnection.setRenegotiationAllowed(__sslCtxFactory.isRenegotiationAllowed()); Connection appConnection = super.newConnection(channel, sslConnection.getDecryptedEndPoint()); sslConnection.getDecryptedEndPoint().setConnection(appConnection); return sslConnection; }
protected void decode(ChannelHandlerContext context, ByteBuf buffer) throws Exception { ChannelPipeline pipeline = context.pipeline(); if (detectSsl && SslHandler.isEncrypted(buffer)) { SSLEngine engine = SSL_SERVER_CONTEXT.getValue().createSSLEngine(); engine.setUseClientMode(false); pipeline.addLast( new SslHandler(engine), new ChunkedWriteHandler(), new PortUnificationServerHandler(delegatingHttpRequestHandler, false, detectGzip)); } else { int magic1 = buffer.getUnsignedByte(buffer.readerIndex()); int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1); if (detectGzip && magic1 == 31 && magic2 == 139) { pipeline.addLast( new JZlibEncoder(ZlibWrapper.GZIP), new JdkZlibDecoder(ZlibWrapper.GZIP), new PortUnificationServerHandler(delegatingHttpRequestHandler, detectSsl, false)); } else if (isHttp(magic1, magic2)) { NettyUtil.initHttpHandlers(pipeline); pipeline.addLast(delegatingHttpRequestHandler); if (BuiltInServer.LOG.isDebugEnabled()) { pipeline.addLast( new ChannelOutboundHandlerAdapter() { @Override public void write( ChannelHandlerContext context, Object message, ChannelPromise promise) throws Exception { if (message instanceof HttpResponse) { // BuiltInServer.LOG.debug("OUT HTTP:\n" + message); HttpResponse response = (HttpResponse) message; BuiltInServer.LOG.debug( "OUT HTTP: " + response.getStatus().code() + " " + response.headers().get("Content-type")); } super.write(context, message, promise); } }); } } else if (magic1 == 'C' && magic2 == 'H') { buffer.skipBytes(2); pipeline.addLast(new CustomHandlerDelegator()); } else { BuiltInServer.LOG.warn("unknown request, first two bytes " + magic1 + " " + magic2); context.close(); } } // must be after new channels handlers addition (netty bug?) ensureThatExceptionHandlerIsLast(pipeline); pipeline.remove(this); context.fireChannelRead(buffer); }
@Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); SSLContext sslContext = Utils.createSSLContext(); SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(true); pipeline.addLast("ssl", new SslHandler(engine)); pipeline.addLast("framer", new LineBasedFrameDecoder(1000 * 1000 * 10, true, false)); pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast("handler", connection); }
public SSLSocketChannelWrapper(SSLContext sslContext, SocketChannel sc, boolean client) throws Exception { super(sc); sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(client); sslEngine.setEnableSessionCreation(true); SSLSession session = sslEngine.getSession(); in = ByteBuffer.allocate(64 * 1024); emptyBuffer = ByteBuffer.allocate(0); int netBufferMax = session.getPacketBufferSize(); netOutBuffer = ByteBuffer.allocate(netBufferMax); netInBuffer = ByteBuffer.allocate(netBufferMax); }
@Override public byte[] accept(byte[] token) throws IOException { checkState(!isEstablished()); if (!isClientModeSet) { engine.setUseClientMode(false); isClientModeSet = true; } addInToken(token); handshake(); return getOutToken(); }
private SSLEngine makeSSLEngine(TLSParams p, SSLContext ctx) { SSLEngine eng = ctx.createSSLEngine(); if (p.getCiphers() != null) { eng.setEnabledCipherSuites(p.getCiphers().toArray(new String[p.getCiphers().size()])); } if (p.isClientAuthRequired()) { eng.setNeedClientAuth(true); } else if (p.isClientAuthRequested()) { eng.setWantClientAuth(true); } eng.setUseClientMode(false); return eng; }
/** * Returns server ssl engine. * * @param context - SSLContext to get SSLEngine from. * @param useSNI - flag used to enable or disable using SNI extension. Needed for Kerberos. */ public static SSLEngine getServerSSLEngine(SSLContext context, boolean useSNI) { SSLEngine serverEngine = context.createSSLEngine(); serverEngine.setUseClientMode(false); if (useSNI) { SNIMatcher matcher = SNIHostName.createSNIMatcher(SNI_PATTERN); List<SNIMatcher> matchers = new ArrayList<>(); matchers.add(matcher); SSLParameters params = serverEngine.getSSLParameters(); params.setSNIMatchers(matchers); serverEngine.setSSLParameters(params); } return serverEngine; }
/** * Returns client ssl engine. * * @param context - SSLContext to get SSLEngine from. * @param useSNI - flag used to enable or disable using SNI extension. Needed for Kerberos. */ public static SSLEngine getClientSSLEngine(SSLContext context, boolean useSNI) { SSLEngine clientEngine = context.createSSLEngine(HOST, 80); clientEngine.setUseClientMode(true); if (useSNI) { SNIHostName serverName = new SNIHostName(SERVER_NAME); List<SNIServerName> serverNames = new ArrayList<>(); serverNames.add(serverName); SSLParameters params = clientEngine.getSSLParameters(); params.setServerNames(serverNames); clientEngine.setSSLParameters(params); } return clientEngine; }
@Test public void testAbruptCloseDuringHandshake() throws Exception { InetSocketAddress address = startServer(version, null); SslContextFactory sslContextFactory = newSslContextFactory(); sslContextFactory.start(); SSLEngine sslEngine = sslContextFactory.newSSLEngine(address); sslEngine.setUseClientMode(true); NextProtoNego.put( sslEngine, new NextProtoNego.ClientProvider() { @Override public boolean supports() { return true; } @Override public void unsupported() {} @Override public String selectProtocol(List<String> protocols) { return null; } }); sslEngine.beginHandshake(); ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize()); sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted); encrypted.flip(); try (SocketChannel channel = SocketChannel.open(address)) { // Send ClientHello, immediately followed by FIN (no TLS Close Alert) channel.write(encrypted); channel.shutdownOutput(); // Read ServerHello from server encrypted.clear(); int read = channel.read(encrypted); encrypted.flip(); Assert.assertTrue(read > 0); ByteBuffer decrypted = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize()); sslEngine.unwrap(encrypted, decrypted); // Now if we read more, we should either read the TLS Close Alert, or directly -1 encrypted.clear(); read = channel.read(encrypted); // Since we have close the connection abruptly, the server also does so Assert.assertTrue(read < 0); } }
private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException { SslContextFactory sslContextFactory = _httpClient.getSslContextFactory(); SSLEngine sslEngine; if (channel != null) { String peerHost = channel.socket().getInetAddress().getHostAddress(); int peerPort = channel.socket().getPort(); sslEngine = sslContextFactory.newSslEngine(peerHost, peerPort); } else { sslEngine = sslContextFactory.newSslEngine(); } sslEngine.setUseClientMode(true); sslEngine.beginHandshake(); return sslEngine; }
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); engine.setUseClientMode(false); pipeline.addLast("ssl", new SslHandler(engine)); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); // and then business logic. pipeline.addLast("handler", new SecureChatServerHandler()); }
private ChannelFuture initializeChannel(InetSocketAddress addr) throws NntpClientConnectionError { final SSLEngine engine; if (this.ssl) { try { engine = this.initializeSsl(); engine.setUseClientMode(true); } catch (NoSuchAlgorithmException | KeyManagementException ex) { throw new NntpClientConnectionError(ex); } } else { engine = null; } ClientBootstrap bootstrap = new ClientBootstrap(channelFactory()); bootstrap.setOption("connectTimeoutMillis", this.connectTimeoutMillis); bootstrap.setOption("tcpNoDelay", true); bootstrap.setOption("keepAlive", true); bootstrap.setOption("reuseAddress", true); bootstrap.setPipelineFactory( new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("BANDWIDTH", trafficHandler); if (engine != null) { pipeline.addLast("ssl", new SslHandler(engine)); } pipeline.addLast("stringenc", new StringEncoder(Charsets.UTF_8)); pipeline.addLast("lineframer", new LineBasedFrameDecoder(4096)); pipeline.addLast( "decoder", new ResponseDecoder( new ResponseStateNotifierImpl(DefaultNntpClient.this.pipeline))); pipeline.addLast( HANDLER_PROCESSOR, new ResponseProcessor(DefaultNntpClient.this.pipeline)); return pipeline; } }); return bootstrap.connect(addr).awaitUninterruptibly(); }
static { try { SSLEngine temporary = getContext().createSSLEngine(); temporary.setUseClientMode(true); String[] enabledCiphers = temporary.getEnabledCipherSuites(); List<String> enabledCiphersList = new LinkedList<>(); for (String cipher : enabledCiphers) { if (!cipher.contains("anon") && !cipher.contains("KRB5") && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) { enabledCiphersList.add(cipher); } } ENABLED_NON_KRB_NOT_ANON_CIPHERS = enabledCiphersList.toArray(new String[0]); } catch (Exception ex) { throw new Error("Unexpected issue", ex); } }
@Override public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("debug-client-head", new DebugHandler("CLIENT_HEAD")); if (this.clientContext.isSecure()) { SSLEngine sslEngine = this.clientContext.getSSLContext().createSSLEngine(); sslEngine.setUseClientMode(true); SslHandler sslHandler = new SslHandler(sslEngine); sslHandler.setEnableRenegotiation(false); sslHandler.setIssueHandshake(true); pipeline.addLast("ssl", sslHandler); pipeline.addLast("client-post-ssl", new DebugHandler("SERVER-POST-SSL")); } if (this.handshake != null) { pipeline.addLast("http-encoder", new HttpRequestEncoder()); pipeline.addLast("http-decoder", new WebSocketHttpResponseDecoder(this.handshake)); pipeline.addLast( "websocket-connection-negotiator", new WebSocketConnectionNegotiator( this.clientContext.getWebSocketAddress(), this.handshake)); pipeline.addLast("stomp-frame-decoder", new WebSocketStompFrameDecoder()); pipeline.addLast("stomp-frame-encoder", new WebSocketStompFrameEncoder()); } else { pipeline.addLast("stomp-frame-decoder", new StompFrameDecoder()); pipeline.addLast("stomp-frame-encoder", new StompFrameEncoder()); } pipeline.addLast("debug-client-mid", new DebugHandler("CLIENT_MID")); pipeline.addLast( "stomp-connection-negotiator", new StompConnectionNegotiator(clientContext, "localhost")); pipeline.addLast("stomp-client-receipt", new ClientReceiptHandler(clientContext)); pipeline.addLast("stomp-message-encoder", new StompMessageEncoder()); pipeline.addLast( "stomp-message-decoder", new StompMessageDecoder(new ClientStompMessageFactory(this.client))); pipeline.addLast("stomp-client-message-handler", new ClientMessageHandler(clientContext)); pipeline.addLast("debug-client-tail", new DebugHandler("CLIENT_TAIL")); return pipeline; }
protected SSLEngine initSocketSSLEngine(Socket socket) throws SSLException { SSLEngine engine = super.initSocketSSLEngine(socket); engine.setUseClientMode(false); switch (this.getSSLConfiguration().getClientAuthentication()) { case NONE: engine.setNeedClientAuth(false); engine.setWantClientAuth(false); break; case REQUEST: engine.setWantClientAuth(true); break; case REQUIRE: engine.setNeedClientAuth(true); break; } return engine; }
private SSLEngine createSSLEngine(LDAPConnectionHandlerCfg config, SSLContext sslContext) throws DirectoryException { try { SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(false); final Set<String> protocols = config.getSSLProtocol(); if (!protocols.isEmpty()) { sslEngine.setEnabledProtocols(protocols.toArray(new String[0])); } final Set<String> ciphers = config.getSSLCipherSuite(); if (!ciphers.isEmpty()) { sslEngine.setEnabledCipherSuites(ciphers.toArray(new String[0])); } switch (config.getSSLClientAuthPolicy()) { case DISABLED: sslEngine.setNeedClientAuth(false); sslEngine.setWantClientAuth(false); break; case REQUIRED: sslEngine.setWantClientAuth(true); sslEngine.setNeedClientAuth(true); break; case OPTIONAL: default: sslEngine.setNeedClientAuth(false); sslEngine.setWantClientAuth(true); break; } return sslEngine; } catch (Exception e) { logger.traceException(e); ResultCode resCode = DirectoryServer.getServerErrorResultCode(); LocalizableMessage message = ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE.get(getExceptionMessage(e)); throw new DirectoryException(resCode, message, e); } }
/* * Constructor for a secure ChannelIO variant. */ protected ChannelIOSecure(SocketChannel sc, boolean blocking, SSLContext sslc) throws IOException { super(sc, blocking); /* * We're a server, so no need to use host/port variant. * * The first call for a server is a NEED_UNWRAP. */ sslEngine = sslc.createSSLEngine(); sslEngine.setUseClientMode(false); initialHSStatus = HandshakeStatus.NEED_UNWRAP; initialHSComplete = false; // Create a buffer using the normal expected packet size we'll // be getting. This may change, depending on the peer's // SSL implementation. netBBSize = sslEngine.getSession().getPacketBufferSize(); inNetBB = ByteBuffer.allocate(netBBSize); outNetBB = ByteBuffer.allocate(netBBSize); outNetBB.position(0); outNetBB.limit(0); }
@Override public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = pipeline(); // Enable HTTPS if necessary. if (ssl) { SSLEngine engine = SecureChatSslContextFactory.getClientContext().createSSLEngine(); engine.setUseClientMode(true); pipeline.addLast("ssl", new SslHandler(engine)); } pipeline.addLast("codec", new HttpClientCodec()); // Remove the following line if you don't want automatic content decompression. pipeline.addLast("inflater", new HttpContentDecompressor()); // to be used since huge file transfer pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); pipeline.addLast("handler", new HttpUploadClientHandler()); return pipeline; }
@Test public void testTcpClose() throws Exception { // This test replaces SSLSocket() with a very manual SSL client // so we can close TCP underneath SSL. SocketChannel client = SocketChannel.open(_connector.socket().getLocalSocketAddress()); client.socket().setSoTimeout(500); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.accept(server); SSLEngine engine = __sslCtxFactory.newSSLEngine(); engine.setUseClientMode(true); engine.beginHandshake(); ByteBuffer appOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer sslOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize() * 2); ByteBuffer appIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer sslIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize() * 2); boolean debug = false; if (debug) System.err.println(engine.getHandshakeStatus()); int loop = 20; while (engine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) { if (--loop == 0) throw new IllegalStateException(); if (engine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { if (debug) System.err.printf( "sslOut %d-%d-%d%n", sslOut.position(), sslOut.limit(), sslOut.capacity()); if (debug) System.err.printf( "appOut %d-%d-%d%n", appOut.position(), appOut.limit(), appOut.capacity()); SSLEngineResult result = engine.wrap(appOut, sslOut); if (debug) System.err.println(result); sslOut.flip(); int flushed = client.write(sslOut); if (debug) System.err.println("out=" + flushed); sslOut.clear(); } if (engine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); if (sslIn.position() == 0) { int filled = client.read(sslIn); if (debug) System.err.println("in=" + filled); } sslIn.flip(); if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); SSLEngineResult result = engine.unwrap(sslIn, appIn); if (debug) System.err.println(result); if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); if (sslIn.hasRemaining()) sslIn.compact(); else sslIn.clear(); if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); } if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable task; while ((task = engine.getDelegatedTask()) != null) task.run(); if (debug) System.err.println(engine.getHandshakeStatus()); } } if (debug) System.err.println("\nSay Hello"); // write a message appOut.put("HelloWorld".getBytes(StandardCharsets.UTF_8)); appOut.flip(); SSLEngineResult result = engine.wrap(appOut, sslOut); if (debug) System.err.println(result); sslOut.flip(); int flushed = client.write(sslOut); if (debug) System.err.println("out=" + flushed); sslOut.clear(); appOut.clear(); // read the response int filled = client.read(sslIn); if (debug) System.err.println("in=" + filled); sslIn.flip(); result = engine.unwrap(sslIn, appIn); if (debug) System.err.println(result); if (sslIn.hasRemaining()) sslIn.compact(); else sslIn.clear(); appIn.flip(); String reply = new String(appIn.array(), appIn.arrayOffset(), appIn.remaining()); appIn.clear(); Assert.assertEquals("HelloWorld", reply); if (debug) System.err.println("Shutting down output"); client.socket().shutdownOutput(); filled = client.read(sslIn); if (debug) System.err.println("in=" + filled); if (filled >= 0) { // this is the old behaviour. sslIn.flip(); try { // Since the client closed abruptly, the server is sending a close alert with a failure engine.unwrap(sslIn, appIn); Assert.fail(); } catch (SSLException x) { // Expected } } sslIn.clear(); filled = client.read(sslIn); Assert.assertEquals(-1, filled); Assert.assertFalse(server.isOpen()); }
@Override public void start() { eventLoopGroup = new NioEventLoopGroup(ioWorkerCount); eventExecutor = new NioEventLoopGroup(executorThreadCount); deployment.start(); final RequestDispatcher dispatcher = new RequestDispatcher( (SynchronousDispatcher) deployment.getDispatcher(), deployment.getProviderFactory(), domain); // Configure the server. if (sslContext == null) { bootstrap .group(eventLoopGroup) .channel(NioServerSocketChannel.class) .childHandler( new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new HttpRequestDecoder()); ch.pipeline().addLast(new HttpObjectAggregator(maxRequestSize)); ch.pipeline().addLast(new HttpResponseEncoder()); ch.pipeline() .addLast( new RestEasyHttpRequestDecoder( dispatcher.getDispatcher(), root, RestEasyHttpRequestDecoder.Protocol.HTTP)); ch.pipeline().addLast(new CorsHeadersChannelHandler()); ch.pipeline().addLast(new RestEasyHttpResponseEncoder(dispatcher)); ch.pipeline().addLast(eventExecutor, new RequestHandler(dispatcher)); } }) .option(ChannelOption.SO_BACKLOG, backlog) .childOption(ChannelOption.SO_KEEPALIVE, true); } else { final SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(false); bootstrap .group(eventLoopGroup) .channel(NioServerSocketChannel.class) .childHandler( new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addFirst(new SslHandler(engine)); ch.pipeline().addLast(new HttpRequestDecoder()); ch.pipeline().addLast(new HttpObjectAggregator(maxRequestSize)); ch.pipeline().addLast(new HttpResponseEncoder()); ch.pipeline() .addLast( new RestEasyHttpRequestDecoder( dispatcher.getDispatcher(), root, RestEasyHttpRequestDecoder.Protocol.HTTPS)); ch.pipeline().addLast(new CorsHeadersChannelHandler()); ch.pipeline().addLast(new RestEasyHttpResponseEncoder(dispatcher)); ch.pipeline().addLast(eventExecutor, new RequestHandler(dispatcher)); } }) .option(ChannelOption.SO_BACKLOG, backlog) .childOption(ChannelOption.SO_KEEPALIVE, true); } bootstrap.bind(port).syncUninterruptibly(); }
@Test public void checkSslEngineBehaviour() throws Exception { SSLEngine server = __sslCtxFactory.newSSLEngine(); SSLEngine client = __sslCtxFactory.newSSLEngine(); ByteBuffer netC2S = ByteBuffer.allocate(server.getSession().getPacketBufferSize()); ByteBuffer netS2C = ByteBuffer.allocate(server.getSession().getPacketBufferSize()); ByteBuffer serverIn = ByteBuffer.allocate(server.getSession().getApplicationBufferSize()); ByteBuffer serverOut = ByteBuffer.allocate(server.getSession().getApplicationBufferSize()); ByteBuffer clientIn = ByteBuffer.allocate(client.getSession().getApplicationBufferSize()); SSLEngineResult result; // start the client client.setUseClientMode(true); client.beginHandshake(); Assert.assertEquals(HandshakeStatus.NEED_WRAP, client.getHandshakeStatus()); // what if we try an unwrap? netS2C.flip(); result = client.unwrap(netS2C, clientIn); // unwrap is a noop assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_WRAP, result.getHandshakeStatus()); netS2C.clear(); // do the needed WRAP of empty buffer result = client.wrap(BufferUtil.EMPTY_BUFFER, netC2S); // unwrap is a noop assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertThat(result.bytesProduced(), greaterThan(0)); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); netC2S.flip(); assertEquals(netC2S.remaining(), result.bytesProduced()); // start the server server.setUseClientMode(false); server.beginHandshake(); Assert.assertEquals(HandshakeStatus.NEED_UNWRAP, server.getHandshakeStatus()); // what if we try a needless wrap? serverOut.put(BufferUtil.toBuffer("Hello World")); serverOut.flip(); result = server.wrap(serverOut, netS2C); // wrap is a noop assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); // Do the needed unwrap, to an empty buffer result = server.unwrap(netC2S, BufferUtil.EMPTY_BUFFER); assertEquals(SSLEngineResult.Status.BUFFER_OVERFLOW, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); // Do the needed unwrap, to a full buffer serverIn.position(serverIn.limit()); result = server.unwrap(netC2S, serverIn); assertEquals(SSLEngineResult.Status.BUFFER_OVERFLOW, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); // Do the needed unwrap, to an empty buffer serverIn.clear(); result = server.unwrap(netC2S, serverIn); assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertThat(result.bytesConsumed(), greaterThan(0)); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_TASK, result.getHandshakeStatus()); server.getDelegatedTask().run(); assertEquals(HandshakeStatus.NEED_WRAP, server.getHandshakeStatus()); }
@Test public void testSslEcho() throws Throwable { ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(Executors.newCachedThreadPool())); ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(Executors.newCachedThreadPool())); EchoHandler sh = new EchoHandler(true); EchoHandler ch = new EchoHandler(false); SSLEngine sse = SecureChatSslContextFactory.getServerContext().createSSLEngine(); SSLEngine cse = SecureChatSslContextFactory.getClientContext().createSSLEngine(); sse.setUseClientMode(false); cse.setUseClientMode(true); // Workaround for blocking I/O transport write-write dead lock. sb.setOption("receiveBufferSize", 1048576); sb.setOption("receiveBufferSize", 1048576); sb.getPipeline().addFirst("ssl", new SslHandler(sse)); sb.getPipeline().addLast("handler", sh); cb.getPipeline().addFirst("ssl", new SslHandler(cse)); cb.getPipeline().addLast("handler", ch); ExecutorService eventExecutor = null; if (isExecutorRequired()) { eventExecutor = new OrderedMemoryAwareThreadPoolExecutor(16, 0, 0); sb.getPipeline().addFirst("executor", new ExecutionHandler(eventExecutor)); cb.getPipeline().addFirst("executor", new ExecutionHandler(eventExecutor)); } Channel sc = sb.bind(new InetSocketAddress(0)); int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); ChannelFuture ccf = cb.connect(new InetSocketAddress(TestUtil.getLocalHost(), port)); ccf.awaitUninterruptibly(); if (!ccf.isSuccess()) { logger.error("Connection attempt failed", ccf.getCause()); sc.close().awaitUninterruptibly(); } assertTrue(ccf.isSuccess()); Channel cc = ccf.getChannel(); ChannelFuture hf = cc.getPipeline().get(SslHandler.class).handshake(); hf.awaitUninterruptibly(); if (!hf.isSuccess()) { logger.error("Handshake failed", hf.getCause()); sh.channel.close().awaitUninterruptibly(); ch.channel.close().awaitUninterruptibly(); sc.close().awaitUninterruptibly(); } assertTrue(hf.isSuccess()); for (int i = 0; i < data.length; ) { int length = Math.min(random.nextInt(1024 * 64), data.length - i); cc.write(ChannelBuffers.wrappedBuffer(data, i, length)); i += length; } while (ch.counter < data.length) { if (sh.exception.get() != null) { break; } if (ch.exception.get() != null) { break; } try { Thread.sleep(1); } catch (InterruptedException e) { // Ignore. } } while (sh.counter < data.length) { if (sh.exception.get() != null) { break; } if (ch.exception.get() != null) { break; } try { Thread.sleep(1); } catch (InterruptedException e) { // Ignore. } } sh.channel.close().awaitUninterruptibly(); ch.channel.close().awaitUninterruptibly(); sc.close().awaitUninterruptibly(); cb.shutdown(); sb.shutdown(); cb.releaseExternalResources(); sb.releaseExternalResources(); if (eventExecutor != null) { eventExecutor.shutdown(); } if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { throw sh.exception.get(); } if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { throw ch.exception.get(); } if (sh.exception.get() != null) { throw sh.exception.get(); } if (ch.exception.get() != null) { throw ch.exception.get(); } }