You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2019/09/23 17:21:25 UTC

[mina-sshd] 02/02: [SSHD-941] Allow user to override min./max. key sizes for a specific session Diffi-Helman group exchange via session properties

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

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 6eb232f3a0b92749fad3c314d47d78a61a85b401
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Mon Sep 23 09:41:46 2019 +0300

    [SSHD-941] Allow user to override min./max. key sizes for a specific session Diffi-Helman group exchange via session properties
---
 CHANGES.md                                                | 10 +++++++++-
 .../main/java/org/apache/sshd/client/kex/DHGClient.java   | 11 ++++++++---
 .../main/java/org/apache/sshd/client/kex/DHGEXClient.java | 13 +++++++++++++
 .../main/java/org/apache/sshd/server/kex/DHGEXServer.java | 15 ++++++++++-----
 .../main/java/org/apache/sshd/server/kex/DHGServer.java   |  3 ++-
 5 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 70c4c90..2ec72a5 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -43,6 +43,10 @@ initialized in the past.
 * The internal moduli used in Diffie-Hellman group exchange are **cached** - lazy-loaded the 1st time such an exchange
 occurs. The cache can be invalidated (and thus force a re-load) by invoking `Moduli#clearInternalModuliCache`.
 
+* `DHGEXClient#init` implementation allows overriding the min./max. key sizes for a specific session Diffi-Helman group
+exchange via properties - see `DHGEXClient#PROP_DHGEX_CLIENT_MIN/MAX_KEY`. Similar applies for `DHGEXServer` but only for
+the message type=30.
+
 ## Behavioral changes and enhancements
 
 * [SSHD-926](https://issues.apache.org/jira/browse/SSHD-930) - Add support for OpenSSH 'lsetstat@openssh.com' SFTP protocol extension.
@@ -50,8 +54,12 @@ occurs. The cache can be invalidated (and thus force a re-load) by invoking `Mod
 * [SSHD-930](https://issues.apache.org/jira/browse/SSHD-930) - Added configuration allowing the user to specify whether client should wait
 for the server's identification before sending its own.
 
-* [SSHD-931](https://issues.apache.org/jira/browse/SSHD-931) - Using an executor supplier instead of a specific instance in `SftpSubsystemFactory`
+* [SSHD-931](https://issues.apache.org/jira/browse/SSHD-931) - Using an executor supplier instead of a specific instance in `SftpSubsystemFactory`.
 
 * [SSHD-934](https://issues.apache.org/jira/browse/SSHD-934) - Fixed ECDSA public key encoding into OpenSSH format.
 
 * [SSHD-937](https://issues.apache.org/jira/browse/SSHD-937) - Provide session instance when creating a subsystem, user authentication, channel.
+
+* [SSHD-941](https://issues.apache.org/jira/browse/SSHD-941) - Allow user to override min./max. key sizes for a specific session Diffi-Helman group
+exchange via properties.
+
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
index cf00249..bed61f3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
@@ -102,8 +102,10 @@ public class DHGClient extends AbstractDHClientKeyExchange {
     public boolean next(int cmd, Buffer buffer) throws Exception {
         Session session = getSession();
         if (log.isDebugEnabled()) {
-            log.debug("next({})[{}] process command={}", this, session, KeyExchange.getSimpleKexOpcodeName(cmd));
+            log.debug("next({})[{}] process command={}",
+                this, session, KeyExchange.getSimpleKexOpcodeName(cmd));
         }
+
         if (cmd != SshConstants.SSH_MSG_KEXDH_REPLY) {
             throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
                 "Protocol error: expected packet SSH_MSG_KEXDH_REPLY, got " + KeyExchange.getSimpleKexOpcodeName(cmd));
@@ -119,7 +121,8 @@ public class DHGClient extends AbstractDHClientKeyExchange {
         serverKey = buffer.getRawPublicKey();
         String keyAlg = KeyUtils.getKeyType(serverKey);
         if (GenericUtils.isEmpty(keyAlg)) {
-            throw new SshException("Unsupported server key type: " + serverKey.getAlgorithm());
+            throw new SshException("Unsupported server key type: " + serverKey.getAlgorithm()
+                + "[" + serverKey.getFormat() + "]");
         }
 
         buffer = new ByteArrayBuffer();
@@ -140,8 +143,10 @@ public class DHGClient extends AbstractDHClientKeyExchange {
         verif.initVerifier(serverKey);
         verif.update(h);
         if (!verif.verify(sig)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED, "KeyExchange signature verification failed for key type=" + keyAlg);
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                "KeyExchange signature verification failed for key type=" + keyAlg);
         }
+
         return true;
     }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
index ced2125..2e23683 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
@@ -23,6 +23,7 @@ import java.math.BigInteger;
 import java.util.Objects;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.PropertyResolverUtils;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.config.keys.KeyUtils;
@@ -42,6 +43,9 @@ import org.apache.sshd.common.util.security.SecurityUtils;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public class DHGEXClient extends AbstractDHClientKeyExchange {
+    public static final String PROP_DHGEX_CLIENT_MIN_KEY = "dhgex-client-min";
+    public static final String PROP_DHGEX_CLIENT_MAX_KEY = "dhgex-client-max";
+
     protected final DHFactory factory;
     protected byte expected;
     protected int min = SecurityUtils.MIN_DHGEX_KEY_SIZE;
@@ -86,10 +90,19 @@ public class DHGEXClient extends AbstractDHClientKeyExchange {
     @Override
     public void init(Session s, byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
         super.init(s, v_s, v_c, i_s, i_c);
+
+        // SSHD-941 give the user a chance to intervene in the choice
+        min = PropertyResolverUtils.getIntProperty(s, PROP_DHGEX_CLIENT_MIN_KEY, min);
+        max = PropertyResolverUtils.getIntProperty(s, PROP_DHGEX_CLIENT_MAX_KEY, max);
+        prf = Math.min(SecurityUtils.PREFERRED_DHGEX_KEY_SIZE, max);
         if (log.isDebugEnabled()) {
             log.debug("init({})[{}] Send SSH_MSG_KEX_DH_GEX_REQUEST - min={}, prf={}, max={}",
                 this, s, min, prf, max);
         }
+        if ((max < min) || (prf < min) || (max < prf)) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+                "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
+        }
 
         Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST, Integer.SIZE);
         buffer.putInt(min);
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
index 55d791f..7a4b8f2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
@@ -31,6 +31,7 @@ import java.util.Objects;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.PropertyResolverUtils;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.kex.DHFactory;
@@ -55,6 +56,9 @@ import org.apache.sshd.server.session.ServerSession;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public class DHGEXServer extends AbstractDHServerKeyExchange {
+    public static final String PROP_DHGEX_SERVER_MIN_KEY = "dhgex-server-min";
+    public static final String PROP_DHGEX_SERVER_MAX_KEY = "dhgex-server-max";
+
     protected final DHFactory factory;
     protected DHG dh;
     protected int min;
@@ -112,9 +116,11 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
         if ((cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD)
                 && (expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST)) {
             oldRequest = true;
-            min = SecurityUtils.MIN_DHGEX_KEY_SIZE;
+            min = PropertyResolverUtils.getIntProperty(
+                session, PROP_DHGEX_SERVER_MIN_KEY, SecurityUtils.MIN_DHGEX_KEY_SIZE);
             prf = buffer.getInt();
-            max = SecurityUtils.getMaxDHGroupExchangeKeySize();
+            max = PropertyResolverUtils.getIntProperty(
+                session, PROP_DHGEX_SERVER_MAX_KEY, SecurityUtils.getMaxDHGroupExchangeKeySize());
 
             if ((max < min) || (prf < min) || (max < prf)) {
                 throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
@@ -307,7 +313,6 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
     protected List<Moduli.DhGroup> loadModuliGroups() throws IOException {
         Session session = getServerSession();
         String moduliStr = session.getString(ServerFactoryManager.MODULI_URL);
-
         List<Moduli.DhGroup> groups = null;
         if (!GenericUtils.isEmpty(moduliStr)) {
             try {
@@ -337,8 +342,8 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
         }
 
         if (log.isDebugEnabled()) {
-            log.debug("loadModuliGroups({})[{}] Loaded moduli groups from {}",
-                this, session, moduliStr);
+            log.debug("loadModuliGroups({})[{}] Loaded {} moduli groups from {}",
+                this, session, GenericUtils.size(groups), moduliStr);
         }
         return groups;
     }
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
index 3dfefad..d74353b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
@@ -88,7 +88,8 @@ public class DHGServer extends AbstractDHServerKeyExchange {
     public boolean next(int cmd, Buffer buffer) throws Exception {
         ServerSession session = getServerSession();
         if (log.isDebugEnabled()) {
-            log.debug("next({})[{}] process command={}", this, session, KeyExchange.getSimpleKexOpcodeName(cmd));
+            log.debug("next({})[{}] process command={}",
+                this, session, KeyExchange.getSimpleKexOpcodeName(cmd));
         }
 
         if (cmd != SshConstants.SSH_MSG_KEXDH_INIT) {