You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2015/03/17 18:35:33 UTC
[3/4] mina-sshd git commit: [SSHD-430] Expose supported built-in
ciphers as an Enum
[SSHD-430] Expose supported built-in ciphers as an Enum
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/eac1704e
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/eac1704e
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/eac1704e
Branch: refs/heads/master
Commit: eac1704e05d23a562512dc6d2bde387c3cea07e9
Parents: 043c7df
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Mar 17 16:10:52 2015 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Mar 17 18:06:11 2015 +0100
----------------------------------------------------------------------
.../main/java/org/apache/sshd/SshBuilder.java | 85 ++++---
.../org/apache/sshd/common/NamedFactory.java | 27 ++-
.../apache/sshd/common/cipher/AES128CBC.java | 9 +-
.../apache/sshd/common/cipher/AES128CTR.java | 9 +-
.../apache/sshd/common/cipher/AES192CBC.java | 9 +-
.../apache/sshd/common/cipher/AES192CTR.java | 9 +-
.../apache/sshd/common/cipher/AES256CBC.java | 9 +-
.../apache/sshd/common/cipher/AES256CTR.java | 9 +-
.../apache/sshd/common/cipher/ARCFOUR128.java | 9 +-
.../apache/sshd/common/cipher/ARCFOUR256.java | 9 +-
.../apache/sshd/common/cipher/BlowfishCBC.java | 9 +-
.../sshd/common/cipher/BuiltinCiphers.java | 234 +++++++++++++++++++
.../apache/sshd/common/cipher/CipherNone.java | 12 +-
.../apache/sshd/common/cipher/CipherUtils.java | 58 +++++
.../apache/sshd/common/cipher/TripleDESCBC.java | 9 +-
.../apache/sshd/common/util/GenericUtils.java | 92 ++++++++
.../java/org/apache/sshd/SshBuilderTest.java | 81 +++++++
.../sshd/common/cipher/BuiltinCiphersTest.java | 94 ++++++++
.../java/org/apache/sshd/util/BaseTest.java | 39 +++-
19 files changed, 748 insertions(+), 64 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
index b87d994..bac6163 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
@@ -18,10 +18,9 @@
*/
package org.apache.sshd;
-import java.security.InvalidKeyException;
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.Collections;
import java.util.List;
import org.apache.sshd.client.ServerKeyVerifier;
@@ -38,16 +37,7 @@ import org.apache.sshd.common.Random;
import org.apache.sshd.common.RequestHandler;
import org.apache.sshd.common.Signature;
import org.apache.sshd.common.TcpipForwarderFactory;
-import org.apache.sshd.common.cipher.AES128CBC;
-import org.apache.sshd.common.cipher.AES128CTR;
-import org.apache.sshd.common.cipher.AES192CBC;
-import org.apache.sshd.common.cipher.AES192CTR;
-import org.apache.sshd.common.cipher.AES256CBC;
-import org.apache.sshd.common.cipher.AES256CTR;
-import org.apache.sshd.common.cipher.ARCFOUR128;
-import org.apache.sshd.common.cipher.ARCFOUR256;
-import org.apache.sshd.common.cipher.BlowfishCBC;
-import org.apache.sshd.common.cipher.TripleDESCBC;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.compression.CompressionNone;
import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
@@ -89,6 +79,9 @@ public class SshBuilder {
return new ServerBuilder();
}
+ /**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
protected static class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder<T, S>> implements ObjectBuilder<T> {
protected Factory<T> factory = null;
@@ -142,7 +135,7 @@ public class SshBuilder {
}
if (cipherFactories == null) {
- cipherFactories = setUpDefaultCiphers();
+ cipherFactories = setUpDefaultCiphers(false);
}
// Compression is not enabled by default
@@ -260,32 +253,48 @@ public class SshBuilder {
return (S) this;
}
- protected static List<NamedFactory<Cipher>> setUpDefaultCiphers() {
- List<NamedFactory<Cipher>> avail = new LinkedList<NamedFactory<Cipher>>();
- avail.add(new AES128CTR.Factory());
- avail.add(new AES192CTR.Factory());
- avail.add(new AES256CTR.Factory());
- avail.add(new ARCFOUR128.Factory());
- avail.add(new ARCFOUR256.Factory());
- avail.add(new AES128CBC.Factory());
- avail.add(new TripleDESCBC.Factory());
- avail.add(new BlowfishCBC.Factory());
- avail.add(new AES192CBC.Factory());
- avail.add(new AES256CBC.Factory());
-
- for (Iterator<NamedFactory<Cipher>> i = avail.iterator(); i.hasNext(); ) {
- final NamedFactory<Cipher> f = i.next();
- try {
- final Cipher c = f.create();
- final byte[] key = new byte[c.getBlockSize()];
- final byte[] iv = new byte[c.getIVSize()];
- c.init(Cipher.Mode.Encrypt, key, iv);
- } catch (InvalidKeyException e) {
- i.remove();
- } catch (Exception e) {
- i.remove();
+ /**
+ * The default {@link BuiltinCiphers} setup in order of preference
+ * as specified by <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5">
+ * ssh_config(5)</A>
+ */
+ public static final List<BuiltinCiphers> DEFAULT_CIPHERS_PREFERENCE =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ BuiltinCiphers.aes128ctr,
+ BuiltinCiphers.aes192ctr,
+ BuiltinCiphers.aes256ctr,
+ BuiltinCiphers.arcfour256,
+ BuiltinCiphers.arcfour128,
+ BuiltinCiphers.aes128cbc,
+ BuiltinCiphers.tripledescbc,
+ BuiltinCiphers.blowfishcbc,
+ // TODO add support for cast128-cbc cipher
+ BuiltinCiphers.aes192cbc,
+ BuiltinCiphers.aes256cbc
+ // TODO add support for arcfour cipher
+ ));
+
+ /**
+ * @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
+ * @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}.
+ * <B>Note:</B> the list may be filtered to exclude unsupported JCE
+ * ciphers according to the <tt>ignoreUnsupported</tt> parameter
+ * @see BuiltinCiphers#isSupported()
+ */
+ protected static List<NamedFactory<Cipher>> setUpDefaultCiphers(boolean ignoreUnsupported) {
+ List<NamedFactory<Cipher>> avail = new ArrayList<NamedFactory<Cipher>>(DEFAULT_CIPHERS_PREFERENCE.size());
+ for (BuiltinCiphers c : DEFAULT_CIPHERS_PREFERENCE) {
+ if (ignoreUnsupported || c.isSupported()) {
+ avail.add(c.create());
}
}
+
return avail;
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
index 47347b4..ba8d60f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
@@ -23,6 +23,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import org.apache.sshd.common.util.GenericUtils;
+
/**
* A named factory is a factory identified by a name.
* Such names are used mainly in the algorithm negotiation at the beginning of the SSH connection.
@@ -48,18 +50,19 @@ public interface NamedFactory<T> extends Factory<T> {
* @return A {@link List} of all the factories names - in same order
* as they appear in the input collection
*/
- public static <T> List<String> getNameList(Collection<NamedFactory<T>> factories) {
- if ((factories == null) || factories.isEmpty()) {
- return Collections.emptyList();
- }
-
- List<String> names=new ArrayList<String>(factories.size());
- for (NamedFactory<T> f : factories) {
- names.add(f.getName());
- }
-
- return names;
- }
+ public static List<String> getNameList(Collection<? extends NamedFactory<?>> factories) {
+ if (GenericUtils.isEmpty(factories)) {
+ return Collections.emptyList();
+ }
+
+ List<String> names = new ArrayList<String>(factories.size());
+ for (NamedFactory<?> f : factories) {
+ names.add(f.getName());
+ }
+
+ return names;
+ }
+
/**
* Create an instance of the specified name by looking up the needed factory
* in the list.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
index 3ea3870..39a1a08 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
@@ -32,9 +32,16 @@ public class AES128CBC extends BaseCipher {
* Named factory for AES128CBC Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "aes128-cbc";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "aes128-cbc";
+ return NAME;
}
+
public Cipher create() {
return new AES128CBC();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
index 2a7dc3a..2cbfb21 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES128CTR.java
@@ -32,9 +32,16 @@ public class AES128CTR extends BaseCipher {
* Named factory for AES128CTR Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "aes128-ctr";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "aes128-ctr";
+ return NAME;
}
+
public Cipher create() {
return new AES128CTR();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
index 87ffdeb..3d26f76 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CBC.java
@@ -32,9 +32,16 @@ public class AES192CBC extends BaseCipher {
* Named factory for AES192CBC Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "aes192-cbc";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "aes192-cbc";
+ return NAME;
}
+
public Cipher create() {
return new AES192CBC();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
index d44c06c..cf13b9f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES192CTR.java
@@ -32,9 +32,16 @@ public class AES192CTR extends BaseCipher {
* Named factory for AES192CBC Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "aes192-ctr";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "aes192-ctr";
+ return NAME;
}
+
public Cipher create() {
return new AES192CTR();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
index 736e594..38122d8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CBC.java
@@ -32,9 +32,16 @@ public class AES256CBC extends BaseCipher {
* Named factory for AES256CBC Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "aes256-cbc";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "aes256-cbc";
+ return NAME;
}
+
public Cipher create() {
return new AES256CBC();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
index 608fc43..718017f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/AES256CTR.java
@@ -32,9 +32,16 @@ public class AES256CTR extends BaseCipher {
* Named factory for AES256CTR Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "aes256-ctr";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "aes256-ctr";
+ return NAME;
}
+
public Cipher create() {
return new AES256CTR();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
index 4ff5f1d..33d6a6e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR128.java
@@ -32,9 +32,16 @@ public class ARCFOUR128 extends BaseRC4Cipher {
* Named factory for ARCFOUR128 Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "arcfour128";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "arcfour128";
+ return NAME;
}
+
public Cipher create() {
return new ARCFOUR128();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
index fed8176..500c1b7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ARCFOUR256.java
@@ -32,9 +32,16 @@ public class ARCFOUR256 extends BaseRC4Cipher {
* Named factory for AES128CTR Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "arcfour256";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "arcfour256";
+ return NAME;
}
+
public Cipher create() {
return new ARCFOUR256();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
index 6a76ad1..b2c6135 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BlowfishCBC.java
@@ -32,9 +32,16 @@ public class BlowfishCBC extends BaseCipher {
* Named factory for BlowfishCBC Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "blowfish-cbc";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "blowfish-cbc";
+ return NAME;
}
+
public Cipher create() {
return new BlowfishCBC();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
new file mode 100644
index 0000000..74c45f1
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
@@ -0,0 +1,234 @@
+/*
+ * 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.sshd.common.cipher;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * Provides easy access to the currently implemented ciphers
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinCiphers implements NamedFactory<NamedFactory<Cipher>> {
+ none(CipherNone.Factory.NAME, CipherNone.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new CipherNone.Factory();
+ }
+ },
+ aes128cbc(AES128CBC.Factory.NAME, AES128CBC.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new AES128CBC.Factory();
+ }
+ },
+ aes128ctr(AES128CTR.Factory.NAME, AES128CTR.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new AES128CTR.Factory();
+ }
+ },
+ aes192cbc(AES192CBC.Factory.NAME, AES192CBC.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new AES192CBC.Factory();
+ }
+ },
+ aes192ctr(AES192CTR.Factory.NAME, AES192CTR.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new AES192CTR.Factory();
+ }
+ },
+ aes256cbc(AES256CBC.Factory.NAME, AES256CBC.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new AES256CBC.Factory();
+ }
+ },
+ aes256ctr(AES256CTR.Factory.NAME, AES256CTR.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new AES256CTR.Factory();
+ }
+ },
+ arcfour128(ARCFOUR128.Factory.NAME, ARCFOUR128.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new ARCFOUR128.Factory();
+ }
+ },
+ arcfour256(ARCFOUR256.Factory.NAME, ARCFOUR256.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new ARCFOUR256.Factory();
+ }
+ },
+ blowfishcbc(BlowfishCBC.Factory.NAME, BlowfishCBC.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new BlowfishCBC.Factory();
+ }
+ },
+ tripledescbc(TripleDESCBC.Factory.NAME, TripleDESCBC.class) {
+ @Override
+ public NamedFactory<Cipher> create() {
+ return new TripleDESCBC.Factory();
+ }
+ };
+
+ private final String factoryName;
+ private Class<? extends Cipher> cipherType;
+
+ @Override
+ public final String getName() {
+ return factoryName;
+ }
+
+ public final Class<? extends Cipher> getCipherType() {
+ return cipherType;
+ }
+
+ BuiltinCiphers(String facName, Class<? extends Cipher> cipherClass) {
+ factoryName = facName;
+ cipherType = cipherClass;
+ }
+
+ private final AtomicReference<Boolean> _supported = new AtomicReference<>(null);
+
+ /**
+ * @return {@code true} if the current JVM configuration supports this
+ * cipher - e.g., AES-256 requires the <A HREF="http://www.oracle.com/technetwork/java/javase/downloads/">
+ * Java Cryptography Extension (JCE)</A>
+ */
+ public boolean isSupported() {
+ Boolean value;
+ synchronized (_supported) {
+ if ((value = _supported.get()) == null) {
+ // see BaseBuilder#fillWithDefaultValues
+ try {
+ Exception t = CipherUtils.checkSupported(create());
+ value = t == null;
+ } catch (Exception e) {
+ value = Boolean.FALSE;
+ }
+
+ _supported.set(value);
+ }
+ }
+
+ return value;
+ }
+
+ public static final Set<BuiltinCiphers> VALUES =
+ Collections.unmodifiableSet(EnumSet.allOf(BuiltinCiphers.class));
+
+ /**
+ * @param s The {@link Enum}'s name - ignored if {@code null}/empty
+ * @return The matching {@link BuiltinCiphers} whose {@link Enum#name()} matches
+ * (case <U>insensitive</U>) the provided argument - {@code null} if no match
+ */
+ public static BuiltinCiphers fromString(String s) {
+ if (GenericUtils.isEmpty(s)) {
+ return null;
+ }
+
+ for (BuiltinCiphers c : VALUES) {
+ if (s.equalsIgnoreCase(c.name())) {
+ return c;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param factory The {@link NamedFactory} for the cipher - ignored if {@code null}
+ * @return The matching {@link BuiltinCiphers} whose factory name matches
+ * (case <U>insensitive</U>) the cipher factory name
+ * @see #fromFactoryName(String)
+ */
+ public static BuiltinCiphers fromFactory(NamedFactory<Cipher> factory) {
+ if (factory == null) {
+ return null;
+ } else {
+ return fromFactoryName(factory.getName());
+ }
+ }
+
+ /**
+ * @param n The factory name - ignored if {@code null}/empty
+ * @return The matching {@link BuiltinCiphers} whose factory name matches
+ * (case <U>insensitive</U>) the provided name - {@code null} if no match
+ */
+ public static BuiltinCiphers fromFactoryName(String n) {
+ if (GenericUtils.isEmpty(n)) {
+ return null;
+ }
+
+ for (BuiltinCiphers c : VALUES) {
+ if (n.equalsIgnoreCase(c.getName())) {
+ return c;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param c The {@link Cipher} instance - ignored if {@code null}
+ * @return The matching {@link BuiltinCiphers} - {@code null} if no match
+ * @see #fromCipherType(Class)
+ */
+ public static BuiltinCiphers fromCipher(Cipher c) {
+ if (c == null) {
+ return null;
+ } else {
+ return fromCipherType(c.getClass());
+ }
+ }
+
+ /**
+ * @param type The cipher type - ignored if {@code null} or not a
+ * {@link Cipher} derived class
+ * @return The matching {@link BuiltinCiphers} - {@code null} if no match
+ */
+ public static BuiltinCiphers fromCipherType(Class<?> type) {
+ if ((type == null) || (!Cipher.class.isAssignableFrom(type))) {
+ return null;
+ }
+
+ for (BuiltinCiphers c : VALUES) {
+ Class<?> t = c.getCipherType();
+ if (t.isAssignableFrom(type)) {
+ return c;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
index 65c921b..95c82d9 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherNone.java
@@ -35,9 +35,16 @@ public class CipherNone implements Cipher {
* Named factory for the no-op Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "none";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "none";
+ return NAME;
}
+
public Cipher create() {
return new CipherNone();
}
@@ -52,9 +59,10 @@ public class CipherNone implements Cipher {
}
public void init(Mode mode, byte[] bytes, byte[] bytes1) throws Exception {
+ // ignored - always succeeds
}
public void update(byte[] input, int inputOffset, int inputLen) throws Exception {
+ // ignored - always succeeds
}
-
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherUtils.java
new file mode 100644
index 0000000..45070f6
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/CipherUtils.java
@@ -0,0 +1,58 @@
+/*
+ * 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.sshd.common.cipher;
+
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.Factory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class CipherUtils {
+ /**
+ * Checks if the provided cipher factory instance generates a cipher
+ * that is supported by the JCE
+ * @param f The cipher factory instance
+ * @return The {@link Exception} that the {@link Cipher#init(org.apache.sshd.common.Cipher.Mode, byte[], byte[])}
+ * call has thrown - {@code null} if successful (i.e., cipher supported)
+ * @see <A HREF="http://www.oracle.com/technetwork/java/javase/downloads/">Java Cryptography Extension (JCE)</A>
+ */
+ public static Exception checkSupported(Factory<? extends Cipher> f) {
+ return checkSupported(f.create());
+ }
+
+ /**
+ * Checks if the provided cipher is supported by the JCE
+ * @param c The {@link Cipher} to be checked
+ * @return The {@link Exception} that the {@link Cipher#init(org.apache.sshd.common.Cipher.Mode, byte[], byte[])}
+ * call has thrown - {@code null} if successful (i.e., cipher supported)
+ * @see <A HREF="http://www.oracle.com/technetwork/java/javase/downloads/">Java Cryptography Extension (JCE)</A>
+ */
+ public static Exception checkSupported(Cipher c) {
+ try {
+ byte[] key=new byte[c.getBlockSize()];
+ byte[] iv=new byte[c.getIVSize()];
+ c.init(Cipher.Mode.Encrypt, key, iv);
+ return null;
+ } catch(Exception e) {
+ return e;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
index bb194c3..5cdae9a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/TripleDESCBC.java
@@ -32,9 +32,16 @@ public class TripleDESCBC extends BaseCipher {
* Named factory for TripleDESCBC Cipher
*/
public static class Factory implements NamedFactory<Cipher> {
+ public static final String NAME = "3des-cbc";
+
+ public Factory() {
+ super();
+ }
+
public String getName() {
- return "3des-cbc";
+ return NAME;
}
+
public Cipher create() {
return new TripleDESCBC();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
new file mode 100644
index 0000000..b02c7ec
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -0,0 +1,92 @@
+/*
+ * 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.sshd.common.util;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class GenericUtils {
+ public static final int length(CharSequence cs) {
+ if (cs == null) {
+ return 0;
+ } else {
+ return cs.length();
+ }
+ }
+
+ public static final boolean isEmpty(CharSequence cs) {
+ if (length(cs) <= 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static final int size(Collection<?> c) {
+ if (c == null) {
+ return 0;
+ } else {
+ return c.size();
+ }
+ }
+
+ public static final boolean isEmpty(Collection<?> c) {
+ if (size(c) <= 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static final int size(Map<?,?> m) {
+ if (m == null) {
+ return 0;
+ } else {
+ return m.size();
+ }
+ }
+
+ public static final boolean isEmpty(Map<?,?> m) {
+ if (size(m) <= 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static final int length(Object ... a) {
+ if (a == null) {
+ return 0;
+ } else {
+ return a.length;
+ }
+ }
+
+ public static final boolean isEmpty(Object ... a) {
+ if (length(a) <= 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/test/java/org/apache/sshd/SshBuilderTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SshBuilderTest.java b/sshd-core/src/test/java/org/apache/sshd/SshBuilderTest.java
new file mode 100644
index 0000000..a1d9a39
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/SshBuilderTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd;
+
+import java.util.List;
+
+import org.apache.sshd.SshBuilder.BaseBuilder;
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.BaseTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SshBuilderTest extends BaseTest {
+ public SshBuilderTest() {
+ super();
+ }
+
+ /**
+ * Make sure that {@link BaseBuilder#setUpDefaultCiphers(boolean)} returns
+ * the correct result - i.e., according to the {@code ingoreUnsupported}
+ * parameter and in the defined preference order
+ */
+ @Test
+ public void testSetUpDefaultCiphers() {
+ for (boolean ignoreUnsupported : new boolean[] { true, false }) {
+ List<NamedFactory<Cipher>> ciphers=BaseBuilder.setUpDefaultCiphers(ignoreUnsupported);
+ int numCiphers=GenericUtils.size(ciphers);
+ // make sure returned list size matches expected count
+ if (ignoreUnsupported) {
+ Assert.assertEquals("Incomplete full ciphers size", BaseBuilder.DEFAULT_CIPHERS_PREFERENCE.size(), numCiphers);
+ } else {
+ int expectedCount=0;
+ for (BuiltinCiphers c : BaseBuilder.DEFAULT_CIPHERS_PREFERENCE) {
+ if (c.isSupported()) {
+ expectedCount++;
+ }
+ }
+ Assert.assertEquals("Incomplete supported ciphers size", expectedCount, numCiphers);
+ }
+
+ // make sure order is according to the default preference list
+ List<String> cipherNames=NamedFactory.Utils.getNameList(ciphers);
+ int nameIndex=0;
+ for (BuiltinCiphers c : BaseBuilder.DEFAULT_CIPHERS_PREFERENCE) {
+ if ((!c.isSupported()) && (!ignoreUnsupported)) {
+ continue;
+ }
+
+ String expectedName=c.getName();
+ Assert.assertTrue("Out of actual ciphers for expected=" + expectedName, nameIndex < numCiphers);
+
+ String actualName=cipherNames.get(nameIndex);
+ Assert.assertEquals("Mismatched cipher at position " + nameIndex + " for ignoreUnsupported=" + ignoreUnsupported, expectedName, actualName);
+ nameIndex++;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
new file mode 100644
index 0000000..f9e2f04
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.sshd.common.cipher;
+
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.util.BaseTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class BuiltinCiphersTest extends BaseTest {
+ public BuiltinCiphersTest() {
+ super();
+ }
+
+ @Test
+ public void testFromEnumName() {
+ for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
+ String name=expected.name();
+
+ for (int index=0; index < name.length(); index++) {
+ BuiltinCiphers actual=BuiltinCiphers.fromString(name);
+ Assert.assertSame(name + " - mismatched enum values", expected, actual);
+ name = shuffleCase(name); // prepare for next time
+ }
+ }
+ }
+
+ @Test
+ public void testFromFactoryName() {
+ for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
+ String name=expected.getName();
+
+ for (int index=0; index < name.length(); index++) {
+ BuiltinCiphers actual=BuiltinCiphers.fromFactoryName(name);
+ Assert.assertSame(name + " - mismatched enum values", expected, actual);
+ name = shuffleCase(name); // prepare for next time
+ }
+ }
+ }
+
+ @Test
+ public void testFromFactory() {
+ for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
+ if (!expected.isSupported()) {
+ System.out.append("Skip unsupported cipher: ").println(expected);
+ continue;
+ }
+
+ NamedFactory<Cipher> factory=expected.create();
+ Assert.assertEquals(expected.name() + " - mismatched factory names", expected.getName(), factory.getName());
+
+ BuiltinCiphers actual=BuiltinCiphers.fromFactory(factory);
+ Assert.assertSame(expected.getName() + " - mismatched enum values", expected, actual);
+ }
+ }
+
+ @Test
+ public void testFromCipher() {
+ for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
+ if (!expected.isSupported()) {
+ System.out.append("Skip unsupported cipher: ").println(expected);
+ continue;
+ }
+
+ NamedFactory<Cipher> factory=expected.create();
+ Cipher cipher=factory.create();
+ assertObjectInstanceOf(expected.name() + " - mismatched cipher type", expected.getCipherType(), cipher);
+
+ BuiltinCiphers actual=BuiltinCiphers.fromCipher(cipher);
+ Assert.assertSame(expected.getName() + " - mismatched enum values", expected, actual);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/eac1704e/sshd-core/src/test/java/org/apache/sshd/util/BaseTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/BaseTest.java b/sshd-core/src/test/java/org/apache/sshd/util/BaseTest.java
index 49b8f31..205c889 100644
--- a/sshd-core/src/test/java/org/apache/sshd/util/BaseTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/util/BaseTest.java
@@ -18,10 +18,13 @@
*/
package org.apache.sshd.util;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.File;
+import org.apache.sshd.common.util.GenericUtils;
import org.junit.Rule;
import org.junit.rules.TestName;
import org.junit.rules.TestWatcher;
@@ -57,12 +60,44 @@ public abstract class BaseTest extends TestWatcher {
System.out.println("\nFinished " + description.getClassName() + ":" + description.getMethodName() + " in " + duration + " ms\n");
}
- public static final File assertHierarchyTargetFolderExists(File folder) {
+ /* ------------------- Useful extra test helpers ---------------------- */
+
+ public static String shuffleCase(CharSequence cs) {
+ if (GenericUtils.isEmpty(cs)) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(cs.length());
+ for (int index = 0; index < cs.length(); index++) {
+ char ch = cs.charAt(index);
+ double v = Math.random();
+ if (Double.compare(v, 0.3d) < 0) {
+ ch = Character.toUpperCase(ch);
+ } else if ((Double.compare(v, 0.3d) >= 0) && (Double.compare(v, 0.6d) < 0)) {
+ ch = Character.toLowerCase(ch);
+ }
+ sb.append(ch);
+ }
+
+ return sb.toString();
+ }
+
+ /* ----------------------- Useful extra assertions --------------------- */
+
+ public static File assertHierarchyTargetFolderExists(File folder) {
if (!folder.exists()) {
assertTrue("Failed to create hierarchy of " + folder.getAbsolutePath(), folder.mkdirs());
}
return folder;
}
-
+
+ public static void assertObjectInstanceOf(String message, Class<?> expected, Object obj) {
+ assertNotNull(message + " - no actual object", obj);
+
+ Class<?> actual=obj.getClass();
+ if (!expected.isAssignableFrom(actual)) {
+ fail(message + " - actual object type (" + actual.getName() + ") incompatible with expected (" + expected.getName() + ")");
+ }
+ }
}