From 93984071e4ce5ccd35f71587d6f117eb60864962 Mon Sep 17 00:00:00 2001 From: Lai Jiang Date: Thu, 11 Jun 2020 17:11:40 -0400 Subject: [PATCH] Log client certificate type and length (#622) * Log client certificate type and length It appears that most client certificates are RSA certs, but we should make sure that is indeed the case. Print out the strength of the cert if it is RSA. Also adds supports for TLS 1.3 and print out the supported cipher suites. * Add a comment about zero length certificate * Make length of non-RSA keys -1 * Don't use TLS 1.3 if JDK SSL provider is used --- .../handler/SslServerInitializer.java | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/networking/src/main/java/google/registry/networking/handler/SslServerInitializer.java b/networking/src/main/java/google/registry/networking/handler/SslServerInitializer.java index 759ef8ef1..af2bb7c79 100644 --- a/networking/src/main/java/google/registry/networking/handler/SslServerInitializer.java +++ b/networking/src/main/java/google/registry/networking/handler/SslServerInitializer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelInitializer; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.ssl.ClientAuth; +import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslProvider; @@ -33,9 +34,11 @@ import io.netty.util.AttributeKey; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; import java.security.PrivateKey; +import java.security.PublicKey; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; import java.util.function.Supplier; import javax.net.ssl.SSLSession; @@ -72,6 +75,7 @@ public class SslServerInitializer extends ChannelInitializer< // change when the artifacts on GCS changes. private final Supplier privateKeySupplier; private final Supplier> certificatesSupplier; + private final ImmutableList supportedSslVersions; public SslServerInitializer( boolean requireClientCert, @@ -88,19 +92,27 @@ public class SslServerInitializer extends ChannelInitializer< this.sslProvider = sslProvider; this.privateKeySupplier = privateKeySupplier; this.certificatesSupplier = certificatesSupplier; + this.supportedSslVersions = + sslProvider == SslProvider.OPENSSL + ? ImmutableList.of("TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1") + // JDK support for TLS 1.3 won't be available until 2020-07-14 at the earliest. + // See: https://java.com/en/jre-jdk-cryptoroadmap.html + : ImmutableList.of("TLSv1.2", "TLSv1.1", "TLSv1"); } @Override protected void initChannel(C channel) throws Exception { - SslHandler sslHandler = + SslContext sslContext = SslContextBuilder.forServer( privateKeySupplier.get(), certificatesSupplier.get().toArray(new X509Certificate[0])) .sslProvider(sslProvider) .trustManager(InsecureTrustManagerFactory.INSTANCE) .clientAuth(requireClientCert ? ClientAuth.REQUIRE : ClientAuth.NONE) - .build() - .newHandler(channel.alloc()); + .protocols(supportedSslVersions) + .build(); + logger.atInfo().log("Available Cipher Suites: %s", sslContext.cipherSuites()); + SslHandler sslHandler = sslContext.newHandler(channel.alloc()); if (requireClientCert) { Promise clientCertificatePromise = channel.eventLoop().newPromise(); Future unusedFuture = @@ -112,18 +124,29 @@ public class SslServerInitializer extends ChannelInitializer< SSLSession sslSession = sslHandler.engine().getSession(); X509Certificate clientCertificate = (X509Certificate) sslSession.getPeerCertificates()[0]; + PublicKey clientPublicKey = clientCertificate.getPublicKey(); + // Note that for non-RSA keys the length would be -1. + int clientCertificateLength = -1; + if (clientPublicKey instanceof RSAPublicKey) { + clientCertificateLength = + ((RSAPublicKey) clientPublicKey).getModulus().bitLength(); + } logger.atInfo().log( "--SSL Information--\n" + "Client Certificate Hash: %s\n" + "SSL Protocol: %s\n" + "Cipher Suite: %s\n" + "Not Before: %s\n" - + "Not After: %s\n", + + "Not After: %s\n" + + "Client Certificate Type: %s\n" + + "Client Certificate Length: %s\n", getCertificateHash(clientCertificate), sslSession.getProtocol(), sslSession.getCipherSuite(), clientCertificate.getNotBefore(), - clientCertificate.getNotAfter()); + clientCertificate.getNotAfter(), + clientPublicKey.getClass().getName(), + clientCertificateLength); try { clientCertificate.checkValidity(); } catch (CertificateNotYetValidException | CertificateExpiredException e) {