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/30 11:17:52 UTC
[3/6] mina-sshd git commit: [SSHD-436] Refactor kex factories
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
deleted file mode 100644
index e6a4023..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHGServer.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.server.kex;
-
-import java.security.KeyPair;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.BufferUtils;
-import org.apache.sshd.server.session.ServerSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public abstract class AbstractDHGServer implements KeyExchange {
-
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private ServerSession session;
- private byte[] V_S;
- private byte[] V_C;
- private byte[] I_S;
- private byte[] I_C;
- private Digest hash;
- private AbstractDH dh;
- private byte[] e;
- private byte[] f;
- private byte[] K;
- private byte[] H;
-
- public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
- if (!(s instanceof ServerSession)) {
- throw new IllegalStateException("Using a server side KeyExchange on a client");
- }
- session = (ServerSession) s;
- this.V_S = V_S;
- this.V_C = V_C;
- this.I_S = I_S;
- this.I_C = I_C;
- dh = getDH();
- hash = dh.getHash();
- hash.init();
- f = dh.getE();
- }
-
- protected abstract AbstractDH getDH() throws Exception;
-
- public boolean next(Buffer buffer) throws Exception {
- byte cmd = buffer.getByte();
- if (cmd != SshConstants.SSH_MSG_KEXDH_INIT) {
- throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
- "Protocol error: expected packet " + SshConstants.SSH_MSG_KEXDH_INIT + ", got " + cmd);
- }
- log.debug("Received SSH_MSG_KEXDH_INIT");
- e = buffer.getMPIntAsBytes();
- dh.setF(e);
- K = dh.getK();
-
- byte[] K_S;
- KeyPair kp = session.getHostKey();
- String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
- Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
- sig.init(kp.getPublic(), kp.getPrivate());
-
- buffer = new Buffer();
- buffer.putRawPublicKey(kp.getPublic());
- K_S = buffer.getCompactData();
-
- buffer.clear();
- buffer.putString(V_C);
- buffer.putString(V_S);
- buffer.putString(I_C);
- buffer.putString(I_S);
- buffer.putString(K_S);
- buffer.putMPInt(e);
- buffer.putMPInt(f);
- buffer.putMPInt(K);
- hash.update(buffer.array(), 0, buffer.available());
- H = hash.digest();
-
- byte[] sigH;
- buffer.clear();
- sig.update(H, 0, H.length);
- buffer.putString(algo);
- buffer.putString(sig.sign());
- sigH = buffer.getCompactData();
-
- if (log.isDebugEnabled()) {
- log.debug("K_S: {}", BufferUtils.printHex(K_S));
- log.debug("f: {}", BufferUtils.printHex(f));
- log.debug("sigH: {}", BufferUtils.printHex(sigH));
- }
-
- // Send response
- log.debug("Send SSH_MSG_KEXDH_REPLY");
- buffer.clear();
- buffer.rpos(5);
- buffer.wpos(5);
- buffer.putByte(SshConstants.SSH_MSG_KEXDH_REPLY);
- buffer.putString(K_S);
- buffer.putString(f);
- buffer.putString(sigH);
- session.writePacket(buffer);
- return true;
- }
-
- public Digest getHash() {
- return hash;
- }
-
- public byte[] getH() {
- return H;
- }
-
- public byte[] getK() {
- return K;
- }
-
- public PublicKey getServerKey() {
- return session.getHostKey().getPublic();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..6d1172b
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
@@ -0,0 +1,50 @@
+/*
+ * 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.server.kex;
+
+import java.security.PublicKey;
+
+import org.apache.sshd.common.kex.dh.AbstractDHKeyExchange;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.server.session.ServerSession;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange {
+
+ protected ServerSession session;
+
+ protected AbstractDHServerKeyExchange() {
+ super();
+ }
+
+ public void init(AbstractSession 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);
+ if (!(s instanceof ServerSession)) {
+ throw new IllegalStateException("Using a server side KeyExchange on a client");
+ }
+ session = (ServerSession) s;
+ }
+
+ public PublicKey getServerKey() {
+ return session.getHostKey().getPublic();
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java
deleted file mode 100644
index abe3474..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG1.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHG1 extends AbstractDHGServer {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "diffie-hellman-group1-sha1";
- }
-
- public KeyExchange create() {
- return new DHG1();
- }
-
- }
-
- @Override
- protected AbstractDH getDH() throws Exception {
- DH dh = new DH();
- dh.setG(DHGroupData.getG());
- dh.setP(DHGroupData.getP1());
- return dh;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java
deleted file mode 100644
index 2a7b925..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHG14.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-
-/**
- * DHG14 does not work with the default JCE implementation provided by Sun
- * because it does not support 2048 bits encryption.
- * It requires BouncyCastle to be used.
- *
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHG14 extends AbstractDHGServer {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "diffie-hellman-group14-sha1";
- }
-
- public KeyExchange create() {
- return new DHG14();
- }
-
- }
-
- @Override
- protected AbstractDH getDH() throws Exception {
- DH dh = new DH();
- dh.setG(DHGroupData.getG());
- dh.setP(DHGroupData.getP14());
- return dh;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java
deleted file mode 100644
index ef777d6..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * 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.server.kex;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URL;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.sshd.common.Digest;
-import org.apache.sshd.common.FactoryManagerUtils;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Random;
-import org.apache.sshd.common.Signature;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.digest.SHA1;
-import org.apache.sshd.common.kex.DH;
-import org.apache.sshd.common.kex.DHGroupData;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.BufferUtils;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.server.ServerFactoryManager;
-import org.apache.sshd.server.session.ServerSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Server side Diffie Hellman Group Exchange
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHGEX implements KeyExchange {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "diffie-hellman-group-exchange-sha1";
- }
-
- public KeyExchange create() {
- return new DHGEX();
- }
-
- }
-
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private ServerSession session;
- private byte[] V_S;
- private byte[] V_C;
- private byte[] I_S;
- private byte[] I_C;
- private Digest hash;
- private DH dh;
- private byte[] e;
- private byte[] f;
- private byte[] K;
- private byte[] H;
-
- int min;
- int prf;
- int max;
- private byte expected;
- boolean oldRequest;
-
- public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
- if (!(s instanceof ServerSession)) {
- throw new IllegalStateException("Using a server side KeyExchange on a client");
- }
- session = (ServerSession) s;
- this.V_S = V_S;
- this.V_C = V_C;
- this.I_S = I_S;
- this.I_C = I_C;
-
- expected = SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST;
- }
-
- public boolean next(Buffer buffer) throws Exception {
- byte cmd = buffer.getByte();
-
- if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
- log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD");
- oldRequest = true;
- min = 1024;
- prf = buffer.getInt();
- max = 8192;
-
- if (max < min || prf < min || max < prf) {
- throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
- "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
- }
- dh = chooseDH(min, prf, max);
- f = dh.getE();
- hash = dh.getHash();
- hash.init();
-
- log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
- buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
- buffer.putMPInt(dh.getP());
- buffer.putMPInt(dh.getG());
- session.writePacket(buffer);
-
- expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
- return false;
- }
- if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
- log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST");
- min = buffer.getInt();
- prf = buffer.getInt();
- max = buffer.getInt();
- if (max < min || prf < min || max < prf) {
- throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
- "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
- }
- dh = chooseDH(min, prf, max);
- f = dh.getE();
- hash = dh.getHash();
- hash.init();
-
- log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
- buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
- buffer.putMPInt(dh.getP());
- buffer.putMPInt(dh.getG());
- session.writePacket(buffer);
-
- expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
- return false;
- }
- if (cmd != expected) {
- throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
- "Protocol error: expected packet " + expected + ", got " + cmd);
- }
-
- if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_INIT) {
- log.debug("Received SSH_MSG_KEX_DH_GEX_INIT");
- e = buffer.getMPIntAsBytes();
- dh.setF(e);
- K = dh.getK();
-
-
- byte[] K_S;
- KeyPair kp = session.getHostKey();
- String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
- Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
- sig.init(kp.getPublic(), kp.getPrivate());
-
- buffer = new Buffer();
- buffer.putRawPublicKey(kp.getPublic());
- K_S = buffer.getCompactData();
-
- buffer.clear();
- buffer.putString(V_C);
- buffer.putString(V_S);
- buffer.putString(I_C);
- buffer.putString(I_S);
- buffer.putString(K_S);
- if (oldRequest) {
- buffer.putInt(prf);
- } else {
- buffer.putInt(min);
- buffer.putInt(prf);
- buffer.putInt(max);
- }
- buffer.putMPInt(dh.getP());
- buffer.putMPInt(dh.getG());
- buffer.putMPInt(e);
- buffer.putMPInt(f);
- buffer.putMPInt(K);
- hash.update(buffer.array(), 0, buffer.available());
- H = hash.digest();
-
- byte[] sigH;
- buffer.clear();
- sig.update(H, 0, H.length);
- buffer.putString(algo);
- buffer.putString(sig.sign());
- sigH = buffer.getCompactData();
-
- if (log.isDebugEnabled()) {
- log.debug("K_S: {}", BufferUtils.printHex(K_S));
- log.debug("f: {}", BufferUtils.printHex(f));
- log.debug("sigH: {}", BufferUtils.printHex(sigH));
- }
-
- // Send response
- log.debug("Send SSH_MSG_KEX_DH_GEX_REPLY");
- buffer.clear();
- buffer.rpos(5);
- buffer.wpos(5);
- buffer.putByte(SshConstants.SSH_MSG_KEX_DH_GEX_REPLY);
- buffer.putString(K_S);
- buffer.putString(f);
- buffer.putString(sigH);
- session.writePacket(buffer);
- return true;
- }
-
- return false;
- }
-
- private DH chooseDH(int min, int prf, int max) throws Exception {
- List<Moduli.DhGroup> groups = loadModuliGroups();
-
- min = Math.max(min, 1024);
- prf = Math.max(prf, 1024);
- // Keys of size > 1024 are not support by default with JCE, so only enable
- // those if BouncyCastle is registered
- prf = Math.min(prf, SecurityUtils.isBouncyCastleRegistered() ? 8192 : 1024);
- max = Math.min(max, 8192);
- int bestSize = 0;
- List<Moduli.DhGroup> selected = new ArrayList<Moduli.DhGroup>();
- for (Moduli.DhGroup group : groups) {
- if (group.size < min || group.size > max) {
- continue;
- }
- if ((group.size > prf && group.size < bestSize) || (group.size > bestSize && bestSize < prf)) {
- bestSize = group.size;
- selected.clear();
- }
- if (group.size == bestSize) {
- selected.add(group);
- }
- }
- if (selected.isEmpty()) {
- log.warn("No suitable primes found, defaulting to DHG1");
- return getDH(new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
- }
- Random random = session.getFactoryManager().getRandomFactory().create();
- int which = random.random(selected.size());
- Moduli.DhGroup group = selected.get(which);
- return getDH(group.p, group.g);
- }
-
- protected List<Moduli.DhGroup> loadModuliGroups() throws IOException {
- List<Moduli.DhGroup> groups = null;
- URL moduli;
- String moduliStr = FactoryManagerUtils.getString(session, ServerFactoryManager.MODULI_URL);
- if (!GenericUtils.isEmpty(moduliStr)) {
- try {
- moduli = new URL(moduliStr);
- groups = Moduli.parseModuli(moduli);
- } catch (IOException e) { // OK - use internal moduli
- log.warn("Error (" + e.getClass().getSimpleName() + ") loading external moduli from " + moduliStr + ": " + e.getMessage());
- }
- }
-
- if (groups == null) {
- moduliStr = "/org/apache/sshd/moduli";
- try {
- if ((moduli = getClass().getResource(moduliStr)) == null) {
- throw new FileNotFoundException("Missing internal moduli file");
- }
-
- moduliStr = moduli.toExternalForm();
- groups = Moduli.parseModuli(moduli);
- } catch (IOException e) {
- log.warn("Error (" + e.getClass().getSimpleName() + ") loading internal moduli from " + moduliStr + ": " + e.getMessage());
- throw e; // this time we MUST throw the exception
- }
- }
-
- log.debug("Loaded moduli groups from {}", moduliStr);
- return groups;
- }
-
- protected DH getDH(BigInteger p, BigInteger g) throws Exception {
- DH dh = new DH(new SHA1.Factory());
- dh.setP(p);
- dh.setG(g);
- return dh;
- }
-
- public Digest getHash() {
- return hash;
- }
-
- public byte[] getH() {
- return H;
- }
-
- public byte[] getK() {
- return K;
- }
-
- public PublicKey getServerKey() {
- return session.getHostKey().getPublic();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java
deleted file mode 100644
index a6dd41e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEX256.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.server.kex;
-
-import java.math.BigInteger;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.digest.SHA256;
-import org.apache.sshd.common.kex.DH;
-
-/**
- * Server side Diffie Hellman Group Exchange
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DHGEX256 extends DHGEX {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "diffie-hellman-group-exchange-sha256";
- }
-
- public KeyExchange create() {
- return new DHGEX256();
- }
-
- }
-
- @Override
- protected DH getDH(BigInteger p, BigInteger g) throws Exception {
- DH dh = new DH(new SHA256.Factory());
- dh.setP(p);
- dh.setG(g);
- return dh;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..5473d65
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
@@ -0,0 +1,283 @@
+/*
+ * 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.server.kex;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.KeyPair;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sshd.common.FactoryManagerUtils;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Random;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.kex.DHG;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.kex.DHGroupData;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.BufferUtils;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.server.ServerFactoryManager;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHGEXServer extends AbstractDHServerKeyExchange {
+
+ protected final DHFactory factory;
+ protected DHG dh;
+ protected int min;
+ protected int prf;
+ protected int max;
+ protected byte expected;
+ protected boolean oldRequest;
+
+ public static NamedFactory<KeyExchange> newFactory(final DHFactory factory) {
+ return new NamedFactory<KeyExchange>() {
+ @Override
+ public KeyExchange create() {
+ return new DHGEXServer(factory);
+ }
+
+ @Override
+ public String getName() {
+ return factory.getName();
+ }
+
+ @Override
+ public String toString() {
+ return NamedFactory.class.getSimpleName()
+ + "<" + KeyExchange.class.getSimpleName() + ">"
+ + "[" + getName() + "]";
+ }
+ };
+ }
+
+ protected DHGEXServer(DHFactory factory) {
+ super();
+ this.factory = factory;
+ }
+
+ public void init(AbstractSession 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);
+ expected = SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST;
+ }
+
+ public boolean next(Buffer buffer) throws Exception {
+ byte cmd = buffer.getByte();
+
+ if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
+ log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD");
+ oldRequest = true;
+ min = 1024;
+ prf = buffer.getInt();
+ max = 8192;
+
+ if (max < min || prf < min || max < prf) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
+ }
+ dh = chooseDH(min, prf, max);
+ f = dh.getE();
+ hash = dh.getHash();
+ hash.init();
+
+ log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
+ buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
+ buffer.putMPInt(dh.getP());
+ buffer.putMPInt(dh.getG());
+ session.writePacket(buffer);
+
+ expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
+ return false;
+ }
+ if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) {
+ log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST");
+ min = buffer.getInt();
+ prf = buffer.getInt();
+ max = buffer.getInt();
+ if (prf < min || max < prf) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Protocol error: bad parameters " + min + " !< " + prf + " !< " + max);
+ }
+ dh = chooseDH(min, prf, max);
+ f = dh.getE();
+ hash = dh.getHash();
+ hash.init();
+
+ log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP");
+ buffer = session.createBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP);
+ buffer.putMPInt(dh.getP());
+ buffer.putMPInt(dh.getG());
+ session.writePacket(buffer);
+
+ expected = SshConstants.SSH_MSG_KEX_DH_GEX_INIT;
+ return false;
+ }
+ if (cmd != expected) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Protocol error: expected packet " + expected + ", got " + cmd);
+ }
+
+ if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_INIT) {
+ log.debug("Received SSH_MSG_KEX_DH_GEX_INIT");
+ e = buffer.getMPIntAsBytes();
+ dh.setF(e);
+ K = dh.getK();
+
+
+ byte[] K_S;
+ KeyPair kp = session.getHostKey();
+ String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
+ Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
+ sig.init(kp.getPublic(), kp.getPrivate());
+
+ buffer = new Buffer();
+ buffer.putRawPublicKey(kp.getPublic());
+ K_S = buffer.getCompactData();
+
+ buffer.clear();
+ buffer.putString(V_C);
+ buffer.putString(V_S);
+ buffer.putString(I_C);
+ buffer.putString(I_S);
+ buffer.putString(K_S);
+ if (oldRequest) {
+ buffer.putInt(prf);
+ } else {
+ buffer.putInt(min);
+ buffer.putInt(prf);
+ buffer.putInt(max);
+ }
+ buffer.putMPInt(dh.getP());
+ buffer.putMPInt(dh.getG());
+ buffer.putMPInt(e);
+ buffer.putMPInt(f);
+ buffer.putMPInt(K);
+ hash.update(buffer.array(), 0, buffer.available());
+ H = hash.digest();
+
+ byte[] sigH;
+ buffer.clear();
+ sig.update(H, 0, H.length);
+ buffer.putString(algo);
+ buffer.putString(sig.sign());
+ sigH = buffer.getCompactData();
+
+ if (log.isDebugEnabled()) {
+ log.debug("K_S: {}", BufferUtils.printHex(K_S));
+ log.debug("f: {}", BufferUtils.printHex(f));
+ log.debug("sigH: {}", BufferUtils.printHex(sigH));
+ }
+
+ // Send response
+ log.debug("Send SSH_MSG_KEX_DH_GEX_REPLY");
+ buffer.clear();
+ buffer.rpos(5);
+ buffer.wpos(5);
+ buffer.putByte(SshConstants.SSH_MSG_KEX_DH_GEX_REPLY);
+ buffer.putString(K_S);
+ buffer.putString(f);
+ buffer.putString(sigH);
+ session.writePacket(buffer);
+ return true;
+ }
+
+ return false;
+ }
+
+ private DHG chooseDH(int min, int prf, int max) throws Exception {
+ List<Moduli.DhGroup> groups = loadModuliGroups();
+
+ min = Math.max(min, 1024);
+ prf = Math.max(prf, 1024);
+ // Keys of size > 1024 are not support by default with JCE, so only enable
+ // those if BouncyCastle is registered
+ prf = Math.min(prf, SecurityUtils.isBouncyCastleRegistered() ? 8192 : 1024);
+ max = Math.min(max, 8192);
+ int bestSize = 0;
+ List<Moduli.DhGroup> selected = new ArrayList<>();
+ for (Moduli.DhGroup group : groups) {
+ if (group.size < min || group.size > max) {
+ continue;
+ }
+ if ((group.size > prf && group.size < bestSize) || (group.size > bestSize && bestSize < prf)) {
+ bestSize = group.size;
+ selected.clear();
+ }
+ if (group.size == bestSize) {
+ selected.add(group);
+ }
+ }
+ if (selected.isEmpty()) {
+ log.warn("No suitable primes found, defaulting to DHG1");
+ return getDH(new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG()));
+ }
+ Random random = session.getFactoryManager().getRandomFactory().create();
+ int which = random.random(selected.size());
+ Moduli.DhGroup group = selected.get(which);
+ return getDH(group.p, group.g);
+ }
+
+ protected List<Moduli.DhGroup> loadModuliGroups() throws IOException {
+ List<Moduli.DhGroup> groups = null;
+ URL moduli;
+ String moduliStr = FactoryManagerUtils.getString(session, ServerFactoryManager.MODULI_URL);
+ if (!GenericUtils.isEmpty(moduliStr)) {
+ try {
+ moduli = new URL(moduliStr);
+ groups = Moduli.parseModuli(moduli);
+ } catch (IOException e) { // OK - use internal moduli
+ log.warn("Error (" + e.getClass().getSimpleName() + ") loading external moduli from " + moduliStr + ": " + e.getMessage());
+ }
+ }
+
+ if (groups == null) {
+ moduliStr = "/org/apache/sshd/moduli";
+ try {
+ if ((moduli = getClass().getResource(moduliStr)) == null) {
+ throw new FileNotFoundException("Missing internal moduli file");
+ }
+
+ moduliStr = moduli.toExternalForm();
+ groups = Moduli.parseModuli(moduli);
+ } catch (IOException e) {
+ log.warn("Error (" + e.getClass().getSimpleName() + ") loading internal moduli from " + moduliStr + ": " + e.getMessage());
+ throw e; // this time we MUST throw the exception
+ }
+ }
+
+ log.debug("Loaded moduli groups from {}", moduliStr);
+ return groups;
+ }
+
+ protected DHG getDH(BigInteger p, BigInteger g) throws Exception {
+ return (DHG) factory.create(p, g);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..13df5c2
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
@@ -0,0 +1,136 @@
+/*
+ * 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.server.kex;
+
+import java.security.KeyPair;
+
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.kex.AbstractDH;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.BufferUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DHGServer extends AbstractDHServerKeyExchange {
+
+ protected final DHFactory factory;
+ protected AbstractDH dh;
+
+ public static NamedFactory<KeyExchange> newFactory(final DHFactory factory) {
+ return new NamedFactory<KeyExchange>() {
+ @Override
+ public KeyExchange create() {
+ return new DHGServer(factory);
+ }
+
+ @Override
+ public String getName() {
+ return factory.getName();
+ }
+
+ @Override
+ public String toString() {
+ return NamedFactory.class.getSimpleName()
+ + "<" + KeyExchange.class.getSimpleName() + ">"
+ + "[" + getName() + "]";
+ }
+ };
+ }
+
+ protected DHGServer(DHFactory factory) {
+ super();
+ this.factory = factory;
+ }
+
+ @Override
+ public void init(AbstractSession 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);
+ dh = factory.create();
+ hash = dh.getHash();
+ hash.init();
+ f = dh.getE();
+ }
+
+ public boolean next(Buffer buffer) throws Exception {
+ byte cmd = buffer.getByte();
+ if (cmd != SshConstants.SSH_MSG_KEXDH_INIT) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Protocol error: expected packet " + SshConstants.SSH_MSG_KEXDH_INIT + ", got " + cmd);
+ }
+ log.debug("Received SSH_MSG_KEXDH_INIT");
+ e = buffer.getMPIntAsBytes();
+ dh.setF(e);
+ K = dh.getK();
+
+ byte[] K_S;
+ KeyPair kp = session.getHostKey();
+ String algo = session.getNegotiated(SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS);
+ Signature sig = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), algo);
+ sig.init(kp.getPublic(), kp.getPrivate());
+
+ buffer = new Buffer();
+ buffer.putRawPublicKey(kp.getPublic());
+ K_S = buffer.getCompactData();
+
+ buffer.clear();
+ buffer.putString(V_C);
+ buffer.putString(V_S);
+ buffer.putString(I_C);
+ buffer.putString(I_S);
+ buffer.putString(K_S);
+ buffer.putMPInt(e);
+ buffer.putMPInt(f);
+ buffer.putMPInt(K);
+ hash.update(buffer.array(), 0, buffer.available());
+ H = hash.digest();
+
+ byte[] sigH;
+ buffer.clear();
+ sig.update(H, 0, H.length);
+ buffer.putString(algo);
+ buffer.putString(sig.sign());
+ sigH = buffer.getCompactData();
+
+ if (log.isDebugEnabled()) {
+ log.debug("K_S: {}", BufferUtils.printHex(K_S));
+ log.debug("f: {}", BufferUtils.printHex(f));
+ log.debug("sigH: {}", BufferUtils.printHex(sigH));
+ }
+
+ // Send response
+ log.debug("Send SSH_MSG_KEXDH_REPLY");
+ buffer.clear();
+ buffer.rpos(5);
+ buffer.wpos(5);
+ buffer.putByte(SshConstants.SSH_MSG_KEXDH_REPLY);
+ buffer.putString(K_S);
+ buffer.putString(f);
+ buffer.putString(sigH);
+ session.writePacket(buffer);
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java
deleted file mode 100644
index 7da6c9a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP256.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP256 extends AbstractDHGServer {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "ecdh-sha2-nistp256";
- }
-
- public KeyExchange create() {
- return new ECDHP256();
- }
-
- }
-
- @Override
- protected AbstractDH getDH() throws Exception {
- ECDH ecdh = new ECDH();
- ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp256);
- return ecdh;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java
deleted file mode 100644
index 093cba7..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP384.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP384 extends AbstractDHGServer {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "ecdh-sha2-nistp384";
- }
-
- public KeyExchange create() {
- return new ECDHP384();
- }
-
- }
-
- @Override
- protected AbstractDH getDH() throws Exception {
- ECDH ecdh = new ECDH();
- ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp384);
- return ecdh;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java
deleted file mode 100644
index 674e95b..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/ECDHP521.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.server.kex;
-
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.kex.AbstractDH;
-import org.apache.sshd.common.kex.ECDH;
-
-/**
- * Elliptic Curve Diffie-Hellman with NIST P-256 curve.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ECDHP521 extends AbstractDHGServer {
-
- public static class Factory implements NamedFactory<KeyExchange> {
-
- public String getName() {
- return "ecdh-sha2-nistp521";
- }
-
- public KeyExchange create() {
- return new ECDHP521();
- }
-
- }
-
- @Override
- protected AbstractDH getDH() throws Exception {
- ECDH ecdh = new ECDH();
- ecdh.setCurveParameters(ECCurves.EllipticCurves.nistp521);
- return ecdh;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/KexTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/KexTest.java
deleted file mode 100644
index 2b866e5..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/KexTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.util.Collections;
-
-import org.apache.sshd.client.kex.DHG1;
-import org.apache.sshd.client.kex.DHG14;
-import org.apache.sshd.client.kex.DHGEX;
-import org.apache.sshd.client.kex.DHGEX256;
-import org.apache.sshd.client.kex.ECDHP256;
-import org.apache.sshd.client.kex.ECDHP384;
-import org.apache.sshd.client.kex.ECDHP521;
-import org.apache.sshd.common.KeyExchange;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.util.BaseTest;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
-import org.apache.sshd.util.TeeOutputStream;
-import org.apache.sshd.util.Utils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test key exchange algorithms.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class KexTest extends BaseTest {
-
- private SshServer sshd;
- private int port;
-
- @Before
- public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
- sshd.start();
- port = sshd.getPort();
- }
-
- @After
- public void tearDown() throws Exception {
- sshd.stop(true);
- }
-
- @Test
- public void testDHGEX256() throws Exception {
- testClient(new DHGEX256.Factory());
- }
-
- @Test
- public void testDHGEX() throws Exception {
- testClient(new DHGEX.Factory());
- }
-
- @Test
- public void testDHG14() throws Exception {
- if (SecurityUtils.isBouncyCastleRegistered()) {
- testClient(new DHG14.Factory());
- }
- }
-
- @Test
- public void testDHG1() throws Exception {
- testClient(new DHG1.Factory());
- }
-
- @Test
- public void testECDHP521() throws Exception {
- testClient(new ECDHP521.Factory());
- }
-
- @Test
- public void testECDHP384() throws Exception {
- testClient(new ECDHP384.Factory());
- }
-
- @Test
- public void testECDHP256() throws Exception {
- testClient(new ECDHP256.Factory());
- }
-
- private void testClient(NamedFactory<KeyExchange> kex) throws Exception {
- SshClient client = SshClient.setUpDefaultClient();
- ByteArrayOutputStream sent = new ByteArrayOutputStream();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
- client.setKeyExchangeFactories(Collections.singletonList(kex));
- client.start();
- ClientSession session = client.connect("smx", "localhost", port).await().getSession();
- session.addPasswordIdentity("smx");
- session.auth().verify();
- ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
-
- PipedOutputStream pipedIn = new PipedOutputStream();
- channel.setIn(new PipedInputStream(pipedIn));
- OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- channel.setOut(out);
- channel.setErr(err);
- assertTrue(channel.open().await().isOpened());
-
- teeOut.write("this is my command\n".getBytes());
- teeOut.flush();
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < 10; i++) {
- sb.append("0123456789");
- }
- sb.append("\n");
- teeOut.write(sb.toString().getBytes());
-
- teeOut.write("exit\n".getBytes());
- teeOut.flush();
-
- channel.waitFor(ClientChannel.CLOSED, 0);
-
- channel.close(false);
- } finally {
- client.stop();
- }
-
- assertArrayEquals(sent.toByteArray(), out.toByteArray());
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
index cd73484..6489265 100644
--- a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
@@ -18,18 +18,23 @@
*/
package org.apache.sshd;
+import static org.junit.Assert.assertArrayEquals;
+
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
-import org.apache.sshd.client.kex.DHG1;
-import org.apache.sshd.common.Cipher;
-import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.client.kex.DHGClient;
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.FactoryManagerUtils;
import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.BlowfishCBC;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
+import org.apache.sshd.common.kex.AbstractDH;
+import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
@@ -38,8 +43,6 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import static org.junit.Assert.assertArrayEquals;
-
public class LoadTest extends BaseTest {
private SshServer sshd;
@@ -84,7 +87,7 @@ public class LoadTest extends BaseTest {
}
protected void test(final String msg, final int nbThreads, final int nbSessionsPerThread) throws Exception {
- final List<Throwable> errors = new ArrayList<Throwable>();
+ final List<Throwable> errors = new ArrayList<>();
final CountDownLatch latch = new CountDownLatch(nbThreads);
for (int i = 0; i < nbThreads; i++) {
Runnable r = new Runnable() {
@@ -109,37 +112,41 @@ public class LoadTest extends BaseTest {
}
protected void runClient(String msg) throws Exception {
- SshClient client = SshClient.setUpDefaultClient();
- try {
- client.getProperties().put(SshClient.MAX_PACKET_SIZE, Integer.toString(1024 * 16));
- client.getProperties().put(SshClient.WINDOW_SIZE, Integer.toString(1024 * 8));
- client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
- new DHG1.Factory()));
- client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList(
- new BlowfishCBC.Factory()));
+ try(SshClient client = SshClient.setUpDefaultClient()) {
+ Map<String,String> props=client.getProperties();
+ FactoryManagerUtils.updateProperty(props, FactoryManager.MAX_PACKET_SIZE, 1024 * 16);
+ FactoryManagerUtils.updateProperty(props, FactoryManager.WINDOW_SIZE, 1024 * 8);
+ client.setKeyExchangeFactories(Arrays.asList(
+ DHGClient.newFactory(BuiltinDHFactories.dhg1)));
+ client.setCipherFactories(Arrays.asList(BuiltinCiphers.blowfishcbc.create()));
client.start();
- ClientSession session = client.connect("sshd", "localhost", port).await().getSession();
- session.addPasswordIdentity("sshd");
- session.auth().verify();
-
- ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- channel.setOut(out);
- channel.setErr(err);
- channel.open().await();
- OutputStream pipedIn = channel.getInvertedIn();
-
- msg += "\nexit\n";
- pipedIn.write(msg.getBytes());
- pipedIn.flush();
-
- channel.waitFor(ClientChannel.CLOSED, 0);
+ try {
+ ClientSession session = client.connect("sshd", "localhost", port).await().getSession();
+ session.addPasswordIdentity("sshd");
+ session.auth().verify();
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
+ channel.setOut(out);
+ channel.setErr(err);
+ try {
+ channel.open().await();
+ OutputStream pipedIn = channel.getInvertedIn();
+
+ msg += "\nexit\n";
+ pipedIn.write(msg.getBytes());
+ pipedIn.flush();
+
+ channel.waitFor(ClientChannel.CLOSED, 0);
+ } finally {
+ channel.close(false);
+ }
- channel.close(false);
- assertArrayEquals(msg.getBytes(), out.toByteArray());
- } finally {
- client.stop();
+ assertArrayEquals("Mismatched message data", msg.getBytes(), out.toByteArray());
+ } finally {
+ client.stop();
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..848dd20
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.client.kex;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.Collections;
+
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshBuilder;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.SshServer;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.kex.BuiltinDHFactories;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.util.BaseTest;
+import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShellFactory;
+import org.apache.sshd.util.TeeOutputStream;
+import org.apache.sshd.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test client key exchange algorithms.
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class KexTest extends BaseTest {
+
+ private SshServer sshd;
+ private int port;
+
+ @Before
+ public void setUp() throws Exception {
+ sshd = SshServer.setUpDefaultServer();
+ sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd.setShellFactory(new EchoShellFactory());
+ sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
+ sshd.start();
+ port = sshd.getPort();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ sshd.stop(true);
+ }
+
+ @Test
+ public void testClientKeyExchanges() throws Exception {
+ Exception err=null;
+
+ for (BuiltinDHFactories f : BuiltinDHFactories.VALUES) {
+ if (!f.isSupported()) {
+ System.out.println("Skip KEX=" + f.getName() + " - unsupported");
+ continue;
+ }
+
+ try {
+ testClient(f);
+ } catch(Exception e) {
+ System.err.println(e.getClass().getSimpleName() + " while test KEX=" + f.getName() + ": " + e.getMessage());
+ err = e;
+ }
+ }
+
+ if (err != null) {
+ throw err;
+ }
+ }
+
+ private void testClient(DHFactory factory) throws Exception {
+ testClient(SshBuilder.ClientBuilder.getKeyExchangeFactory(factory));
+ }
+
+ private void testClient(NamedFactory<KeyExchange> kex) throws Exception {
+ System.out.println("testClient - KEX=" + kex.getName());
+
+ ByteArrayOutputStream sent = new ByteArrayOutputStream();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try(SshClient client = SshClient.setUpDefaultClient()) {
+ client.setKeyExchangeFactories(Collections.singletonList(kex));
+ client.start();
+
+ try {
+ ClientSession session = client.connect("smx", "localhost", port).await().getSession();
+ session.addPasswordIdentity("smx");
+ session.auth().verify();
+ ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
+
+ try(PipedOutputStream pipedIn = new PipedOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ OutputStream teeOut = new TeeOutputStream(sent, pipedIn)) {
+
+ channel.setIn(new PipedInputStream(pipedIn));
+ channel.setOut(out);
+ channel.setErr(err);
+ assertTrue(channel.open().await().isOpened());
+
+ teeOut.write("this is my command\n".getBytes());
+ teeOut.flush();
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 10; i++) {
+ sb.append("0123456789");
+ }
+ sb.append("\n");
+ teeOut.write(sb.toString().getBytes());
+
+ teeOut.write("exit\n".getBytes());
+ teeOut.flush();
+
+ channel.waitFor(ClientChannel.CLOSED, 0);
+ } finally {
+ channel.close(false);
+ }
+ } finally {
+ client.stop();
+ }
+ }
+
+ assertArrayEquals(kex.getName(), sent.toByteArray(), out.toByteArray());
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/73551939/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java
new file mode 100644
index 0000000..6a53dd3
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/BuiltinDHFactoriesTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.kex;
+
+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 BuiltinDHFactoriesTest extends BaseTest {
+
+ public BuiltinDHFactoriesTest() {
+ super();
+ }
+
+ @Test
+ public void testFromName() {
+ for (BuiltinDHFactories expected : BuiltinDHFactories.VALUES) {
+ String name = expected.getName();
+ BuiltinDHFactories actual = BuiltinDHFactories.fromFactoryName(name);
+ Assert.assertSame(name, expected, actual);
+ }
+ }
+
+}