Repository: mina-sshd
Updated Branches:
  refs/heads/master 19d5e8edd -> 3ddd221b3


[SSHD-390] Support switching to a none cipher on the client side for 
performances

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/c4c42ca4
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/c4c42ca4
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/c4c42ca4

Branch: refs/heads/master
Commit: c4c42ca4cf489571c45a2a3d9898c01b1a8e8ee4
Parents: 19d5e8e
Author: Guillaume Nodet <[email protected]>
Authored: Tue Dec 16 21:56:41 2014 +0100
Committer: Guillaume Nodet <[email protected]>
Committed: Tue Dec 16 21:56:41 2014 +0100

----------------------------------------------------------------------
 .../java/org/apache/sshd/ClientSession.java     | 15 +++++++++
 .../sshd/client/session/ClientSessionImpl.java  | 34 ++++++++++++++++++++
 .../test/java/org/apache/sshd/ClientTest.java   | 17 ++++++++++
 3 files changed, 66 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c4c42ca4/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/ClientSession.java 
b/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
index 482719b..bee81f7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
@@ -34,6 +34,7 @@ import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.SshFuture;
 
 /**
  * An authenticated session to a given SSH server
@@ -230,4 +231,18 @@ public interface ClientSession extends Session {
      */
     ClientFactoryManager getFactoryManager();
 
+    /**
+     * Switch to a none cipher for performance.
+     *
+     * This should be done after the authentication phase has been performed.
+     * After such a switch, interactive channels are not allowed anymore.
+     * Both client and server must have been configured to support the none 
cipher.
+     * If that's not the case, the returned future will be set with an 
exception.
+     *
+     * @return an {@link SshFuture} that can be used to wait for the exchange
+     *         to be finished
+     * @throws IOException if a key exchange is already running
+     */
+    SshFuture switchToNoneCipher() throws IOException;
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c4c42ca4/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java 
b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
index 76a8bca..9309674 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.net.SocketAddress;
 import java.security.KeyPair;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -53,7 +54,11 @@ import org.apache.sshd.common.SessionListener;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.cipher.CipherNone;
+import org.apache.sshd.common.future.DefaultSshFuture;
+import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.session.AbstractConnectionService;
 import org.apache.sshd.common.session.AbstractSession;
 import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.util.Buffer;
@@ -188,6 +193,32 @@ public class ClientSessionImpl extends AbstractSession 
implements ClientSession
         }
     }
 
+    @Override
+    public SshFuture switchToNoneCipher() throws IOException {
+        if (!(currentService instanceof AbstractConnectionService)
+                || !((AbstractConnectionService) 
currentService).getChannels().isEmpty()) {
+            throw new IllegalStateException("The switch to the none cipher 
must be done immediately after authentication");
+        }
+        if (kexState.compareAndSet(KEX_STATE_DONE, KEX_STATE_INIT)) {
+            reexchangeFuture = new DefaultSshFuture(null);
+            if 
(!serverProposal[SshConstants.PROPOSAL_ENC_ALGS_CTOS].matches("(^|.*,)none($|,.*)")
+                    || 
!serverProposal[SshConstants.PROPOSAL_ENC_ALGS_STOC].matches("(^|.*,)none($|,.*)"))
 {
+                reexchangeFuture.setValue(new SshException("Server does not 
support none cipher"));
+            } else if 
(!clientProposal[SshConstants.PROPOSAL_ENC_ALGS_CTOS].matches("(^|.*,)none($|,.*)")
+                    || 
!clientProposal[SshConstants.PROPOSAL_ENC_ALGS_STOC].matches("(^|.*,)none($|,.*)"))
 {
+                reexchangeFuture.setValue(new SshException("Client does not 
support none cipher"));
+            } else {
+                log.info("Switching to none cipher");
+                clientProposal[SshConstants.PROPOSAL_ENC_ALGS_CTOS] = "none";
+                clientProposal[SshConstants.PROPOSAL_ENC_ALGS_STOC] = "none";
+                I_C = sendKexInit(clientProposal);
+            }
+            return reexchangeFuture;
+        } else {
+            throw new SshException("In flight key exchange");
+        }
+    }
+
     public ClientChannel createChannel(String type) throws IOException {
         return createChannel(type, null);
     }
@@ -205,6 +236,9 @@ public class ClientSessionImpl extends AbstractSession 
implements ClientSession
     }
 
     public ChannelShell createShellChannel() throws IOException {
+        if (inCipher instanceof CipherNone || outCipher instanceof CipherNone) 
{
+            throw new IllegalStateException("Interactive channels are not 
supported with none cipher");
+        }
         ChannelShell channel = new ChannelShell();
         getConnectionService().registerChannel(channel);
         return channel;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c4c42ca4/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java 
b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
index 245973d..45881d9 100644
--- a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
@@ -51,6 +51,7 @@ import org.apache.sshd.common.Service;
 import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.cipher.CipherNone;
 import org.apache.sshd.common.forward.TcpipServerChannel;
 import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.SshFutureListener;
@@ -744,6 +745,22 @@ public class ClientTest extends BaseTest {
         client.stop();
     }
 
+    @Test
+    public void testSwitchToNoneCipher() throws Exception {
+        sshd.getCipherFactories().add(new CipherNone.Factory());
+        client.getCipherFactories().add(new CipherNone.Factory());
+        client.start();
+        ClientSession session = client.connect("smx", "localhost", 
port).await().getSession();
+        session.addPasswordIdentity("smx");
+        session.auth().verify();
+        session.switchToNoneCipher().await();
+
+        ClientChannel channel = session.createSubsystemChannel("sftp");
+        channel.open().verify();
+
+        client.stop();
+    }
+
     private void suspend(IoSession ioSession) {
         if (ioSession instanceof MinaSession) {
             ((MinaSession) ioSession).suspend();

Reply via email to