You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by mi...@apache.org on 2020/01/14 15:15:25 UTC

[geode] branch develop updated: GEODE-7414_1: Define interface (#4505)

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

mivanac pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new dddfce0  GEODE-7414_1: Define interface (#4505)
dddfce0 is described below

commit dddfce0a273a542744b6baab1d3ea535d11894c7
Author: Mario Ivanac <48...@users.noreply.github.com>
AuthorDate: Tue Jan 14 16:14:59 2020 +0100

    GEODE-7414_1: Define interface (#4505)
    
    * GEODE-7414_1: Introduction of SSL Parameter Extension
    
    - Define interface
    - added config parameter
    - added SSLParameterExtension implementation
---
 .../integrationTest/resources/assembly_content.txt |   4 +
 ...SSLSocketParameterExtensionIntegrationTest.java | 242 +++++++++++++++++++++
 .../geode/distributed/ConfigurationProperties.java |  16 ++
 .../internal/AbstractDistributionConfig.java       |   3 +
 .../distributed/internal/DistributionConfig.java   |  30 +++
 .../internal/DistributionConfigImpl.java           |  20 +-
 .../org/apache/geode/internal/admin/SSLConfig.java |  42 +++-
 .../internal/net/SSLConfigurationFactory.java      |   2 +
 .../apache/geode/internal/net/SocketCreator.java   |  16 ++
 .../apache/geode/net/SSLParameterExtension.java    |  44 ++++
 .../internal/DistributionConfigJUnitTest.java      |   4 +-
 .../topics/gemfire_properties.html.md.erb          |   7 +
 12 files changed, 424 insertions(+), 6 deletions(-)

diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index 7fca5a5..1ea16d7 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -887,6 +887,10 @@ javadoc/org/apache/geode/modules/util/TouchReplicatedRegionEntriesFunction.html
 javadoc/org/apache/geode/modules/util/package-frame.html
 javadoc/org/apache/geode/modules/util/package-summary.html
 javadoc/org/apache/geode/modules/util/package-tree.html
+javadoc/org/apache/geode/net/SSLParameterExtension.html
+javadoc/org/apache/geode/net/package-frame.html
+javadoc/org/apache/geode/net/package-summary.html
+javadoc/org/apache/geode/net/package-tree.html
 javadoc/org/apache/geode/package-frame.html
 javadoc/org/apache/geode/package-summary.html
 javadoc/org/apache/geode/package-tree.html
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/net/SSLSocketParameterExtensionIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/net/SSLSocketParameterExtensionIntegrationTest.java
new file mode 100644
index 0000000..18c67d4
--- /dev/null
+++ b/geode-core/src/integrationTest/java/org/apache/geode/net/SSLSocketParameterExtensionIntegrationTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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.geode.net;
+
+import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_CIPHERS;
+import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED;
+import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_PROTOCOLS;
+import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_REQUIRE_AUTHENTICATION;
+import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_SYSTEM_ID;
+import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
+import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION;
+import static org.apache.geode.internal.security.SecurableCommunicationChannel.CLUSTER;
+import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIServerName;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ErrorCollector;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.DistributionConfigImpl;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.internal.net.SocketCreator;
+import org.apache.geode.internal.net.SocketCreatorFactory;
+import org.apache.geode.test.dunit.IgnoredException;
+import org.apache.geode.test.junit.categories.MembershipTest;
+
+@Category({MembershipTest.class})
+public class SSLSocketParameterExtensionIntegrationTest {
+
+  private static final String MESSAGE =
+      SSLSocketParameterExtensionIntegrationTest.class.getName() + " Message";
+
+  private AtomicReference<String> messageFromClient = new AtomicReference<>();
+
+  private DistributionConfig distributionConfig;
+  private SocketCreator socketCreator;
+  private InetAddress localHost;
+  private Thread serverThread;
+  private ServerSocket serverSocket;
+  private Socket clientSocket;
+  private InternalCache cache;
+
+  @Rule
+  public ErrorCollector errorCollector = new ErrorCollector();
+
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Rule
+  public TestName testName = new TestName();
+
+
+  private Throwable serverException;
+
+  @Before
+  public void setUp() throws Exception {
+    IgnoredException.addIgnoredException("javax.net.ssl.SSLException: Read timed out");
+
+    File keystore = findTestKeystore();
+    System.setProperty("javax.net.ssl.trustStore", keystore.getCanonicalPath());
+    System.setProperty("javax.net.ssl.trustStorePassword", "password");
+    System.setProperty("javax.net.ssl.keyStore", keystore.getCanonicalPath());
+    System.setProperty("javax.net.ssl.keyStorePassword", "password");
+
+    Properties properties = new Properties();
+    properties.setProperty(MCAST_PORT, "0");
+    properties.setProperty(CLUSTER_SSL_ENABLED, "true");
+    properties.setProperty(CLUSTER_SSL_REQUIRE_AUTHENTICATION, "true");
+    properties.setProperty(CLUSTER_SSL_CIPHERS, "any");
+    properties.setProperty(CLUSTER_SSL_PROTOCOLS, "TLSv1.2");
+    properties.setProperty(SSL_PARAMETER_EXTENSION, MySSLParameterExtension.class.getName());
+    properties.setProperty(DISTRIBUTED_SYSTEM_ID, "11");
+
+    cache = (InternalCache) new CacheFactory(properties).create();
+
+    this.distributionConfig = new DistributionConfigImpl(properties);
+
+    SocketCreatorFactory.setDistributionConfig(this.distributionConfig);
+    this.socketCreator = SocketCreatorFactory.getSocketCreatorForComponent(CLUSTER);
+
+    this.localHost = InetAddress.getLocalHost();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (this.clientSocket != null) {
+      this.clientSocket.close();
+    }
+    if (this.serverSocket != null) {
+      this.serverSocket.close();
+    }
+    if (this.serverThread != null && this.serverThread.isAlive()) {
+      this.serverThread.interrupt();
+    }
+    SocketCreatorFactory.close();
+    cache.close();
+  }
+
+  @Test
+  public void securedSocketCheckExtensions() throws Exception {
+    this.serverSocket = this.socketCreator.createServerSocket(0, 0, this.localHost);
+    this.serverThread = startServer(this.serverSocket, 15000);
+
+    int serverPort = this.serverSocket.getLocalPort();
+    this.clientSocket = this.socketCreator.connectForServer(this.localHost, serverPort);
+
+    SSLSocket sslSocket = (SSLSocket) this.clientSocket;
+
+    List<SNIServerName> serverNames = new ArrayList<>(1);
+    SNIHostName serverName = new SNIHostName("11");
+    serverNames.add(serverName);
+
+    assertThat(sslSocket.getSSLParameters().getServerNames()).isEqualTo(serverNames);
+
+    // transmit expected string from Client to Server
+    ObjectOutputStream output = new ObjectOutputStream(this.clientSocket.getOutputStream());
+    output.writeObject(MESSAGE);
+    output.flush();
+
+    // this is the real assertion of this test
+    await().until(() -> {
+      return !serverThread.isAlive();
+    });
+    assertNull(serverException);
+    assertThat(this.messageFromClient.get()).isEqualTo(MESSAGE);
+  }
+
+  private File findTestKeystore() throws IOException {
+    return copyKeystoreResourceToFile("/ssl/trusted.keystore");
+  }
+
+  public File copyKeystoreResourceToFile(final String name) throws IOException {
+    URL resource = getClass().getResource(name);
+    assertThat(resource).isNotNull();
+
+    File file = this.temporaryFolder.newFile(name.replaceFirst(".*/", ""));
+    FileUtils.copyURLToFile(resource, file);
+    return file;
+  }
+
+  private Thread startServer(final ServerSocket serverSocket, int timeoutMillis) throws Exception {
+    Thread serverThread = new Thread(new MyThreadGroup(this.testName.getMethodName()), () -> {
+      try {
+        Socket socket = serverSocket.accept();
+        SocketCreatorFactory.getSocketCreatorForComponent(CLUSTER).handshakeIfSocketIsSSL(socket,
+            timeoutMillis);
+        assertThat(socket.getSoTimeout()).isEqualTo(0);
+
+        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
+        messageFromClient.set((String) ois.readObject());
+      } catch (Throwable throwable) {
+        serverException = throwable;
+      }
+    }, this.testName.getMethodName() + "-server");
+
+    serverThread.start();
+    return serverThread;
+  }
+
+  private class MyThreadGroup extends ThreadGroup {
+
+    public MyThreadGroup(final String name) {
+      super(name);
+    }
+
+    @Override
+    public void uncaughtException(final Thread thread, final Throwable throwable) {
+      errorCollector.addError(throwable);
+    }
+  }
+
+  public static class MySSLParameterExtension implements SSLParameterExtension {
+    DistributionConfig config;
+
+    @Override
+    public void init(DistributionConfig config) {
+      this.config = config;
+    }
+
+    @Override
+    public SSLParameters modifySSLClientSocketParameters(SSLParameters parameters) {
+      List<SNIServerName> serverNames = new ArrayList<>(1);
+      SNIHostName serverName = new SNIHostName(String.valueOf(config.getDistributedSystemId()));
+      serverNames.add(serverName);
+      parameters.setServerNames(serverNames);
+      return parameters;
+    }
+
+    @Override
+    public SSLParameters modifySSLServerSocketParameters(SSLParameters parameters) {
+      List<SNIServerName> serverNames = new ArrayList<>(1);
+      SNIHostName serverName = new SNIHostName("server");
+      serverNames.add(serverName);
+      parameters.setServerNames(serverNames);
+      return parameters;
+    }
+
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java b/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java
index d06b962..f07988f 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java
@@ -2155,6 +2155,22 @@ public interface ConfigurationProperties {
    * <U>Since</U>: Geode 1.0
    */
   String SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION = "ssl-web-require-authentication";
+
+  /**
+   * The static String definition of the <i>"ssl-parameter-extension"</i> property
+   *
+   * <U>Description</U>SSLParameterExtension module name for Clients that want to use SSL Parameter
+   * extensions.
+   * Module must implement SSLParameterExtension interface.
+   * </p>
+   * <U>Default</U>: ""
+   * </p>
+   * <U>Since</U>: Geode 1.12
+   * </p>
+   * <U>Allowed values</U>: class name
+   */
+  String SSL_PARAMETER_EXTENSION = "ssl-parameter-extension";
+
   /**
    * The static String definition of the <i>"validate-serializable-objects"</i> property
    *
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java
index c21d330..f88e14d 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java
@@ -158,6 +158,7 @@ import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_TYPE;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_LOCATOR_ALIAS;
+import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_PROTOCOLS;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_REQUIRE_AUTHENTICATION;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_ALIAS;
@@ -1474,6 +1475,8 @@ public abstract class AbstractDistributionConfig extends AbstractConfig
     m.put(SSL_DEFAULT_ALIAS, "The default certificate alias to be used in a multi-key keystore");
     m.put(SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION,
         "This property determines is the HTTP service with use mutual ssl authentication.");
+    m.put(SSL_PARAMETER_EXTENSION,
+        "User defined fully qualified class name implementing SSLParameterExtension interface for SSL parameter extensions. Defaults to \"{0}\". Legal values can be any \"class name\" implementing SSLParameterExtension that is present in the classpath.");
     m.put(VALIDATE_SERIALIZABLE_OBJECTS,
         "If true checks incoming java serializable objects against a filter");
     m.put(SERIALIZABLE_OBJECT_FILTER, "The filter to check incoming java serializables against");
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java
index d91bd6c..89a19a6 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java
@@ -158,6 +158,7 @@ import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_TYPE;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_LOCATOR_ALIAS;
+import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_PROTOCOLS;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_REQUIRE_AUTHENTICATION;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_ALIAS;
@@ -5257,6 +5258,35 @@ public interface DistributionConfig extends Config, LogConfig, StatisticsConfig
    */
   boolean DEFAULT_SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION = false;
 
+
+  /**
+   * Returns user defined class name SSL Parameter Extension in
+   * {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION}
+   */
+  @ConfigAttributeGetter(name = SSL_PARAMETER_EXTENSION)
+  String getSSLParameterExtension();
+
+  /**
+   * Sets the user defined class name in {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION}
+   * property.
+   */
+  @ConfigAttributeSetter(name = SSL_PARAMETER_EXTENSION)
+  void setSSLParameterExtension(String attValue);
+
+  /**
+   * The name of class for {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION} property
+   */
+  @ConfigAttribute(type = String.class)
+  String SSL_PARAMETER_EXTENSION_NAME = SSL_PARAMETER_EXTENSION;
+
+  /**
+   * The default {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION} class name.
+   * <p>
+   * Actual value of this is fully qualified <code>"class name"</code>.
+   */
+  String DEFAULT_SSL_PARAMETER_EXTENSION = "";
+
+
   /**
    * Returns the value of the {@link ConfigurationProperties#VALIDATE_SERIALIZABLE_OBJECTS} property
    */
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java
index 55d79b2..8a599ba 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java
@@ -628,6 +628,11 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement
 
   private String sslDefaultAlias = DEFAULT_SSL_ALIAS;
 
+  /**
+   * The SSL Parameter Extension class name
+   */
+  private String sslParameterExtension = DEFAULT_SSL_PARAMETER_EXTENSION;
+
   private Map<String, ConfigSource> sourceMap =
       Collections.synchronizedMap(new HashMap<>());
 
@@ -867,6 +872,7 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement
     this.sslProperties = other.getSSLProperties();
     this.sslDefaultAlias = other.getSSLDefaultAlias();
     this.sslWebServiceRequireAuthentication = other.getSSLWebRequireAuthentication();
+    this.sslParameterExtension = other.getSSLParameterExtension();
 
     validateSerializableObjects = other.getValidateSerializableObjects();
     serializableObjectFilter = other.getSerializableObjectFilter();
@@ -3112,6 +3118,16 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement
   }
 
   @Override
+  public String getSSLParameterExtension() {
+    return sslParameterExtension;
+  }
+
+  @Override
+  public void setSSLParameterExtension(final String extension) {
+    sslParameterExtension = extension;
+  }
+
+  @Override
   public boolean getValidateSerializableObjects() {
     return validateSerializableObjects;
   }
@@ -3288,6 +3304,7 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement
         .append(sslKeyStorePassword, that.sslKeyStorePassword)
         .append(sslTrustStore, that.sslTrustStore)
         .append(sslTrustStorePassword, that.sslTrustStorePassword)
+        .append(sslParameterExtension, that.sslParameterExtension)
         .append(locatorSSLAlias, that.locatorSSLAlias).append(sslDefaultAlias, that.sslDefaultAlias)
         .append(sourceMap, that.sourceMap).append(userCommandPackages, that.userCommandPackages)
         .append(offHeapMemorySize, that.offHeapMemorySize).append(shiroInit, that.shiroInit)
@@ -3360,7 +3377,8 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement
         .append(httpServiceSSLAlias).append(securableCommunicationChannels).append(sslProtocols)
         .append(sslCiphers).append(sslRequireAuthentication).append(sslKeyStore)
         .append(sslKeyStoreType).append(sslKeyStorePassword).append(sslTrustStore)
-        .append(sslTrustStorePassword).append(sslWebServiceRequireAuthentication)
+        .append(sslTrustStorePassword).append(sslParameterExtension)
+        .append(sslWebServiceRequireAuthentication)
         .append(locatorSSLAlias).append(sslDefaultAlias).append(sourceMap)
         .append(userCommandPackages).append(offHeapMemorySize).append(lockMemory).append(shiroInit)
         .append(modifiable).append(threadMonitorEnabled).append(threadMonitorInterval)
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java b/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java
index 79b0283..b1e3f07 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java
@@ -23,10 +23,15 @@ import java.security.KeyStore;
 import java.util.Iterator;
 import java.util.Properties;
 
+import org.apache.commons.lang3.StringUtils;
+
 import org.apache.geode.annotations.Immutable;
 import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.internal.security.CallbackInstantiator;
 import org.apache.geode.internal.security.SecurableCommunicationChannel;
 import org.apache.geode.management.internal.SSLUtil;
+import org.apache.geode.net.SSLParameterExtension;
 
 /**
  * The SSL configuration settings for a GemFire distributed system.
@@ -60,6 +65,9 @@ public class SSLConfig {
   @Immutable
   private final Properties properties;
 
+  @Immutable
+  private final SSLParameterExtension sslParameterExtension;
+
   private SSLConfig(boolean endpointIdentification,
       boolean useDefaultSSLContext,
       boolean enabled,
@@ -74,7 +82,8 @@ public class SSLConfig {
       String truststoreType,
       String alias,
       SecurableCommunicationChannel securableCommunicationChannel,
-      Properties properties) {
+      Properties properties,
+      SSLParameterExtension sslParameterExtension) {
     this.endpointIdentification = endpointIdentification;
     this.useDefaultSSLContext = useDefaultSSLContext;
     this.enabled = enabled;
@@ -90,6 +99,7 @@ public class SSLConfig {
     this.alias = alias;
     this.securableCommunicationChannel = securableCommunicationChannel;
     this.properties = properties;
+    this.sslParameterExtension = sslParameterExtension;
   }
 
   public String getAlias() {
@@ -160,6 +170,10 @@ public class SSLConfig {
     return securableCommunicationChannel;
   }
 
+  public SSLParameterExtension getSSLParameterExtension() {
+    return sslParameterExtension;
+  }
+
   @Override
   public String toString() {
     return "SSLConfig{" + "enabled=" + enabled + ", protocols='" + protocols + '\'' + ", ciphers='"
@@ -168,7 +182,8 @@ public class SSLConfig {
         + '\'' + ", truststore='" + truststore + '\'' + ", truststorePassword='"
         + truststorePassword + '\'' + ", truststoreType='" + truststoreType + '\'' + ", alias='"
         + alias + '\'' + ", securableCommunicationChannel=" + securableCommunicationChannel
-        + ", properties=" + properties + '}';
+        + ", properties=" + properties + '\'' + ", sslParameterExtension=" + sslParameterExtension
+        + '}';
   }
 
   /**
@@ -217,6 +232,7 @@ public class SSLConfig {
     private String alias = null;
     private SecurableCommunicationChannel securableCommunicationChannel = null;
     private Properties properties = new Properties();
+    private SSLParameterExtension sslParameterExtension = null;
 
     public Builder() {}
 
@@ -224,7 +240,7 @@ public class SSLConfig {
       return new SSLConfig(endpointIdentification, useDefaultSSLContext, enabled,
           protocols, ciphers, requireAuth, keystore, keystoreType, keystorePassword,
           truststore, truststorePassword, truststoreType, alias, securableCommunicationChannel,
-          properties);
+          properties, sslParameterExtension);
     }
 
     public Builder setAlias(final String alias) {
@@ -307,6 +323,26 @@ public class SSLConfig {
       return this;
     }
 
+    public Builder setSSLParameterExtension(
+        final String sslParameterExtensionConfig) {
+      if (StringUtils.isBlank(sslParameterExtensionConfig)) {
+        this.sslParameterExtension = null;
+        return this;
+      }
+      SSLParameterExtension sslParameterExtension =
+          CallbackInstantiator.getObjectOfTypeFromClassName(sslParameterExtensionConfig,
+              SSLParameterExtension.class);
+      InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance();
+
+      if (ids == null) {
+        this.sslParameterExtension = null;
+        return this;
+      }
+      sslParameterExtension.init(ids.getConfig());
+      this.sslParameterExtension = sslParameterExtension;
+      return this;
+    }
+
     public String getKeystore() {
       return keystore;
     }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java b/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java
index b6c12c0..259d578 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java
@@ -58,6 +58,7 @@ public class SSLConfigurationFactory {
       configureLegacyClusterSSL(distributionConfig, sslConfigBuilder);
     }
     sslConfigBuilder.setSecurableCommunicationChannel(sslEnabledComponent);
+
     switch (sslEnabledComponent) {
       case ALL: {
         break;
@@ -140,6 +141,7 @@ public class SSLConfigurationFactory {
     sslConfigBuilder.setRequireAuth(distributionConfig.getSSLRequireAuthentication());
     sslConfigBuilder.setAlias(distributionConfig.getSSLDefaultAlias());
     sslConfigBuilder.setUseDefaultSSLContext(distributionConfig.getSSLUseDefaultContext());
+    sslConfigBuilder.setSSLParameterExtension(distributionConfig.getSSLParameterExtension());
 
     return sslConfigBuilder;
   }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java b/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java
index 807315c..439de6a 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java
@@ -84,8 +84,10 @@ import org.apache.geode.internal.util.ArgumentRedactor;
 import org.apache.geode.internal.util.PasswordUtil;
 import org.apache.geode.logging.internal.log4j.api.LogService;
 import org.apache.geode.management.internal.SSLUtil;
+import org.apache.geode.net.SSLParameterExtension;
 import org.apache.geode.util.internal.GeodeGlossary;
 
+
 /**
  * Analyze configuration data (gemfire.properties) and configure sockets accordingly for SSL.
  * <p>
@@ -967,6 +969,14 @@ public class SocketCreator {
     if (!"any".equalsIgnoreCase(ciphers[0])) {
       serverSocket.setEnabledCipherSuites(ciphers);
     }
+
+    SSLParameterExtension sslParameterExtension = this.sslConfig.getSSLParameterExtension();
+    if (sslParameterExtension != null) {
+      SSLParameters modifiedParams =
+          sslParameterExtension.modifySSLServerSocketParameters(serverSocket.getSSLParameters());
+      serverSocket.setSSLParameters(modifiedParams);
+    }
+
   }
 
   /**
@@ -982,6 +992,12 @@ public class SocketCreator {
 
       SSLParameters modifiedParams =
           checkAndEnableHostnameValidation(sslSocket.getSSLParameters());
+
+      SSLParameterExtension sslParameterExtension = this.sslConfig.getSSLParameterExtension();
+      if (sslParameterExtension != null) {
+        modifiedParams =
+            sslParameterExtension.modifySSLClientSocketParameters(modifiedParams);
+      }
       sslSocket.setSSLParameters(modifiedParams);
 
       String[] protocols = this.sslConfig.getProtocolsAsStringArray();
diff --git a/geode-core/src/main/java/org/apache/geode/net/SSLParameterExtension.java b/geode-core/src/main/java/org/apache/geode/net/SSLParameterExtension.java
new file mode 100644
index 0000000..0ed4465
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/net/SSLParameterExtension.java
@@ -0,0 +1,44 @@
+/*
+ * 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.geode.net;
+
+import javax.net.ssl.SSLParameters;
+
+import org.apache.geode.distributed.internal.DistributionConfig;
+
+/**
+ * User implementation of a SSLParameter extension logic.
+ *
+ * @since Geode 1.12
+ */
+
+public interface SSLParameterExtension {
+  /**
+   * Initialize the SSLParameterExtension.
+   *
+   * @param config the DistributionConfig
+   */
+  default void init(DistributionConfig config) {}
+
+  default SSLParameters modifySSLClientSocketParameters(SSLParameters parameters) {
+    return parameters;
+  }
+
+  default SSLParameters modifySSLServerSocketParameters(SSLParameters parameters) {
+    return parameters;
+  }
+
+}
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java b/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java
index fd53247..64d0022 100644
--- a/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java
@@ -103,7 +103,7 @@ public class DistributionConfigJUnitTest {
   @Test
   public void testGetAttributeNames() {
     String[] attNames = AbstractDistributionConfig._getAttNames();
-    assertThat(attNames.length).isEqualTo(167);
+    assertThat(attNames.length).isEqualTo(168);
 
     List boolList = new ArrayList();
     List intList = new ArrayList();
@@ -139,7 +139,7 @@ public class DistributionConfigJUnitTest {
     // are.
     assertEquals(35, boolList.size());
     assertEquals(35, intList.size());
-    assertEquals(87, stringList.size());
+    assertEquals(88, stringList.size());
     assertEquals(5, fileList.size());
     assertEquals(5, otherList.size());
   }
diff --git a/geode-docs/reference/topics/gemfire_properties.html.md.erb b/geode-docs/reference/topics/gemfire_properties.html.md.erb
index afbfdea..8a23f6b 100644
--- a/geode-docs/reference/topics/gemfire_properties.html.md.erb
+++ b/geode-docs/reference/topics/gemfire_properties.html.md.erb
@@ -679,6 +679,13 @@ When enabled, also sets ssl-endpoint-identification-enabled to true.</td>
 </tr>
 
 <tr>
+<td>ssl-parameter-extension</td>
+<td>Specifies the implementation of the <code>SSLParameterExtension</code> interface that implements the SSL parameter extensions.</td>
+<td>S, L</td>
+<td><em>not set</em></td>
+</tr>
+
+<tr>
 <td>ssl-protocols</td>
 <td>Comma-separated list of SSL protocols or "any"</td>
 <td>S, L</td>