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/24 15:52:15 UTC
[mina-sshd] branch master updated: [SSHD-943] Provide session
instance when KEX factory is invoked in order to create a KeyExchange
instance
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
The following commit(s) were added to refs/heads/master by this push:
new f82e0db [SSHD-943] Provide session instance when KEX factory is invoked in order to create a KeyExchange instance
f82e0db is described below
commit f82e0db2ca23f806d8e31ced9156132f76017483
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Tue Sep 24 10:54:22 2019 +0300
[SSHD-943] Provide session instance when KEX factory is invoked in order to create a KeyExchange instance
---
CHANGES.md | 11 ++--
.../java/org/apache/sshd/common/NamedFactory.java | 7 +--
.../keyprovider/MultiKeyIdentityIterator.java | 4 +-
.../sshd/common/session/SessionContextHolder.java | 6 +--
.../java/org/apache/sshd/client/ClientBuilder.java | 29 +++++++---
.../client/kex/AbstractDHClientKeyExchange.java | 10 +---
.../java/org/apache/sshd/client/kex/DHGClient.java | 17 +++---
.../org/apache/sshd/client/kex/DHGEXClient.java | 29 +++++-----
.../java/org/apache/sshd/common/BaseBuilder.java | 22 ++++----
.../sshd/common/config/SshConfigFileReader.java | 61 ++++++++++++++--------
.../sshd/common/kex/AbstractKexFactoryManager.java | 9 ++--
.../apache/sshd/common/kex/KexFactoryManager.java | 4 +-
.../org/apache/sshd/common/kex/KeyExchange.java | 6 +--
.../apache/sshd/common/kex/KeyExchangeFactory.java | 15 ++++--
.../sshd/common/kex/dh/AbstractDHKeyExchange.java | 18 +++----
.../apache/sshd/common/session/SessionHolder.java | 7 ++-
.../common/session/helpers/AbstractSession.java | 14 ++---
.../java/org/apache/sshd/server/ServerBuilder.java | 24 +++++++--
.../server/kex/AbstractDHServerKeyExchange.java | 10 +---
.../org/apache/sshd/server/kex/DHGEXServer.java | 11 ++--
.../java/org/apache/sshd/server/kex/DHGServer.java | 11 ++--
.../java/org/apache/sshd/KeyReExchangeTest.java | 20 +++----
.../sshd/client/ClientSessionListenerTest.java | 36 ++++++++-----
.../java/org/apache/sshd/client/kex/KexTest.java | 12 +++--
.../sshd/common/kex/KexFactoryManagerTest.java | 4 +-
.../sshd/server/ServerSessionListenerTest.java | 42 +++++++++------
26 files changed, 265 insertions(+), 174 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 2ec72a5..10f493f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -31,6 +31,9 @@ the standard does not specifically specify the behavior regarding symbolic links
* `ChannelFactory` is a proper interface and it has been refactored to contain a
`createChannel` method that accepts the session instance through which the request is made.
+* `KeyExchangeFactory` is a proper interface and it has been refactored to contain a
+`createKeyExchange` method that accepts the session instance through which the request is made.
+
## Minor code helpers
* `SessionListener` supports `sessionPeerIdentificationReceived` that is invoked once successful
@@ -43,9 +46,9 @@ 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.
+* `DHGEXClient` 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/PRF_KEY`. Similar applies for `DHGEXServer` but only for
+the message type=30 (old request).
## Behavioral changes and enhancements
@@ -63,3 +66,5 @@ for the server's identification before sending its own.
* [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.
+* [SSHD-943](https://issues.apache.org/jira/browse/SSHD-943) - Provide session instance when KEX factory is invoked in order to create a KeyExchange instance.
+
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/NamedFactory.java b/sshd-common/src/main/java/org/apache/sshd/common/NamedFactory.java
index 5386447..024c327 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/NamedFactory.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/NamedFactory.java
@@ -41,7 +41,8 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
* @return a newly created object or {@code null} if the factory is not in the list
*/
static <T> T create(Collection<? extends NamedFactory<? extends T>> factories, String name) {
- NamedFactory<? extends T> f = NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, factories);
+ NamedFactory<? extends T> f =
+ NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, factories);
if (f != null) {
return f.create();
} else {
@@ -49,7 +50,7 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
}
}
- static <S extends OptionalFeature, T, E extends NamedFactory<T>> List<NamedFactory<T>> setUpTransformedFactories(
+ static <S extends OptionalFeature, E extends NamedResource> List<E> setUpTransformedFactories(
boolean ignoreUnsupported, Collection<? extends S> preferred, Function<? super S, ? extends E> xform) {
return preferred.stream()
.filter(f -> ignoreUnsupported || f.isSupported())
@@ -57,7 +58,7 @@ public interface NamedFactory<T> extends Factory<T>, NamedResource {
.collect(Collectors.toList());
}
- static <T, E extends NamedFactory<T> & OptionalFeature> List<NamedFactory<T>> setUpBuiltinFactories(
+ static <E extends NamedResource & OptionalFeature> List<E> setUpBuiltinFactories(
boolean ignoreUnsupported, Collection<? extends E> preferred) {
return preferred.stream()
.filter(f -> ignoreUnsupported || f.isSupported())
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
index 09d5f29..3f01f18 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.sshd.common.session.SessionContext;
+import org.apache.sshd.common.session.SessionContextHolder;
/**
* Iterates over several {@link KeyIdentityProvider}-s exhausting their
@@ -33,7 +34,7 @@ import org.apache.sshd.common.session.SessionContext;
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public class MultiKeyIdentityIterator implements Iterator<KeyPair> {
+public class MultiKeyIdentityIterator implements Iterator<KeyPair>, SessionContextHolder {
protected Iterator<KeyPair> currentProvider;
protected boolean finished;
private final SessionContext sessionContext;
@@ -48,6 +49,7 @@ public class MultiKeyIdentityIterator implements Iterator<KeyPair> {
return providers;
}
+ @Override
public SessionContext getSessionContext() {
return sessionContext;
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContextHolder.java
similarity index 86%
copy from sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java
copy to sshd-common/src/main/java/org/apache/sshd/common/session/SessionContextHolder.java
index 280bbf0..79edb7e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContextHolder.java
@@ -20,10 +20,8 @@
package org.apache.sshd.common.session;
/**
- * @param <S> Type of {@link Session} being held
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-@FunctionalInterface
-public interface SessionHolder<S extends Session> {
- S getSession();
+public interface SessionContextHolder {
+ SessionContext getSessionContext();
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
index 7c60a59..46d7ba9 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
@@ -37,12 +37,15 @@ import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.channel.ChannelFactory;
import org.apache.sshd.common.channel.RequestHandler;
import org.apache.sshd.common.compression.BuiltinCompressions;
+import org.apache.sshd.common.compression.Compression;
import org.apache.sshd.common.compression.CompressionFactory;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.kex.DHFactory;
import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.signature.BuiltinSignatures;
+import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.server.forward.ForwardedTcpipFactory;
/**
@@ -81,7 +84,9 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
BuiltinSignatures.dsa
));
- public static final Function<DHFactory, NamedFactory<KeyExchange>> DH2KEX = factory ->
+ @SuppressWarnings("checkstyle:Indentation")
+ public static final Function<DHFactory, KeyExchangeFactory> DH2KEX =
+ factory ->
factory == null
? null
: factory.isGroupExchange()
@@ -136,11 +141,11 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
super.fillWithDefaultValues();
if (signatureFactories == null) {
- signatureFactories = NamedFactory.setUpBuiltinFactories(false, DEFAULT_SIGNATURE_PREFERENCE);
+ signatureFactories = setUpDefaultSignatureFactories(false);
}
if (compressionFactories == null) {
- compressionFactories = NamedFactory.setUpBuiltinFactories(false, DEFAULT_COMPRESSION_FACTORIES);
+ compressionFactories = setUpDefaultCompressionFactories(false);
}
if (keyExchangeFactories == null) {
@@ -188,11 +193,21 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
return client;
}
+ @SuppressWarnings({ "unchecked", "rawtypes" }) // safe due to the hierarchy
+ public static List<NamedFactory<Signature>> setUpDefaultSignatureFactories(boolean ignoreUnsupported) {
+ return (List) NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_SIGNATURE_PREFERENCE);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" }) // safe due to the hierarchy
+ public static List<NamedFactory<Compression>> setUpDefaultCompressionFactories(boolean ignoreUnsupported) {
+ return (List) NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_COMPRESSION_FACTORIES);
+ }
+
/**
* @param ignoreUnsupported If {@code true} then all the default
- * key exchanges are included, regardless of whether they are currently
- * supported by the JCE. Otherwise, only the supported ones out of the
- * list are included
+ * key exchanges are included, regardless of whether they are currently
+ * supported by the JCE. Otherwise, only the supported ones out of the
+ * list are included
* @return A {@link List} of the default {@link NamedFactory}
* instances of the {@link KeyExchange}s according to the preference
* order defined by {@link #DEFAULT_KEX_PREFERENCE}.
@@ -200,7 +215,7 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
* key exchanges according to the <tt>ignoreUnsupported</tt> parameter
* @see org.apache.sshd.common.kex.BuiltinDHFactories#isSupported()
*/
- public static List<NamedFactory<KeyExchange>> setUpDefaultKeyExchanges(boolean ignoreUnsupported) {
+ public static List<KeyExchangeFactory> setUpDefaultKeyExchanges(boolean ignoreUnsupported) {
return NamedFactory.setUpTransformedFactories(ignoreUnsupported, DEFAULT_KEX_PREFERENCE, DH2KEX);
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java
index c654b65..3158a2a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/AbstractDHClientKeyExchange.java
@@ -33,8 +33,8 @@ import org.apache.sshd.common.util.ValidateUtils;
public abstract class AbstractDHClientKeyExchange extends AbstractDHKeyExchange implements ClientSessionHolder {
protected PublicKey serverKey;
- protected AbstractDHClientKeyExchange() {
- super();
+ protected AbstractDHClientKeyExchange(Session session) {
+ super(ValidateUtils.checkInstanceOf(session, ClientSession.class, "Using a client side KeyExchange on a server: %s", session));
}
@Override
@@ -43,12 +43,6 @@ public abstract class AbstractDHClientKeyExchange extends AbstractDHKeyExchange
}
@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);
- ValidateUtils.checkInstanceOf(s, ClientSession.class, "Using a client side KeyExchange on a server: %s", s);
- }
-
- @Override
public PublicKey getServerKey() {
return serverKey;
}
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 bed61f3..810e352 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
@@ -46,7 +46,9 @@ public class DHGClient extends AbstractDHClientKeyExchange {
protected final DHFactory factory;
protected AbstractDH dh;
- protected DHGClient(DHFactory factory) {
+ protected DHGClient(DHFactory factory, Session session) {
+ super(session);
+
this.factory = Objects.requireNonNull(factory, "No factory");
}
@@ -63,8 +65,8 @@ public class DHGClient extends AbstractDHClientKeyExchange {
}
@Override
- public KeyExchange create() {
- return new DHGClient(delegate);
+ public KeyExchange createKeyExchange(Session session) throws Exception {
+ return new DHGClient(delegate, session);
}
@Override
@@ -77,17 +79,20 @@ public class DHGClient 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);
+ public void init(byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
+ super.init(v_s, v_c, i_s, i_c);
+
dh = getDH();
hash = dh.getHash();
hash.init();
e = dh.getE();
+ Session s = getSession();
if (log.isDebugEnabled()) {
log.debug("init({})[{}] Send SSH_MSG_KEXDH_INIT", this, s);
}
- Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_KEXDH_INIT, e.length + Integer.SIZE);
+ Buffer buffer =
+ s.createBuffer(SshConstants.SSH_MSG_KEXDH_INIT, e.length + Integer.SIZE);
buffer.putMPInt(e);
s.writePacket(buffer);
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 2e23683..c6dcc35 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
@@ -45,20 +45,28 @@ import org.apache.sshd.common.util.security.SecurityUtils;
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";
+ public static final String PROP_DHGEX_CLIENT_PRF_KEY = "dhgex-client-prf";
protected final DHFactory factory;
protected byte expected;
- protected int min = SecurityUtils.MIN_DHGEX_KEY_SIZE;
+ protected int min;
protected int prf;
protected int max;
protected AbstractDH dh;
protected byte[] p;
protected byte[] g;
- protected DHGEXClient(DHFactory factory) {
+ protected DHGEXClient(DHFactory factory, Session session) {
+ super(session);
this.factory = Objects.requireNonNull(factory, "No factory");
- this.max = SecurityUtils.getMaxDHGroupExchangeKeySize();
- this.prf = Math.min(SecurityUtils.PREFERRED_DHGEX_KEY_SIZE, max);
+
+ // SSHD-941 give the user a chance to intervene in the choice
+ min = PropertyResolverUtils.getIntProperty(
+ session, PROP_DHGEX_CLIENT_MIN_KEY, SecurityUtils.MIN_DHGEX_KEY_SIZE);
+ max = PropertyResolverUtils.getIntProperty(
+ session, PROP_DHGEX_CLIENT_MAX_KEY, SecurityUtils.getMaxDHGroupExchangeKeySize());
+ prf = PropertyResolverUtils.getIntProperty(
+ session, PROP_DHGEX_CLIENT_PRF_KEY, Math.min(SecurityUtils.PREFERRED_DHGEX_KEY_SIZE, max));
}
@Override
@@ -74,8 +82,8 @@ public class DHGEXClient extends AbstractDHClientKeyExchange {
}
@Override
- public KeyExchange create() {
- return new DHGEXClient(delegate);
+ public KeyExchange createKeyExchange(Session session) throws Exception {
+ return new DHGEXClient(delegate, session);
}
@Override
@@ -88,13 +96,10 @@ 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);
+ public void init(byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
+ super.init(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);
+ Session s = getSession();
if (log.isDebugEnabled()) {
log.debug("init({})[{}] Send SSH_MSG_KEX_DH_GEX_REQUEST - min={}, prf={}, max={}",
this, s, min, prf, max);
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java b/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
index 5dc33ce..904726c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java
@@ -35,7 +35,7 @@ import org.apache.sshd.common.forward.DefaultForwarderFactory;
import org.apache.sshd.common.forward.ForwardingFilterFactory;
import org.apache.sshd.common.helpers.AbstractFactoryManager;
import org.apache.sshd.common.kex.BuiltinDHFactories;
-import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.mac.BuiltinMacs;
import org.apache.sshd.common.mac.Mac;
import org.apache.sshd.common.random.Random;
@@ -128,7 +128,7 @@ public class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder
DefaultUnknownChannelReferenceHandler.INSTANCE;
protected Factory<T> factory;
- protected List<NamedFactory<KeyExchange>> keyExchangeFactories;
+ protected List<KeyExchangeFactory> keyExchangeFactories;
protected List<NamedFactory<Cipher>> cipherFactories;
protected List<NamedFactory<Compression>> compressionFactories;
protected List<NamedFactory<Mac>> macFactories;
@@ -178,7 +178,7 @@ public class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder
return me();
}
- public S keyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
+ public S keyExchangeFactories(List<KeyExchangeFactory> keyExchangeFactories) {
this.keyExchangeFactories = keyExchangeFactories;
return me();
}
@@ -283,9 +283,9 @@ public class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder
/**
* @param ignoreUnsupported If {@code true} then all the default
- * ciphers are included, regardless of whether they are currently
- * supported by the JCE. Otherwise, only the supported ones out of the
- * list are included
+ * ciphers are included, regardless of whether they are currently
+ * supported by the JCE. Otherwise, only the supported ones out of the
+ * list are included
* @return A {@link List} of the default {@link NamedFactory}
* instances of the {@link Cipher}s according to the preference
* order defined by {@link #DEFAULT_CIPHERS_PREFERENCE}.
@@ -293,14 +293,15 @@ public class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder
* ciphers according to the <tt>ignoreUnsupported</tt> parameter
* @see BuiltinCiphers#isSupported()
*/
+ @SuppressWarnings({ "unchecked", "rawtypes" }) // safe due to the hierarchy
public static List<NamedFactory<Cipher>> setUpDefaultCiphers(boolean ignoreUnsupported) {
- return NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_CIPHERS_PREFERENCE);
+ return (List) NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_CIPHERS_PREFERENCE);
}
/**
* @param ignoreUnsupported If {@code true} all the available built-in
- * {@link Mac} factories are added, otherwise only those that are supported
- * by the current JDK setup
+ * {@link Mac} factories are added, otherwise only those that are supported
+ * by the current JDK setup
* @return A {@link List} of the default {@link NamedFactory}
* instances of the {@link Mac}s according to the preference
* order defined by {@link #DEFAULT_MAC_PREFERENCE}.
@@ -308,7 +309,8 @@ public class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder
* MACs according to the <tt>ignoreUnsupported</tt> parameter
* @see BuiltinMacs#isSupported()
*/
+ @SuppressWarnings({ "unchecked", "rawtypes" }) // safe due to the hierarchy
public static List<NamedFactory<Mac>> setUpDefaultMacs(boolean ignoreUnsupported) {
- return NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_MAC_PREFERENCE);
+ return (List) NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_MAC_PREFERENCE);
}
}
\ No newline at end of file
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
index 46f34a1..c0205c7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
@@ -38,6 +38,7 @@ import org.apache.sshd.common.helpers.AbstractFactoryManager;
import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.common.kex.DHFactory;
import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.mac.BuiltinMacs;
import org.apache.sshd.common.mac.Mac;
import org.apache.sshd.common.signature.BuiltinSignatures;
@@ -162,11 +163,13 @@ public final class SshConfigFileReader {
return manager;
}
- public static <M extends AbstractFactoryManager> M configureCiphers(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureCiphers(
+ M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(props, "No properties to configure");
return configureCiphers(manager,
- props.getStringProperty(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_CIPHERS),
- lenient, ignoreUnsupported);
+ props.getStringProperty(
+ ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_CIPHERS),
+ lenient, ignoreUnsupported);
}
public static <M extends AbstractFactoryManager> M configureCiphers(
@@ -175,18 +178,22 @@ public final class SshConfigFileReader {
BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(value);
Collection<String> unsupported = result.getUnsupportedFactories();
- ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), "Unsupported cipher(s) (%s) in %s", unsupported, value);
+ ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported),
+ "Unsupported cipher(s) (%s) in %s", unsupported, value);
List<NamedFactory<Cipher>> factories =
- BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories());
- manager.setCipherFactories(ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/unsupported ciphers(s): %s", value));
+ BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories());
+ manager.setCipherFactories(
+ ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/unsupported ciphers(s): %s", value));
return manager;
}
- public static <M extends AbstractFactoryManager> M configureSignatures(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureSignatures(
+ M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(props, "No properties to configure");
return configureSignatures(manager,
- props.getStringProperty(ConfigFileReaderSupport.HOST_KEY_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_HOST_KEY_ALGORITHMS),
+ props.getStringProperty(
+ ConfigFileReaderSupport.HOST_KEY_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_HOST_KEY_ALGORITHMS),
lenient, ignoreUnsupported);
}
@@ -196,11 +203,13 @@ public final class SshConfigFileReader {
BuiltinSignatures.ParseResult result = BuiltinSignatures.parseSignatureList(value);
Collection<String> unsupported = result.getUnsupportedFactories();
- ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), "Unsupported signatures (%s) in %s", unsupported, value);
+ ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported),
+ "Unsupported signatures (%s) in %s", unsupported, value);
List<NamedFactory<Signature>> factories =
- BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories());
- manager.setSignatureFactories(ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported signatures: %s", value));
+ BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories());
+ manager.setSignatureFactories(
+ ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported signatures: %s", value));
return manager;
}
@@ -208,7 +217,8 @@ public final class SshConfigFileReader {
M manager, PropertyResolver resolver, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(resolver, "No properties to configure");
return configureMacs(manager,
- resolver.getStringProperty(ConfigFileReaderSupport.MACS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_MACS),
+ resolver.getStringProperty(
+ ConfigFileReaderSupport.MACS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_MACS),
lenient, ignoreUnsupported);
}
@@ -218,11 +228,13 @@ public final class SshConfigFileReader {
BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(value);
Collection<String> unsupported = result.getUnsupportedFactories();
- ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), "Unsupported MAC(s) (%s) in %s", unsupported, value);
+ ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported),
+ "Unsupported MAC(s) (%s) in %s", unsupported, value);
List<NamedFactory<Mac>> factories =
- BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories());
- manager.setMacFactories(ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported MAC(s): %s", value));
+ BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories());
+ manager.setMacFactories(
+ ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported MAC(s): %s", value));
return manager;
}
@@ -242,25 +254,30 @@ public final class SshConfigFileReader {
* @see ConfigFileReaderSupport#DEFAULT_KEX_ALGORITHMS DEFAULT_KEX_ALGORITHMS
*/
public static <M extends AbstractFactoryManager> M configureKeyExchanges(
- M manager, PropertyResolver props, boolean lenient, Function<? super DHFactory, ? extends NamedFactory<KeyExchange>> xformer, boolean ignoreUnsupported) {
+ M manager, PropertyResolver props, boolean lenient,
+ Function<? super DHFactory, ? extends KeyExchangeFactory> xformer, boolean ignoreUnsupported) {
Objects.requireNonNull(props, "No properties to configure");
return configureKeyExchanges(manager,
- props.getStringProperty(ConfigFileReaderSupport.KEX_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_KEX_ALGORITHMS),
+ props.getStringProperty(
+ ConfigFileReaderSupport.KEX_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_KEX_ALGORITHMS),
lenient, xformer, ignoreUnsupported);
}
public static <M extends AbstractFactoryManager> M configureKeyExchanges(
- M manager, String value, boolean lenient, Function<? super DHFactory, ? extends NamedFactory<KeyExchange>> xformer, boolean ignoreUnsupported) {
+ M manager, String value, boolean lenient,
+ Function<? super DHFactory, ? extends KeyExchangeFactory> xformer, boolean ignoreUnsupported) {
Objects.requireNonNull(manager, "No manager to configure");
Objects.requireNonNull(xformer, "No DHFactory transformer");
BuiltinDHFactories.ParseResult result = BuiltinDHFactories.parseDHFactoriesList(value);
Collection<String> unsupported = result.getUnsupportedFactories();
- ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), "Unsupported KEX(s) (%s) in %s", unsupported, value);
+ ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported),
+ "Unsupported KEX(s) (%s) in %s", unsupported, value);
- List<NamedFactory<KeyExchange>> factories =
- NamedFactory.setUpTransformedFactories(ignoreUnsupported, result.getParsedFactories(), xformer);
- manager.setKeyExchangeFactories(ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported KEXS(s): %s", value));
+ List<KeyExchangeFactory> factories =
+ NamedFactory.setUpTransformedFactories(ignoreUnsupported, result.getParsedFactories(), xformer);
+ manager.setKeyExchangeFactories(
+ ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported KEXS(s): %s", value));
return manager;
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java
index 8f1d159..b4cd952 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java
@@ -19,6 +19,7 @@
package org.apache.sshd.common.kex;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -38,7 +39,7 @@ public abstract class AbstractKexFactoryManager
extends AbstractInnerCloseable
implements KexFactoryManager {
private final KexFactoryManager delegate;
- private List<NamedFactory<KeyExchange>> keyExchangeFactories;
+ private List<KeyExchangeFactory> keyExchangeFactories;
private List<NamedFactory<Cipher>> cipherFactories;
private List<NamedFactory<Compression>> compressionFactories;
private List<NamedFactory<Mac>> macFactories;
@@ -58,14 +59,14 @@ public abstract class AbstractKexFactoryManager
}
@Override
- public List<NamedFactory<KeyExchange>> getKeyExchangeFactories() {
+ public List<KeyExchangeFactory> getKeyExchangeFactories() {
KexFactoryManager parent = getDelegate();
return resolveEffectiveFactories(keyExchangeFactories,
(parent == null) ? Collections.emptyList() : parent.getKeyExchangeFactories());
}
@Override
- public void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
+ public void setKeyExchangeFactories(List<KeyExchangeFactory> keyExchangeFactories) {
this.keyExchangeFactories = keyExchangeFactories;
}
@@ -129,7 +130,7 @@ public abstract class AbstractKexFactoryManager
this.kexExtensionHandler = kexExtensionHandler;
}
- protected <V> List<V> resolveEffectiveFactories(List<V> local, List<V> inherited) {
+ protected <V, C extends Collection<V>> C resolveEffectiveFactories(C local, C inherited) {
if (GenericUtils.isEmpty(local)) {
return inherited;
} else {
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java
index 6c873d2..a537227 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java
@@ -47,9 +47,9 @@ public interface KexFactoryManager extends SignatureFactoriesManager, KexExtensi
*
* @return a list of named <code>KeyExchange</code> factories, never {@code null}
*/
- List<NamedFactory<KeyExchange>> getKeyExchangeFactories();
+ List<KeyExchangeFactory> getKeyExchangeFactories();
- void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories);
+ void setKeyExchangeFactories(List<KeyExchangeFactory> keyExchangeFactories);
/**
* Retrieve the list of named factories for <code>Cipher</code>.
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchange.java
index f1b23b6..b47f0bc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchange.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchange.java
@@ -26,6 +26,7 @@ import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.digest.Digest;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionHolder;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.logging.LoggingUtils;
@@ -35,7 +36,7 @@ import org.apache.sshd.common.util.logging.LoggingUtils;
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public interface KeyExchange extends NamedResource {
+public interface KeyExchange extends NamedResource, SessionHolder<Session> {
NavigableMap<Integer, String> GROUP_KEX_OPCODES_MAP =
Collections.unmodifiableNavigableMap(
LoggingUtils.generateMnemonicMap(SshConstants.class, "SSH_MSG_KEX_DH_GEX_"));
@@ -47,14 +48,13 @@ public interface KeyExchange extends NamedResource {
/**
* Initialize the key exchange algorithm.
*
- * @param session the session using this algorithm
* @param v_s the server identification string
* @param v_c the client identification string
* @param i_s the server key initialization packet
* @param i_c the client key initialization packet
* @throws Exception if an error occurs
*/
- void init(Session session, byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception;
+ void init(byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception;
/**
* Process the next packet
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchangeFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchangeFactory.java
index cea659d..f9288e2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchangeFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/KeyExchangeFactory.java
@@ -19,13 +19,18 @@
package org.apache.sshd.common.kex;
-import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.session.Session;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-// CHECKSTYLE:OFF
-public interface KeyExchangeFactory extends NamedFactory<KeyExchange> {
- // nothing extra
+public interface KeyExchangeFactory extends NamedResource {
+ /**
+ * @param session The {@link Session} for which the factory is invoked
+ * @return The {@link KeyExchange} instance to be used
+ * @throws Exception If failed to create
+ */
+ KeyExchange createKeyExchange(Session session) throws Exception;
}
-//CHECKSTYLE:ON
+
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
index 8bcfdae..7f29782 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
@@ -19,19 +19,18 @@
package org.apache.sshd.common.kex.dh;
+import java.util.Objects;
+
import org.apache.sshd.common.digest.Digest;
import org.apache.sshd.common.kex.KeyExchange;
import org.apache.sshd.common.session.Session;
-import org.apache.sshd.common.session.SessionHolder;
-import org.apache.sshd.common.session.helpers.AbstractSession;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.logging.AbstractLoggingBean;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implements KeyExchange, SessionHolder<AbstractSession> {
-
+public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implements KeyExchange {
protected byte[] v_s;
protected byte[] v_c;
protected byte[] i_s;
@@ -42,15 +41,14 @@ public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implemen
protected byte[] k;
protected byte[] h;
- private AbstractSession session;
+ private final Session session;
- protected AbstractDHKeyExchange() {
- super();
+ protected AbstractDHKeyExchange(Session session) {
+ this.session = Objects.requireNonNull(session, "No session provided");
}
@Override
- public void init(Session s, byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
- this.session = ValidateUtils.checkInstanceOf(s, AbstractSession.class, "Not an abstract session: %s", s);
+ public void init(byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
this.v_s = ValidateUtils.checkNotNullAndNotEmpty(v_s, "No v_s value");
this.v_c = ValidateUtils.checkNotNullAndNotEmpty(v_c, "No v_c value");
this.i_s = ValidateUtils.checkNotNullAndNotEmpty(i_s, "No i_s value");
@@ -58,7 +56,7 @@ public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implemen
}
@Override
- public AbstractSession getSession() {
+ public Session getSession() {
return session;
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java b/sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java
index 280bbf0..3a6491d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/SessionHolder.java
@@ -24,6 +24,11 @@ package org.apache.sshd.common.session;
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
@FunctionalInterface
-public interface SessionHolder<S extends Session> {
+public interface SessionHolder<S extends Session> extends SessionContextHolder {
+ @Override
+ default SessionContext getSessionContext() {
+ return getSession();
+ }
+
S getSession();
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
index cc5c926..4bb43e2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
@@ -44,6 +44,7 @@ import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.RuntimeSshException;
import org.apache.sshd.common.Service;
import org.apache.sshd.common.SshConstants;
@@ -63,6 +64,7 @@ import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.kex.KexState;
import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.kex.extension.KexExtensionHandler;
import org.apache.sshd.common.kex.extension.KexExtensionHandler.AvailabilityPhase;
import org.apache.sshd.common.kex.extension.KexExtensionHandler.KexPhase;
@@ -639,12 +641,12 @@ public abstract class AbstractSession extends SessionHelper {
Map<KexProposalOption, String> result = negotiate();
String kexAlgorithm = result.get(KexProposalOption.ALGORITHMS);
- Collection<? extends NamedFactory<KeyExchange>> kexFactories = getKeyExchangeFactories();
+ Collection<? extends KeyExchangeFactory> kexFactories = getKeyExchangeFactories();
+ KeyExchangeFactory kexFactory = NamedResource.findByName(
+ kexAlgorithm, String.CASE_INSENSITIVE_ORDER, kexFactories);
+ ValidateUtils.checkNotNull(kexFactory, "Unknown negotiated KEX algorithm: %s", kexAlgorithm);
synchronized (pendingPackets) {
- kex = ValidateUtils.checkNotNull(
- NamedFactory.create(kexFactories, kexAlgorithm),
- "Unknown negotiated KEX algorithm: %s",
- kexAlgorithm);
+ kex = kexFactory.createKeyExchange(this);
}
byte[] v_s = serverVersion.getBytes(StandardCharsets.UTF_8);
@@ -655,7 +657,7 @@ public abstract class AbstractSession extends SessionHelper {
i_s = getServerKexData();
i_c = getClientKexData();
}
- kex.init(this, v_s, v_c, i_s, i_c);
+ kex.init(v_s, v_c, i_s, i_c);
signalSessionEvent(SessionListener.Event.KexCompleted);
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
index 0510141..9dbfac1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerBuilder.java
@@ -29,11 +29,14 @@ import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.channel.ChannelFactory;
import org.apache.sshd.common.channel.RequestHandler;
import org.apache.sshd.common.compression.BuiltinCompressions;
+import org.apache.sshd.common.compression.Compression;
import org.apache.sshd.common.compression.CompressionFactory;
import org.apache.sshd.common.kex.DHFactory;
import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.signature.BuiltinSignatures;
+import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator;
import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
@@ -52,8 +55,9 @@ import org.apache.sshd.server.kex.DHGServer;
* SshServer builder
*/
public class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
-
- public static final Function<DHFactory, NamedFactory<KeyExchange>> DH2KEX = factory ->
+ @SuppressWarnings("checkstyle:Indentation")
+ public static final Function<DHFactory, KeyExchangeFactory> DH2KEX =
+ factory ->
factory == null
? null
: factory.isGroupExchange()
@@ -126,11 +130,11 @@ public class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
super.fillWithDefaultValues();
if (compressionFactories == null) {
- compressionFactories = NamedFactory.setUpBuiltinFactories(false, DEFAULT_COMPRESSION_FACTORIES);
+ compressionFactories = setUpDefaultCompressionFactories(false);
}
if (signatureFactories == null) {
- signatureFactories = NamedFactory.setUpBuiltinFactories(false, DEFAULT_SIGNATURE_PREFERENCE);
+ signatureFactories = setUpDefaultSignatureFactories(false);
}
if (keyExchangeFactories == null) {
@@ -168,6 +172,16 @@ public class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
return server;
}
+ @SuppressWarnings({ "unchecked", "rawtypes" }) // safe due to the hierarchy
+ public static List<NamedFactory<Signature>> setUpDefaultSignatureFactories(boolean ignoreUnsupported) {
+ return (List) NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_SIGNATURE_PREFERENCE);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" }) // safe due to the hierarchy
+ public static List<NamedFactory<Compression>> setUpDefaultCompressionFactories(boolean ignoreUnsupported) {
+ return (List) NamedFactory.setUpBuiltinFactories(ignoreUnsupported, DEFAULT_COMPRESSION_FACTORIES);
+ }
+
/**
* @param ignoreUnsupported If {@code true} then all the default
* key exchanges are included, regardless of whether they are currently
@@ -180,7 +194,7 @@ public class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
* key exchanges according to the <tt>ignoreUnsupported</tt> parameter
* @see org.apache.sshd.common.kex.BuiltinDHFactories#isSupported()
*/
- public static List<NamedFactory<KeyExchange>> setUpDefaultKeyExchanges(boolean ignoreUnsupported) {
+ public static List<KeyExchangeFactory> setUpDefaultKeyExchanges(boolean ignoreUnsupported) {
return NamedFactory.setUpTransformedFactories(ignoreUnsupported, DEFAULT_KEX_PREFERENCE, DH2KEX);
}
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
index 831086c..7c11ec5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
@@ -32,8 +32,8 @@ import org.apache.sshd.server.session.ServerSessionHolder;
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange implements ServerSessionHolder {
- protected AbstractDHServerKeyExchange() {
- super();
+ protected AbstractDHServerKeyExchange(Session s) {
+ super(ValidateUtils.checkInstanceOf(s, ServerSession.class, "Using a client side KeyExchange on a server: %s", s));
}
@Override
@@ -42,12 +42,6 @@ public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange
}
@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);
- ValidateUtils.checkInstanceOf(s, ServerSession.class, "Using a server side KeyExchange on a client: %s", s);
- }
-
- @Override
public PublicKey getServerKey() {
ServerSession session = getServerSession();
return Objects.requireNonNull(session.getHostKey(), "No server key pair available").getPublic();
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 7a4b8f2..27ed991 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
@@ -67,7 +67,8 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
protected byte expected;
protected boolean oldRequest;
- protected DHGEXServer(DHFactory factory) {
+ protected DHGEXServer(DHFactory factory, Session session) {
+ super(session);
this.factory = Objects.requireNonNull(factory, "No factory");
}
@@ -79,8 +80,8 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
public static KeyExchangeFactory newFactory(DHFactory factory) {
return new KeyExchangeFactory() {
@Override
- public KeyExchange create() {
- return new DHGEXServer(factory);
+ public KeyExchange createKeyExchange(Session session) throws Exception {
+ return new DHGEXServer(factory, session);
}
@Override
@@ -98,8 +99,8 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
}
@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);
+ public void init(byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
+ super.init(v_s, v_c, i_s, i_c);
expected = SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST;
}
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 d74353b..e5dad22 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
@@ -45,7 +45,8 @@ public class DHGServer extends AbstractDHServerKeyExchange {
protected final DHFactory factory;
protected AbstractDH dh;
- protected DHGServer(DHFactory factory) {
+ protected DHGServer(DHFactory factory, Session session) {
+ super(session);
this.factory = Objects.requireNonNull(factory, "No factory");
}
@@ -57,8 +58,8 @@ public class DHGServer extends AbstractDHServerKeyExchange {
public static KeyExchangeFactory newFactory(final DHFactory factory) {
return new KeyExchangeFactory() {
@Override
- public KeyExchange create() {
- return new DHGServer(factory);
+ public KeyExchange createKeyExchange(Session session) throws Exception {
+ return new DHGServer(factory, session);
}
@Override
@@ -76,8 +77,8 @@ public class DHGServer extends AbstractDHServerKeyExchange {
}
@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);
+ public void init(byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception {
+ super.init(v_s, v_c, i_s, i_c);
dh = factory.create();
hash = dh.getHash();
hash.init();
diff --git a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
index 9390383..13bcd56 100644
--- a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
@@ -42,13 +42,13 @@ import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.future.KeyExchangeFuture;
import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.util.io.NullOutputStream;
@@ -150,21 +150,21 @@ public class KeyReExchangeTest extends BaseTestSupport {
try (SshClient client = setupTestClient()) {
client.getCipherFactories().add(BuiltinCiphers.none);
// replace the original KEX factories with wrapped ones that we can fail intentionally
- List<NamedFactory<KeyExchange>> kexFactories = new ArrayList<>();
- final AtomicBoolean successfulInit = new AtomicBoolean(true);
- final AtomicBoolean successfulNext = new AtomicBoolean(true);
- final ClassLoader loader = getClass().getClassLoader();
- final Class<?>[] interfaces = {KeyExchange.class};
- for (final NamedFactory<KeyExchange> factory : client.getKeyExchangeFactories()) {
- kexFactories.add(new NamedFactory<KeyExchange>() {
+ List<KeyExchangeFactory> kexFactories = new ArrayList<>();
+ AtomicBoolean successfulInit = new AtomicBoolean(true);
+ AtomicBoolean successfulNext = new AtomicBoolean(true);
+ ClassLoader loader = getClass().getClassLoader();
+ Class<?>[] interfaces = {KeyExchange.class};
+ for (KeyExchangeFactory factory : client.getKeyExchangeFactories()) {
+ kexFactories.add(new KeyExchangeFactory() {
@Override
public String getName() {
return factory.getName();
}
@Override
- public KeyExchange create() {
- final KeyExchange proxiedInstance = factory.create();
+ public KeyExchange createKeyExchange(Session s) throws Exception {
+ KeyExchange proxiedInstance = factory.createKeyExchange(s);
return (KeyExchange) Proxy.newProxyInstance(loader, interfaces, (proxy, method, args) -> {
String name = method.getName();
if ("init".equals(name) && (!successfulInit.get())) {
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java b/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
index e5e928a..8669ba8 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
@@ -31,10 +31,14 @@ import org.apache.sshd.client.auth.keyboard.UserInteraction;
import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.Cipher;
+import org.apache.sshd.common.cipher.CipherFactory;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.mac.MacFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.util.GenericUtils;
@@ -91,18 +95,21 @@ public class ClientSessionListenerTest extends BaseTestSupport {
@Test
public void testSessionListenerCanModifyKEXNegotiation() throws Exception {
- final Map<KexProposalOption, NamedFactory<?>> kexParams = new EnumMap<>(KexProposalOption.class);
+ Map<KexProposalOption, NamedResource> kexParams = new EnumMap<>(KexProposalOption.class);
kexParams.put(KexProposalOption.ALGORITHMS, getLeastFavorite(KeyExchange.class, client.getKeyExchangeFactories()));
- kexParams.put(KexProposalOption.C2SENC, getLeastFavorite(Cipher.class, client.getCipherFactories()));
- kexParams.put(KexProposalOption.C2SMAC, getLeastFavorite(Mac.class, client.getMacFactories()));
+ kexParams.put(KexProposalOption.C2SENC, getLeastFavorite(CipherFactory.class, client.getCipherFactories()));
+ kexParams.put(KexProposalOption.C2SMAC, getLeastFavorite(MacFactory.class, client.getMacFactories()));
SessionListener listener = new SessionListener() {
@Override
@SuppressWarnings("unchecked")
public void sessionCreated(Session session) {
- session.setKeyExchangeFactories(Collections.singletonList((NamedFactory<KeyExchange>) kexParams.get(KexProposalOption.ALGORITHMS)));
- session.setCipherFactories(Collections.singletonList((NamedFactory<Cipher>) kexParams.get(KexProposalOption.C2SENC)));
- session.setMacFactories(Collections.singletonList((NamedFactory<Mac>) kexParams.get(KexProposalOption.C2SMAC)));
+ session.setKeyExchangeFactories(
+ Collections.singletonList((KeyExchangeFactory) kexParams.get(KexProposalOption.ALGORITHMS)));
+ session.setCipherFactories(
+ Collections.singletonList((NamedFactory<Cipher>) kexParams.get(KexProposalOption.C2SENC)));
+ session.setMacFactories(
+ Collections.singletonList((NamedFactory<Mac>) kexParams.get(KexProposalOption.C2SMAC)));
}
};
client.addSessionListener(listener);
@@ -120,16 +127,17 @@ public class ClientSessionListenerTest extends BaseTestSupport {
@Test
public void testSessionListenerCanInfluenceAuthentication() throws IOException {
- final AtomicInteger verificationCount = new AtomicInteger();
- final ServerKeyVerifier verifier = (sshClientSession, remoteAddress, serverKey) -> {
+ AtomicInteger verificationCount = new AtomicInteger();
+ ServerKeyVerifier verifier = (sshClientSession, remoteAddress, serverKey) -> {
verificationCount.incrementAndGet();
return true;
};
-
SessionListener listener = new SessionListener() {
@Override
public void sessionEvent(Session session, Event event) {
- if ((!session.isAuthenticated()) && (session instanceof ClientSession) && Event.KexCompleted.equals(event)) {
+ if ((!session.isAuthenticated())
+ && (session instanceof ClientSession)
+ && Event.KexCompleted.equals(event)) {
ClientSession clientSession = (ClientSession) session;
clientSession.setServerKeyVerifier(verifier);
clientSession.setUserInteraction(UserInteraction.NONE);
@@ -149,14 +157,18 @@ public class ClientSessionListenerTest extends BaseTestSupport {
}
}
- private static <V> NamedFactory<V> getLeastFavorite(Class<V> type, List<? extends NamedFactory<V>> factories) {
+ private static <V extends NamedResource> NamedResource getLeastFavorite(
+ Class<V> type, List<? extends NamedResource> factories) {
int numFactories = GenericUtils.size(factories);
assertTrue("No factories for " + type.getSimpleName(), numFactories > 0);
return factories.get(numFactories - 1);
}
private ClientSession createTestClientSession() throws IOException {
- ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession();
+ ClientSession session =
+ client.connect(getCurrentTestName(), TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession();
try {
session.addPasswordIdentity(getCurrentTestName());
session.auth().verify(5L, TimeUnit.SECONDS);
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
index 678521f..da599ba 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
@@ -34,10 +34,9 @@ import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.common.kex.BuiltinDHFactories;
-import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.test.BaseTestSupport;
@@ -119,12 +118,15 @@ public class KexTest extends BaseTestSupport {
testClient(ClientBuilder.DH2KEX.apply(factory));
}
- private void testClient(NamedFactory<KeyExchange> kex) throws Exception {
+ private void testClient(KeyExchangeFactory kex) throws Exception {
try (ByteArrayOutputStream sent = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
client.setKeyExchangeFactories(Collections.singletonList(kex));
- try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ try (ClientSession session =
+ client.connect(getCurrentTestName(), TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession()) {
session.addPasswordIdentity(getCurrentTestName());
session.auth().verify(5L, TimeUnit.SECONDS);
@@ -153,7 +155,7 @@ public class KexTest extends BaseTestSupport {
teeOut.flush();
Collection<ClientChannelEvent> result =
- channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
+ channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannelEvent.TIMEOUT));
}
}
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java b/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
index 0832ab4..acfd70a 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
@@ -140,12 +140,12 @@ public class KexFactoryManagerTest extends BaseTestSupport {
}
@Override
- public List<NamedFactory<KeyExchange>> getKeyExchangeFactories() {
+ public List<KeyExchangeFactory> getKeyExchangeFactories() {
return null;
}
@Override
- public void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
+ public void setKeyExchangeFactories(List<KeyExchangeFactory> keyExchangeFactories) {
throw new UnsupportedOperationException("N/A");
}
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
index 50d83ed..ffa54a4 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
@@ -32,11 +32,14 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.Cipher;
+import org.apache.sshd.common.cipher.CipherFactory;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.kex.KexProposalOption;
-import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.mac.MacFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.util.GenericUtils;
@@ -165,18 +168,21 @@ public class ServerSessionListenerTest extends BaseTestSupport {
@Test
public void testSessionListenerCanModifyKEXNegotiation() throws Exception {
- final Map<KexProposalOption, NamedFactory<?>> kexParams = new EnumMap<>(KexProposalOption.class);
- kexParams.put(KexProposalOption.ALGORITHMS, getLeastFavorite(KeyExchange.class, sshd.getKeyExchangeFactories()));
- kexParams.put(KexProposalOption.S2CENC, getLeastFavorite(Cipher.class, sshd.getCipherFactories()));
- kexParams.put(KexProposalOption.S2CMAC, getLeastFavorite(Mac.class, sshd.getMacFactories()));
+ Map<KexProposalOption, NamedResource> kexParams = new EnumMap<>(KexProposalOption.class);
+ kexParams.put(KexProposalOption.ALGORITHMS, getLeastFavorite(KeyExchangeFactory.class, sshd.getKeyExchangeFactories()));
+ kexParams.put(KexProposalOption.S2CENC, getLeastFavorite(CipherFactory.class, sshd.getCipherFactories()));
+ kexParams.put(KexProposalOption.S2CMAC, getLeastFavorite(MacFactory.class, sshd.getMacFactories()));
SessionListener listener = new SessionListener() {
@Override
@SuppressWarnings("unchecked")
public void sessionCreated(Session session) {
- session.setKeyExchangeFactories(Collections.singletonList((NamedFactory<KeyExchange>) kexParams.get(KexProposalOption.ALGORITHMS)));
- session.setCipherFactories(Collections.singletonList((NamedFactory<Cipher>) kexParams.get(KexProposalOption.S2CENC)));
- session.setMacFactories(Collections.singletonList((NamedFactory<Mac>) kexParams.get(KexProposalOption.S2CMAC)));
+ session.setKeyExchangeFactories(
+ Collections.singletonList((KeyExchangeFactory) kexParams.get(KexProposalOption.ALGORITHMS)));
+ session.setCipherFactories(
+ Collections.singletonList((NamedFactory<Cipher>) kexParams.get(KexProposalOption.S2CENC)));
+ session.setMacFactories(
+ Collections.singletonList((NamedFactory<Mac>) kexParams.get(KexProposalOption.S2CMAC)));
}
};
sshd.addSessionListener(listener);
@@ -194,9 +200,9 @@ public class ServerSessionListenerTest extends BaseTestSupport {
@Test
public void testSessionListenerCanModifyAuthentication() throws Exception {
- final AtomicInteger passCount = new AtomicInteger(0);
- final PasswordAuthenticator defaultPassAuth = sshd.getPasswordAuthenticator();
- final PasswordAuthenticator passAuth = (username, password, session) -> {
+ AtomicInteger passCount = new AtomicInteger(0);
+ PasswordAuthenticator defaultPassAuth = sshd.getPasswordAuthenticator();
+ PasswordAuthenticator passAuth = (username, password, session) -> {
passCount.incrementAndGet();
return defaultPassAuth.authenticate(username, password, session);
};
@@ -215,22 +221,28 @@ public class ServerSessionListenerTest extends BaseTestSupport {
sshd.addSessionListener(listener);
try (ClientSession session = createTestClientSession()) {
- assertNotSame("Mismatched default password authenticator", passAuth, sshd.getPasswordAuthenticator());
- assertNotSame("Mismatched default kb authenticator", KeyboardInteractiveAuthenticator.NONE, sshd.getKeyboardInteractiveAuthenticator());
+ assertNotSame("Mismatched default password authenticator",
+ passAuth, sshd.getPasswordAuthenticator());
+ assertNotSame("Mismatched default kb authenticator",
+ KeyboardInteractiveAuthenticator.NONE, sshd.getKeyboardInteractiveAuthenticator());
assertEquals("Authenticator override not invoked", 1, passCount.get());
} finally {
sshd.removeSessionListener(listener);
}
}
- private static <V> NamedFactory<V> getLeastFavorite(Class<V> type, List<? extends NamedFactory<V>> factories) {
+ private static <V extends NamedResource> NamedResource getLeastFavorite(
+ Class<V> type, List<? extends NamedResource> factories) {
int numFactories = GenericUtils.size(factories);
assertTrue("No factories for " + type.getSimpleName(), numFactories > 0);
return factories.get(numFactories - 1);
}
private ClientSession createTestClientSession() throws Exception {
- ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession();
+ ClientSession session =
+ client.connect(getCurrentTestName(), TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession();
try {
session.addPasswordIdentity(getCurrentTestName());
session.auth().verify(11L, TimeUnit.SECONDS);