[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); + } +}
