From e4d400fa4abb80b90b0cf850bd9d2c462fc42a00 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Fri, 25 Oct 2019 21:57:46 +0900 Subject: [PATCH] Accept Iterable as argument to SslContextBuilder methods. (#9711) Motivation: It is common, especially in frameworks, for the parameters to `SslContextBuilder` methods to be built up as a `List` or similar `Iterable`. It is currently difficult to use `SslContextBuilder` in this case because it requires a conversion to array. Modification: Add overloads for methods that accept varargs to also accept `Iterable`, delegating by copying into an array. Result: Fixes #9293 --- .../netty/handler/ssl/SslContextBuilder.java | 92 +++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/handler/src/main/java/io/netty/handler/ssl/SslContextBuilder.java b/handler/src/main/java/io/netty/handler/ssl/SslContextBuilder.java index 85818f94d2..66b7d84f2a 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslContextBuilder.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslContextBuilder.java @@ -16,21 +16,24 @@ package io.netty.handler.ssl; -import static java.util.Objects.requireNonNull; - import io.netty.util.internal.UnstableApi; -import java.security.KeyStore; -import java.security.Provider; import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; import javax.net.ssl.TrustManagerFactory; - import java.io.File; import java.io.InputStream; +import java.security.KeyStore; import java.security.PrivateKey; +import java.security.Provider; import java.security.cert.X509Certificate; -import javax.net.ssl.SSLEngine; +import java.util.ArrayList; +import java.util.List; + +import static io.netty.util.internal.EmptyArrays.EMPTY_STRINGS; +import static io.netty.util.internal.EmptyArrays.EMPTY_X509_CERTIFICATES; +import static java.util.Objects.requireNonNull; /** * Builder for configuring a new SslContext for creation. @@ -77,6 +80,17 @@ public final class SslContextBuilder { return new SslContextBuilder(true).keyManager(key, keyCertChain); } + /** + * Creates a builder for new server-side {@link SslContext}. + * + * @param key a PKCS#8 private key + * @param keyCertChain the X.509 certificate chain + * @see #keyManager(PrivateKey, X509Certificate[]) + */ + public static SslContextBuilder forServer(PrivateKey key, Iterable keyCertChain) { + return forServer(key, toArray(keyCertChain, EMPTY_X509_CERTIFICATES)); + } + /** * Creates a builder for new server-side {@link SslContext}. * @@ -119,6 +133,20 @@ public final class SslContextBuilder { return new SslContextBuilder(true).keyManager(key, keyPassword, keyCertChain); } + /** + * Creates a builder for new server-side {@link SslContext}. + * + * @param key a PKCS#8 private key + * @param keyCertChain the X.509 certificate chain + * @param keyPassword the password of the {@code keyFile}, or {@code null} if it's not + * password-protected + * @see #keyManager(File, File, String) + */ + public static SslContextBuilder forServer( + PrivateKey key, String keyPassword, Iterable keyCertChain) { + return forServer(key, keyPassword, toArray(keyCertChain, EMPTY_X509_CERTIFICATES)); + } + /** * Creates a builder for new server-side {@link SslContext}. * @@ -215,6 +243,13 @@ public final class SslContextBuilder { return this; } + /** + * Trusted certificates for verifying the remote endpoint's certificate, {@code null} uses the system default. + */ + public SslContextBuilder trustManager(Iterable trustCertCollection) { + return trustManager(toArray(trustCertCollection, EMPTY_X509_CERTIFICATES)); + } + /** * Trusted manager for verifying the remote endpoint's certificate. {@code null} uses the system default. */ @@ -257,6 +292,17 @@ public final class SslContextBuilder { return keyManager(key, null, keyCertChain); } + /** + * Identifying certificate for this host. {@code keyCertChain} and {@code key} may + * be {@code null} for client contexts, which disables mutual authentication. + * + * @param key a PKCS#8 private key + * @param keyCertChain an X.509 certificate chain + */ + public SslContextBuilder keyManager(PrivateKey key, Iterable keyCertChain) { + return keyManager(key, toArray(keyCertChain, EMPTY_X509_CERTIFICATES)); + } + /** * Identifying certificate for this host. {@code keyCertChainFile} and {@code keyFile} may * be {@code null} for client contexts, which disables mutual authentication. @@ -341,6 +387,20 @@ public final class SslContextBuilder { return this; } + /** + * Identifying certificate for this host. {@code keyCertChain} and {@code key} may + * be {@code null} for client contexts, which disables mutual authentication. + * + * @param key a PKCS#8 private key file + * @param keyPassword the password of the {@code key}, or {@code null} if it's not + * password-protected + * @param keyCertChain an X.509 certificate chain + */ + public SslContextBuilder keyManager(PrivateKey key, String keyPassword, + Iterable keyCertChain) { + return keyManager(key, keyPassword, toArray(keyCertChain, EMPTY_X509_CERTIFICATES)); + } + /** * Identifying manager for this host. {@code keyManagerFactory} may be {@code null} for * client contexts, which disables mutual authentication. Using a {@link KeyManagerFactory} @@ -427,6 +487,15 @@ public final class SslContextBuilder { return this; } + /** + * The TLS protocol versions to enable. + * @param protocols The protocols to enable, or {@code null} to enable the default protocols. + * @see SSLEngine#setEnabledCipherSuites(String[]) + */ + public SslContextBuilder protocols(Iterable protocols) { + return protocols(toArray(protocols, EMPTY_STRINGS)); + } + /** * {@code true} if the first write request shouldn't be encrypted. */ @@ -464,4 +533,15 @@ public final class SslContextBuilder { ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout, enableOcsp, keyStoreType); } } + + private static T[] toArray(Iterable iterable, T[] prototype) { + if (iterable == null) { + return null; + } + final List list = new ArrayList(); + for (T element : iterable) { + list.add(element); + } + return list.toArray(prototype); + } }