[SSHD-700 Added support for Secure Shell Authentication Agent Protocol Draft 02
* See https://tools.ietf.org/html/draft-ietf-secsh-agent-02 Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/dd299ae7 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/dd299ae7 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/dd299ae7 Branch: refs/heads/master Commit: dd299ae7aca4d1073a97756372ab0a1af851d852 Parents: 008f1b6 Author: Lyor Goldstein <[email protected]> Authored: Sat Oct 1 16:09:26 2016 +0300 Committer: Lyor Goldstein <[email protected]> Committed: Sat Oct 1 16:09:26 2016 +0300 ---------------------------------------------------------------------- .../org/apache/sshd/agent/SshAgentFactory.java | 14 +++++- .../org/apache/sshd/agent/SshAgentServer.java | 11 ++++- .../sshd/agent/local/AgentForwardedChannel.java | 5 +-- .../sshd/agent/local/AgentServerProxy.java | 7 ++- .../local/ChannelAgentForwardingFactory.java | 13 ++++-- .../sshd/agent/local/LocalAgentFactory.java | 10 ++++- .../sshd/agent/local/ProxyAgentFactory.java | 7 +-- .../sshd/agent/unix/AgentForwardedChannel.java | 4 +- .../sshd/agent/unix/AgentServerProxy.java | 3 +- .../org/apache/sshd/agent/unix/AprLibrary.java | 6 +-- .../unix/ChannelAgentForwardingFactory.java | 13 ++++-- .../sshd/agent/unix/UnixAgentFactory.java | 46 ++++++++++++++------ .../java/org/apache/sshd/client/SshClient.java | 15 ++++--- .../channel/PtyCapableChannelSession.java | 5 ++- .../sshd/server/channel/ChannelSession.java | 31 ++++++------- .../sshd/server/forward/ForwardingFilter.java | 6 ++- .../forward/StaticDecisionForwardingFilter.java | 8 ++-- .../java/org/apache/sshd/agent/AgentTest.java | 39 +++++++++-------- .../sshd/common/ForwardingFilterTest.java | 4 +- 19 files changed, 158 insertions(+), 89 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/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 8176230..551d14d 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 @@ -19,6 +19,7 @@ package org.apache.sshd.agent; import java.io.IOException; +import java.util.List; import org.apache.sshd.common.FactoryManager; import org.apache.sshd.common.NamedFactory; @@ -29,15 +30,24 @@ import org.apache.sshd.common.session.ConnectionService; * The <code>SshAgentFactory</code> is used to communicate with an SshAgent. */ public interface SshAgentFactory { + /** + * Value that can be set in order to control the type of authentication + * channel being requested when forwarding a PTY session. If not defined + * then {@link #DEFAULT_PROXY_AUTH_CHANNEL_TYPE} is used + */ + String PROXY_AUTH_CHANNEL_TYPE = "ssh-agent-factory-proxy-auth-channel-type"; + // see also https://tools.ietf.org/html/draft-ietf-secsh-agent-02 + String DEFAULT_PROXY_AUTH_CHANNEL_TYPE = "[email protected]"; /** * The channels are requested by the ssh server when forwarding a client request. * The channel will receive agent requests and need to forward them to the agent, * either local or through another proxy. * - * @return The (named) channel factory used to create channels on the client side + * @param manager The {@link FactoryManager} through which the request is made + * @return The (named) channel factories used to create channels on the client side */ - NamedFactory<Channel> getChannelForwardingFactory(); + List<NamedFactory<Channel>> getChannelForwardingFactories(FactoryManager manager); /** * Create an SshAgent that can be used on the client side by the authentication http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentServer.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentServer.java b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentServer.java index 1cb5cb9..4ff5de3 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentServer.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentServer.java @@ -25,7 +25,7 @@ public interface SshAgentServer extends Channel { /** * Value that can be set on the {@link org.apache.sshd.common.FactoryManager} - * to configure the channel open timeout value (millis). If not specified + * or the session to configure the channel open timeout value (millis). If not specified * then {@link #DEFAULT_CHANNEL_OPEN_TIMEOUT} value is used */ String CHANNEL_OPEN_TIMEOUT_PROP = "ssh-agent-server-channel-open-timeout"; @@ -33,6 +33,15 @@ public interface SshAgentServer extends Channel { long DEFAULT_CHANNEL_OPEN_TIMEOUT = TimeUnit.SECONDS.toMillis(30L); /** + * Value used to configure the type of proxy forwarding channel to be + * used. If not specified, then {@link #DEFAULT_PROXY_CHANNEL_TYPE} + * is used + */ + String PROXY_CHANNEL_TYPE = "ssh-agent-server-channel-proxy-type"; + // see also https://tools.ietf.org/html/draft-ietf-secsh-agent-02 + String DEFAULT_PROXY_CHANNEL_TYPE = "[email protected]"; + + /** * @return Agent server identifier */ String getId(); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentForwardedChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentForwardedChannel.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentForwardedChannel.java index 18ae890..355856a 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentForwardedChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentForwardedChannel.java @@ -36,12 +36,11 @@ import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; public class AgentForwardedChannel extends AbstractClientChannel { - private final Queue<Buffer> messages = new ArrayBlockingQueue<>(10); private final Buffer receiveBuffer = new ByteArrayBuffer(); - public AgentForwardedChannel() { - super("[email protected]"); + public AgentForwardedChannel(String channelType) { + super(channelType); } public SshAgent getAgent() { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/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 a21a976..967fc5a 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 @@ -26,6 +26,7 @@ import org.apache.sshd.agent.SshAgent; import org.apache.sshd.agent.SshAgentServer; import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.session.ConnectionService; +import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.logging.AbstractLoggingBean; @@ -44,7 +45,9 @@ public class AgentServerProxy extends AbstractLoggingBean implements SshAgentSer public SshAgent createClient() throws IOException { try { - AgentForwardedChannel channel = new AgentForwardedChannel(); + Session session = this.service.getSession(); + String channelType = PropertyResolverUtils.getStringProperty(session, PROXY_CHANNEL_TYPE, DEFAULT_PROXY_CHANNEL_TYPE); + AgentForwardedChannel channel = new AgentForwardedChannel(channelType); this.service.registerChannel(channel); channel.open().verify(PropertyResolverUtils.getLongProperty(channel, CHANNEL_OPEN_TIMEOUT_PROP, DEFAULT_CHANNEL_OPEN_TIMEOUT)); return channel.getAgent(); @@ -59,7 +62,7 @@ public class AgentServerProxy extends AbstractLoggingBean implements SshAgentSer throw (IOException) t; } - throw (IOException) new IOException("Failed (" + t.getClass().getSimpleName() + ") to create client: " + t.getMessage(), t); + throw new IOException("Failed (" + t.getClass().getSimpleName() + ") to create client: " + t.getMessage(), t); } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwardingFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwardingFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwardingFactory.java index 2fed297..1396b61 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwardingFactory.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwardingFactory.java @@ -21,20 +21,25 @@ package org.apache.sshd.agent.local; import org.apache.sshd.common.channel.Channel; import org.apache.sshd.common.channel.ChannelFactory; +import org.apache.sshd.common.util.ValidateUtils; /** * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ public class ChannelAgentForwardingFactory implements ChannelFactory { - public static final ChannelAgentForwardingFactory INSTANCE = new ChannelAgentForwardingFactory(); + public static final ChannelAgentForwardingFactory OPENSSH = new ChannelAgentForwardingFactory("[email protected]"); + // see https://tools.ietf.org/html/draft-ietf-secsh-agent-02 + public static final ChannelAgentForwardingFactory IETF = new ChannelAgentForwardingFactory("auth-agent"); - public ChannelAgentForwardingFactory() { - super(); + private final String name; + + public ChannelAgentForwardingFactory(String name) { + this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No channel factory name specified"); } @Override public String getName() { - return "[email protected]"; + return name; } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/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 8ff02a9..0ad3664 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 @@ -19,6 +19,9 @@ package org.apache.sshd.agent.local; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.apache.sshd.agent.SshAgent; import org.apache.sshd.agent.SshAgentFactory; @@ -30,6 +33,9 @@ import org.apache.sshd.common.channel.Channel; import org.apache.sshd.common.session.ConnectionService; public class LocalAgentFactory implements SshAgentFactory { + public static final List<NamedFactory<Channel>> DEFAULT_FORWARDING_CHANNELS = + Collections.unmodifiableList( + Arrays.<NamedFactory<Channel>>asList(ChannelAgentForwardingFactory.OPENSSH, ChannelAgentForwardingFactory.IETF)); private final SshAgent agent; @@ -46,8 +52,8 @@ public class LocalAgentFactory implements SshAgentFactory { } @Override - public NamedFactory<Channel> getChannelForwardingFactory() { - return ChannelAgentForwardingFactory.INSTANCE; + public List<NamedFactory<Channel>> getChannelForwardingFactories(FactoryManager manager) { + return DEFAULT_FORWARDING_CHANNELS; } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/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 39edf4e..07aae54 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 @@ -19,6 +19,7 @@ package org.apache.sshd.agent.local; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -26,6 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.sshd.agent.SshAgent; import org.apache.sshd.agent.SshAgentFactory; import org.apache.sshd.agent.SshAgentServer; +import org.apache.sshd.agent.unix.UnixAgentFactory; import org.apache.sshd.common.FactoryManager; import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.PropertyResolverUtils; @@ -39,7 +41,6 @@ import org.apache.sshd.server.session.ServerSession; * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ public class ProxyAgentFactory implements SshAgentFactory { - private final Map<String, AgentServerProxy> proxies = new ConcurrentHashMap<>(); public ProxyAgentFactory() { @@ -47,8 +48,8 @@ public class ProxyAgentFactory implements SshAgentFactory { } @Override - public NamedFactory<Channel> getChannelForwardingFactory() { - return ChannelAgentForwardingFactory.INSTANCE; + public List<NamedFactory<Channel>> getChannelForwardingFactories(FactoryManager manager) { + return UnixAgentFactory.DEFAULT_FORWARDING_CHANNELS; } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java index 88fae33..01888af 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java @@ -33,8 +33,8 @@ public class AgentForwardedChannel extends AbstractClientChannel implements Runn private final long socket; - public AgentForwardedChannel(long socket) { - super("[email protected]"); + public AgentForwardedChannel(long socket, String channelType) { + super(channelType); this.socket = socket; } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/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 62b8e8f..3a8fa8c 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 @@ -103,7 +103,8 @@ public class AgentServerProxy extends AbstractLoggingBean implements SshAgentSer Session session = AgentServerProxy.this.service.getSession(); Socket.timeoutSet(clientSock, PropertyResolverUtils.getIntProperty(session, AUTH_SOCKET_TIMEOUT, DEFAULT_AUTH_SOCKET_TIMEOUT)); - AgentForwardedChannel channel = new AgentForwardedChannel(clientSock); + String channelType = PropertyResolverUtils.getStringProperty(session, PROXY_CHANNEL_TYPE, DEFAULT_PROXY_CHANNEL_TYPE); + AgentForwardedChannel channel = new AgentForwardedChannel(clientSock, channelType); AgentServerProxy.this.service.registerChannel(channel); channel.open().verify(PropertyResolverUtils.getLongProperty(session, CHANNEL_OPEN_TIMEOUT_PROP, DEFAULT_CHANNEL_OPEN_TIMEOUT)); } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/agent/unix/AprLibrary.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AprLibrary.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AprLibrary.java index d77e2c3..34940ab 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AprLibrary.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AprLibrary.java @@ -41,7 +41,7 @@ import org.apache.tomcat.jni.Pool; * * @author <a href="http://mina.apache.org">Apache MINA Project</a> */ -final class AprLibrary { +public final class AprLibrary { // is APR library was initialized (load of native libraries) private static AprLibrary library; @@ -76,7 +76,7 @@ final class AprLibrary { * * @return the current APR library singleton */ - static synchronized AprLibrary getInstance() { + public static synchronized AprLibrary getInstance() { if (!isInitialized()) { initialize(); } @@ -98,7 +98,7 @@ final class AprLibrary { * * @return true if the Library is initialized, false otherwise */ - static synchronized boolean isInitialized() { + public static synchronized boolean isInitialized() { return library != null; } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwardingFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwardingFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwardingFactory.java index dd04036..4f31f41 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwardingFactory.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwardingFactory.java @@ -22,21 +22,26 @@ import java.util.concurrent.ExecutorService; import org.apache.sshd.common.channel.Channel; import org.apache.sshd.common.channel.ChannelFactory; +import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.threads.ExecutorServiceCarrier; /** * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ public class ChannelAgentForwardingFactory implements ChannelFactory, ExecutorServiceCarrier { - public static final ChannelAgentForwardingFactory INSTANCE = new ChannelAgentForwardingFactory(); + public static final ChannelAgentForwardingFactory OPENSSH = new ChannelAgentForwardingFactory("[email protected]"); + // see https://tools.ietf.org/html/draft-ietf-secsh-agent-02 + public static final ChannelAgentForwardingFactory IETF = new ChannelAgentForwardingFactory("auth-agent"); - public ChannelAgentForwardingFactory() { - super(); + private final String name; + + public ChannelAgentForwardingFactory(String name) { + this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No channel factory name specified"); } @Override public String getName() { - return "[email protected]"; + return name; } @Override // user can override to provide an alternative http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/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 16fc4bd..d838d32 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 @@ -19,6 +19,10 @@ package org.apache.sshd.agent.unix; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.concurrent.ExecutorService; import org.apache.sshd.agent.SshAgent; @@ -26,6 +30,7 @@ import org.apache.sshd.agent.SshAgentFactory; import org.apache.sshd.agent.SshAgentServer; import org.apache.sshd.common.FactoryManager; import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.NamedResource; import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshException; import org.apache.sshd.common.channel.Channel; @@ -40,20 +45,12 @@ import org.apache.sshd.server.session.ServerSession; * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ public class UnixAgentFactory implements SshAgentFactory, ExecutorServiceConfigurer { + public static final List<NamedFactory<Channel>> DEFAULT_FORWARDING_CHANNELS = + Collections.unmodifiableList( + Arrays.<NamedFactory<Channel>>asList(ChannelAgentForwardingFactory.OPENSSH, ChannelAgentForwardingFactory.IETF)); + private ExecutorService executor; private boolean shutdownExecutor; - private final NamedFactory<Channel> factory = new ChannelAgentForwardingFactory() { - @Override - public ExecutorService getExecutorService() { - return UnixAgentFactory.this.getExecutorService(); - } - - @Override - public boolean isShutdownOnExit() { - return UnixAgentFactory.this.isShutdownOnExit(); - } - - }; public UnixAgentFactory() { super(); @@ -85,8 +82,29 @@ public class UnixAgentFactory implements SshAgentFactory, ExecutorServiceConfigu } @Override - public NamedFactory<Channel> getChannelForwardingFactory() { - return factory; + public List<NamedFactory<Channel>> getChannelForwardingFactories(FactoryManager manager) { + final ExecutorServiceConfigurer configurer = this; + return Collections.unmodifiableList(new ArrayList<NamedFactory<Channel>>(DEFAULT_FORWARDING_CHANNELS.size()) { + // Not serializing it + private static final long serialVersionUID = 1L; + + { + for (NamedResource r : DEFAULT_FORWARDING_CHANNELS) { + String channelType = r.getName(); + add(new ChannelAgentForwardingFactory(channelType) { + @Override + public ExecutorService getExecutorService() { + return configurer.getExecutorService(); + } + + @Override + public boolean isShutdownOnExit() { + return configurer.isShutdownOnExit(); + } + }); + } + } + }); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java index 17f8bb4..f5df111 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java @@ -383,21 +383,24 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa // if no client identities override use the default KeyPairProvider defaultIdentities = getKeyPairProvider(); if (defaultIdentities == null) { - setKeyPairProvider(new DefaultClientIdentitiesWatcher( - this::getClientIdentityLoader, - this::getFilePasswordProvider)); + setKeyPairProvider(new DefaultClientIdentitiesWatcher(this::getClientIdentityLoader, this::getFilePasswordProvider)); } // Register the additional agent forwarding channel if needed SshAgentFactory agentFactory = getAgentFactory(); if (agentFactory != null) { + List<NamedFactory<Channel>> forwarders = + ValidateUtils.checkNotNullAndNotEmpty( + agentFactory.getChannelForwardingFactories(this), "No agent channel forwarding factories for %s", agentFactory); List<NamedFactory<Channel>> factories = getChannelFactories(); if (GenericUtils.isEmpty(factories)) { - factories = new ArrayList<>(); + factories = forwarders; } else { - factories = new ArrayList<>(factories); + // create a copy in case un-modifiable original + factories = new ArrayList<>(factories.size() + forwarders.size()); + factories.addAll(factories); + factories.addAll(forwarders); } - factories.add(ValidateUtils.checkNotNull(agentFactory.getChannelForwardingFactory(), "No agent channel forwarding factory for %s", agentFactory)); setChannelFactories(factories); } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java index 669ae0d..6bcdf53 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java @@ -24,6 +24,8 @@ import java.util.EnumMap; import java.util.LinkedHashMap; import java.util.Map; +import org.apache.sshd.agent.SshAgentFactory; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.channel.PtyMode; import org.apache.sshd.common.channel.SttySupport; @@ -225,9 +227,10 @@ public class PtyCapableChannelSession extends ChannelSession { log.debug("doOpenPty({}) Send agent forwarding request", this); } + String channelType = PropertyResolverUtils.getStringProperty(session, SshAgentFactory.PROXY_AUTH_CHANNEL_TYPE, SshAgentFactory.DEFAULT_PROXY_AUTH_CHANNEL_TYPE); Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, Long.SIZE); buffer.putInt(getRecipient()); - buffer.putString("[email protected]"); + buffer.putString(channelType); buffer.putBoolean(false); // want-reply writePacket(buffer); } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java index 78d32fa..65fda21 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java @@ -318,10 +318,11 @@ public class ChannelSession extends AbstractServerChannel { } return RequestHandler.Result.ReplyFailure; } + case "auth-agent-req": // see https://tools.ietf.org/html/draft-ietf-secsh-agent-02 case "[email protected]": - return handleAgentForwarding(buffer, wantReply); + return handleAgentForwarding(requestType, buffer, wantReply); case "x11-req": - return handleX11Forwarding(buffer, wantReply); + return handleX11Forwarding(requestType, buffer, wantReply); default: return super.handleInternalRequest(requestType, wantReply, buffer); } @@ -695,23 +696,23 @@ public class ChannelSession extends AbstractServerChannel { return v != null ? v.intValue() : 0; } - protected RequestHandler.Result handleAgentForwarding(Buffer buffer, boolean wantReply) throws IOException { + protected RequestHandler.Result handleAgentForwarding(String requestType, Buffer buffer, boolean wantReply) throws IOException { ServerSession session = getServerSession(); FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No session factory manager"); ForwardingFilter filter = manager.getTcpipForwardingFilter(); SshAgentFactory factory = manager.getAgentFactory(); try { - if ((factory == null) || (filter == null) || (!filter.canForwardAgent(session))) { + if ((factory == null) || (filter == null) || (!filter.canForwardAgent(session, requestType))) { if (log.isDebugEnabled()) { - log.debug("handleAgentForwarding(" + this + ")[haveFactory=" + (factory != null) + ",haveFilter=" + (filter != null) + "] filtered out"); + log.debug("handleAgentForwarding(" + this + ")[haveFactory=" + (factory != null) + ",haveFilter=" + (filter != null) + "] filtered out request=" + requestType); } return RequestHandler.Result.ReplyFailure; } } catch (Error e) { - log.warn("handleAgentForwarding({}) failed ({}) to consult forwarding filter: {}", - this, e.getClass().getSimpleName(), e.getMessage()); + log.warn("handleAgentForwarding({}) failed ({}) to consult forwarding filter for '{}': {}", + this, e.getClass().getSimpleName(), requestType, e.getMessage()); if (log.isDebugEnabled()) { - log.debug("handleAgentForwarding(" + this + ") filter consultation failure details", e); + log.debug("handleAgentForwarding(" + this + ")[" + requestType + "] filter consultation failure details", e); } throw new RuntimeSshException(e); } @@ -729,7 +730,7 @@ public class ChannelSession extends AbstractServerChannel { return RequestHandler.Result.ReplySuccess; } - protected RequestHandler.Result handleX11Forwarding(Buffer buffer, boolean wantReply) throws IOException { + protected RequestHandler.Result handleX11Forwarding(String requestType, Buffer buffer, boolean wantReply) throws IOException { ServerSession session = getServerSession(); boolean singleConnection = buffer.getBoolean(); String authProtocol = buffer.getString(); @@ -739,18 +740,18 @@ public class ChannelSession extends AbstractServerChannel { FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager"); ForwardingFilter filter = manager.getTcpipForwardingFilter(); try { - if ((filter == null) || (!filter.canForwardX11(session))) { + if ((filter == null) || (!filter.canForwardX11(session, requestType))) { if (log.isDebugEnabled()) { - log.debug("handleX11Forwarding({}) single={}, protocol={}, cookie={}, screen={}, filter={}: filtered", - this, singleConnection, authProtocol, authCookie, screenId, filter); + log.debug("handleX11Forwarding({}) single={}, protocol={}, cookie={}, screen={}, filter={}: filtered request={}", + this, singleConnection, authProtocol, authCookie, screenId, filter, requestType); } return RequestHandler.Result.ReplyFailure; } } catch (Error e) { - log.warn("handleX11Forwarding({}) failed ({}) to consult forwarding filter: {}", - this, e.getClass().getSimpleName(), e.getMessage()); + log.warn("handleX11Forwarding({}) failed ({}) to consult forwarding filter for '{}': {}", + this, e.getClass().getSimpleName(), requestType, e.getMessage()); if (log.isDebugEnabled()) { - log.debug("handleX11Forwarding(" + this + ") filter consultation failure details", e); + log.debug("handleX11Forwarding(" + this + ")[" + requestType + "] filter consultation failure details", e); } throw new RuntimeSshException(e); } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java index 09bacab..6c94581 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java @@ -45,9 +45,10 @@ public interface ForwardingFilter { * </p> * * @param session The {@link Session} requesting permission to forward the agent. + * @param requestType The request type string that triggered this call * @return true if the agent forwarding is permitted, false if denied. */ - boolean canForwardAgent(Session session); + boolean canForwardAgent(Session session, String requestType); /** * <p> @@ -61,9 +62,10 @@ public interface ForwardingFilter { * </p> * * @param session The {@link Session} requesting permission to forward X11 connections. + * @param requestType The request type string that triggered this call * @return true if the X11 forwarding is permitted, false if denied. */ - boolean canForwardX11(Session session); + boolean canForwardX11(Session session, String requestType); /** * <p> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/main/java/org/apache/sshd/server/forward/StaticDecisionForwardingFilter.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/StaticDecisionForwardingFilter.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/StaticDecisionForwardingFilter.java index a4a46fb..00ef488 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/forward/StaticDecisionForwardingFilter.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/StaticDecisionForwardingFilter.java @@ -41,13 +41,13 @@ public class StaticDecisionForwardingFilter extends AbstractLoggingBean implemen } @Override - public boolean canForwardAgent(Session session) { - return checkAcceptance("[email protected]", session, SshdSocketAddress.LOCALHOST_ADDRESS); + public boolean canForwardAgent(Session session, String requestType) { + return checkAcceptance(requestType, session, SshdSocketAddress.LOCALHOST_ADDRESS); } @Override - public boolean canForwardX11(Session session) { - return checkAcceptance("x11-req", session, SshdSocketAddress.LOCALHOST_ADDRESS); + public boolean canForwardX11(Session session, String requestType) { + return checkAcceptance(requestType, session, SshdSocketAddress.LOCALHOST_ADDRESS); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java index e27b505..b846df6 100644 --- a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java @@ -31,6 +31,7 @@ import org.apache.sshd.agent.local.LocalAgentFactory; import org.apache.sshd.agent.local.ProxyAgentFactory; import org.apache.sshd.agent.unix.AgentClient; import org.apache.sshd.agent.unix.AgentServer; +import org.apache.sshd.agent.unix.AprLibrary; import org.apache.sshd.client.SshClient; import org.apache.sshd.client.channel.ChannelShell; import org.apache.sshd.client.session.ClientSession; @@ -46,6 +47,7 @@ import org.apache.sshd.util.test.EchoShell; import org.apache.sshd.util.test.EchoShellFactory; import org.apache.sshd.util.test.Utils; import org.junit.Assume; +import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; @@ -56,25 +58,29 @@ public class AgentTest extends BaseTestSupport { super(); } - @Test - public void testAgentServer() throws Exception { + @BeforeClass + public static void checkTestAssumptions() { // TODO: revisit this test to work without BC Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered()); + AprLibrary library = null; + try { + library = AprLibrary.getInstance(); + } catch (RuntimeException e) { + Throwable cause = e.getCause(); + if (cause instanceof UnsatisfiedLinkError) { + library = null; + } else { + throw e; + } + } + Assume.assumeTrue("Native library N/A", library != null); + } + + @Test + public void testAgentServer() throws Exception { try (AgentServer agent = new AgentServer()) { - String authSocket; - try { - authSocket = agent.start(); - } catch (RuntimeException e) { - Throwable cause = e.getCause(); - if (cause instanceof UnsatisfiedLinkError) { - // the native library is not available, so these tests should be skipped - authSocket = null; - } else { - throw e; - } - } - Assume.assumeTrue("Native library N/A", authSocket != null); + String authSocket = agent.start(); try (SshAgent client = new AgentClient(authSocket)) { List<Pair<PublicKey, String>> keys = client.getIdentities(); @@ -100,9 +106,6 @@ public class AgentTest extends BaseTestSupport { @Test @SuppressWarnings("checkstyle:nestedtrydepth") public void testAgentForwarding() throws Exception { - // TODO: revisit this test to work without BC - Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered()); - TestEchoShellFactory shellFactory = new TestEchoShellFactory(); ProxyAgentFactory agentFactory = new ProxyAgentFactory(); LocalAgentFactory localAgentFactory = new LocalAgentFactory(); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/dd299ae7/sshd-core/src/test/java/org/apache/sshd/common/ForwardingFilterTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/ForwardingFilterTest.java b/sshd-core/src/test/java/org/apache/sshd/common/ForwardingFilterTest.java index 2c3531a..38e3443 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/ForwardingFilterTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/ForwardingFilterTest.java @@ -71,8 +71,8 @@ public class ForwardingFilterTest extends BaseTestSupport { assertEquals("Mismatched acceptance status", expected, filter.isAccepted()); Session session = Mockito.mock(Session.class); - assertEquals("Mismatched 'canForwardAgent' result", expected, filter.canForwardAgent(session)); - assertEquals("Mismatched 'canForwardX11' result", expected, filter.canForwardX11(session)); + assertEquals("Mismatched 'canForwardAgent' result", expected, filter.canForwardAgent(session, "auth-agent-req")); + assertEquals("Mismatched 'canForwardX11' result", expected, filter.canForwardX11(session, "x11-req")); assertEquals("Mismatched 'canListen' result", expected, filter.canListen(SshdSocketAddress.LOCALHOST_ADDRESS, session)); for (ForwardingFilter.Type t : ForwardingFilter.Type.VALUES) {
