[SSHD-195] Client side welcome banner support

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

Branch: refs/heads/master
Commit: 1937ee8ebbebb2886ba5bcab0705a80e57a8f286
Parents: 34098da
Author: Guillaume Nodet <[email protected]>
Authored: Wed Jul 17 10:28:59 2013 +0200
Committer: Guillaume Nodet <[email protected]>
Committed: Wed Jul 17 10:28:59 2013 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshClient.java    | 10 +++
 .../sshd/client/ClientFactoryManager.java       |  7 ++
 .../org/apache/sshd/client/UserInteraction.java | 35 +++++++++
 .../sshd/client/session/ClientSessionImpl.java  | 43 +++++++----
 .../sshd/server/session/ServerSession.java      |  2 +-
 .../java/org/apache/sshd/WelcomeBannerTest.java | 79 ++++++++++++++++++++
 6 files changed, 159 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1937ee8e/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java 
b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index c0b8167..336145f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -40,6 +40,7 @@ import 
org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.apache.sshd.client.ClientFactoryManager;
 import org.apache.sshd.client.ServerKeyVerifier;
 import org.apache.sshd.client.SessionFactory;
+import org.apache.sshd.client.UserInteraction;
 import org.apache.sshd.client.channel.ChannelShell;
 import org.apache.sshd.client.future.ConnectFuture;
 import org.apache.sshd.client.future.DefaultConnectFuture;
@@ -134,6 +135,7 @@ public class SshClient extends AbstractFactoryManager 
implements ClientFactoryMa
 
     protected IoConnector connector;
     protected SessionFactory sessionFactory;
+    protected UserInteraction userInteraction;
 
     private ServerKeyVerifier serverKeyVerifier;
 
@@ -156,6 +158,14 @@ public class SshClient extends AbstractFactoryManager 
implements ClientFactoryMa
         this.serverKeyVerifier = serverKeyVerifier;
     }
 
+    public UserInteraction getUserInteraction() {
+        return userInteraction;
+    }
+
+    public void setUserInteraction(UserInteraction userInteraction) {
+        this.userInteraction = userInteraction;
+    }
+
     protected void checkConfig() {
         if (getKeyExchangeFactories() == null) {
             throw new IllegalArgumentException("KeyExchangeFactories not set");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1937ee8e/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java 
b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
index 3812b8c..f83d618 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
@@ -54,4 +54,11 @@ public interface ClientFactoryManager extends FactoryManager 
{
      * @return A <code>TcpipForwarderFactory</code>
      */
     TcpipForwarderFactory getTcpipForwarderFactory();
+
+    /**
+     * Retrieve the UserInteraction object to communicate with the user.
+     *
+     * @return A <code>UserInteraction</code> or <code>null</code>
+     */
+    UserInteraction getUserInteraction();
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1937ee8e/sshd-core/src/main/java/org/apache/sshd/client/UserInteraction.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/UserInteraction.java 
b/sshd-core/src/main/java/org/apache/sshd/client/UserInteraction.java
new file mode 100644
index 0000000..72dbca5
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/UserInteraction.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ * Interface used by the ssh client to communicate with the end user.
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public interface UserInteraction {
+
+    /**
+     * Displays the welcome banner to the user.
+     *
+     * @param banner the welcome banner
+     */
+    void welcome(String banner);
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1937ee8e/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 35748ef..37f7175 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
@@ -30,6 +30,7 @@ import org.apache.sshd.ClientChannel;
 import org.apache.sshd.ClientSession;
 import org.apache.sshd.client.ClientFactoryManager;
 import org.apache.sshd.client.ServerKeyVerifier;
+import org.apache.sshd.client.UserInteraction;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.client.UserAuth;
 import org.apache.sshd.client.auth.UserAuthAgent;
@@ -345,22 +346,32 @@ public class ClientSessionImpl extends AbstractSession 
implements ClientSession
                         if (userAuth == null) {
                             throw new IllegalStateException("State is 
userAuth, but no user auth pending!!!");
                         }
-                        buffer.rpos(buffer.rpos() - 1);
-                        switch (userAuth.next(buffer)) {
-                             case Success:
-                                 authFuture.setAuthed(true);
-                                 username = userAuth.getUsername();
-                                 authed = true;
-                                 setState(State.Running);
-                                 startHeartBeat();
-                                 break;
-                             case Failure:
-                                 authFuture.setAuthed(false);
-                                 userAuth = null;
-                                 setState(State.WaitForAuth);
-                                 break;
-                             case Continued:
-                                 break;
+                        if (cmd == 
SshConstants.Message.SSH_MSG_USERAUTH_BANNER) {
+                            String welcome = buffer.getString();
+                            String lang = buffer.getString();
+                            log.debug("Welcome banner: " + welcome);
+                            UserInteraction ui = 
getClientFactoryManager().getUserInteraction();
+                            if (ui != null) {
+                                ui.welcome(welcome);
+                            }
+                        } else {
+                            buffer.rpos(buffer.rpos() - 1);
+                            switch (userAuth.next(buffer)) {
+                                 case Success:
+                                     authFuture.setAuthed(true);
+                                     username = userAuth.getUsername();
+                                     authed = true;
+                                     setState(State.Running);
+                                     startHeartBeat();
+                                     break;
+                                 case Failure:
+                                     authFuture.setAuthed(false);
+                                     userAuth = null;
+                                     setState(State.WaitForAuth);
+                                     break;
+                                 case Continued:
+                                     break;
+                            }
                         }
                         break;
                     case Running:

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1937ee8e/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java 
b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
index d87fdd4..4582519 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
@@ -447,7 +447,7 @@ public class ServerSession extends AbstractSession {
                 if (welcomeBanner != null) {
                     buffer = 
createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_BANNER, 0);
                     buffer.putString(welcomeBanner);
-                    buffer.putString("\n");
+                    buffer.putString("en");
                     writePacket(buffer);
                 }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1937ee8e/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java 
b/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
new file mode 100644
index 0000000..bb5a222
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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 org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.BogusPublickeyAuthenticator;
+import org.apache.sshd.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.ServerSocket;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static junit.framework.Assert.assertEquals;
+
+public class WelcomeBannerTest {
+
+    private static final String WELCOME = "Welcome to SSHD";
+
+    private SshServer sshd;
+    private int port;
+
+    @Before
+    public void setUp() throws Exception {
+        ServerSocket s = new ServerSocket(0);
+        port = s.getLocalPort();
+        s.close();
+
+        sshd = SshServer.setUpDefaultServer();
+        sshd.setPort(port);
+        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+        sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
+        sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
+        sshd.getProperties().put(SshServer.WELCOME_BANNER, WELCOME);
+        sshd.start();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (sshd != null) {
+            sshd.stop(true);
+            Thread.sleep(50);
+        }
+    }
+
+    @Test
+    public void testBanner() throws Exception {
+        final AtomicReference<String> welcome = new AtomicReference<String>();
+        SshClient client = SshClient.setUpDefaultClient();
+        client.setUserInteraction(new UserInteraction() {
+            public void welcome(String banner) {
+                welcome.set(banner);
+            }
+        });
+        client.start();
+        ClientSession session = client.connect("localhost", 
port).await().getSession();
+        session.authPassword("smx", "smx").await().isSuccess();
+        assertEquals(WELCOME, welcome.get());
+        session.close(true);
+    }
+}

Reply via email to