use of io.netty.handler.ssl.SslHandshakeCompletionEvent in project vert.x by eclipse.
the class ChannelProvider method initSSL.
private void initSSL(Handler<Channel> handler, SocketAddress peerAddress, String serverName, boolean ssl, boolean useAlpn, Channel ch, Promise<Channel> channelHandler) {
if (ssl) {
SslHandler sslHandler = new SslHandler(sslHelper.createEngine(context.owner(), peerAddress, serverName, useAlpn));
sslHandler.setHandshakeTimeout(sslHelper.getSslHandshakeTimeout(), sslHelper.getSslHandshakeTimeoutUnit());
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("ssl", sslHandler);
pipeline.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof SslHandshakeCompletionEvent) {
// Notify application
SslHandshakeCompletionEvent completion = (SslHandshakeCompletionEvent) evt;
if (completion.isSuccess()) {
// Remove from the pipeline after handshake result
ctx.pipeline().remove(this);
applicationProtocol = sslHandler.applicationProtocol();
if (handler != null) {
context.dispatch(ch, handler);
}
channelHandler.setSuccess(ctx.channel());
} else {
SSLHandshakeException sslException = new SSLHandshakeException("Failed to create SSL connection");
sslException.initCause(completion.cause());
channelHandler.setFailure(sslException);
}
}
ctx.fireUserEventTriggered(evt);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Ignore these exception as they will be reported to the handler
}
});
}
}
use of io.netty.handler.ssl.SslHandshakeCompletionEvent in project netty by netty.
the class SocketSslEchoTest method testSslEcho.
public void testSslEcho(ServerBootstrap sb, Bootstrap cb) throws Throwable {
final ExecutorService delegatedTaskExecutor = Executors.newCachedThreadPool();
reset();
sb.childOption(ChannelOption.AUTO_READ, autoRead);
cb.option(ChannelOption.AUTO_READ, autoRead);
sb.childHandler(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel sch) {
serverChannel = sch;
if (serverUsesDelegatedTaskExecutor) {
SSLEngine sse = serverCtx.newEngine(sch.alloc());
serverSslHandler = new SslHandler(sse, delegatedTaskExecutor);
} else {
serverSslHandler = serverCtx.newHandler(sch.alloc());
}
serverSslHandler.setHandshakeTimeoutMillis(0);
sch.pipeline().addLast("ssl", serverSslHandler);
if (useChunkedWriteHandler) {
sch.pipeline().addLast(new ChunkedWriteHandler());
}
sch.pipeline().addLast("serverHandler", serverHandler);
}
});
final CountDownLatch clientHandshakeEventLatch = new CountDownLatch(1);
cb.handler(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel sch) {
clientChannel = sch;
if (clientUsesDelegatedTaskExecutor) {
SSLEngine cse = clientCtx.newEngine(sch.alloc());
clientSslHandler = new SslHandler(cse, delegatedTaskExecutor);
} else {
clientSslHandler = clientCtx.newHandler(sch.alloc());
}
clientSslHandler.setHandshakeTimeoutMillis(0);
sch.pipeline().addLast("ssl", clientSslHandler);
if (useChunkedWriteHandler) {
sch.pipeline().addLast(new ChunkedWriteHandler());
}
sch.pipeline().addLast("clientHandler", clientHandler);
sch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof SslHandshakeCompletionEvent) {
clientHandshakeEventLatch.countDown();
}
ctx.fireUserEventTriggered(evt);
}
});
}
});
final Channel sc = sb.bind().sync().channel();
cb.connect(sc.localAddress()).sync();
final Future<Channel> clientHandshakeFuture = clientSslHandler.handshakeFuture();
// Wait for the handshake to complete before we flush anything. SslHandler should flush non-application data.
clientHandshakeFuture.sync();
clientHandshakeEventLatch.await();
clientChannel.writeAndFlush(Unpooled.wrappedBuffer(data, 0, FIRST_MESSAGE_SIZE));
clientSendCounter.set(FIRST_MESSAGE_SIZE);
boolean needsRenegotiation = renegotiation.type == RenegotiationType.CLIENT_INITIATED;
Future<Channel> renegoFuture = null;
while (clientSendCounter.get() < data.length) {
int clientSendCounterVal = clientSendCounter.get();
int length = Math.min(random.nextInt(1024 * 64), data.length - clientSendCounterVal);
ByteBuf buf = Unpooled.wrappedBuffer(data, clientSendCounterVal, length);
if (useCompositeByteBuf) {
buf = Unpooled.compositeBuffer().addComponent(true, buf);
}
ChannelFuture future = clientChannel.writeAndFlush(buf);
clientSendCounter.set(clientSendCounterVal += length);
future.sync();
if (needsRenegotiation && clientSendCounterVal >= data.length / 2) {
needsRenegotiation = false;
clientSslHandler.engine().setEnabledCipherSuites(new String[] { renegotiation.cipherSuite });
renegoFuture = clientSslHandler.renegotiate();
logStats("CLIENT RENEGOTIATES");
assertThat(renegoFuture, is(not(sameInstance(clientHandshakeFuture))));
}
}
// Ensure all data has been exchanged.
while (clientRecvCounter.get() < data.length) {
if (serverException.get() != null) {
break;
}
if (serverException.get() != null) {
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore.
}
}
while (serverRecvCounter.get() < data.length) {
if (serverException.get() != null) {
break;
}
if (clientException.get() != null) {
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore.
}
}
// Wait until renegotiation is done.
if (renegoFuture != null) {
renegoFuture.sync();
}
if (serverHandler.renegoFuture != null) {
serverHandler.renegoFuture.sync();
}
serverChannel.close().awaitUninterruptibly();
clientChannel.close().awaitUninterruptibly();
sc.close().awaitUninterruptibly();
delegatedTaskExecutor.shutdown();
if (serverException.get() != null && !(serverException.get() instanceof IOException)) {
throw serverException.get();
}
if (clientException.get() != null && !(clientException.get() instanceof IOException)) {
throw clientException.get();
}
if (serverException.get() != null) {
throw serverException.get();
}
if (clientException.get() != null) {
throw clientException.get();
}
// When renegotiation is done, at least the initiating side should be notified.
try {
switch(renegotiation.type) {
case SERVER_INITIATED:
assertThat(serverSslHandler.engine().getSession().getCipherSuite(), is(renegotiation.cipherSuite));
assertThat(serverNegoCounter.get(), is(2));
assertThat(clientNegoCounter.get(), anyOf(is(1), is(2)));
break;
case CLIENT_INITIATED:
assertThat(serverNegoCounter.get(), anyOf(is(1), is(2)));
assertThat(clientSslHandler.engine().getSession().getCipherSuite(), is(renegotiation.cipherSuite));
assertThat(clientNegoCounter.get(), is(2));
break;
case NONE:
assertThat(serverNegoCounter.get(), is(1));
assertThat(clientNegoCounter.get(), is(1));
}
} finally {
logStats("STATS");
}
}
use of io.netty.handler.ssl.SslHandshakeCompletionEvent in project netty by netty.
the class Http2MultiplexTransportTest method testSslException.
private void testSslException(SslProvider provider, final boolean tlsv13) throws Exception {
assumeTrue(SslProvider.isAlpnSupported(provider));
if (tlsv13) {
assumeTrue(SslProvider.isTlsv13Supported(provider));
}
final String protocol = tlsv13 ? "TLSv1.3" : "TLSv1.2";
SelfSignedCertificate ssc = null;
try {
ssc = new SelfSignedCertificate();
final SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).trustManager(new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
throw new CertificateExpiredException();
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
throw new CertificateExpiredException();
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}).sslProvider(provider).ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE).protocols(protocol).applicationProtocolConfig(new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1)).clientAuth(ClientAuth.REQUIRE).build();
ServerBootstrap sb = new ServerBootstrap();
sb.group(eventLoopGroup);
sb.channel(NioServerSocketChannel.class);
sb.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(sslCtx.newHandler(ch.alloc()));
ch.pipeline().addLast(new Http2FrameCodecBuilder(true).build());
ch.pipeline().addLast(new Http2MultiplexHandler(DISCARD_HANDLER));
}
});
serverChannel = sb.bind(new InetSocketAddress(NetUtil.LOCALHOST, 0)).syncUninterruptibly().channel();
final SslContext clientCtx = SslContextBuilder.forClient().keyManager(ssc.key(), ssc.cert()).sslProvider(provider).ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE).trustManager(InsecureTrustManagerFactory.INSTANCE).protocols(protocol).applicationProtocolConfig(new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1)).build();
final CountDownLatch latch = new CountDownLatch(2);
final AtomicReference<AssertionError> errorRef = new AtomicReference<AssertionError>();
Bootstrap bs = new Bootstrap();
bs.group(eventLoopGroup);
bs.channel(NioSocketChannel.class);
bs.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(clientCtx.newHandler(ch.alloc()));
ch.pipeline().addLast(new Http2FrameCodecBuilder(false).build());
ch.pipeline().addLast(new Http2MultiplexHandler(DISCARD_HANDLER));
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof SslHandshakeCompletionEvent) {
SslHandshakeCompletionEvent handshakeCompletionEvent = (SslHandshakeCompletionEvent) evt;
if (handshakeCompletionEvent.isSuccess()) {
// the mTLS failure will be send in the next round-trip.
if (!tlsv13) {
errorRef.set(new AssertionError("TLSv1.3 expected"));
}
Http2StreamChannelBootstrap h2Bootstrap = new Http2StreamChannelBootstrap(ctx.channel());
h2Bootstrap.handler(new ChannelInboundHandlerAdapter() {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (cause.getCause() instanceof SSLException) {
latch.countDown();
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
latch.countDown();
}
});
h2Bootstrap.open().addListener(new FutureListener<Channel>() {
@Override
public void operationComplete(Future<Channel> future) {
if (future.isSuccess()) {
future.getNow().writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers(), false));
}
}
});
} else if (handshakeCompletionEvent.cause() instanceof SSLException) {
// the mTLS failure will be send in the same round-trip.
if (tlsv13) {
errorRef.set(new AssertionError("TLSv1.2 expected"));
}
latch.countDown();
latch.countDown();
}
}
}
});
}
});
clientChannel = bs.connect(serverChannel.localAddress()).syncUninterruptibly().channel();
latch.await();
AssertionError error = errorRef.get();
if (error != null) {
throw error;
}
} finally {
if (ssc != null) {
ssc.delete();
}
}
}
use of io.netty.handler.ssl.SslHandshakeCompletionEvent in project rest.li by linkedin.
the class Http2AlpnHandler method userEventTriggered.
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof SslHandshakeCompletionEvent) {
SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
if (handshakeEvent.isSuccess()) {
LOG.debug("SSL handshake succeeded");
SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
if (sslHandler == null) {
ctx.fireExceptionCaught(new IllegalStateException("cannot find a SslHandler in the pipeline (required for " + "application-level protocol negotiation)"));
return;
}
String protocol = sslHandler.applicationProtocol();
if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
LOG.debug("HTTP/2 is negotiated");
// Add HTTP/2 handler
// by "adding before" the alpn handler, we guarantee that once the alpnPromise is completed
// the request will be handled by the codec and all the possible exceptions thrown will be
// handled by a single stream instead of the whole channel
ctx.pipeline().addBefore(PIPELINE_ALPN_HANDLER, Http2StreamCodec.PIPELINE_HTTP2_CODEC_HANDLER, _http2Handler);
// Remove handler from pipeline after negotiation is complete
ctx.pipeline().remove(this);
_alpnPromise.setSuccess();
} else {
LOG.error("Protocol {}, instead of HTTP/2, is negotiated through ALPN", protocol);
_alpnPromise.setFailure(new IllegalStateException("HTTP/2 ALPN negotiation failed"));
}
} else {
LOG.error("SSL handshake failed", handshakeEvent.cause());
_alpnPromise.setFailure(handshakeEvent.cause());
}
}
ctx.fireUserEventTriggered(evt);
}
use of io.netty.handler.ssl.SslHandshakeCompletionEvent in project vert.x by eclipse.
the class SslHandshakeCompletionHandler method userEventTriggered.
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof SniCompletionEvent) {
// Shall we care ?
SniCompletionEvent completion = (SniCompletionEvent) evt;
Attribute<String> val = ctx.channel().attr(SERVER_NAME_ATTR);
val.set(completion.hostname());
} else if (evt instanceof SslHandshakeCompletionEvent) {
SslHandshakeCompletionEvent completion = (SslHandshakeCompletionEvent) evt;
if (completion.isSuccess()) {
ctx.pipeline().remove(this);
promise.setSuccess(null);
} else {
promise.tryFailure(completion.cause());
}
} else {
ctx.fireUserEventTriggered(evt);
}
}
Aggregations