This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 01f11a4a3960fa07a66725ac53945ec8338855b0
Author: Benoit Tellier <[email protected]>
AuthorDate: Wed Mar 23 10:48:45 2022 +0700

    JAMES-3738 Extract Encryption instanciation and configuration out of 
AbstractConfigurableAsyncServer
---
 .../apache/james/protocols/netty/Encryption.java   |   4 +
 .../protocols/lib/LegacyJavaEncryptionFactory.java |  81 ++++++++++++
 .../org/apache/james/protocols/lib/SslConfig.java  | 145 +++++++++++++++++++++
 .../lib/netty/AbstractConfigurableAsyncServer.java | 101 +-------------
 4 files changed, 237 insertions(+), 94 deletions(-)

diff --git 
a/protocols/netty/src/main/java/org/apache/james/protocols/netty/Encryption.java
 
b/protocols/netty/src/main/java/org/apache/james/protocols/netty/Encryption.java
index 95baeda558..19b8b18441 100644
--- 
a/protocols/netty/src/main/java/org/apache/james/protocols/netty/Encryption.java
+++ 
b/protocols/netty/src/main/java/org/apache/james/protocols/netty/Encryption.java
@@ -34,6 +34,10 @@ import io.netty.handler.ssl.SslHandler;
  */
 public interface Encryption {
 
+    interface Factory {
+        Encryption create() throws Exception;
+    }
+
     @VisibleForTesting
     static Encryption createTls(SSLContext context) {
         return createTls(context, null, ClientAuth.NONE);
diff --git 
a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java
 
b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java
new file mode 100644
index 0000000000..49dcaf643b
--- /dev/null
+++ 
b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java
@@ -0,0 +1,81 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.lib;
+
+import java.util.Optional;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.X509ExtendedKeyManager;
+
+import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.protocols.netty.Encryption;
+
+import nl.altindag.ssl.SSLFactory;
+import nl.altindag.ssl.util.PemUtils;
+
+public class LegacyJavaEncryptionFactory implements Encryption.Factory {
+    private final FileSystem fileSystem;
+    private final SslConfig sslConfig;
+
+    public LegacyJavaEncryptionFactory(FileSystem fileSystem, SslConfig 
sslConfig) {
+        this.fileSystem = fileSystem;
+        this.sslConfig = sslConfig;
+    }
+
+    @Override
+    public Encryption create() throws Exception {
+        SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder()
+            .withSslContextAlgorithm("TLS");
+        if (sslConfig.getKeystore() != null) {
+            char[] passwordAsCharArray = 
Optional.ofNullable(sslConfig.getSecret())
+                .orElse("")
+                .toCharArray();
+            sslFactoryBuilder.withIdentityMaterial(
+                fileSystem.getFile(sslConfig.getKeystore()).toPath(),
+                passwordAsCharArray,
+                passwordAsCharArray,
+                sslConfig.getKeystoreType());
+        } else {
+            X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial(
+                fileSystem.getResource(sslConfig.getCertificates()),
+                fileSystem.getResource(sslConfig.getPrivateKey()),
+                Optional.ofNullable(sslConfig.getSecret())
+                    .map(String::toCharArray)
+                    .orElse(null));
+
+            sslFactoryBuilder.withIdentityMaterial(keyManager);
+        }
+
+        if (sslConfig.getClientAuth() != null && sslConfig.getTruststore() != 
null) {
+            sslFactoryBuilder.withTrustMaterial(
+                fileSystem.getFile(sslConfig.getTruststore()).toPath(),
+                sslConfig.getTruststoreSecret(),
+                sslConfig.getKeystoreType());
+        }
+
+        SSLContext context = sslFactoryBuilder.build().getSslContext();
+
+        if (sslConfig.useStartTLS()) {
+            return Encryption.createStartTls(context, 
sslConfig.getEnabledCipherSuites(), sslConfig.getClientAuth());
+        } else {
+           return Encryption.createTls(context, 
sslConfig.getEnabledCipherSuites(), sslConfig.getClientAuth());
+        }
+    }
+}
diff --git 
a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/SslConfig.java
 
b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/SslConfig.java
new file mode 100644
index 0000000000..7f5121bedb
--- /dev/null
+++ 
b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/SslConfig.java
@@ -0,0 +1,145 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.lib;
+
+import org.apache.commons.configuration2.HierarchicalConfiguration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.configuration2.tree.ImmutableNode;
+import org.apache.james.protocols.api.ClientAuth;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SslConfig {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(SslConfig.class);
+
+    public static SslConfig parse(HierarchicalConfiguration<ImmutableNode> 
config) throws ConfigurationException {
+        boolean useStartTLS = config.getBoolean("tls.[@startTLS]", false);
+        boolean useSSL = config.getBoolean("tls.[@socketTLS]", false);
+
+        ClientAuth clientAuth;
+        if (config.getProperty("tls.clientAuth") != null || 
config.getKeys("tls.clientAuth").hasNext()) {
+            clientAuth = ClientAuth.NEED;
+        } else {
+            clientAuth = ClientAuth.NONE;
+        }
+
+        if (useSSL && useStartTLS) {
+            throw new ConfigurationException("startTLS is only supported when 
using plain sockets");
+        }
+
+        if (useStartTLS || useSSL) {
+            String[] enabledCipherSuites = 
config.getStringArray("tls.supportedCipherSuites.cipherSuite");
+            String keystore = config.getString("tls.keystore", null);
+            String privateKey = config.getString("tls.privateKey", null);
+            String certificates = config.getString("tls.certificates", null);
+            String keystoreType = config.getString("tls.keystoreType", "JKS");
+            if (keystore == null && (privateKey == null || certificates == 
null)) {
+                throw new ConfigurationException("keystore or (privateKey and 
certificates) needs to get configured");
+            }
+            String secret = config.getString("tls.secret", null);
+
+            String truststore = config.getString("tls.clientAuth.truststore", 
null);
+            String truststoreType = 
config.getString("tls.clientAuth.truststoreType", "JKS");
+            char[] truststoreSecret = 
config.getString("tls.clientAuth.truststoreSecret", "").toCharArray();
+            LOGGER.info("TLS enabled with auth {} using truststore {}", 
clientAuth, truststore);
+
+            return new SslConfig(useStartTLS, useSSL, clientAuth, keystore, 
keystoreType, privateKey, certificates, secret, truststore, truststoreType, 
enabledCipherSuites, truststoreSecret);
+        } else {
+            return new SslConfig(useStartTLS, useSSL, clientAuth, null, null, 
null, null, null, null, null, null, null);
+        }
+    }
+
+    private final boolean useStartTLS;
+    private final boolean useSSL;
+    private final ClientAuth clientAuth;
+    private final String keystore;
+    private final String keystoreType;
+    private final String privateKey;
+    private final String certificates;
+    private final String secret;
+    private final String truststore;
+    private final String truststoreType;
+    private final String[] enabledCipherSuites;
+    private final char[] truststoreSecret;
+
+    public SslConfig(boolean useStartTLS, boolean useSSL, ClientAuth 
clientAuth, String keystore, String keystoreType, String privateKey,
+                     String certificates, String secret, String truststore, 
String truststoreType, String[] enabledCipherSuites, char[] truststoreSecret) {
+        this.useStartTLS = useStartTLS;
+        this.useSSL = useSSL;
+        this.clientAuth = clientAuth;
+        this.keystore = keystore;
+        this.keystoreType = keystoreType;
+        this.privateKey = privateKey;
+        this.certificates = certificates;
+        this.secret = secret;
+        this.truststore = truststore;
+        this.truststoreType = truststoreType;
+        this.enabledCipherSuites = enabledCipherSuites;
+        this.truststoreSecret = truststoreSecret;
+    }
+
+    public ClientAuth getClientAuth() {
+        return clientAuth;
+    }
+
+    public boolean useStartTLS() {
+        return useStartTLS;
+    }
+
+    public String[] getEnabledCipherSuites() {
+        return enabledCipherSuites;
+    }
+
+    public boolean useSSL() {
+        return useSSL;
+    }
+
+    public String getKeystore() {
+        return keystore;
+    }
+
+    public String getKeystoreType() {
+        return keystoreType;
+    }
+
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    public String getCertificates() {
+        return certificates;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public String getTruststore() {
+        return truststore;
+    }
+
+    public String getTruststoreType() {
+        return truststoreType;
+    }
+
+    public char[] getTruststoreSecret() {
+        return truststoreSecret;
+    }
+}
diff --git 
a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
 
b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
index de8b5f2397..3935072f87 100644
--- 
a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
+++ 
b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
@@ -31,8 +31,6 @@ import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.X509ExtendedKeyManager;
 
 import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.HierarchicalConfiguration;
@@ -41,7 +39,8 @@ import org.apache.commons.configuration2.tree.ImmutableNode;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.lifecycle.api.Configurable;
-import org.apache.james.protocols.api.ClientAuth;
+import org.apache.james.protocols.lib.LegacyJavaEncryptionFactory;
+import org.apache.james.protocols.lib.SslConfig;
 import org.apache.james.protocols.lib.jmx.ServerMBean;
 import org.apache.james.protocols.netty.AbstractAsyncServer;
 import org.apache.james.protocols.netty.AbstractChannelPipelineFactory;
@@ -57,8 +56,6 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.channel.ChannelOption;
 import io.netty.util.concurrent.DefaultEventExecutorGroup;
 import io.netty.util.concurrent.EventExecutorGroup;
-import nl.altindag.ssl.SSLFactory;
-import nl.altindag.ssl.util.PemUtils;
 
 
 /**
@@ -90,31 +87,13 @@ public abstract class AbstractConfigurableAsyncServer 
extends AbstractAsyncServe
 
     protected int connPerIP;
 
-    private boolean useStartTLS;
-    private boolean useSSL;
-
-    private ClientAuth clientAuth;
-
     protected int connectionLimit;
 
     private String helloName;
 
-    private String keystore;
-    private String keystoreType;
-    private String privateKey;
-    private String certificates;
-
-    private String secret;
-
-    private String truststore;
-    private String truststoreType;
-    private char[] truststoreSecret;
-
+    private SslConfig sslConfig;
     protected Encryption encryption;
 
-
-    private String[] enabledCipherSuites;
-
     private ChannelHandlerFactory frameHandlerFactory;
 
     private EventExecutorGroup executorGroup;
@@ -231,35 +210,7 @@ public abstract class AbstractConfigurableAsyncServer 
extends AbstractAsyncServe
             }
         }
 
-        useStartTLS = config.getBoolean("tls.[@startTLS]", false);
-        useSSL = config.getBoolean("tls.[@socketTLS]", false);
-
-        if (config.getProperty("tls.clientAuth") != null || 
config.getKeys("tls.clientAuth").hasNext()) {
-            clientAuth = ClientAuth.NEED;
-        } else {
-            clientAuth = ClientAuth.NONE;
-        }
-
-        if (useSSL && useStartTLS) {
-            throw new ConfigurationException("startTLS is only supported when 
using plain sockets");
-        }
-
-        if (useStartTLS || useSSL) {
-            enabledCipherSuites = 
config.getStringArray("tls.supportedCipherSuites.cipherSuite");
-            keystore = config.getString("tls.keystore", null);
-            privateKey = config.getString("tls.privateKey", null);
-            certificates = config.getString("tls.certificates", null);
-            keystoreType = config.getString("tls.keystoreType", "JKS");
-            if (keystore == null && (privateKey == null || certificates == 
null)) {
-                throw new ConfigurationException("keystore or (privateKey and 
certificates) needs to get configured");
-            }
-            secret = config.getString("tls.secret", null);
-
-            truststore = config.getString("tls.clientAuth.truststore", null);
-            truststoreType = config.getString("tls.clientAuth.truststoreType", 
"JKS");
-            truststoreSecret = 
config.getString("tls.clientAuth.truststoreSecret", "").toCharArray();
-            LOGGER.info("TLS enabled with auth {} using truststore {}", 
clientAuth, truststore);
-        }
+        sslConfig = SslConfig.parse(config);
 
         Optional.ofNullable(config.getBoolean("gracefulShutdown", 
null)).ifPresent(this::setGracefulShutdown);
 
@@ -301,10 +252,6 @@ public abstract class AbstractConfigurableAsyncServer 
extends AbstractAsyncServe
         return port;
     }
 
-    public boolean useSSL() {
-        return useSSL;
-    }
-
     @PreDestroy
     public final void destroy() {
         
@@ -398,43 +345,9 @@ public abstract class AbstractConfigurableAsyncServer 
extends AbstractAsyncServe
      * @throws Exception
      */
     protected void buildSSLContext() throws Exception {
-        if (useStartTLS || useSSL) {
-            SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder()
-                .withSslContextAlgorithm("TLS");
-            if (keystore != null) {
-                char[] passwordAsCharArray = Optional.ofNullable(secret)
-                    .orElse("")
-                    .toCharArray();
-                sslFactoryBuilder.withIdentityMaterial(
-                    fileSystem.getFile(keystore).toPath(),
-                    passwordAsCharArray,
-                    passwordAsCharArray,
-                    keystoreType);
-            } else {
-                X509ExtendedKeyManager keyManager = 
PemUtils.loadIdentityMaterial(
-                    fileSystem.getResource(certificates),
-                    fileSystem.getResource(privateKey),
-                    Optional.ofNullable(secret)
-                        .map(String::toCharArray)
-                        .orElse(null));
-
-                sslFactoryBuilder.withIdentityMaterial(keyManager);
-            }
-
-            if (clientAuth != null && truststore != null) {
-                sslFactoryBuilder.withTrustMaterial(
-                    fileSystem.getFile(truststore).toPath(),
-                    truststoreSecret,
-                    truststoreType);
-            }
-
-            SSLContext context = sslFactoryBuilder.build().getSslContext();
-
-            if (useStartTLS) {
-                encryption = Encryption.createStartTls(context, 
enabledCipherSuites, clientAuth);
-            } else {
-                encryption = Encryption.createTls(context, 
enabledCipherSuites, clientAuth);
-            }
+        if (sslConfig.useSSL() || sslConfig.useStartTLS()) {
+            encryption = new LegacyJavaEncryptionFactory(fileSystem, sslConfig)
+                .create();
         }
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to