You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/11/26 06:33:04 UTC
[03/10] mina-sshd git commit: [SSHD-599] Allow per-session override
of KEX and authentication related configuration
[SSHD-599] Allow per-session override of KEX and authentication related configuration
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/e9dd7f47
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/e9dd7f47
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/e9dd7f47
Branch: refs/heads/master
Commit: e9dd7f4757556bc5e4464647b259fe8a6cdd0b24
Parents: f839083
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Thu Nov 26 07:19:03 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Thu Nov 26 07:19:03 2015 +0200
----------------------------------------------------------------------
.../client/ClientAuthenticationManager.java | 76 ++++
.../sshd/client/ClientFactoryManager.java | 59 +--
.../java/org/apache/sshd/client/SshClient.java | 107 ++++--
.../auth/UserAuthKeyboardInteractive.java | 12 +-
.../sshd/client/auth/UserAuthPassword.java | 8 +-
.../sshd/client/auth/UserAuthPublicKey.java | 43 ++-
.../sshd/client/auth/UserInteraction.java | 73 ++--
.../client/auth/pubkey/KeyPairIdentity.java | 6 +-
.../keys/BuiltinClientIdentitiesWatcher.java | 14 +
.../config/keys/ClientIdentitiesWatcher.java | 32 +-
.../config/keys/ClientIdentityFileWatcher.java | 30 +-
.../keys/DefaultClientIdentitiesWatcher.java | 19 +
.../org/apache/sshd/client/kex/DHGClient.java | 4 +-
.../org/apache/sshd/client/kex/DHGEXClient.java | 4 +-
.../client/session/AbstractClientSession.java | 378 +++++++++++++++++++
.../sshd/client/session/ClientSession.java | 19 +-
.../sshd/client/session/ClientSessionImpl.java | 337 +----------------
.../client/session/ClientUserAuthService.java | 57 ++-
.../sshd/common/AbstractFactoryManager.java | 73 +---
.../org/apache/sshd/common/FactoryManager.java | 43 +--
.../auth/AbstractUserAuthMethodFactory.java | 5 +
.../common/kex/AbstractKexFactoryManager.java | 137 +++++++
.../sshd/common/kex/KexFactoryManager.java | 75 ++++
.../keyprovider/KeyPairProviderHolder.java | 1 +
.../sshd/common/session/AbstractSession.java | 49 ++-
.../common/session/AbstractSessionFactory.java | 7 -
.../org/apache/sshd/common/session/Session.java | 4 +-
.../apache/sshd/common/util/GenericUtils.java | 20 +
.../org/apache/sshd/common/util/Supplier.java | 29 ++
.../server/ServerAuthenticationManager.java | 166 ++++++++
.../sshd/server/ServerFactoryManager.java | 68 +---
.../java/org/apache/sshd/server/SshServer.java | 58 +--
.../auth/UserAuthKeyboardInteractive.java | 7 +-
.../sshd/server/auth/UserAuthPassword.java | 6 +-
.../sshd/server/auth/UserAuthPublicKey.java | 12 +-
.../sshd/server/auth/gss/UserAuthGSS.java | 32 +-
...DefaultKeyboardInteractiveAuthenticator.java | 8 +-
.../KeyboardInteractiveAuthenticator.java | 20 +
.../org/apache/sshd/server/kex/DHGEXServer.java | 3 +-
.../org/apache/sshd/server/kex/DHGServer.java | 4 +-
.../server/session/AbstractServerSession.java | 107 ++++++
.../sshd/server/session/ServerSession.java | 3 +-
.../sshd/server/session/ServerSessionImpl.java | 33 +-
.../server/session/ServerUserAuthService.java | 43 ++-
.../java/org/apache/sshd/WelcomeBannerTest.java | 5 +
.../sshd/client/ClientSessionListenerTest.java | 188 +++++++++
.../java/org/apache/sshd/client/ClientTest.java | 21 +-
.../hosts/HostConfigEntryResolverTest.java | 7 +-
.../client/session/ClientSessionImplTest.java | 40 ++
.../sshd/common/auth/AuthenticationTest.java | 15 +
.../deprecated/ClientUserAuthServiceOld.java | 6 +-
.../deprecated/UserAuthKeyboardInteractive.java | 4 +-
.../sshd/deprecated/UserAuthPublicKey.java | 9 +-
.../sshd/server/ServerSessionListenerTest.java | 259 +++++++++++++
.../java/org/apache/sshd/server/ServerTest.java | 72 +---
55 files changed, 1988 insertions(+), 929 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/ClientAuthenticationManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientAuthenticationManager.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientAuthenticationManager.java
new file mode 100644
index 0000000..de41b9a
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientAuthenticationManager.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.sshd.client.auth.UserAuth;
+import org.apache.sshd.client.auth.UserInteraction;
+import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
+import org.apache.sshd.common.NamedFactory;
+
+/**
+ * Holds information required for the client to perform authentication with the server
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ClientAuthenticationManager {
+
+ /**
+ * Ordered comma separated list of authentications methods.
+ * Authentications methods accepted by the server will be tried in the given order.
+ * If not configured or {@code null}/empty, then the session's {@link #getUserAuthFactories()}
+ * is used as-is
+ */
+ String PREFERRED_AUTHS = "preferred-auths";
+
+ /**
+ * Specifies the number of interactive prompts before giving up.
+ * The argument to this keyword must be an integer.
+ */
+ String PASSWORD_PROMPTS = "password-prompts";
+
+ /**
+ * Default value for {@link #PASSWORD_PROMPTS} if none configured
+ */
+ int DEFAULT_PASSWORD_PROMPTS = 3;
+
+ /**
+ * Retrieve the server key verifier to be used to check the key when connecting
+ * to an SSH server.
+ *
+ * @return the {@link ServerKeyVerifier} to use - never {@code null}
+ */
+ ServerKeyVerifier getServerKeyVerifier();
+ void setServerKeyVerifier(ServerKeyVerifier serverKeyVerifier);
+
+ /**
+ * @return A {@link UserInteraction} object to communicate with the user
+ * (may be {@code null} to indicate that no such communication is allowed)
+ */
+ UserInteraction getUserInteraction();
+ void setUserInteraction(UserInteraction userInteraction);
+
+ /**
+ * @return a {@link List} of {@link UserAuth} {@link NamedFactory}-ies - never
+ * {@code null}/empty
+ */
+ List<NamedFactory<UserAuth>> getUserAuthFactories();
+ void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories);
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
index 11000d2..c9337e5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
@@ -18,15 +18,9 @@
*/
package org.apache.sshd.client;
-import java.util.List;
-
-import org.apache.sshd.client.auth.UserAuth;
-import org.apache.sshd.client.auth.UserInteraction;
import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
import org.apache.sshd.client.config.keys.ClientIdentityLoader;
-import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
/**
@@ -35,12 +29,12 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider;
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public interface ClientFactoryManager extends FactoryManager {
-
+public interface ClientFactoryManager extends FactoryManager, ClientAuthenticationManager {
/**
* Key used to set the heartbeat interval in milliseconds (0 to disable = default)
*/
String HEARTBEAT_INTERVAL = "hearbeat-interval";
+
/**
* Default value for {@link #HEARTBEAT_INTERVAL} if none configured
*/
@@ -50,30 +44,13 @@ public interface ClientFactoryManager extends FactoryManager {
* Key used to check the heartbeat request that should be sent to the server
*/
String HEARTBEAT_REQUEST = "heartbeat-request";
+
/**
* Default value for {@link ClientFactoryManager#HEARTBEAT_REQUEST} is none configured
*/
String DEFAULT_KEEP_ALIVE_HEARTBEAT_STRING = "keepalive@sshd.apache.org";
/**
- * Ordered comma separated list of authentications methods.
- * Authentications methods accepted by the server will be tried in the given order.
- * If not configured or {@code null}/empty, then the session's {@link #getUserAuthFactories()}
- * is used as-is
- */
- String PREFERRED_AUTHS = "preferred-auths";
-
- /**
- * Specifies the number of interactive prompts before giving up.
- * The argument to this keyword must be an integer.
- */
- String PASSWORD_PROMPTS = "password-prompts";
- /**
- * Default value for {@link #PASSWORD_PROMPTS} if none configured
- */
- int DEFAULT_PASSWORD_PROMPTS = 3;
-
- /**
* Whether to ignore invalid identities files when pre-initializing
* the client session
* @see ClientIdentityLoader#isValidLocation(String)
@@ -86,40 +63,24 @@ public interface ClientFactoryManager extends FactoryManager {
boolean DEFAULT_IGNORE_INVALID_IDENTITIES = true;
/**
- * Retrieve the server key verifier to be used to check the key when connecting
- * to an ssh server.
- *
- * @return the server key verifier to use
- */
- ServerKeyVerifier getServerKeyVerifier();
-
- /**
- * @return A {@link UserInteraction} object to communicate with the user
- * (may be {@code null} to indicate that no such communication is allowed)
- */
- UserInteraction getUserInteraction();
-
- /**
- * @return a {@link List} of {@link UserAuth} {@link NamedFactory}-ies - never
- * {@code null}/empty
- */
- List<NamedFactory<UserAuth>> getUserAuthFactories();
-
- /**
* @return The {@link HostConfigEntryResolver} to use in order to resolve the
- * effective session parameters
+ * effective session parameters - never {@code null}
*/
HostConfigEntryResolver getHostConfigEntryResolver();
+ void setHostConfigEntryResolver(HostConfigEntryResolver resolver);
/**
* @return The {@link ClientIdentityLoader} to use in order to load client
- * key pair identities
+ * key pair identities - never {@code null}
*/
ClientIdentityLoader getClientIdentityLoader();
+ void setClientIdentityLoader(ClientIdentityLoader loader);
/**
* @return The {@link FilePasswordProvider} to use if need to load encrypted
- * identities keys
+ * identities keys - never {@code null}
+ * @see FilePasswordProvider#EMPTY
*/
FilePasswordProvider getFilePasswordProvider();
+ void setFilePasswordProvider(FilePasswordProvider provider);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 fdb4dbb..02f7db2 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
@@ -66,7 +66,6 @@ import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.client.session.ClientConnectionServiceFactory;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.client.session.ClientSessionCreator;
-import org.apache.sshd.client.session.ClientSessionImpl;
import org.apache.sshd.client.session.ClientUserAuthServiceFactory;
import org.apache.sshd.client.session.SessionFactory;
import org.apache.sshd.client.simple.AbstractSimpleClientSessionCreator;
@@ -85,12 +84,14 @@ import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoConnectFuture;
import org.apache.sshd.common.io.IoConnector;
+import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.keyprovider.AbstractFileKeyPairProvider;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.Supplier;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.io.NoCloseInputStream;
@@ -194,8 +195,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
return serverKeyVerifier;
}
+ @Override
public void setServerKeyVerifier(ServerKeyVerifier serverKeyVerifier) {
- this.serverKeyVerifier = serverKeyVerifier;
+ this.serverKeyVerifier = ValidateUtils.checkNotNull(serverKeyVerifier, "No server key verifier");
}
@Override
@@ -203,8 +205,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
return hostConfigEntryResolver;
}
+ @Override
public void setHostConfigEntryResolver(HostConfigEntryResolver resolver) {
- this.hostConfigEntryResolver = resolver;
+ this.hostConfigEntryResolver = ValidateUtils.checkNotNull(resolver, "No host configuration entry resolver");
}
@Override
@@ -212,8 +215,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
return filePasswordProvider;
}
+ @Override
public void setFilePasswordProvider(FilePasswordProvider provider) {
- this.filePasswordProvider = provider;
+ this.filePasswordProvider = ValidateUtils.checkNotNull(provider, "No file password provider");
}
@Override
@@ -221,8 +225,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
return clientIdentityLoader;
}
+ @Override
public void setClientIdentityLoader(ClientIdentityLoader loader) {
- this.clientIdentityLoader = loader;
+ this.clientIdentityLoader = ValidateUtils.checkNotNull(loader, "No client identity loader");
}
@Override
@@ -230,6 +235,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
return userInteraction;
}
+ @Override
public void setUserInteraction(UserInteraction userInteraction) {
this.userInteraction = userInteraction;
}
@@ -239,8 +245,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
return userAuthFactories;
}
+ @Override
public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
- this.userAuthFactories = userAuthFactories;
+ this.userAuthFactories = ValidateUtils.checkNotNullAndNotEmpty(userAuthFactories, "No user auth factories");
}
@Override
@@ -256,7 +263,19 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
// if no client identities override use the default
KeyPairProvider defaultIdentities = getKeyPairProvider();
if (defaultIdentities == null) {
- setKeyPairProvider(new DefaultClientIdentitiesWatcher(getClientIdentityLoader(), getFilePasswordProvider()));
+ setKeyPairProvider(new DefaultClientIdentitiesWatcher(
+ new Supplier<ClientIdentityLoader>() {
+ @Override
+ public ClientIdentityLoader get() {
+ return getClientIdentityLoader();
+ }
+ },
+ new Supplier<FilePasswordProvider>() {
+ @Override
+ public FilePasswordProvider get() {
+ return getFilePasswordProvider();
+ }
+ }));
}
// Register the additional agent forwarding channel if needed
@@ -453,38 +472,63 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
final ConnectFuture connectFuture, final String username, final SocketAddress address,
final Collection<? extends KeyPair> identities, final boolean useDefaultIdentities) {
return new SshFutureListener<IoConnectFuture>() {
- @SuppressWarnings("synthetic-access")
@Override
+ @SuppressWarnings("synthetic-access")
public void operationComplete(IoConnectFuture future) {
if (future.isCanceled()) {
connectFuture.cancel();
- } else if (future.getException() != null) {
- connectFuture.setException(future.getException());
- } else {
- ClientSessionImpl session = (ClientSessionImpl) AbstractSession.getSession(future.getSession());
- session.setUsername(username);
+ return;
+ }
- if (useDefaultIdentities) {
- session.setKeyPairProvider(getKeyPairProvider());
+ Throwable t = future.getException();
+ if (t != null) {
+ if (log.isDebugEnabled()) {
+ log.debug("operationComplete({}@{}) failed ({}): {}",
+ username, address, t.getClass().getSimpleName(), t.getMessage());
}
+ connectFuture.setException(t);
+ } else {
+ onConnectOperationComplete(future.getSession(), connectFuture, username, address, identities, useDefaultIdentities);
+ }
+ }
+ };
+ }
- int numIds = GenericUtils.size(identities);
- if (numIds > 0) {
- if (log.isDebugEnabled()) {
- log.debug("doConnect({}@{}) adding {} identities", username, address, numIds);
- }
- for (KeyPair kp : identities) {
- if (log.isTraceEnabled()) {
- log.trace("doConnect({}@{}) add identity type={}, fingerprint={}",
- username, address, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
- }
- session.addPublicKeyIdentity(kp);
- }
+ protected void onConnectOperationComplete(IoSession ioSession, ConnectFuture connectFuture,
+ String username, SocketAddress address, Collection<? extends KeyPair> identities, boolean useDefaultIdentities) {
+ ClientSession session = (ClientSession) AbstractSession.getSession(ioSession);
+ session.setUsername(username);
+
+ if (useDefaultIdentities) {
+ // check if session listener intervened
+ KeyPairProvider kpSession = session.getKeyPairProvider();
+ KeyPairProvider kpClient = ValidateUtils.checkNotNull(getKeyPairProvider(), "No default key-pair provider");
+ if (kpSession == null) {
+ session.setKeyPairProvider(kpClient);
+ } else {
+ if (kpSession != kpClient) {
+ if (log.isDebugEnabled()) {
+ log.debug("onConnectOperationComplete({}) key-pair provider override", session);
}
- connectFuture.setSession(session);
}
}
- };
+ }
+
+ int numIds = GenericUtils.size(identities);
+ if (numIds > 0) {
+ if (log.isDebugEnabled()) {
+ log.debug("onConnectOperationComplete({}@{}) adding {} identities", username, address, numIds);
+ }
+ for (KeyPair kp : identities) {
+ if (log.isTraceEnabled()) {
+ log.trace("onConnectOperationComplete({}@{}) add identity type={}, fingerprint={}",
+ username, address, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
+ }
+ session.addPublicKeyIdentity(kp);
+ }
+ }
+
+ connectFuture.setSession(session);
}
protected IoConnector createConnector() {
@@ -699,6 +743,11 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
client.start();
client.setUserInteraction(new UserInteraction() {
@Override
+ public boolean isInteractionAllowed(ClientSession session) {
+ return true;
+ }
+
+ @Override
public void welcome(ClientSession clientSession, String banner, String lang) {
stdout.println(banner);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
index 34ba100..553a544 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
@@ -24,7 +24,7 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.ClientAuthenticationManager;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.SshConstants;
@@ -94,7 +94,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
}
}
passwords = pwds.iterator();
- maxTrials = PropertyResolverUtils.getIntProperty(session, ClientFactoryManager.PASSWORD_PROMPTS, ClientFactoryManager.DEFAULT_PASSWORD_PROMPTS);
+ maxTrials = PropertyResolverUtils.getIntProperty(session, ClientAuthenticationManager.PASSWORD_PROMPTS, ClientAuthenticationManager.DEFAULT_PASSWORD_PROMPTS);
ValidateUtils.checkTrue(maxTrials > 0, "Non-positive max. trials: %d", maxTrials);
}
@@ -184,7 +184,9 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
session.writePacket(buffer);
return true;
}
- throw new IllegalStateException("process(" + session + ")[" + service + ") received unknown packet: cmd=" + cmd);
+
+ throw new IllegalStateException("process(" + session + ")[" + service + ")"
+ + " received unknown packet: cmd=" + SshConstants.getCommandMessageName(cmd));
}
protected String getExchangeLanguageTag(ClientSession session) {
@@ -229,8 +231,8 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
return new String[]{candidate};
} else {
ClientSession session = getClientSession();
- UserInteraction ui = UserInteraction.Utils.resolveUserInteraction(session);
- if (ui != null) {
+ UserInteraction ui = session.getUserInteraction();
+ if ((ui != null) && ui.isInteractionAllowed(session)) {
return ui.interactive(session, name, instruction, lang, prompt, echo);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
index 4924f0c..450c915 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
@@ -81,9 +81,8 @@ public class UserAuthPassword extends AbstractUserAuth {
if (cmd == SshConstants.SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) {
String prompt = buffer.getString();
String lang = buffer.getString();
- UserInteraction ui = UserInteraction.Utils.resolveUserInteraction(session);
-
- if (ui != null) {
+ UserInteraction ui = session.getUserInteraction();
+ if ((ui != null) && ui.isInteractionAllowed(session)) {
String password = ui.getUpdatedPassword(session, prompt, lang);
if (GenericUtils.isEmpty(password)) {
if (log.isDebugEnabled()) {
@@ -104,7 +103,8 @@ public class UserAuthPassword extends AbstractUserAuth {
return false;
}
- throw new IllegalStateException("process(" + username + "@" + session + ")[" + service + "] received unknown packet: cmd=" + cmd);
+ throw new IllegalStateException("process(" + username + "@" + session + ")[" + service + "]"
+ + " received unknown packet: cmd=" + SshConstants.getCommandMessageName(cmd));
}
/**
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
index 525eb43..d4b0db4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
@@ -37,7 +37,9 @@ import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.kex.KeyExchange;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.Pair;
+import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
@@ -65,16 +67,24 @@ public class UserAuthPublicKey extends AbstractUserAuth {
List<PublicKeyIdentity> ids = new ArrayList<>();
for (Object o : identities) {
if (o instanceof KeyPair) {
- ids.add(new KeyPairIdentity(session.getFactoryManager(), (KeyPair) o));
+ ids.add(new KeyPairIdentity(session, (KeyPair) o));
}
}
- FactoryManager manager = session.getFactoryManager();
+ FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No session factory manager");
SshAgentFactory factory = manager.getAgentFactory();
if (factory != null) {
- this.agent = factory.createClient(manager);
- for (Pair<PublicKey, String> pair : agent.getIdentities()) {
- ids.add(new KeyAgentIdentity(agent, pair.getFirst()));
+ this.agent = ValidateUtils.checkNotNull(factory.createClient(manager), "No agent created");
+ Collection<Pair<PublicKey, String>> agentKeys = agent.getIdentities();
+ if (GenericUtils.size(agentKeys) > 0) {
+ for (Pair<PublicKey, String> pair : agentKeys) {
+ PublicKey key = pair.getFirst();
+ if (log.isDebugEnabled()) {
+ log.debug("init({}) add agent public key type={}: comment={}, fingerprint={}",
+ session, pair.getSecond(), KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+ }
+ ids.add(new KeyAgentIdentity(agent, key));
+ }
}
} else {
this.agent = null;
@@ -82,8 +92,12 @@ public class UserAuthPublicKey extends AbstractUserAuth {
KeyPairProvider provider = session.getKeyPairProvider();
if (provider != null) {
- for (KeyPair pair : provider.loadKeys()) {
- ids.add(new KeyPairIdentity(manager, pair));
+ for (KeyPair kp : provider.loadKeys()) {
+ if (log.isDebugEnabled()) {
+ log.debug("init({}) add provider public key type={}: {}",
+ session, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
+ }
+ ids.add(new KeyPairIdentity(session, kp));
}
}
this.keys = ids.iterator();
@@ -103,8 +117,8 @@ public class UserAuthPublicKey extends AbstractUserAuth {
String algo = KeyUtils.getKeyType(key);
String name = getName();
if (log.isDebugEnabled()) {
- log.debug("process({}@{})[{}] Send SSH_MSG_USERAUTH_REQUEST request {} algo={}",
- username, session, service, name, algo);
+ log.debug("process({}@{})[{}] Send SSH_MSG_USERAUTH_REQUEST request {} type={} - fingerprint={}",
+ username, session, service, name, algo, KeyUtils.getFingerPrint(key));
}
buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST);
@@ -130,8 +144,8 @@ public class UserAuthPublicKey extends AbstractUserAuth {
String algo = KeyUtils.getKeyType(key);
String name = getName();
if (log.isDebugEnabled()) {
- log.debug("process({}@{})[{}] Send SSH_MSG_USERAUTH_REQUEST reply {} algo={}",
- username, session, service, name, algo);
+ log.debug("process({}@{})[{}] Send SSH_MSG_USERAUTH_REQUEST reply {} type={} - fingerprint={}",
+ username, session, service, name, algo, KeyUtils.getFingerPrint(key));
}
buffer = session.prepareBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, BufferUtils.clear(buffer));
@@ -154,7 +168,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
bs.putPublicKey(key);
byte[] sig = current.sign(bs.getCompactData());
- bs = new ByteArrayBuffer();
+ bs = new ByteArrayBuffer(algo.length() + sig.length + Long.SIZE);
bs.putString(algo);
bs.putBytes(sig);
buffer.putBytes(bs.array(), bs.rpos(), bs.available());
@@ -163,7 +177,8 @@ public class UserAuthPublicKey extends AbstractUserAuth {
return true;
}
- throw new IllegalStateException("process(" + username + "@" + session + ")[" + service + "] received unknown packet: cmd=" + cmd);
+ throw new IllegalStateException("process(" + username + "@" + session + ")[" + service + "]"
+ + " received unknown packet: cmd=" + SshConstants.getCommandMessageName(cmd));
}
@Override
@@ -173,6 +188,8 @@ public class UserAuthPublicKey extends AbstractUserAuth {
agent.close();
} catch (IOException e) {
throw new RuntimeException("Failed (" + e.getClass().getSimpleName() + ") to close agent: " + e.getMessage(), e);
+ } finally {
+ agent = null;
}
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/auth/UserInteraction.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserInteraction.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserInteraction.java
index a05dfbc..700055a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserInteraction.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserInteraction.java
@@ -18,7 +18,6 @@
*/
package org.apache.sshd.client.auth;
-import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.session.ClientSession;
/**
@@ -28,6 +27,44 @@ import org.apache.sshd.client.session.ClientSession;
* @see <a href="https://www.ietf.org/rfc/rfc4256.txt">RFC 4256</A>
*/
public interface UserInteraction {
+ /**
+ * A useful "placeholder" that indicates that no interaction is expected.
+ * <B>Note:</B> throws {@link IllegalStateException} is any of the interaction
+ * methods is called
+ */
+ UserInteraction NONE = new UserInteraction() {
+ @Override
+ public boolean isInteractionAllowed(ClientSession session) {
+ return false;
+ }
+
+ @Override
+ public void welcome(ClientSession session, String banner, String lang) {
+ // ignored
+ }
+
+ @Override
+ public String[] interactive(ClientSession session, String name, String instruction, String lang, String[] prompt, boolean[] echo) {
+ throw new IllegalStateException("interactive(" + session + ")[" + name + "] unexpected call");
+ }
+
+ @Override
+ public String getUpdatedPassword(ClientSession session, String prompt, String lang) {
+ throw new IllegalStateException("getUpdatedPassword(" + session + ")[" + prompt + "] unexpected call");
+ }
+
+ @Override
+ public String toString() {
+ return "NONE";
+ }
+ };
+
+ /**
+ *
+ * @param session The {@link ClientSession}
+ * @return {@code true} if user interaction allowed for this session
+ */
+ boolean isInteractionAllowed(ClientSession session);
/**
* Displays the welcome banner to the user.
@@ -70,38 +107,4 @@ public interface UserInteraction {
* be it other passwords, public keys, etc...)
*/
String getUpdatedPassword(ClientSession session, String prompt, String lang);
-
- // CHECKSTYLE:OFF
- final class Utils {
- // CHECKSTYLE:ON
-
- private Utils() {
- throw new UnsupportedOperationException("No instance allowed");
- }
-
- /**
- * Checks which {@link UserInteraction} instance to use - if the session
- * has a specific one, then it is used. Otherwise, the {@link ClientFactoryManager}
- * (if any is available) is consulted.
- *
- * @param session The {@link ClientSession}
- * @return The resolved user interaction instance
- * @see ClientSession#getUserInteraction()
- * @see ClientSession#getFactoryManager()
- * @see ClientFactoryManager#getUserInteraction()
- */
- public static UserInteraction resolveUserInteraction(ClientSession session) {
- if (session == null) {
- return null;
- }
-
- UserInteraction ui = session.getUserInteraction();
- if (ui == null) {
- ClientFactoryManager manager = session.getFactoryManager();
- ui = (manager == null) ? null : manager.getUserInteraction();
- }
-
- return ui;
- }
- }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
index 40b3837..e84195f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
@@ -21,9 +21,9 @@ package org.apache.sshd.client.auth.pubkey;
import java.security.KeyPair;
import java.security.PublicKey;
-import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.kex.KexFactoryManager;
import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.common.util.ValidateUtils;
@@ -34,9 +34,9 @@ import org.apache.sshd.common.util.ValidateUtils;
*/
public class KeyPairIdentity implements PublicKeyIdentity {
private final KeyPair pair;
- private final FactoryManager manager;
+ private final KexFactoryManager manager;
- public KeyPairIdentity(FactoryManager manager, KeyPair pair) {
+ public KeyPairIdentity(KexFactoryManager manager, KeyPair pair) {
this.manager = ValidateUtils.checkNotNull(manager, "No manager");
this.pair = ValidateUtils.checkNotNull(pair, "No key pair");
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
index 694b1dd..fb104b4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
@@ -32,6 +32,7 @@ import org.apache.sshd.common.config.keys.BuiltinIdentities;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.Supplier;
import org.apache.sshd.common.util.ValidateUtils;
/**
@@ -47,6 +48,19 @@ public class BuiltinClientIdentitiesWatcher extends ClientIdentitiesWatcher {
public BuiltinClientIdentitiesWatcher(Path keysFolder, Collection<String> ids, boolean supportedOnly,
ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ this(keysFolder, ids, supportedOnly,
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(loader, "No client identity loader")),
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(provider, "No password provider")),
+ strict);
+ }
+
+ public BuiltinClientIdentitiesWatcher(Path keysFolder, boolean supportedOnly,
+ Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
+ this(keysFolder, NamedResource.Utils.getNameList(BuiltinIdentities.VALUES), supportedOnly, loader, provider, strict);
+ }
+
+ public BuiltinClientIdentitiesWatcher(Path keysFolder, Collection<String> ids, boolean supportedOnly,
+ Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
super(getBuiltinIdentitiesPaths(keysFolder, ids), loader, provider, strict);
this.supportedOnly = supportedOnly;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
index aa26b8b..e0d930a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
@@ -30,6 +30,8 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.Supplier;
+import org.apache.sshd.common.util.ValidateUtils;
/**
* Watches over a group of files that contains client identities
@@ -39,11 +41,26 @@ import org.apache.sshd.common.util.GenericUtils;
public class ClientIdentitiesWatcher extends AbstractKeyPairProvider implements KeyPairProvider {
private final Collection<ClientIdentityProvider> providers;
- public ClientIdentitiesWatcher(Collection<? extends Path> paths, ClientIdentityLoader loader, FilePasswordProvider provider) {
+ public ClientIdentitiesWatcher(Collection<? extends Path> paths,
+ ClientIdentityLoader loader, FilePasswordProvider provider) {
this(paths, loader, provider, true);
}
- public ClientIdentitiesWatcher(Collection<? extends Path> paths, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ public ClientIdentitiesWatcher(Collection<? extends Path> paths,
+ ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ this(paths,
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(loader, "No client identity loader")),
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(provider, "No password provider")),
+ strict);
+ }
+
+ public ClientIdentitiesWatcher(Collection<? extends Path> paths,
+ Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider) {
+ this(paths, loader, provider, true);
+ }
+
+ public ClientIdentitiesWatcher(Collection<? extends Path> paths,
+ Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
this(buildProviders(paths, loader, provider, strict));
}
@@ -77,7 +94,16 @@ public class ClientIdentitiesWatcher extends AbstractKeyPairProvider implements
return keys;
}
- public static List<ClientIdentityProvider> buildProviders(Collection<? extends Path> paths, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ public static List<ClientIdentityProvider> buildProviders(
+ Collection<? extends Path> paths, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ return buildProviders(paths,
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(loader, "No client identity loader")),
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(provider, "No password provider")),
+ strict);
+ }
+
+ public static List<ClientIdentityProvider> buildProviders(
+ Collection<? extends Path> paths, Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
if (GenericUtils.isEmpty(paths)) {
return Collections.emptyList();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
index bdd2bf5..2923ba2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
@@ -27,7 +27,9 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.Pair;
+import org.apache.sshd.common.util.Supplier;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.io.ModifiableFileWatcher;
@@ -40,8 +42,8 @@ import org.apache.sshd.common.util.io.ModifiableFileWatcher;
*/
public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements ClientIdentityProvider {
private final AtomicReference<KeyPair> identityHolder = new AtomicReference<>(null);
- private final ClientIdentityLoader loader;
- private final FilePasswordProvider provider;
+ private final Supplier<ClientIdentityLoader> loaderHolder;
+ private final Supplier<FilePasswordProvider> providerHolder;
private final boolean strict;
public ClientIdentityFileWatcher(Path path, ClientIdentityLoader loader, FilePasswordProvider provider) {
@@ -49,9 +51,20 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
}
public ClientIdentityFileWatcher(Path path, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ this(path,
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(loader, "No client identity loader")),
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(provider, "No password provider")),
+ strict);
+ }
+
+ public ClientIdentityFileWatcher(Path path, Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider) {
+ this(path, loader, provider, true);
+ }
+
+ public ClientIdentityFileWatcher(Path path, Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
super(path);
- this.loader = ValidateUtils.checkNotNull(loader, "No client identity loader");
- this.provider = ValidateUtils.checkNotNull(provider, "No password provided");
+ this.loaderHolder = ValidateUtils.checkNotNull(loader, "No client identity loader");
+ this.providerHolder = ValidateUtils.checkNotNull(provider, "No password provider");
this.strict = strict;
}
@@ -60,11 +73,11 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
}
public final ClientIdentityLoader getClientIdentityLoader() {
- return loader;
+ return loaderHolder.get();
}
public final FilePasswordProvider getFilePasswordProvider() {
- return provider;
+ return providerHolder.get();
}
@Override
@@ -101,14 +114,15 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
}
String location = path.toString();
- ClientIdentityLoader idLoader = getClientIdentityLoader();
+ ClientIdentityLoader idLoader = ValidateUtils.checkNotNull(getClientIdentityLoader(), "No client identity loader");
if (idLoader.isValidLocation(location)) {
- return idLoader.loadClientIdentity(location, getFilePasswordProvider());
+ return idLoader.loadClientIdentity(location, ValidateUtils.checkNotNull(getFilePasswordProvider(), "No file password provider"));
}
if (log.isDebugEnabled()) {
log.debug("reloadClientIdentity({}) invalid location", location);
}
+
return null;
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
index a689599..ba1719f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
@@ -24,6 +24,9 @@ import java.util.List;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.PublicKeyEntry;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.Supplier;
+import org.apache.sshd.common.util.ValidateUtils;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -38,6 +41,22 @@ public class DefaultClientIdentitiesWatcher extends BuiltinClientIdentitiesWatch
}
public DefaultClientIdentitiesWatcher(boolean supportedOnly, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
+ this(supportedOnly,
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(loader, "No client identity loader")),
+ GenericUtils.supplierOf(ValidateUtils.checkNotNull(provider, "No password provider")),
+ strict);
+ }
+
+ public DefaultClientIdentitiesWatcher(Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider) {
+ this(loader, provider, true);
+ }
+
+ public DefaultClientIdentitiesWatcher(Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
+ this(true, loader, provider, strict);
+ }
+
+ public DefaultClientIdentitiesWatcher(boolean supportedOnly,
+ Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
super(PublicKeyEntry.getDefaultKeysFolderPath(), supportedOnly, loader, provider, strict);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
index 95af92c..9ffdb9c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
@@ -18,7 +18,6 @@
*/
package org.apache.sshd.client.kex;
-import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
@@ -130,8 +129,7 @@ public class DHGClient extends AbstractDHClientKeyExchange {
hash.update(buffer.array(), 0, buffer.available());
h = hash.digest();
- FactoryManager manager = session.getFactoryManager();
- Signature verif = ValidateUtils.checkNotNull(NamedFactory.Utils.create(manager.getSignatureFactories(), keyAlg),
+ Signature verif = ValidateUtils.checkNotNull(NamedFactory.Utils.create(session.getSignatureFactories(), keyAlg),
"No verifier located for algorithm=%s",
keyAlg);
verif.initVerifier(serverKey);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
index ac00fe3..cff00d8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
@@ -21,7 +21,6 @@ package org.apache.sshd.client.kex;
import java.math.BigInteger;
-import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
@@ -159,9 +158,8 @@ public class DHGEXClient extends AbstractDHClientKeyExchange {
hash.update(buffer.array(), 0, buffer.available());
h = hash.digest();
- FactoryManager manager = session.getFactoryManager();
Signature verif = ValidateUtils.checkNotNull(
- NamedFactory.Utils.create(manager.getSignatureFactories(), keyAlg),
+ NamedFactory.Utils.create(session.getSignatureFactories(), keyAlg),
"No verifier located for algorithm=%s",
keyAlg);
verif.initVerifier(serverKey);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
new file mode 100644
index 0000000..76d042b
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
@@ -0,0 +1,378 @@
+/*
+ * 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.nio.file.FileSystem;
+import java.security.KeyPair;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.auth.UserAuth;
+import org.apache.sshd.client.auth.UserInteraction;
+import org.apache.sshd.client.channel.ChannelDirectTcpip;
+import org.apache.sshd.client.channel.ChannelExec;
+import org.apache.sshd.client.channel.ChannelSubsystem;
+import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
+import org.apache.sshd.client.scp.DefaultScpClient;
+import org.apache.sshd.client.scp.ScpClient;
+import org.apache.sshd.client.subsystem.sftp.DefaultSftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpFileSystem;
+import org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider;
+import org.apache.sshd.client.subsystem.sftp.SftpVersionSelector;
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.forward.TcpipForwarder;
+import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.scp.ScpTransferEventListener;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractClientSession extends AbstractSession implements ClientSession {
+ /**
+ * Compares 2 password identities - returns zero ONLY if <U>both</U> compared
+ * objects are {@link String}s and equal to each other
+ */
+ public static final Comparator<Object> PASSWORD_IDENTITY_COMPARATOR = new Comparator<Object>() {
+ @Override
+ public int compare(Object o1, Object o2) {
+ if (!(o1 instanceof String) || !(o2 instanceof String)) {
+ return -1;
+ } else {
+ return ((String) o1).compareTo((String) o2);
+ }
+ }
+ };
+
+ /**
+ * Compares 2 {@link KeyPair} identities - returns zero ONLY if <U>both</U> compared
+ * objects are {@link KeyPair}s and equal to each other
+ */
+ public static final Comparator<Object> KEYPAIR_IDENTITY_COMPARATOR = new Comparator<Object>() {
+ @Override
+ public int compare(Object o1, Object o2) {
+ if ((!(o1 instanceof KeyPair)) || (!(o2 instanceof KeyPair))) {
+ return -1;
+ } else if (KeyUtils.compareKeyPairs((KeyPair) o1, (KeyPair) o2)) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ private final List<Object> identities = new ArrayList<>();
+ private ServerKeyVerifier serverKeyVerifier;
+ private UserInteraction userInteraction;
+ private List<NamedFactory<UserAuth>> userAuthFactories;
+ private ScpTransferEventListener scpListener;
+
+ protected AbstractClientSession(ClientFactoryManager factoryManager, IoSession ioSession) {
+ super(false, factoryManager, ioSession);
+ }
+
+ @Override
+ public ClientFactoryManager getFactoryManager() {
+ return (ClientFactoryManager) super.getFactoryManager();
+ }
+
+ @Override
+ public ServerKeyVerifier getServerKeyVerifier() {
+ return resolveEffectiveProvider(ServerKeyVerifier.class, serverKeyVerifier, getFactoryManager().getServerKeyVerifier());
+ }
+
+ @Override
+ public void setServerKeyVerifier(ServerKeyVerifier serverKeyVerifier) {
+ this.serverKeyVerifier = serverKeyVerifier; // OK if null - inherit from parent
+ }
+
+ @Override
+ public UserInteraction getUserInteraction() {
+ return resolveEffectiveProvider(UserInteraction.class, userInteraction, getFactoryManager().getUserInteraction());
+ }
+
+ @Override
+ public void setUserInteraction(UserInteraction userInteraction) {
+ this.userInteraction = userInteraction; // OK if null - inherit from parent
+ }
+
+ @Override
+ public List<NamedFactory<UserAuth>> getUserAuthFactories() {
+ return resolveEffectiveFactories(UserAuth.class, userAuthFactories, getFactoryManager().getUserAuthFactories());
+ }
+
+ @Override
+ public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
+ this.userAuthFactories = userAuthFactories; // OK if null/empty - inherit from parent
+ }
+
+ protected List<Object> getRegisteredIdentities() {
+ return identities;
+ }
+
+ @Override
+ public void addPasswordIdentity(String password) {
+ identities.add(ValidateUtils.checkNotNullAndNotEmpty(password, "No password provided"));
+ if (log.isDebugEnabled()) { // don't show the password in the log
+ log.debug("addPasswordIdentity({}) {}", this, KeyUtils.getFingerPrint(password));
+ }
+ }
+
+ @Override
+ public String removePasswordIdentity(String password) {
+ if (GenericUtils.isEmpty(password)) {
+ return null;
+ }
+
+ int index = findIdentityIndex(PASSWORD_IDENTITY_COMPARATOR, password);
+ if (index >= 0) {
+ return (String) identities.remove(index);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void addPublicKeyIdentity(KeyPair kp) {
+ ValidateUtils.checkNotNull(kp, "No key-pair to add");
+ ValidateUtils.checkNotNull(kp.getPublic(), "No public key");
+ ValidateUtils.checkNotNull(kp.getPrivate(), "No private key");
+
+ identities.add(kp);
+
+ if (log.isDebugEnabled()) {
+ log.debug("addPublicKeyIdentity({}) {}", this, KeyUtils.getFingerPrint(kp.getPublic()));
+ }
+ }
+
+ @Override
+ public KeyPair removePublicKeyIdentity(KeyPair kp) {
+ if (kp == null) {
+ return null;
+ }
+
+ int index = findIdentityIndex(KEYPAIR_IDENTITY_COMPARATOR, kp);
+ if (index >= 0) {
+ return (KeyPair) identities.remove(index);
+ } else {
+ return null;
+ }
+ }
+
+ protected int findIdentityIndex(Comparator<? super Object> comp, Object target) {
+ for (int index = 0; index < identities.size(); index++) {
+ Object value = identities.get(index);
+ if (comp.compare(value, target) == 0) {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+
+ @Override
+ public ClientChannel createChannel(String type) throws IOException {
+ return createChannel(type, null);
+ }
+
+ @Override
+ public ClientChannel createChannel(String type, String subType) throws IOException {
+ if (ClientChannel.CHANNEL_SHELL.equals(type)) {
+ return createShellChannel();
+ } else if (ClientChannel.CHANNEL_EXEC.equals(type)) {
+ return createExecChannel(subType);
+ } else if (ClientChannel.CHANNEL_SUBSYSTEM.equals(type)) {
+ return createSubsystemChannel(subType);
+ } else {
+ throw new IllegalArgumentException("Unsupported channel type " + type);
+ }
+ }
+
+ @Override
+ public ChannelExec createExecChannel(String command) throws IOException {
+ ChannelExec channel = new ChannelExec(command);
+ ConnectionService service = getConnectionService();
+ int id = service.registerChannel(channel);
+ if (log.isDebugEnabled()) {
+ log.debug("createExecChannel({})[{}] created id={}", this, command, id);
+ }
+ return channel;
+ }
+
+ @Override
+ public ChannelSubsystem createSubsystemChannel(String subsystem) throws IOException {
+ ChannelSubsystem channel = new ChannelSubsystem(subsystem);
+ ConnectionService service = getConnectionService();
+ int id = service.registerChannel(channel);
+ if (log.isDebugEnabled()) {
+ log.debug("createSubsystemChannel({})[{}] created id={}", this, subsystem, id);
+ }
+ return channel;
+ }
+
+ @Override
+ public ChannelDirectTcpip createDirectTcpipChannel(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
+ ChannelDirectTcpip channel = new ChannelDirectTcpip(local, remote);
+ ConnectionService service = getConnectionService();
+ int id = service.registerChannel(channel);
+ if (log.isDebugEnabled()) {
+ log.debug("createDirectTcpipChannel({})[{} => {}] created id={}", this, local, remote, id);
+ }
+ return channel;
+ }
+
+ protected ClientUserAuthService getUserAuthService() {
+ return getService(ClientUserAuthService.class);
+ }
+
+ protected ConnectionService getConnectionService() {
+ return getService(ConnectionService.class);
+ }
+
+ @Override
+ public ScpTransferEventListener getScpTransferEventListener() {
+ return scpListener;
+ }
+
+ @Override
+ public void setScpTransferEventListener(ScpTransferEventListener listener) {
+ scpListener = listener;
+ }
+
+ @Override
+ public ScpClient createScpClient() {
+ return createScpClient(getScpTransferEventListener());
+ }
+
+ @Override
+ public ScpClient createScpClient(ScpTransferEventListener listener) {
+ return new DefaultScpClient(this, listener);
+ }
+
+ @Override // TODO make this a default method in JDK-8
+ public SftpClient createSftpClient() throws IOException {
+ return createSftpClient(SftpVersionSelector.CURRENT);
+ }
+
+ @Override // TODO make this a default method in JDK-8
+ public SftpClient createSftpClient(final int version) throws IOException {
+ return createSftpClient(SftpVersionSelector.Utils.fixedVersionSelector(version));
+ }
+
+ @Override
+ public SftpClient createSftpClient(SftpVersionSelector selector) throws IOException {
+ DefaultSftpClient client = new DefaultSftpClient(this);
+ client.negotiateVersion(selector);
+ return client;
+ }
+
+ @Override
+ public FileSystem createSftpFileSystem() throws IOException {
+ return createSftpFileSystem(SftpVersionSelector.CURRENT);
+ }
+
+ @Override
+ public FileSystem createSftpFileSystem(int version) throws IOException {
+ return createSftpFileSystem(SftpVersionSelector.Utils.fixedVersionSelector(version));
+ }
+
+ @Override
+ public FileSystem createSftpFileSystem(SftpVersionSelector selector) throws IOException {
+ return createSftpFileSystem(selector, SftpClient.DEFAULT_READ_BUFFER_SIZE, SftpClient.DEFAULT_WRITE_BUFFER_SIZE);
+ }
+
+ @Override
+ public FileSystem createSftpFileSystem(int version, int readBufferSize, int writeBufferSize) throws IOException {
+ return createSftpFileSystem(SftpVersionSelector.Utils.fixedVersionSelector(version), readBufferSize, writeBufferSize);
+ }
+
+ @Override
+ public FileSystem createSftpFileSystem(int readBufferSize, int writeBufferSize) throws IOException {
+ return createSftpFileSystem(SftpVersionSelector.CURRENT, readBufferSize, writeBufferSize);
+ }
+
+ @Override
+ public FileSystem createSftpFileSystem(SftpVersionSelector selector, int readBufferSize, int writeBufferSize) throws IOException {
+ SftpFileSystemProvider provider = new SftpFileSystemProvider((org.apache.sshd.client.SshClient) getFactoryManager(), selector);
+ SftpFileSystem fs = provider.newFileSystem(this);
+ fs.setReadBufferSize(readBufferSize);
+ fs.setWriteBufferSize(writeBufferSize);
+ return fs;
+ }
+
+ @Override
+ public SshdSocketAddress startLocalPortForwarding(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
+ return getTcpipForwarder().startLocalPortForwarding(local, remote);
+ }
+
+ @Override
+ public void stopLocalPortForwarding(SshdSocketAddress local) throws IOException {
+ getTcpipForwarder().stopLocalPortForwarding(local);
+ }
+
+ @Override
+ public SshdSocketAddress startRemotePortForwarding(SshdSocketAddress remote, SshdSocketAddress local) throws IOException {
+ return getTcpipForwarder().startRemotePortForwarding(remote, local);
+ }
+
+ @Override
+ public void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException {
+ getTcpipForwarder().stopRemotePortForwarding(remote);
+ }
+
+ @Override
+ public SshdSocketAddress startDynamicPortForwarding(SshdSocketAddress local) throws IOException {
+ return getTcpipForwarder().startDynamicPortForwarding(local);
+ }
+
+ @Override
+ public void stopDynamicPortForwarding(SshdSocketAddress local) throws IOException {
+ getTcpipForwarder().stopDynamicPortForwarding(local);
+ }
+
+ protected TcpipForwarder getTcpipForwarder() {
+ ConnectionService service = ValidateUtils.checkNotNull(getConnectionService(), "No connection service");
+ return ValidateUtils.checkNotNull(service.getTcpipForwarder(), "No forwarder");
+ }
+
+ @Override
+ protected String resolveAvailableSignaturesProposal(FactoryManager manager) {
+ // the client does not have to provide keys for the available signatures
+ ValidateUtils.checkTrue(manager == getFactoryManager(), "Mismatched factory manager instances");
+ return NamedResource.Utils.getNames(getSignatureFactories());
+ }
+
+ @Override
+ public void startService(String name) throws Exception {
+ throw new IllegalStateException("Starting services is not supported on the client side: " + name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
index 87e50f5..6ffb863 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
@@ -25,8 +25,8 @@ import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.apache.sshd.client.ClientAuthenticationManager;
import org.apache.sshd.client.ClientFactoryManager;
-import org.apache.sshd.client.auth.UserInteraction;
import org.apache.sshd.client.channel.ChannelDirectTcpip;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
@@ -70,7 +70,7 @@ import org.apache.sshd.common.session.Session;
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public interface ClientSession extends Session, KeyPairProviderHolder {
+public interface ClientSession extends Session, KeyPairProviderHolder, ClientAuthenticationManager {
enum ClientSessionEvent {
TIMEOUT,
CLOSED,
@@ -105,21 +105,6 @@ public interface ClientSession extends Session, KeyPairProviderHolder {
KeyPair removePublicKeyIdentity(KeyPair kp);
/**
- * @return The <U>specific</U> {@link UserInteraction} for this
- * session. May be {@code null} indicating that the
- * {@link ClientFactoryManager#getUserInteraction()} (if any) should
- * be used
- */
- UserInteraction getUserInteraction();
-
- /**
- * @param userInteraction The <U>specific</U> {@link UserInteraction} for this
- * session. May be {@code null} indicating that the
- * {@link ClientFactoryManager#getUserInteraction()} (if any) should be used
- */
- void setUserInteraction(UserInteraction userInteraction);
-
- /**
* Starts the authentication process.
* User identities will be tried until the server successfully authenticate the user.
* User identities must be provided before calling this method using
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 0c9de7c..58eee3d 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
@@ -20,12 +20,8 @@ package org.apache.sshd.client.session;
import java.io.IOException;
import java.net.SocketAddress;
-import java.nio.file.FileSystem;
-import java.security.KeyPair;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
@@ -34,42 +30,23 @@ import java.util.Map;
import java.util.Set;
import org.apache.sshd.client.ClientFactoryManager;
-import org.apache.sshd.client.auth.UserInteraction;
-import org.apache.sshd.client.channel.ChannelDirectTcpip;
-import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
-import org.apache.sshd.client.channel.ChannelSubsystem;
-import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.future.DefaultAuthFuture;
import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
-import org.apache.sshd.client.scp.DefaultScpClient;
-import org.apache.sshd.client.scp.ScpClient;
-import org.apache.sshd.client.subsystem.sftp.DefaultSftpClient;
-import org.apache.sshd.client.subsystem.sftp.SftpClient;
-import org.apache.sshd.client.subsystem.sftp.SftpFileSystem;
-import org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider;
-import org.apache.sshd.client.subsystem.sftp.SftpVersionSelector;
import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.NamedResource;
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.cipher.BuiltinCiphers;
import org.apache.sshd.common.cipher.CipherNone;
-import org.apache.sshd.common.config.keys.KeyUtils;
-import org.apache.sshd.common.forward.TcpipForwarder;
import org.apache.sshd.common.future.DefaultKeyExchangeFuture;
import org.apache.sshd.common.future.KeyExchangeFuture;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.kex.KexState;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.session.AbstractConnectionService;
-import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.util.GenericUtils;
@@ -81,39 +58,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public class ClientSessionImpl extends AbstractSession implements ClientSession {
- /**
- * Compares 2 password identities - returns zero ONLY if <U>both</U> compared
- * objects are {@link String}s and equal to each other
- */
- public static final Comparator<Object> PASSWORD_IDENTITY_COMPARATOR = new Comparator<Object>() {
- @Override
- public int compare(Object o1, Object o2) {
- if (!(o1 instanceof String) || !(o2 instanceof String)) {
- return -1;
- } else {
- return ((String) o1).compareTo((String) o2);
- }
- }
- };
-
- /**
- * Compares 2 {@link KeyPair} identities - returns zero ONLY if <U>both</U> compared
- * objects are {@link KeyPair}s and equal to each other
- */
- public static final Comparator<Object> KEYPAIR_IDENTITY_COMPARATOR = new Comparator<Object>() {
- @Override
- public int compare(Object o1, Object o2) {
- if ((!(o1 instanceof KeyPair)) || (!(o2 instanceof KeyPair))) {
- return -1;
- } else if (KeyUtils.compareKeyPairs((KeyPair) o1, (KeyPair) o2)) {
- return 0;
- } else {
- return 1;
- }
- }
- };
-
+public class ClientSessionImpl extends AbstractClientSession {
protected AuthFuture authFuture;
/**
@@ -126,14 +71,12 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
private ServiceFactory currentServiceFactory;
private Service nextService;
private ServiceFactory nextServiceFactory;
- private final List<Object> identities = new ArrayList<>();
- private UserInteraction userInteraction;
- private ScpTransferEventListener scpListener;
- private KeyPairProvider keyPairProvider;
public ClientSessionImpl(ClientFactoryManager client, IoSession session) throws Exception {
- super(false, client, session);
- log.debug("Client session created: {}", session);
+ super(client, session);
+ if (log.isDebugEnabled()) {
+ log.debug("Client session created: {}", session);
+ }
// 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.
@@ -152,6 +95,11 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
authFuture = new DefaultAuthFuture(lock);
authFuture.setAuthed(false);
+
+ // Inform the listener of the newly created session
+ SessionListener listener = getSessionListenerProxy();
+ listener.sessionCreated(this);
+
sendClientIdentification();
kexState.set(KexState.INIT);
sendKexInit();
@@ -171,90 +119,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
@Override
- public ClientFactoryManager getFactoryManager() {
- return (ClientFactoryManager) super.getFactoryManager();
- }
-
- @Override
- public KeyPairProvider getKeyPairProvider() {
- return keyPairProvider;
- }
-
- public void setKeyPairProvider(KeyPairProvider keyPairProvider) {
- this.keyPairProvider = keyPairProvider;
- }
-
- @Override
- public void addPasswordIdentity(String password) {
- identities.add(ValidateUtils.checkNotNullAndNotEmpty(password, "No password provided"));
- if (log.isDebugEnabled()) { // don't show the password in the log
- log.debug("addPasswordIdentity({}) {}", this, KeyUtils.getFingerPrint(password));
- }
- }
-
- @Override
- public String removePasswordIdentity(String password) {
- if (GenericUtils.isEmpty(password)) {
- return null;
- }
-
- int index = findIdentityIndex(PASSWORD_IDENTITY_COMPARATOR, password);
- if (index >= 0) {
- return (String) identities.remove(index);
- } else {
- return null;
- }
- }
-
- @Override
- public void addPublicKeyIdentity(KeyPair kp) {
- ValidateUtils.checkNotNull(kp, "No key-pair to add");
- ValidateUtils.checkNotNull(kp.getPublic(), "No public key");
- ValidateUtils.checkNotNull(kp.getPrivate(), "No private key");
-
- identities.add(kp);
-
- if (log.isDebugEnabled()) {
- log.debug("addPublicKeyIdentity({}) {}", this, KeyUtils.getFingerPrint(kp.getPublic()));
- }
- }
-
- @Override
- public KeyPair removePublicKeyIdentity(KeyPair kp) {
- if (kp == null) {
- return null;
- }
-
- int index = findIdentityIndex(KEYPAIR_IDENTITY_COMPARATOR, kp);
- if (index >= 0) {
- return (KeyPair) identities.remove(index);
- } else {
- return null;
- }
- }
-
- protected int findIdentityIndex(Comparator<? super Object> comp, Object target) {
- for (int index = 0; index < identities.size(); index++) {
- Object value = identities.get(index);
- if (comp.compare(value, target) == 0) {
- return index;
- }
- }
-
- return -1;
- }
-
- @Override
- public UserInteraction getUserInteraction() {
- return userInteraction;
- }
-
- @Override
- public void setUserInteraction(UserInteraction userInteraction) {
- this.userInteraction = userInteraction;
- }
-
- @Override
public AuthFuture auth() throws IOException {
if (username == null) {
throw new IllegalStateException("No username specified when the session was created");
@@ -262,7 +126,7 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
ClientUserAuthService authService = getUserAuthService();
synchronized (lock) {
- authFuture = authService.auth(identities, nextServiceName());
+ authFuture = authService.auth(getRegisteredIdentities(), nextServiceName());
return authFuture;
}
}
@@ -350,24 +214,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
@Override
- public ClientChannel createChannel(String type) throws IOException {
- return createChannel(type, null);
- }
-
- @Override
- public ClientChannel createChannel(String type, String subType) throws IOException {
- if (ClientChannel.CHANNEL_SHELL.equals(type)) {
- return createShellChannel();
- } else if (ClientChannel.CHANNEL_EXEC.equals(type)) {
- return createExecChannel(subType);
- } else if (ClientChannel.CHANNEL_SUBSYSTEM.equals(type)) {
- return createSubsystemChannel(subType);
- } else {
- throw new IllegalArgumentException("Unsupported channel type " + type);
- }
- }
-
- @Override
public ChannelShell createShellChannel() throws IOException {
if ((inCipher instanceof CipherNone) || (outCipher instanceof CipherNone)) {
throw new IllegalStateException("Interactive channels are not supported with none cipher");
@@ -382,153 +228,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
@Override
- public ChannelExec createExecChannel(String command) throws IOException {
- ChannelExec channel = new ChannelExec(command);
- ConnectionService service = getConnectionService();
- int id = service.registerChannel(channel);
- if (log.isDebugEnabled()) {
- log.debug("createExecChannel({})[{}] created id={}", this, command, id);
- }
- return channel;
- }
-
- @Override
- public ChannelSubsystem createSubsystemChannel(String subsystem) throws IOException {
- ChannelSubsystem channel = new ChannelSubsystem(subsystem);
- ConnectionService service = getConnectionService();
- int id = service.registerChannel(channel);
- if (log.isDebugEnabled()) {
- log.debug("createSubsystemChannel({})[{}] created id={}", this, subsystem, id);
- }
- return channel;
- }
-
- @Override
- public ChannelDirectTcpip createDirectTcpipChannel(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
- ChannelDirectTcpip channel = new ChannelDirectTcpip(local, remote);
- ConnectionService service = getConnectionService();
- int id = service.registerChannel(channel);
- if (log.isDebugEnabled()) {
- log.debug("createDirectTcpipChannel({})[{} => {}] created id={}", this, local, remote, id);
- }
- return channel;
- }
-
- private ClientUserAuthService getUserAuthService() {
- return getService(ClientUserAuthService.class);
- }
-
- private ConnectionService getConnectionService() {
- return getService(ConnectionService.class);
- }
-
- @Override
- public ScpTransferEventListener getScpTransferEventListener() {
- return scpListener;
- }
-
- @Override
- public void setScpTransferEventListener(ScpTransferEventListener listener) {
- scpListener = listener;
- }
-
- @Override
- public ScpClient createScpClient() {
- return createScpClient(getScpTransferEventListener());
- }
-
- @Override
- public ScpClient createScpClient(ScpTransferEventListener listener) {
- return new DefaultScpClient(this, listener);
- }
-
- @Override // TODO make this a default method in JDK-8
- public SftpClient createSftpClient() throws IOException {
- return createSftpClient(SftpVersionSelector.CURRENT);
- }
-
- @Override // TODO make this a default method in JDK-8
- public SftpClient createSftpClient(final int version) throws IOException {
- return createSftpClient(SftpVersionSelector.Utils.fixedVersionSelector(version));
- }
-
- @Override
- public SftpClient createSftpClient(SftpVersionSelector selector) throws IOException {
- DefaultSftpClient client = new DefaultSftpClient(this);
- client.negotiateVersion(selector);
- return client;
- }
-
- @Override
- public FileSystem createSftpFileSystem() throws IOException {
- return createSftpFileSystem(SftpVersionSelector.CURRENT);
- }
-
- @Override
- public FileSystem createSftpFileSystem(int version) throws IOException {
- return createSftpFileSystem(SftpVersionSelector.Utils.fixedVersionSelector(version));
- }
-
- @Override
- public FileSystem createSftpFileSystem(SftpVersionSelector selector) throws IOException {
- return createSftpFileSystem(selector, SftpClient.DEFAULT_READ_BUFFER_SIZE, SftpClient.DEFAULT_WRITE_BUFFER_SIZE);
- }
-
- @Override
- public FileSystem createSftpFileSystem(int version, int readBufferSize, int writeBufferSize) throws IOException {
- return createSftpFileSystem(SftpVersionSelector.Utils.fixedVersionSelector(version), readBufferSize, writeBufferSize);
- }
-
- @Override
- public FileSystem createSftpFileSystem(int readBufferSize, int writeBufferSize) throws IOException {
- return createSftpFileSystem(SftpVersionSelector.CURRENT, readBufferSize, writeBufferSize);
- }
-
- @Override
- public FileSystem createSftpFileSystem(SftpVersionSelector selector, int readBufferSize, int writeBufferSize) throws IOException {
- SftpFileSystemProvider provider = new SftpFileSystemProvider((org.apache.sshd.client.SshClient) getFactoryManager(), selector);
- SftpFileSystem fs = provider.newFileSystem(this);
- fs.setReadBufferSize(readBufferSize);
- fs.setWriteBufferSize(writeBufferSize);
- return fs;
- }
-
- @Override
- public SshdSocketAddress startLocalPortForwarding(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
- return getTcpipForwarder().startLocalPortForwarding(local, remote);
- }
-
- @Override
- public void stopLocalPortForwarding(SshdSocketAddress local) throws IOException {
- getTcpipForwarder().stopLocalPortForwarding(local);
- }
-
- @Override
- public SshdSocketAddress startRemotePortForwarding(SshdSocketAddress remote, SshdSocketAddress local) throws IOException {
- return getTcpipForwarder().startRemotePortForwarding(remote, local);
- }
-
- @Override
- public void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException {
- getTcpipForwarder().stopRemotePortForwarding(remote);
- }
-
- @Override
- public SshdSocketAddress startDynamicPortForwarding(SshdSocketAddress local) throws IOException {
- return getTcpipForwarder().startDynamicPortForwarding(local);
- }
-
- @Override
- public void stopDynamicPortForwarding(SshdSocketAddress local) throws IOException {
- getTcpipForwarder().stopDynamicPortForwarding(local);
- }
-
- protected TcpipForwarder getTcpipForwarder() {
- ConnectionService service = ValidateUtils.checkNotNull(getConnectionService(), "No connection service");
- return ValidateUtils.checkNotNull(service.getTcpipForwarder(), "No forwarder");
- }
-
- @Override
protected void handleMessage(Buffer buffer) throws Exception {
synchronized (lock) {
super.handleMessage(buffer);
@@ -639,12 +338,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
@Override
- protected String resolveAvailableSignaturesProposal(FactoryManager manager) {
- // the client does not have to provide keys for the available signatures
- return NamedResource.Utils.getNames(manager.getSignatureFactories());
- }
-
- @Override
protected void receiveKexInit(Map<KexProposalOption, String> proposal, byte[] seed) throws IOException {
mergeProposals(serverProposal, proposal);
i_s = seed;
@@ -652,8 +345,7 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
@Override
protected void checkKeys() throws SshException {
- ClientFactoryManager manager = getFactoryManager();
- ServerKeyVerifier serverKeyVerifier = manager.getServerKeyVerifier();
+ ServerKeyVerifier serverKeyVerifier = ValidateUtils.checkNotNull(getServerKeyVerifier(), "No server key verifier");
SocketAddress remoteAddress = ioSession.getRemoteAddress();
if (!serverKeyVerifier.verifyServerKey(this, remoteAddress, kex.getServerKey())) {
@@ -692,11 +384,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
@Override
- public void startService(String name) throws Exception {
- throw new IllegalStateException("Starting services is not supported on the client side: " + name);
- }
-
- @Override
public Map<Object, Object> getMetadataMap() {
return metadataMap;
}