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 2014/01/29 12:02:15 UTC
[5/5] git commit: [SSHD-282] Abstract the SSH Service to make it more
pluggable
[SSHD-282] Abstract the SSH Service to make it more pluggable
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/03aa3979
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/03aa3979
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/03aa3979
Branch: refs/heads/master
Commit: 03aa3979d47b92ad7b01fcfe1e2833a050b7118d
Parents: 1ea3dfe
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Jan 29 12:01:53 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Jan 29 12:01:53 2014 +0100
----------------------------------------------------------------------
.../main/java/org/apache/sshd/SshClient.java | 8 +
.../main/java/org/apache/sshd/SshServer.java | 8 +
.../org/apache/sshd/agent/SshAgentFactory.java | 11 +-
.../sshd/agent/common/AgentForwardSupport.java | 9 +-
.../sshd/agent/local/AgentServerProxy.java | 9 +-
.../agent/local/ChannelAgentForwarding.java | 2 +-
.../sshd/agent/local/LocalAgentFactory.java | 6 +-
.../sshd/agent/local/ProxyAgentFactory.java | 11 +-
.../sshd/agent/unix/AgentServerProxy.java | 9 +-
.../sshd/agent/unix/UnixAgentFactory.java | 11 +-
.../apache/sshd/client/auth/UserAuthAgent.java | 5 +-
.../client/session/ClientConnectionService.java | 209 +++++++++
.../sshd/client/session/ClientSessionImpl.java | 387 ++++-------------
.../client/session/ClientUserAuthService.java | 201 +++++++++
.../sshd/common/AbstractFactoryManager.java | 8 +
.../java/org/apache/sshd/common/Channel.java | 3 +-
.../org/apache/sshd/common/FactoryManager.java | 7 +
.../java/org/apache/sshd/common/Service.java | 53 +++
.../org/apache/sshd/common/ServiceFactory.java | 58 +++
.../java/org/apache/sshd/common/Session.java | 27 +-
.../sshd/common/TcpipForwarderFactory.java | 6 +-
.../sshd/common/channel/AbstractChannel.java | 7 +-
.../common/forward/DefaultTcpipForwarder.java | 11 +-
.../forward/DefaultTcpipForwarderFactory.java | 5 +-
.../sshd/common/forward/TcpipServerChannel.java | 2 +-
.../session/AbstractConnectionService.java | 271 ++++++++++++
.../sshd/common/session/AbstractSession.java | 133 ++----
.../sshd/common/session/ConnectionService.java | 63 +++
.../sshd/server/channel/ChannelSession.java | 4 +-
.../server/session/ServerConnectionService.java | 232 ++++++++++
.../sshd/server/session/ServerSession.java | 419 ++-----------------
.../server/session/ServerUserAuthService.java | 261 ++++++++++++
.../sshd/server/x11/X11ForwardSupport.java | 13 +-
33 files changed, 1618 insertions(+), 851 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/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 410ae51..8d4e169 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -51,7 +51,9 @@ 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.client.keyverifier.AcceptAllServerKeyVerifier;
+import org.apache.sshd.client.session.ClientConnectionService;
import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.client.session.ClientUserAuthService;
import org.apache.sshd.common.AbstractFactoryManager;
import org.apache.sshd.common.Channel;
import org.apache.sshd.common.Cipher;
@@ -216,6 +218,12 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
if (getIoServiceFactory() == null) {
setIoServiceFactory(new DefaultIoServiceFactory());
}
+ if (getServiceFactories() == null) {
+ setServiceFactories(Arrays.asList(
+ new ClientUserAuthService.Factory(),
+ new ClientConnectionService.Factory()
+ ));
+ }
}
public void start() {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index eaf27ea..56e84cd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -105,7 +105,9 @@ import org.apache.sshd.server.kex.ECDHP384;
import org.apache.sshd.server.kex.ECDHP521;
import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.session.ServerConnectionService;
import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.server.session.ServerUserAuthService;
import org.apache.sshd.server.session.SessionFactory;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.server.session.ServerSessionTimeoutListener;
@@ -298,6 +300,12 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
if (getIoServiceFactory() == null) {
setIoServiceFactory(new DefaultIoServiceFactory());
}
+ if (getServiceFactories() == null) {
+ setServiceFactories(Arrays.asList(
+ new ServerUserAuthService.Factory(),
+ new ServerConnectionService.Factory()
+ ));
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
index d169d47..ff50ac5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
@@ -21,8 +21,10 @@ package org.apache.sshd.agent;
import java.io.IOException;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
/**
* The <code>SshAgentFactory</code> is used to communicate with an SshAgent.
@@ -41,19 +43,20 @@ public interface SshAgentFactory {
/**
* Create an SshAgent that can be used on the client side by the authentication
* process to send possible keys.
- * @param session
+ *
+ * @param manager
* @return
*/
- SshAgent createClient(Session session) throws IOException;
+ SshAgent createClient(FactoryManager manager) throws IOException;
/**
* Create the server side that will be used by other SSH clients.
* It will usually create a channel that will forward the requests
* to the original client.
*
- * @param session
+ * @param service
* @return
*/
- SshAgentServer createServer(Session session) throws IOException;
+ SshAgentServer createServer(ConnectionService service) throws IOException;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
index 0692b7e..cd879e1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,18 +34,18 @@ public class AgentForwardSupport {
private static final Logger log = LoggerFactory.getLogger(AgentForwardSupport.class);
- private final ServerSession session;
+ private final ConnectionService service;
private String agentId;
private SshAgentServer agentServer;
- public AgentForwardSupport(ServerSession session) {
- this.session = session;
+ public AgentForwardSupport(ConnectionService service) {
+ this.service = service;
}
public String initialize() throws IOException {
try {
if (agentId == null) {
- agentServer = session.getFactoryManager().getAgentFactory().createServer(session);
+ agentServer = service.getSession().getFactoryManager().getAgentFactory().createServer(service);
agentId = agentServer.getId();
}
return agentId;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
index 2630faf..15c23b2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
@@ -24,6 +24,7 @@ import java.util.UUID;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,18 +36,18 @@ public class AgentServerProxy implements SshAgentServer {
private static final Logger LOG = LoggerFactory.getLogger(AgentServerProxy.class);
- private final ServerSession session;
+ private final ConnectionService service;
private String id;
- public AgentServerProxy(ServerSession session) throws IOException {
- this.session = session;
+ public AgentServerProxy(ConnectionService service) throws IOException {
+ this.service = service;
this.id = UUID.randomUUID().toString();
}
public SshAgent createClient() throws IOException {
try {
AgentForwardedChannel channel = new AgentForwardedChannel();
- this.session.registerChannel(channel);
+ this.service.registerChannel(channel);
OpenFuture future = channel.open().await();
Throwable t = future.getException();
if (t instanceof Exception) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
index 4903315..bdd5165 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
@@ -66,7 +66,7 @@ public class ChannelAgentForwarding extends AbstractServerChannel {
final OpenFuture f = new DefaultOpenFuture(this);
try {
out = new ChannelOutputStream(this, remoteWindow, log, SshConstants.Message.SSH_MSG_CHANNEL_DATA);
- agent = session.getFactoryManager().getAgentFactory().createClient(session);
+ agent = session.getFactoryManager().getAgentFactory().createClient(session.getFactoryManager());
client = new AgentClient();
f.setOpened();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
index 014206f..15c494a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
@@ -25,8 +25,10 @@ import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.agent.common.AgentDelegate;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
public class LocalAgentFactory implements SshAgentFactory {
@@ -48,11 +50,11 @@ public class LocalAgentFactory implements SshAgentFactory {
return new ChannelAgentForwarding.Factory();
}
- public SshAgent createClient(Session session) throws IOException {
+ public SshAgent createClient(FactoryManager manager) throws IOException {
return new AgentDelegate(agent);
}
- public SshAgentServer createServer(Session session) throws IOException {
+ public SshAgentServer createServer(ConnectionService service) throws IOException {
return null;
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
index 2ae8223..fd918c0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
@@ -26,8 +26,10 @@ import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
public class ProxyAgentFactory implements SshAgentFactory {
@@ -38,8 +40,8 @@ public class ProxyAgentFactory implements SshAgentFactory {
return new ChannelAgentForwarding.Factory();
}
- public SshAgent createClient(Session session) throws IOException {
- String proxyId = session.getFactoryManager().getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
+ public SshAgent createClient(FactoryManager manager) throws IOException {
+ String proxyId = manager.getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
if (proxyId == null) {
throw new IllegalStateException("No " + SshAgent.SSH_AUTHSOCKET_ENV_NAME + " environment variable set");
}
@@ -50,11 +52,12 @@ public class ProxyAgentFactory implements SshAgentFactory {
return proxy.createClient();
}
- public SshAgentServer createServer(Session session) throws IOException {
+ public SshAgentServer createServer(ConnectionService service) throws IOException {
+ Session session = service.getSession();
if (!(session instanceof ServerSession)) {
throw new IllegalStateException("The session used to create an agent server proxy must be a server session");
}
- final AgentServerProxy proxy = new AgentServerProxy((ServerSession) session);
+ final AgentServerProxy proxy = new AgentServerProxy(service);
proxies.put(proxy.getId(), proxy);
return new SshAgentServer() {
public String getId() {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
index f773237..f358740 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.apache.tomcat.jni.Local;
import org.apache.tomcat.jni.Pool;
@@ -38,15 +39,15 @@ public class AgentServerProxy implements SshAgentServer {
private static final Logger LOG = LoggerFactory.getLogger(AgentServerProxy.class);
- private final ServerSession session;
+ private final ConnectionService service;
private String authSocket;
private long pool;
private long handle;
private Thread thread;
private boolean closed;
- public AgentServerProxy(ServerSession session) throws IOException {
- this.session = session;
+ public AgentServerProxy(ConnectionService service) throws IOException {
+ this.service = service;
try {
String authSocket = AprLibrary.createLocalSocketAddress();
pool = Pool.create(AprLibrary.getInstance().getRootPool());
@@ -70,7 +71,7 @@ public class AgentServerProxy implements SshAgentServer {
}
Socket.timeoutSet(clientSock, 10000000);
AgentForwardedChannel channel = new AgentForwardedChannel(clientSock);
- AgentServerProxy.this.session.registerChannel(channel);
+ AgentServerProxy.this.service.registerChannel(channel);
OpenFuture future = channel.open().await();
Throwable t = future.getException();
if (t instanceof Exception) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
index f82c95f..87797d3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
@@ -24,8 +24,10 @@ import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
public class UnixAgentFactory implements SshAgentFactory {
@@ -34,16 +36,17 @@ public class UnixAgentFactory implements SshAgentFactory {
return new ChannelAgentForwarding.Factory();
}
- public SshAgent createClient(Session session) throws IOException {
- String authSocket = session.getFactoryManager().getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
+ public SshAgent createClient(FactoryManager manager) throws IOException {
+ String authSocket = manager.getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
SshAgent agent = new AgentClient(authSocket);
return agent;
}
- public SshAgentServer createServer(Session session) throws IOException {
+ public SshAgentServer createServer(ConnectionService service) throws IOException {
+ Session session = service.getSession();
if (!(session instanceof ServerSession)) {
throw new IllegalStateException("The session used to create an agent server proxy must be a server session");
}
- return new AgentServerProxy((ServerSession) session);
+ return new AgentServerProxy(service);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
index fa68ff9..5fe5926 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
@@ -39,7 +39,10 @@ public class UserAuthAgent extends AbstractUserAuth {
public UserAuthAgent(ClientSessionImpl session, String service, String username) throws IOException {
super(session, service, username);
- this.agent = session.getFactoryManager().getAgentFactory().createClient(session);
+ if (session.getFactoryManager().getAgentFactory() == null) {
+ throw new IllegalStateException("No ssh agent factory has been configured");
+ }
+ this.agent = session.getFactoryManager().getAgentFactory().createClient(session.getFactoryManager());
this.keys = agent.getIdentities().iterator();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
new file mode 100644
index 0000000..bc9e316
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
@@ -0,0 +1,209 @@
+/*
+ * 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.session;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.session.AbstractConnectionService;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.channel.OpenChannelException;
+
+/**
+ * Client side <code>ssh-connection</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClientConnectionService extends AbstractConnectionService {
+
+ public static class Factory implements ServiceFactory {
+
+ public String getName() {
+ return "ssh-connection";
+ }
+
+ public Service create(Session session) throws IOException {
+ return new ClientConnectionService(session);
+ }
+ }
+
+ public ClientConnectionService(Session s) throws SshException {
+ super(s);
+ if (!(s instanceof ClientSessionImpl)) {
+ throw new IllegalStateException("Client side service used on server side");
+ }
+ }
+
+ @Override
+ public void start() {
+ if (!((ClientSessionImpl) session).isAuthenticated()) {
+ throw new IllegalStateException("Session is not authenticated");
+ }
+ startHeartBeat();
+ }
+
+ protected void startHeartBeat() {
+ String intervalStr = session.getFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_INTERVAL);
+ try {
+ int interval = intervalStr != null ? Integer.parseInt(intervalStr) : 0;
+ if (interval > 0) {
+ session.getFactoryManager().getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {
+ public void run() {
+ sendHeartBeat();
+ }
+ }, interval, interval, TimeUnit.MILLISECONDS);
+ }
+ } catch (NumberFormatException e) {
+ log.warn("Ignoring bad heartbeat interval: {}", intervalStr);
+ }
+ }
+
+ protected void sendHeartBeat() {
+ try {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_GLOBAL_REQUEST, 0);
+ String request = session.getFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_REQUEST);
+ if (request == null) {
+ request = "keepalive@sshd.apache.org";
+ }
+ buf.putString(request);
+ buf.putBoolean(false);
+ session.writePacket(buf);
+ } catch (IOException e) {
+ log.info("Error sending keepalive message", e);
+ }
+ }
+
+ public void process(SshConstants.Message cmd, Buffer buffer) throws Exception {
+ switch (cmd) {
+ case SSH_MSG_CHANNEL_OPEN:
+ channelOpen(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+ channelOpenConfirmation(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_FAILURE:
+ channelOpenFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_REQUEST:
+ channelRequest(buffer);
+ break;
+ case SSH_MSG_CHANNEL_DATA:
+ channelData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EXTENDED_DATA:
+ channelExtendedData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_FAILURE:
+ channelFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_WINDOW_ADJUST:
+ channelWindowAdjust(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EOF:
+ channelEof(buffer);
+ break;
+ case SSH_MSG_CHANNEL_CLOSE:
+ channelClose(buffer);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported command: " + cmd);
+ }
+ }
+
+ // TODO: remove from interface
+ public String initAgentForward() throws IOException {
+ throw new IllegalStateException("Server side operation");
+ }
+
+ // TODO: remove from interface
+ public String createX11Display(boolean singleConnection, String authenticationProtocol, String authenticationCookie, int screen) throws IOException {
+ throw new IllegalStateException("Server side operation");
+ }
+
+ private void channelOpen(Buffer buffer) throws Exception {
+ String type = buffer.getString();
+ final int id = buffer.getInt();
+ final int rwsize = buffer.getInt();
+ final int rmpsize = buffer.getInt();
+
+ log.info("Received SSH_MSG_CHANNEL_OPEN {}", type);
+
+ if (closing) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
+ buf.putString("SSH server is shutting down: " + type);
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+
+ final Channel channel = NamedFactory.Utils.create(getSession().getFactoryManager().getChannelFactories(), type);
+ if (channel == null) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
+ buf.putString("Unsupported channel type: " + type);
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+
+ final int channelId = registerChannel(channel);
+ channel.open(id, rwsize, rmpsize, buffer).addListener(new SshFutureListener<OpenFuture>() {
+ public void operationComplete(OpenFuture future) {
+ try {
+ if (future.isOpened()) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
+ buf.putInt(id);
+ buf.putInt(channelId);
+ buf.putInt(channel.getLocalWindow().getSize());
+ buf.putInt(channel.getLocalWindow().getPacketSize());
+ session.writePacket(buf);
+ } else if (future.getException() != null) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ if (future.getException() instanceof OpenChannelException) {
+ buf.putInt(((OpenChannelException)future.getException()).getReasonCode());
+ buf.putString(future.getException().getMessage());
+ } else {
+ buf.putInt(0);
+ buf.putString("Error opening channel: " + future.getException().getMessage());
+ }
+ buf.putString("");
+ session.writePacket(buf);
+ }
+ } catch (IOException e) {
+ session.exceptionCaught(e);
+ }
+ }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/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 2d4e68c..ce3e030 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.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -32,7 +33,6 @@ import org.apache.sshd.client.ScpClient;
import org.apache.sshd.client.ServerKeyVerifier;
import org.apache.sshd.client.SftpClient;
import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.UserInteraction;
import org.apache.sshd.client.auth.UserAuthAgent;
import org.apache.sshd.client.auth.UserAuthKeyboardInteractive;
import org.apache.sshd.client.auth.UserAuthPassword;
@@ -43,22 +43,19 @@ import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ChannelSubsystem;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.future.DefaultAuthFuture;
-import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.client.scp.DefaultScpClient;
import org.apache.sshd.client.sftp.DefaultSftpClient;
-import org.apache.sshd.common.Channel;
-import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.SshdSocketAddress;
-import org.apache.sshd.common.future.CloseFuture;
-import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.server.channel.OpenChannelException;
/**
* TODO Add javadoc
@@ -67,149 +64,83 @@ import org.apache.sshd.server.channel.OpenChannelException;
*/
public class ClientSessionImpl extends AbstractSession implements ClientSession {
- private static final String AUTHENTICATION_SERVICE = "ssh-connection";
-
- private UserAuth userAuth;
- /**
- * The AuthFuture that is being used by the current auth request. This encodes the state.
- * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
- */
- private volatile AuthFuture authFuture;
-
/**
* For clients to store their own metadata
*/
private Map<Object, Object> metadataMap = new HashMap<Object, Object>();
+ private ServiceFactory currentServiceFactory;
+
+ private Service nextService;
+ private ServiceFactory nextServiceFactory;
+
+ protected AuthFuture authFuture;
+
public ClientSessionImpl(ClientFactoryManager client, IoSession session) throws Exception {
super(client, session);
log.info("Session created...");
+ // Need to set the initial service early as calling code likes to start trying to
+ // manipulate it before the connection has even been established. For instance, to
+ // set the authPassword.
+ List<ServiceFactory> factories = client.getServiceFactories();
+ if (factories == null || factories.isEmpty() || factories.size() > 2) {
+ throw new IllegalArgumentException("One or two services must be configured");
+ }
+ currentServiceFactory = factories.get(0);
+ currentService = currentServiceFactory.create(this);
+ if (factories.size() > 1) {
+ nextServiceFactory = factories.get(1);
+ nextService = nextServiceFactory.create(this);
+ } else {
+ nextServiceFactory = null;
+ }
+ authFuture = new DefaultAuthFuture(lock);
+ authFuture.setAuthed(false);
sendClientIdentification();
sendKexInit();
- // Maintain the current auth status in the authFuture.
- authFuture = new DefaultAuthFuture(lock);
}
public ClientFactoryManager getClientFactoryManager() {
return (ClientFactoryManager) factoryManager;
}
- /**
- * return true if/when ready for auth; false if never ready.
- * @return server is ready and waiting for auth
- */
- private boolean readyForAuth() {
- // isDone indicates that the last auth finished and a new one can commence.
- while (!this.authFuture.isDone()) {
- log.debug("waiting to send authentication");
- try {
- this.authFuture.await();
- } catch (InterruptedException e) {
- log.debug("Unexpected interrupt", e);
- throw new RuntimeException(e);
- }
- }
- if (this.authFuture.isSuccess()) {
- log.debug("already authenticated");
- throw new IllegalStateException("Already authenticated");
- }
- if (this.authFuture.getException() != null) {
- log.debug("probably closed", this.authFuture.getException());
- return false;
- }
- if (!this.authFuture.isFailure()) {
- log.debug("unexpected state");
- throw new IllegalStateException("Unexpected authentication state");
- }
- if (this.userAuth != null) {
- log.debug("authentication already in progress");
- throw new IllegalStateException("Authentication already in progress?");
- }
- log.debug("ready to try authentication with new lock");
- // The new future !isDone() - i.e., in progress blocking out other waits.
- this.authFuture = new DefaultAuthFuture(lock);
- return true;
- }
-
- /**
- * execute one step in user authentication.
- * @param buffer
- * @throws IOException
- */
- private void processUserAuth(Buffer buffer) throws IOException {
- log.debug("processing {}", userAuth);
- switch (userAuth.next(buffer)) {
- case Success:
- log.debug("succeeded with {}", userAuth);
- this.authed = true;
- this.username = userAuth.getUsername();
- setState(State.Running);
- // Will wake up anyone sitting in waitFor
- authFuture.setAuthed(true);
- startHeartBeat();
- break;
- case Failure:
- log.debug("failed with {}", userAuth);
- this.userAuth = null;
- setState(State.WaitForAuth);
- // Will wake up anyone sitting in waitFor
- this.authFuture.setAuthed(false);
- break;
- case Continued:
- // Will wake up anyone sitting in waitFor
- setState(State.UserAuth);
- log.debug("continuing with {}", userAuth);
- break;
- }
- }
-
public AuthFuture authAgent(String user) throws IOException {
- log.debug("Trying agent authentication");
- if (getFactoryManager().getAgentFactory() == null) {
- throw new IllegalStateException("No ssh agent factory has been configured");
- }
- synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthAgent(this, AUTHENTICATION_SERVICE, user);
- processUserAuth(null);
- }
- return authFuture;
- }
+ return tryAuth(new UserAuthAgent(this, nextServiceName(), user));
}
public AuthFuture authPassword(String user, String password) throws IOException {
- log.debug("Trying password authentication");
- synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthPassword(this, AUTHENTICATION_SERVICE, user, password);
- processUserAuth(null);
- }
- return authFuture;
- }
+ return tryAuth(new UserAuthPassword(this, nextServiceName(), user, password));
}
public AuthFuture authInteractive(String user, String password) throws IOException {
- log.debug("Trying keyboard-interactive authentication");
- synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthKeyboardInteractive(this, AUTHENTICATION_SERVICE, user, password);
- processUserAuth(null);
- }
- return authFuture;
- }
+ return tryAuth(new UserAuthKeyboardInteractive(this, nextServiceName(), user, password));
}
public AuthFuture authPublicKey(String user, KeyPair key) throws IOException {
- log.debug("Trying publickey authentication");
+ return tryAuth(new UserAuthPublicKey(this, nextServiceName(), user, key));
+ }
+
+ private AuthFuture tryAuth(UserAuth auth) throws IOException {
synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthPublicKey(this, AUTHENTICATION_SERVICE, user, key);
- processUserAuth(null);
- }
- return authFuture;
+ return authFuture = getUserAuthService().auth(auth);
}
}
+ private String nextServiceName() {
+ return nextServiceFactory.getName();
+ }
+
+ protected void switchToNextService() throws IOException {
+ if (nextService == null) {
+ throw new IllegalStateException("No service available");
+ }
+ currentServiceFactory = nextServiceFactory;
+ currentService = nextService;
+ nextServiceFactory = null;
+ nextService = null;
+ currentService.start();
+ }
+
public ClientChannel createChannel(String type) throws IOException {
return createChannel(type, null);
}
@@ -228,28 +159,46 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
public ChannelShell createShellChannel() throws IOException {
ChannelShell channel = new ChannelShell();
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
public ChannelExec createExecChannel(String command) throws IOException {
ChannelExec channel = new ChannelExec(command);
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
public ChannelSubsystem createSubsystemChannel(String subsystem) throws IOException {
ChannelSubsystem channel = new ChannelSubsystem(subsystem);
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
public ChannelDirectTcpip createDirectTcpipChannel(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
ChannelDirectTcpip channel = new ChannelDirectTcpip(local, remote);
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
+ private ClientUserAuthService getUserAuthService() {
+ return findService(ClientUserAuthService.class);
+ }
+
+ private ConnectionService getConnectionService() {
+ return findService(ConnectionService.class);
+ }
+
+ private <T> T findService(Class<T> clazz) {
+ if (clazz.isInstance(currentService)) {
+ return clazz.cast(currentService);
+ }
+ if (clazz.isInstance(nextService)) {
+ return clazz.cast(nextService);
+ }
+ throw new IllegalStateException("Attempted to access unknown service " + clazz.getSimpleName());
+ }
+
public ScpClient createScpClient() {
return new DefaultScpClient(this);
}
@@ -259,29 +208,19 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
public SshdSocketAddress startLocalPortForwarding(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
- return getTcpipForwarder().startLocalPortForwarding(local, remote);
+ return getConnectionService().getTcpipForwarder().startLocalPortForwarding(local, remote);
}
public void stopLocalPortForwarding(SshdSocketAddress local) throws IOException {
- getTcpipForwarder().stopLocalPortForwarding(local);
+ getConnectionService().getTcpipForwarder().stopLocalPortForwarding(local);
}
public SshdSocketAddress startRemotePortForwarding(SshdSocketAddress remote, SshdSocketAddress local) throws IOException {
- return getTcpipForwarder().startRemotePortForwarding(remote, local);
+ return getConnectionService().getTcpipForwarder().startRemotePortForwarding(remote, local);
}
public void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException {
- getTcpipForwarder().stopRemotePortForwarding(remote);
- }
-
- @Override
- public CloseFuture close(boolean immediately) {
- synchronized (lock) {
- if (!authFuture.isDone()) {
- authFuture.setException(new SshException("Session is closed"));
- }
- return super.close(immediately);
- }
+ getConnectionService().getTcpipForwarder().stopRemotePortForwarding(remote);
}
protected void handleMessage(Buffer buffer) throws Exception {
@@ -344,37 +283,24 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
log.info("Received SSH_MSG_NEWKEYS");
receiveNewKeys(false);
- sendAuthRequest();
- setState(State.AuthRequestSent);
+ log.info("Send SSH_MSG_SERVICE_REQUEST for {}", currentServiceFactory.getName());
+ Buffer request = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_REQUEST, 0);
+ request.putString(currentServiceFactory.getName());
+ writePacket(request);
+ setState(State.ServiceRequestSent);
+ // Assuming that MINA-SSHD only implements "explicit server authentication" it is permissible
+ // for the client's service to start sending data before the service-accept has been received.
+ // If "implicit authentication" were to ever be supported, then this would need to be
+ // called after service-accept comes back. See SSH-TRANSPORT.
+ currentService.start();
break;
- case AuthRequestSent:
+ case ServiceRequestSent:
if (cmd != SshConstants.Message.SSH_MSG_SERVICE_ACCEPT) {
disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Protocol error: expected packet SSH_MSG_SERVICE_ACCEPT, got " + cmd);
return;
}
- authFuture.setAuthed(false);
- setState(State.WaitForAuth);
- break;
- case WaitForAuth:
- // We're waiting for the client to send an authentication request
- // TODO: handle unexpected incoming packets
- break;
- case UserAuth:
- if (userAuth == null) {
- throw new IllegalStateException("State is userAuth, but no user auth pending!!!");
- }
- 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);
- processUserAuth(buffer);
- }
+ log.info("Received SSH_MSG_SERVICE_ACCEPT");
+ setState(State.Running);
break;
case Running:
switch (cmd) {
@@ -384,38 +310,9 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
case SSH_MSG_REQUEST_FAILURE:
requestFailure(buffer);
break;
- case SSH_MSG_CHANNEL_OPEN:
- channelOpen(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
- channelOpenConfirmation(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN_FAILURE:
- channelOpenFailure(buffer);
- break;
- case SSH_MSG_CHANNEL_REQUEST:
- channelRequest(buffer);
- break;
- case SSH_MSG_CHANNEL_DATA:
- channelData(buffer);
- break;
- case SSH_MSG_CHANNEL_EXTENDED_DATA:
- channelExtendedData(buffer);
- break;
- case SSH_MSG_CHANNEL_FAILURE:
- channelFailure(buffer);
- break;
- case SSH_MSG_CHANNEL_WINDOW_ADJUST:
- channelWindowAdjust(buffer);
- break;
- case SSH_MSG_CHANNEL_EOF:
- channelEof(buffer);
- break;
- case SSH_MSG_CHANNEL_CLOSE:
- channelClose(buffer);
- break;
default:
- throw new IllegalStateException("Unsupported command: " + cmd);
+ currentService.process(cmd, buffer);
+ break;
}
break;
default:
@@ -472,37 +369,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
}
- protected void startHeartBeat() {
- String intervalStr = getClientFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_INTERVAL);
- try {
- int interval = intervalStr != null ? Integer.parseInt(intervalStr) : 0;
- if (interval > 0) {
- getClientFactoryManager().getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {
- public void run() {
- sendHeartBeat();
- }
- }, interval, interval, TimeUnit.MILLISECONDS);
- }
- } catch (NumberFormatException e) {
- log.warn("Ignoring bad heartbeat interval: {}", intervalStr);
- }
- }
-
- protected void sendHeartBeat() {
- try {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_GLOBAL_REQUEST, 0);
- String request = getClientFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_REQUEST);
- if (request == null) {
- request = "keepalive@sshd.apache.org";
- }
- buf.putString(request);
- buf.putBoolean(false);
- writePacket(buf);
- } catch (IOException e) {
- log.info("Error sending keepalive message", e);
- }
- }
-
protected boolean readIdentification(Buffer buffer) throws IOException {
serverVersion = doReadIdentification(buffer);
if (serverVersion == null) {
@@ -540,75 +406,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
}
- private void sendAuthRequest() throws Exception {
- log.info("Send SSH_MSG_SERVICE_REQUEST for ssh-userauth");
- Buffer buffer = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_REQUEST, 0);
- buffer.putString("ssh-userauth");
- writePacket(buffer);
- }
-
- private void channelOpen(Buffer buffer) throws Exception {
- String type = buffer.getString();
- final int id = buffer.getInt();
- final int rwsize = buffer.getInt();
- final int rmpsize = buffer.getInt();
-
- log.info("Received SSH_MSG_CHANNEL_OPEN {}", type);
-
- if (closing) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
- buf.putString("SSH server is shutting down: " + type);
- buf.putString("");
- writePacket(buf);
- return;
- }
-
- final Channel channel = NamedFactory.Utils.create(getFactoryManager().getChannelFactories(), type);
- if (channel == null) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
- buf.putString("Unsupported channel type: " + type);
- buf.putString("");
- writePacket(buf);
- return;
- }
-
- final int channelId = getNextChannelId();
- channels.put(channelId, channel);
- channel.init(this, channelId);
- channel.open(id, rwsize, rmpsize, buffer).addListener(new SshFutureListener<OpenFuture>() {
- public void operationComplete(OpenFuture future) {
- try {
- if (future.isOpened()) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
- buf.putInt(id);
- buf.putInt(channelId);
- buf.putInt(channel.getLocalWindow().getSize());
- buf.putInt(channel.getLocalWindow().getPacketSize());
- writePacket(buf);
- } else if (future.getException() != null) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- if (future.getException() instanceof OpenChannelException) {
- buf.putInt(((OpenChannelException)future.getException()).getReasonCode());
- buf.putString(future.getException().getMessage());
- } else {
- buf.putInt(0);
- buf.putString("Error opening channel: " + future.getException().getMessage());
- }
- buf.putString("");
- writePacket(buf);
- }
- } catch (IOException e) {
- exceptionCaught(e);
- }
- }
- });
- }
-
public Map<Object, Object> getMetadataMap() {
return metadataMap;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
new file mode 100644
index 0000000..9527d34
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
@@ -0,0 +1,201 @@
+/*
+ * 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.session;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.UserAuth;
+import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.DefaultAuthFuture;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Client side <code>ssh-auth</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClientUserAuthService implements Service {
+
+ public static class Factory implements ServiceFactory {
+
+ public String getName() {
+ return "ssh-userauth";
+ }
+
+ public Service create(Session session) throws IOException {
+ return new ClientUserAuthService(session);
+ }
+ }
+
+ /** Our logger */
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * When !authFuture.isDone() the current authentication
+ */
+ private UserAuth userAuth;
+
+ /**
+ * The AuthFuture that is being used by the current auth request. This encodes the state.
+ * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
+ */
+ private volatile AuthFuture authFuture;
+
+ protected final ClientSessionImpl session;
+ protected final Object lock;
+
+ public ClientUserAuthService(Session s) {
+ if (!(s instanceof ClientSessionImpl)) {
+ throw new IllegalStateException("Client side service used on server side");
+ }
+ session = (ClientSessionImpl) s;
+ lock = session.getLock();
+ // Maintain the current auth status in the authFuture.
+ authFuture = new DefaultAuthFuture(lock);
+ }
+
+ public ClientSessionImpl getSession() {
+ return session;
+ }
+
+ public void start() {
+ synchronized (lock) {
+ log.debug("accepted");
+ // kick start the authentication process by failing the pending auth.
+ this.authFuture.setAuthed(false);
+ }
+ }
+
+ public void process(SshConstants.Message cmd, Buffer buffer) throws Exception {
+ if (this.authFuture.isSuccess()) {
+ throw new IllegalStateException("UserAuth message delivered to authenticated client");
+ } else if (this.authFuture.isDone()) {
+ log.debug("Ignoring random message");
+ // ignore for now; TODO: random packets
+ } else if (cmd == SshConstants.Message.SSH_MSG_USERAUTH_BANNER) {
+ String welcome = buffer.getString();
+ String lang = buffer.getString();
+ log.debug("Welcome banner: {}", welcome);
+ UserInteraction ui = session.getClientFactoryManager().getUserInteraction();
+ if (ui != null) {
+ ui.welcome(welcome);
+ }
+ } else {
+ buffer.rpos(buffer.rpos() - 1);
+ processUserAuth(buffer);
+ }
+ }
+
+ /**
+ * return true if/when ready for auth; false if never ready.
+ * @return server is ready and waiting for auth
+ */
+ private boolean readyForAuth(UserAuth userAuth) {
+ // isDone indicates that the last auth finished and a new one can commence.
+ while (!this.authFuture.isDone()) {
+ log.debug("waiting to send authentication");
+ try {
+ this.authFuture.await();
+ } catch (InterruptedException e) {
+ log.debug("Unexpected interrupt", e);
+ throw new RuntimeException(e);
+ }
+ }
+ if (this.authFuture.isSuccess()) {
+ log.debug("already authenticated");
+ throw new IllegalStateException("Already authenticated");
+ }
+ if (this.authFuture.getException() != null) {
+ log.debug("probably closed", this.authFuture.getException());
+ return false;
+ }
+ if (!this.authFuture.isFailure()) {
+ log.debug("unexpected state");
+ throw new IllegalStateException("Unexpected authentication state");
+ }
+ if (this.userAuth != null) {
+ log.debug("authentication already in progress");
+ throw new IllegalStateException("Authentication already in progress?");
+ }
+ // Set up the next round of authentication. Each round gets a new lock.
+ this.userAuth = userAuth;
+ // The new future !isDone() - i.e., in progress blocking out other waits.
+ this.authFuture = new DefaultAuthFuture(lock);
+ log.debug("ready to try authentication with new lock");
+ return true;
+ }
+
+ /**
+ * execute one step in user authentication.
+ * @param buffer
+ * @throws IOException
+ */
+ private void processUserAuth(Buffer buffer) throws IOException {
+ log.debug("processing {}", userAuth);
+ switch (userAuth.next(buffer)) {
+ case Success:
+ log.debug("succeeded with {}", userAuth);
+ session.setAuthenticated(userAuth.getUsername());
+ session.switchToNextService();
+ // Will wake up anyone sitting in waitFor
+ authFuture.setAuthed(true);
+ break;
+ case Failure:
+ log.debug("failed with {}", userAuth);
+ this.userAuth = null;
+ // Will wake up anyone sitting in waitFor
+ this.authFuture.setAuthed(false);
+ break;
+ case Continued:
+ // Will wake up anyone sitting in waitFor
+ log.debug("continuing with {}", userAuth);
+ break;
+ }
+ }
+
+ public CloseFuture close(boolean immediately) {
+ if (!authFuture.isDone()) {
+ authFuture.setException(new SshException("Session is closed"));
+ }
+ CloseFuture future = new DefaultCloseFuture(lock);
+ future.setClosed();
+ return future;
+ }
+
+ public AuthFuture auth(UserAuth userAuth) throws IOException {
+ log.debug("Trying authentication with {}", userAuth);
+ synchronized (lock) {
+ if (readyForAuth(userAuth)) {
+ processUserAuth(null);
+ }
+ return authFuture;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index eaa1088..450dce4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -59,6 +59,7 @@ public abstract class AbstractFactoryManager implements FactoryManager {
protected TcpipForwarderFactory tcpipForwarderFactory;
protected ForwardingFilter tcpipForwardingFilter;
protected FileSystemFactory fileSystemFactory;
+ protected List<ServiceFactory> serviceFactories;
protected AbstractFactoryManager() {
loadVersion();
@@ -228,4 +229,11 @@ public abstract class AbstractFactoryManager implements FactoryManager {
this.fileSystemFactory = fileSystemFactory;
}
+ public List<ServiceFactory> getServiceFactories() {
+ return serviceFactories;
+ }
+
+ public void setServiceFactories(List<ServiceFactory> serviceFactories) {
+ this.serviceFactories = serviceFactories;
+ }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Channel.java b/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
index 6e2c030..aceaef3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.channel.Window;
import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
/**
@@ -58,7 +59,7 @@ public interface Channel {
CloseFuture close(boolean immediately);
- void init(Session session, int id) throws IOException;
+ void init(ConnectionService service, Session session, int id) throws IOException;
/**
* For a server channel, this method will actually open the channel
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index f5bc47c..86e0155 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -177,4 +177,11 @@ public interface FactoryManager {
*/
FileSystemFactory getFileSystemFactory();
+ /**
+ * Retrieve the list of SSH <code>Service</code> factories.
+ *
+ * @return a list of named <code>Service</code> factories, never <code>null</code>
+ */
+ List<ServiceFactory> getServiceFactories();
+
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/Service.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Service.java b/sshd-core/src/main/java/org/apache/sshd/common/Service.java
new file mode 100644
index 0000000..e3f60b3
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Service.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * See RFC 4253 [SSH-TRANS] and the SSH_MSG_SERVICE_REQUEST packet. Examples include ssh-userauth
+ * and ssh-connection but developers are also free to implement their own custom service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface Service {
+
+ Session getSession();
+
+ // TODO: this is specific to clients
+ void start();
+
+ /**
+ * Service the request.
+ * @param buffer
+ * @throws Exception
+ */
+ void process(SshConstants.Message cmd, Buffer buffer) throws Exception;
+
+ /**
+ * Close the service.
+ * @param immediately
+ *
+ */
+ CloseFuture close(boolean immediately);
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
new file mode 100644
index 0000000..b70b963
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.io.IOException;
+import java.util.List;
+
+public interface ServiceFactory {
+
+ /**
+ * Name of this factory
+ * @return
+ */
+ String getName();
+
+ Service create(Session session) throws IOException;
+
+ /**
+ * Utility class to help using NamedFactories
+ */
+ public static class Utils {
+
+ /**
+ * Create an instance of the specified name by looking up the needed factory
+ * in the list.
+ *
+ * @param factories list of available factories
+ * @param name the factory name to use
+ * @return a newly created object or <code>null</code> if the factory is not in the list
+ */
+ public static Service create(List<ServiceFactory> factories, String name, Session session) throws IOException {
+ if (factories != null) {
+ for (ServiceFactory f : factories) {
+ if (f.getName().equals(name)) {
+ return f.create(session);
+ }
+ }
+ }
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/Session.java
index 52be5cf..cc968e3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Session.java
@@ -31,7 +31,7 @@ import org.apache.sshd.common.util.Buffer;
public interface Session {
public enum State {
- ReceiveKexInit, Kex, ReceiveNewKeys, AuthRequestSent, WaitForAuth, UserAuth, Running, Closed
+ ReceiveKexInit, Kex, ReceiveNewKeys, ServiceRequestSent, WaitForServiceRequest, Running, Closed
}
/**
@@ -135,27 +135,10 @@ public interface Session {
* {@link org.apache.sshd.common.SshException}.
*
* @param t the exception to process
- * @throws IOException
*/
void exceptionCaught(Throwable t);
/**
- * Register a newly created channel with a new unique identifier
- *
- * @param channel the channel to register
- * @return the id of this channel
- * @throws Exception
- */
- int registerChannel(Channel channel) throws Exception;
-
- /**
- * Remove this channel from the list of managed channels
- *
- * @param channel the channel
- */
- void unregisterChannel(Channel channel);
-
- /**
* Add a session |listener|.
*
* @param listener the session listener to add
@@ -170,12 +153,6 @@ public interface Session {
void removeListener(SessionListener listener);
/**
- * Retrieve the tcpip forwarder
- * @return
- */
- TcpipForwarder getTcpipForwarder();
-
- /**
* Type safe key for storage within the user attributes of {@link org.apache.sshd.common.session.AbstractSession}.
* Typically it is used as a static variable that is shared between the producer
* and the consumer. To further restrict access the setting or getting it from
@@ -191,7 +168,7 @@ public interface Session {
* s.setAttribute(MY_KEY, value);
* }
*
- * @param T type of value stored in the attribute.
+ * @param <T> type of value stored in the attribute.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
index c19fb5f..1bf6a45 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
@@ -18,6 +18,8 @@
*/
package org.apache.sshd.common;
+import org.apache.sshd.common.session.ConnectionService;
+
/**
* A factory for creating TcpipForwarder objects for client Port forwarding
*/
@@ -27,9 +29,9 @@ public interface TcpipForwarderFactory {
* Creates the TcpipForwarder to be used for TCP/IP port forwards for
* this ClientSession.
*
- * @param session the Session the connections are forwarded through
+ * @param service the service the connections are forwarded through
* @return the TcpipForwarder that will listen for connections and set up forwarding
*/
- public TcpipForwarder create(Session session);
+ public TcpipForwarder create(ConnectionService service);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
index 95ca72f..05b633a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
@@ -29,6 +29,7 @@ import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.DefaultCloseFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.BufferUtils;
import org.slf4j.Logger;
@@ -48,6 +49,7 @@ public abstract class AbstractChannel implements Channel {
protected final Object lock = new Object();
protected final Window localWindow = new Window(this, null, getClass().getName().contains(".client."), true);
protected final Window remoteWindow = new Window(this, null, getClass().getName().contains(".client."), false);
+ protected ConnectionService service;
protected Session session;
protected int id;
protected int recipient;
@@ -80,7 +82,8 @@ public abstract class AbstractChannel implements Channel {
throw new IllegalStateException();
}
- public void init(Session session, int id) {
+ public void init(ConnectionService service, Session session, int id) {
+ this.service = service;
this.session = session;
this.id = id;
configureWindow();
@@ -101,7 +104,7 @@ public abstract class AbstractChannel implements Channel {
postClose();
closeFuture.setClosed();
notifyStateChanged();
- session.unregisterChannel(AbstractChannel.this);
+ service.unregisterChannel(AbstractChannel.this);
}
});
} else {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
index 640e1a2..45d8612 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
@@ -38,6 +38,7 @@ import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoHandler;
import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.Readable;
import org.slf4j.Logger;
@@ -52,14 +53,16 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTcpipForwarder.class);
+ private final ConnectionService service;
private final Session session;
private final Map<Integer, SshdSocketAddress> localToRemote = new HashMap<Integer, SshdSocketAddress>();
private final Map<Integer, SshdSocketAddress> remoteToLocal = new HashMap<Integer, SshdSocketAddress>();
private final Set<SshdSocketAddress> localForwards = new HashSet<SshdSocketAddress>();
protected IoAcceptor acceptor;
- public DefaultTcpipForwarder(Session session) {
- this.session = session;
+ public DefaultTcpipForwarder(ConnectionService service) {
+ this.service = service;
+ this.session = service.getSession();
}
//
@@ -174,12 +177,12 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
channel = new TcpipClientChannel(TcpipClientChannel.Type.Forwarded, session, null);
}
session.setAttribute(TcpipClientChannel.class, channel);
- this.session.registerChannel(channel);
+ this.service.registerChannel(channel);
channel.open().addListener(new SshFutureListener<OpenFuture>() {
public void operationComplete(OpenFuture future) {
Throwable t = future.getException();
if (t != null) {
- DefaultTcpipForwarder.this.session.unregisterChannel(channel);
+ DefaultTcpipForwarder.this.service.unregisterChannel(channel);
channel.close(false);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
index 9de1d4a..a732d7e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
@@ -21,6 +21,7 @@ package org.apache.sshd.common.forward;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.TcpipForwarder;
import org.apache.sshd.common.TcpipForwarderFactory;
+import org.apache.sshd.common.session.ConnectionService;
/**
* The default {link TcpipForwarderFactory} implementation.
@@ -30,8 +31,8 @@ import org.apache.sshd.common.TcpipForwarderFactory;
*/
public class DefaultTcpipForwarderFactory implements TcpipForwarderFactory
{
- public TcpipForwarder create( Session session )
+ public TcpipForwarder create( ConnectionService service )
{
- return new DefaultTcpipForwarder( session );
+ return new DefaultTcpipForwarder( service );
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
index 6ba0e7d..2e98811 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
@@ -98,7 +98,7 @@ public class TcpipServerChannel extends AbstractServerChannel {
SshdSocketAddress address = null;
switch (type) {
case Direct: address = new SshdSocketAddress(hostToConnect, portToConnect); break;
- case Forwarded: address = getSession().getTcpipForwarder().getForwardedPort(portToConnect); break;
+ case Forwarded: address = service.getTcpipForwarder().getForwardedPort(portToConnect); break;
}
final ForwardingFilter filter = getSession().getFactoryManager().getTcpipForwardingFilter();
if (address == null || filter == null || !filter.canConnect(address, getSession())) {