Discussion:
[09/12] mina-sshd git commit: [SSHD-859] Moved 'resolveAttribute' method to AttributeRepository
l***@apache.org
2018-11-18 04:55:04 UTC
Permalink
[SSHD-859] Moved 'resolveAttribute' method to AttributeRepository


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

Branch: refs/heads/master
Commit: 8be6ef9dfd63d7558b2c89550143eb52c10cc39f
Parents: 71516eb
Author: Lyor Goldstein <***@apache.org>
Authored: Tue Nov 13 08:21:30 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 9 ++++++---
.../org/apache/sshd/common/AttributeRepository.java | 13 +++++++++++++
.../java/org/apache/sshd/common/AttributeStore.java | 10 ----------
3 files changed, 19 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8be6ef9d/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 7ed1296..95c17cf 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,10 +2,13 @@

## Major code re-factoring

-* `AttributeKey` moved from `AttributeStore` to `AttributeRepository`
+* `AttributeStore` "read" methods moved to (new class) `AttributeRepository`

-* `getAttribute` moved from `AttributeStore` to `AttributeRepository` + added
-`attributeKeys` method.
+ * `AttributeKey` moved to `AttributeRepository`
+
+ * `getAttribute` and `resolveAttribute` moved to `AttributeRepository`
+
+ * Added `attributeKeys` enumeration method to `AttributeRepository`.

* `DEFAULT_PORT` moved from `SshConfigFileReader` to `SshConstants`


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8be6ef9d/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java b/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java
index f754e87..c197100 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java
@@ -72,6 +72,19 @@ public interface AttributeRepository {
<T> T getAttribute(AttributeKey<T> key);

/**
+ * Attempts to resolve the associated value by going up the store's
+ * hierarchy (if any)
+ *
+ * @param <T> The generic attribute type
+ * @param key The key of the attribute; must not be {@code null}.
+ * @return {@code null} if there is no value associated with the specified key
+ * either in this repository or any of its ancestors (if any available)
+ */
+ default <T> T resolveAttribute(AttributeKey<T> key) {
+ return getAttribute(key);
+ }
+
+ /**
* @return A {@link Collection} <u>snapshot</u> of all the currently registered
* attributes in the repository
*/

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8be6ef9d/sshd-common/src/main/java/org/apache/sshd/common/AttributeStore.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/AttributeStore.java b/sshd-common/src/main/java/org/apache/sshd/common/AttributeStore.java
index cc5665a..466cafe 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/AttributeStore.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/AttributeStore.java
@@ -77,15 +77,5 @@ public interface AttributeStore extends AttributeRepository {
* @return The removed value; {@code null} if no previous value
*/
<T> T removeAttribute(AttributeKey<T> key);
-
- /**
- * Attempts to resolve the associated value by going up the store's
- * hierarchy (if any)
- *
- * @param <T> The generic attribute type
- * @param key The key of the attribute; must not be {@code null}.
- * @return {@code null} if there is no value associated with the specified key
- */
- <T> T resolveAttribute(AttributeKey<T> key);
}
l***@apache.org
2018-11-18 04:55:01 UTC
Permalink
[SSHD-850] Updated CHANGES.md to reflect correctly latest changes to FilePasswordProvider


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

Branch: refs/heads/master
Commit: 71516ebb633e1feb153b915f6e6dc6725df9423e
Parents: 34ac8a7
Author: Lyor Goldstein <***@apache.org>
Authored: Tue Nov 13 08:12:44 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 41 ++++++++++++++------
.../sshd/client/config/keys/ClientIdentity.java | 10 ++---
.../sshd/common/config/keys/IdentityUtils.java | 2 +-
.../common/util/security/SecurityUtils.java | 2 +-
.../common/util/security/SecurityUtilsTest.java | 17 +++++---
.../java/org/apache/sshd/client/SshClient.java | 4 +-
.../openpgp/PGPKeyPairResourceParserTest.java | 5 ++-
.../keys/loader/putty/PuttyKeyUtilsTest.java | 4 +-
8 files changed, 56 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index cc604ce..7ed1296 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,8 +12,8 @@
* Added new `sessionDisconnect` method to `SessionListener`

* `ReservedSessionMessagesHandler#handleUnimplementedMessage` has an extra `cmd` argument
-and is called both for `SSH_MSG_UNIMPLEMENTED` and also for any unexpected/unrecognized command
-encountered during the session message processing loop.
+and is called both for `SSH_MSG_UNIMPLEMENTED` as well as for any other unexpected/unrecognized
+command encountered during the session message processing loop.

* `ClientSessionCreator` has extra `connect` methods with an `AttributeRepository`
connection context argument
@@ -22,22 +22,41 @@ connection context argument
accept also an `AttributeRepository` connection context argument (propagated from the
`ClientSessionCreator#connect` invocation).

-* `FilePasswordProvider` has an extra method (`handleDecodeAttemptResult`) that enables
-user to try and repeat an encrypted private key decoding using a different password. Furthermore,
-the interface methods are also provided with a retry index that indicates the number of the time
-they have ben re-invoked for the same resource (including on success).
+* `FilePasswordProvider`
+
+ * Added an extra method (`handleDecodeAttemptResult`) that enables users to try and repeat an
+ encrypted private key decoding using a different password.
+
+ * The interface methods are also provided with a retry index that indicates the number of
+ times they have been re-invoked for the same resource (including on success).

* `SshAgent#getIdentities` returns an `Iterable` rather than a `List`

* `SftpFileSystemProvider` and its associated helper classes have been moved to
`org.apache.sshd.client.subsystem.sftp.fs` package

-* Added `SftpFileSystemClientSessionInitializer` support in `SftpFileSystemProvider`
+## Behavioral changes and enhancements
+
+* [SSHD-849](https://issues.apache.org/jira/browse/SSHD-849) - Data forwarding code makes sure all
+pending packets have been sent to the peer channel when closing the tunnel gracefully.
+
+* [SSHD-850](https://issues.apache.org/jira/browse/SSHD-850) - Add capability to retry a failed private key decryption
+
+* [SSHD-857](https://issues.apache.org/jira/browse/SSHD-857) - Add session disconnect event signalling to SessionListener
+
+ * Also calling `ReservedSessionMessagesHandler#handleUnimplementedMessage` not only for `SSH_MSG_UNIMPLEMENTED` but
+ also for any unexpected/unrecognized command encountered during the session message processing loop.
+
+* [SSHD-859](https://issues.apache.org/jira/browse/SSHD-859) - Provide client session connection context that is propagated to the SSH session
+
+ * Also added connection context argument (propagated from the `ClientSessionCreator#connect` invocation)
+ to`connectionEstablished` and `abortEstablishedConnection` methods of `IoServiceEventListener`.

-## Behavioral changes
+* [SSHD-860](https://issues.apache.org/jira/browse/SSHD-860) - `UserAuthPublicKeyIterator` uses lazy loading of public key
+identities both from agent and client session

-* [SSHD-860](https://issues.apache.org/jira/browse/SSHD-860)
+ * Also using lazy identity `KeyPair`(s) loading in `ClientIdentitiesWatcher`

- * `UserAuthPublicKeyIterator` uses lazy loading of public key identities both from agent and client session
+* [SSHD-861](https://issues.apache.org/jira/browse/SSHD-861) - Fixed username/password encoding for `SftpFileSystem` URI(s)

- * Using lazy identity `KeyPair`(s) loading in `ClientIdentitiesWatcher`
+ * Also added `SftpFileSystemClientSessionInitializer` support in `SftpFileSystemProvider`

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
index 931d96f..13f5c34 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
@@ -101,7 +101,7 @@ public final class ClientIdentity {
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -126,7 +126,7 @@ public final class ClientIdentity {
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -149,7 +149,7 @@ public final class ClientIdentity {
* access rights are excluded from consideration
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -171,7 +171,7 @@ public final class ClientIdentity {
* access rights are excluded from consideration
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -198,7 +198,7 @@ public final class ClientIdentity {
* holding the specified type
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
index fbc3ce7..9cf3859 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
@@ -127,7 +127,7 @@ public final class IdentityUtils {
* <U>insensitive</U>), value=the {@link Path} of file with the identity key
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link OpenOption}s to use when reading the key data
* @return A {@link Map} of the identities where key=identity type (case

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
index e05f429..1534f95 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
@@ -469,7 +469,7 @@ public final class SecurityUtils {

/**
* @param resourceKey An identifier of the key being loaded - used as
- * argument to the {@link FilePasswordProvider#getPassword(String)}
+ * argument to the {@link FilePasswordProvider#getPassword(String, int)}
* invocation
* @param inputStream The {@link InputStream} for the <U>private</U> key
* @param provider A {@link FilePasswordProvider} - may be {@code null}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
index f244fd4..cdb4967 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
@@ -107,7 +107,8 @@ public class SecurityUtilsTest extends JUnitTestSupport {
}
}

- private KeyPair testLoadEncryptedRSAPrivateKey(String algorithm) throws IOException, GeneralSecurityException {
+ private KeyPair testLoadEncryptedRSAPrivateKey(String algorithm)
+ throws IOException, GeneralSecurityException {
return testLoadRSAPrivateKey(DEFAULT_PASSWORD.replace(' ', '-') + "-RSA-" + algorithm.toUpperCase() + "-key");
}

@@ -146,8 +147,9 @@ public class SecurityUtilsTest extends JUnitTestSupport {
return testLoadPrivateKey(name, RSAPublicKey.class, RSAPrivateKey.class);
}

- private KeyPair testLoadPrivateKey(String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
- throws IOException, GeneralSecurityException {
+ private KeyPair testLoadPrivateKey(
+ String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
+ throws IOException, GeneralSecurityException {
Path folder = getTestResourcesFolder();
Path file = folder.resolve(name);
KeyPair kpFile = testLoadPrivateKeyFile(file, pubType, prvType);
@@ -167,15 +169,18 @@ public class SecurityUtilsTest extends JUnitTestSupport {
return kpResource;
}

- private static KeyPair testLoadPrivateKeyResource(String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
+ private static KeyPair testLoadPrivateKeyResource(
+ String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
return testLoadPrivateKey(name, new ClassLoadableResourceKeyPairProvider(name), pubType, prvType);
}

- private static KeyPair testLoadPrivateKeyFile(Path file, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
+ private static KeyPair testLoadPrivateKeyFile(
+ Path file, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
return testLoadPrivateKey(file.toString(), new FileKeyPairProvider(file), pubType, prvType);
}

- private static KeyPair testLoadPrivateKey(String resourceKey, AbstractResourceKeyPairProvider<?> provider,
+ private static KeyPair testLoadPrivateKey(
+ String resourceKey, AbstractResourceKeyPairProvider<?> provider,
Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
provider.setPasswordFinder(TEST_PASSWORD_PROVIDER);
Iterable<KeyPair> iterator = provider.loadKeys();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/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 227a4d5..6c3e9c8 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
@@ -792,7 +792,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -818,7 +818,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
+ * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java b/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
index bf2b8bb..6bb2f70 100644
--- a/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
+++ b/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
@@ -67,14 +67,15 @@ public class PGPKeyPairResourceParserTest extends JUnitTestSupport {
this.resourceName = resourceName;
this.result = result;
this.passwordProvider = new FilePasswordProvider() {
-
@Override
@SuppressWarnings("synthetic-access")
public String getPassword(String resourceKey, int retryIndex) throws IOException {
switch (result) {
case IGNORE:
case TERMINATE:
- return "qweryuiop123456!@#$%^";
+ assertEquals("Mismatched retries invocation count", 0, retryIndex);
+ assertEquals("Mismatched retries tracking count", retryIndex, retriesCount.get());
+ return "qwertyuiop123456!@#$%^";
case RETRY: {
int count = retriesCount.incrementAndGet();
assertEquals("Mismatched retries count", count, retryIndex + 1);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/71516ebb/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java b/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
index 3cf2b4f..8f1f2eb 100644
--- a/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
+++ b/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
@@ -147,7 +147,9 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {
switch (result) {
case IGNORE:
case TERMINATE:
- return "qweryuiop123456!@#$%^";
+ assertEquals("Mismatched retries invocation count", 0, retryIndex);
+ assertEquals("Mismatched retries tracking count", retryIndex, retriesCount.get());
+ return "qwertyuiop123456!@#$%^";
case RETRY: {
int count = retriesCount.incrementAndGet();
assertEquals("Mismatched retries count", retryIndex + 1, count);
l***@apache.org
2018-11-18 04:55:02 UTC
Permalink
[SSHD-862] Re-factored ApacheSshdSftpSessionFactory to lazy-load the private key (if any) only after session established


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

Branch: refs/heads/master
Commit: 20be0e9d05427ae65e3ea5e2f61205fe69ff9def
Parents: 210f638
Author: Lyor Goldstein <***@apache.org>
Authored: Wed Nov 14 07:42:17 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 2 +
.../keys/FilePasswordProviderManager.java | 36 +++++
.../sshd/client/ClientFactoryManager.java | 12 +-
.../sftp/ApacheSshdSftpSessionFactory.java | 142 +++++++++++++------
4 files changed, 142 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20be0e9d/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index a07e953..57d53f6 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -46,6 +46,8 @@ accept also an `AttributeRepository` connection context argument (propagated fro

* `ClientIdentityProvider` accepts a `SessionContext` argument in its `getClientIdentity` method

+* `ApacheSshdSftpSessionFactory#get/setPrivateKey` has been renamed to `get/setPrivateKeyLocation`
+
## Behavioral changes and enhancements

* [SSHD-849](https://issues.apache.org/jira/browse/SSHD-849) - Data forwarding code makes sure all

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20be0e9d/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProviderManager.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProviderManager.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProviderManager.java
new file mode 100644
index 0000000..aae151c
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProviderManager.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.config.keys;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface FilePasswordProviderManager {
+ /**
+ * @return The {@link FilePasswordProvider} to use if need to load encrypted
+ * 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/20be0e9d/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 26ca4bd..35b42b1 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
@@ -22,7 +22,7 @@ import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
import org.apache.sshd.client.config.keys.ClientIdentityLoader;
import org.apache.sshd.client.session.ClientProxyConnectorHolder;
import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.config.keys.FilePasswordProviderManager;

/**
* The <code>ClientFactoryManager</code> enable the retrieval of additional
@@ -33,6 +33,7 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider;
public interface ClientFactoryManager
extends FactoryManager,
ClientProxyConnectorHolder,
+ FilePasswordProviderManager,
ClientAuthenticationManager {

/**
@@ -91,13 +92,4 @@ public interface ClientFactoryManager
ClientIdentityLoader getClientIdentityLoader();

void setClientIdentityLoader(ClientIdentityLoader loader);
-
- /**
- * @return The {@link FilePasswordProvider} to use if need to load encrypted
- * 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/20be0e9d/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
----------------------------------------------------------------------
diff --git a/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java b/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
index 3c0a65c..cbd6f22 100644
--- a/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
+++ b/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
@@ -19,7 +19,9 @@

package org.apache.sshd.spring.integration.sftp;

+import java.io.IOException;
import java.io.InputStream;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.Collection;
@@ -40,6 +42,7 @@ import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.auth.MutableBasicCredentials;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.config.keys.FilePasswordProviderManager;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.loader.pem.PEMResourceParserUtils;
import org.apache.sshd.common.future.CloseFuture;
@@ -63,12 +66,9 @@ import org.springframework.integration.file.remote.session.SharedSessionCapable;
public class ApacheSshdSftpSessionFactory
extends AbstractLoggingBean
implements SessionFactory<DirEntry>, SharedSessionCapable,
- MutableBasicCredentials, SimpleClientConfigurator,
+ MutableBasicCredentials, FilePasswordProviderManager, SimpleClientConfigurator,
InitializingBean, DisposableBean {

- // TODO add support for loading multiple private keys
- protected volatile KeyPair privateKeyPair;
-
private final boolean sharedSession;
private final AtomicReference<ClientSession> sharedSessionHolder = new AtomicReference<>();

@@ -76,8 +76,11 @@ public class ApacheSshdSftpSessionFactory
private volatile int portValue = SshConstants.DEFAULT_PORT;
private volatile String userValue;
private volatile String passwordValue;
+ // TODO add support for loading multiple private keys
+ private volatile KeyPair privateKeyPair;
private volatile Resource privateKey;
private volatile String privateKeyPassphrase;
+ private volatile FilePasswordProvider passwordProvider;
private volatile Properties sessionConfig;
private volatile long connTimeout = DEFAULT_CONNECT_TIMEOUT;
private volatile long authTimeout = DEFAULT_AUTHENTICATION_TIMEOUT;
@@ -142,17 +145,17 @@ public class ApacheSshdSftpSessionFactory

/**
* The password to authenticate against the remote host. If a password is
- * not provided, then a {@link #setPrivateKey(Resource)} call is mandatory.
+ * not provided, then a {@link #setPrivateKeyLocation(Resource)} call is mandatory.
*
* @param password The password to use - if {@code null} then no password
- * is set - in which case the {@link #getPrivateKey()} resource is used
+ * is set - in which case the {@link #getPrivateKeyLocation()} resource is used
*/
@Override
public void setPassword(String password) {
this.passwordValue = password;
}

- public Resource getPrivateKey() {
+ public Resource getPrivateKeyLocation() {
return privateKey;
}

@@ -163,7 +166,7 @@ public class ApacheSshdSftpSessionFactory
*
* @param privateKey The private key {@link Resource}
*/
- public void setPrivateKey(Resource privateKey) {
+ public void setPrivateKeyLocation(Resource privateKey) {
this.privateKey = privateKey;
}

@@ -179,6 +182,16 @@ public class ApacheSshdSftpSessionFactory
this.privateKeyPassphrase = privateKeyPassphrase;
}

+ @Override
+ public FilePasswordProvider getFilePasswordProvider() {
+ return passwordProvider;
+ }
+
+ @Override
+ public void setFilePasswordProvider(FilePasswordProvider provider) {
+ this.passwordProvider = provider;
+ }
+
public KeyPair getPrivateKeyPair() {
return privateKeyPair;
}
@@ -268,11 +281,12 @@ public class ApacheSshdSftpSessionFactory
synchronized (sharedSessionHolder) {
sharedSession = sharedSessionHolder.getAndSet(null);
}
+
if (sharedSession != null) {
log.info("resetSharedSession - session={}", sharedSession);
sharedSession.close(false).addListener(new SshFutureListener<CloseFuture>() {
- @SuppressWarnings("synthetic-access")
@Override
+ @SuppressWarnings("synthetic-access")
public void operationComplete(CloseFuture future) {
log.info("resetSharedSession - session closed: {}", sharedSession);
}
@@ -283,15 +297,10 @@ public class ApacheSshdSftpSessionFactory
@Override
public void afterPropertiesSet() throws Exception {
KeyPair kp = getPrivateKeyPair();
- if (kp == null) {
- Resource privateKeyLocation = getPrivateKey();
- if (privateKeyLocation != null) {
- kp = loadPrivateKey(privateKeyLocation, getPrivateKeyPassphrase());
- log.info("afterPropertiesSet() - loaded private key={}", privateKeyLocation);
- setPrivateKeyPair(kp);
- }
- }
- ValidateUtils.checkState(GenericUtils.isNotEmpty(getPassword()) || (kp != null), "Either password or private key must be set");
+ Resource privateKeyLocation = getPrivateKeyLocation();
+ ValidateUtils.checkState(
+ GenericUtils.isNotEmpty(getPassword()) || (kp != null) || (privateKeyLocation != null),
+ "Either password or private key must be provided");

SshClient client = getSshClient();
if (client == null) {
@@ -320,19 +329,66 @@ public class ApacheSshdSftpSessionFactory
}
}

- protected KeyPair loadPrivateKey(Resource keyResource, String keyPassword) throws Exception {
- FilePasswordProvider passwordProvider = GenericUtils.isEmpty(keyPassword)
- ? FilePasswordProvider.EMPTY
- : FilePasswordProvider.of(keyPassword);
+ protected KeyPair resolveKeyIdentity(ClientSession session) throws IOException, GeneralSecurityException {
+ KeyPair kp = getPrivateKeyPair();
+ if (kp != null) {
+ return kp;
+ }
+
+ Resource location = getPrivateKeyLocation();
+ if (location == null) {
+ return null;
+ }
+
+ kp = loadPrivateKey(session, location, getPrivateKeyPassphrase());
+ if (kp != null) {
+ setPrivateKeyPair(kp); // cache it for re-use
+ }
+
+ return kp;
+ }
+
+ protected FilePasswordProvider resolveFilePasswordProvider(ClientSession session, Resource keyResource, String keyPassword) {
+ FilePasswordProvider provider = getFilePasswordProvider();
+ if (provider != null) {
+ return provider;
+ }
+
+ return GenericUtils.isEmpty(keyPassword)
+ ? FilePasswordProvider.EMPTY
+ : FilePasswordProvider.of(keyPassword);
+ }
+
+ protected KeyPair loadPrivateKey(ClientSession session, Resource keyResource, String keyPassword)
+ throws IOException, GeneralSecurityException {
+ boolean debugEnabled = log.isDebugEnabled();
+ if (debugEnabled) {
+ log.debug("loadPrivateKey({}) loading from {}", session, keyResource);
+ }
+
+ FilePasswordProvider provider = resolveFilePasswordProvider(session, keyResource, keyPassword);
Collection<KeyPair> keyPairs;
try (InputStream inputStream = keyResource.getInputStream()) {
- keyPairs = PEMResourceParserUtils.PROXY.loadKeyPairs(keyResource.toString(), passwordProvider, inputStream);
+ keyPairs = PEMResourceParserUtils.PROXY.loadKeyPairs(keyResource.toString(), provider, inputStream);
}

int numLoaded = GenericUtils.size(keyPairs);
- ValidateUtils.checkState(numLoaded > 0, "No keys loaded from %s", keyResource);
+ if (numLoaded <= 0) {
+ if (debugEnabled) {
+ log.debug("loadPrivateKey({}) no keys loaded from {}", session, keyResource);
+ }
+ }
+
+ // TODO add support for multiple keys
ValidateUtils.checkState(numLoaded == 1, "Multiple keys loaded from %s", keyResource);
- return keyPairs.iterator().next();
+
+ KeyPair kp = GenericUtils.head(keyPairs);
+ if (debugEnabled) {
+ PublicKey pubKey = kp.getPublic();
+ log.debug("loadPrivateKey({}) loaded {} key={} from {}",
+ session, KeyUtils.getKeyType(pubKey), KeyUtils.getFingerPrint(pubKey), keyResource);
+ }
+ return kp;
}

@Override
@@ -344,7 +400,8 @@ public class ApacheSshdSftpSessionFactory
session = resolveClientSession(sharedInstance);

SftpVersionSelector selector = getSftpVersionSelector();
- SftpClient sftpClient = SftpClientFactory.instance().createSftpClient(session, selector);
+ SftpClientFactory sftpFactory = SftpClientFactory.instance();
+ SftpClient sftpClient = sftpFactory.createSftpClient(session, selector);
try {
ClientSession sessionInstance = session;
Session<DirEntry> result = sharedInstance
@@ -402,14 +459,10 @@ public class ApacheSshdSftpSessionFactory
protected ClientSession createClientSession() throws Exception {
String hostname = ValidateUtils.checkNotNullAndNotEmpty(getHost(), "Host must not be empty");
String username = ValidateUtils.checkNotNullAndNotEmpty(getUsername(), "User must not be empty");
- String passwordIdentity = getPassword();
- KeyPair kp = getPrivateKeyPair();
- ValidateUtils.checkState(GenericUtils.isNotEmpty(passwordIdentity) || (kp != null),
- "Either password or private key must be set");
ClientSession session = createClientSession(hostname, username, getPort(), getEffectiveTimeoutValue(getConnectTimeout()));
try {
session = configureClientSessionProperties(session, getSessionConfig());
- session = authenticateClientSession(session, passwordIdentity, kp, getEffectiveTimeoutValue(getAuthenticationTimeout()));
+ session = authenticateClientSession(session, getEffectiveTimeoutValue(getAuthenticationTimeout()));

ClientSession newSession = session;
if (log.isDebugEnabled()) {
@@ -424,7 +477,7 @@ public class ApacheSshdSftpSessionFactory
}
}

- protected ClientSession createClientSession(String hostname, String username, int port, long timeout) throws Exception {
+ protected ClientSession createClientSession(String hostname, String username, int port, long timeout) throws IOException {
SshClient client = getSshClient();
if (log.isDebugEnabled()) {
log.debug("createClientSession({}@{}:{}) waitTimeout={}", username, hostname, port, timeout);
@@ -433,7 +486,7 @@ public class ApacheSshdSftpSessionFactory
return connectFuture.verify(timeout).getSession();
}

- protected ClientSession configureClientSessionProperties(ClientSession session, Properties props) throws Exception {
+ protected ClientSession configureClientSessionProperties(ClientSession session, Properties props) throws IOException {
if (GenericUtils.isEmpty(props)) {
return session;
}
@@ -450,22 +503,31 @@ public class ApacheSshdSftpSessionFactory
return session;
}

- protected ClientSession authenticateClientSession(
- ClientSession session, String passwordIdentity, KeyPair privateKeyIdentity, long timeout) throws Exception {
- if (log.isDebugEnabled()) {
- PublicKey key = (privateKeyIdentity == null) ? null : privateKeyIdentity.getPublic();
- log.debug("authenticateClientSession({}) password?={}, key={}/{}",
- session, GenericUtils.isNotEmpty(passwordIdentity), KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
- }
+ protected ClientSession authenticateClientSession(ClientSession session, long timeout)
+ throws IOException, GeneralSecurityException {
+ boolean debugEnabled = log.isDebugEnabled();

+ String passwordIdentity = getPassword();
if (GenericUtils.isNotEmpty(passwordIdentity)) {
+ if (debugEnabled) {
+ log.debug("authenticateClientSession({}) using password identity", session);
+ }
session.addPasswordIdentity(passwordIdentity);
}

+ KeyPair privateKeyIdentity = resolveKeyIdentity(session);
if (privateKeyIdentity != null) {
+ if (debugEnabled) {
+ PublicKey pubKey = privateKeyIdentity.getPublic();
+ log.debug("authenticateClientSession({}) using {} key={}",
+ session, KeyUtils.getKeyType(pubKey), KeyUtils.getFingerPrint(pubKey));
+ }
session.addPublicKeyIdentity(privateKeyIdentity);
}

+ if (debugEnabled) {
+ log.debug("authenticateClientSession({}) authenticate - timeout=", session, timeout);
+ }
session.auth().verify(timeout);
return session;
}
l***@apache.org
2018-11-18 04:55:00 UTC
Permalink
[SSHD-862] Established SessionContext 'succinct' representation of a session


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

Branch: refs/heads/master
Commit: c649ac5abc008215d95268ad0df5d80dbe12c065
Parents: 8be6ef9
Author: Lyor Goldstein <***@apache.org>
Authored: Tue Nov 13 08:22:40 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 2 +
.../apache/sshd/common/PropertyResolver.java | 5 +-
.../sshd/common/session/SessionContext.java | 96 ++++++++++++++++++++
.../util/net/ConnectionEndpointsIndicator.java | 37 ++++++++
.../client/session/AbstractClientSession.java | 4 +-
.../forward/ExplicitPortForwardingTracker.java | 4 +-
.../org/apache/sshd/common/io/IoSession.java | 15 +--
.../org/apache/sshd/common/session/Session.java | 83 ++++-------------
.../common/session/helpers/AbstractSession.java | 2 +-
.../common/session/helpers/SessionHelper.java | 7 +-
.../server/channel/PuttyRequestHandler.java | 7 +-
.../server/session/AbstractServerSession.java | 4 +-
.../session/helpers/AbstractSessionTest.java | 5 +-
.../java/org/apache/sshd/server/ServerTest.java | 5 +-
14 files changed, 181 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 95c17cf..8af2a71 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,8 @@

* `DEFAULT_PORT` moved from `SshConfigFileReader` to `SshConstants`

+* Moved some session "summary" related definitions from `Session` to `SessionContext` (which `Session` extends)
+
* Added new `sessionDisconnect` method to `SessionListener`

* `ReservedSessionMessagesHandler#handleUnimplementedMessage` has an extra `cmd` argument

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java b/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java
index 91c3d41..d7f5f19 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java
@@ -57,7 +57,7 @@ public interface PropertyResolver {

/**
* @return The parent resolver that can be used to query for missing
- * properties - {@code null} if no parent
+ * properties - {@code null} if no parent
*/
PropertyResolver getParentPropertyResolver();

@@ -81,7 +81,8 @@ public interface PropertyResolver {
* be converted into one.
* </P>
*
- * @return a valid <code>Map</code> containing configuration values, never {@code null}
+ * @return a valid <code>Map</code> containing configuration values, never {@code null}.
+ * <b>Note:</b> may be immutable.
*/
Map<String, Object> getProperties();


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
new file mode 100644
index 0000000..87827bd
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.session;
+
+import org.apache.sshd.common.AttributeRepository;
+import org.apache.sshd.common.PropertyResolver;
+import org.apache.sshd.common.auth.UsernameHolder;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.net.ConnectionEndpointsIndicator;
+
+/**
+ * A &quot;succinct&quot; summary of the most important attributes of an SSH session
+ *
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface SessionContext
+ extends ConnectionEndpointsIndicator,
+ UsernameHolder,
+ PropertyResolver,
+ AttributeRepository {
+ /**
+ * Default prefix expected for the client / server identification string
+ * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253 - section 4.2</A>
+ */
+ String DEFAULT_SSH_VERSION_PREFIX = "SSH-2.0-";
+
+ /**
+ * Backward compatible special prefix
+ * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-5">RFC 4253 - section 5</A>
+ */
+ String FALLBACK_SSH_VERSION_PREFIX = "SSH-1.99-";
+
+ /**
+ * Maximum number of characters for any single line sent as part
+ * of the initial handshake - according to
+ * <A HREF="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253 - section 4.2</A>:</BR>
+ *
+ * <P><CODE>
+ * The maximum length of the string is 255 characters,
+ * including the Carriage Return and Line Feed.
+ * </CODE></P>
+ */
+ int MAX_VERSION_LINE_LENGTH = 256;
+
+ /**
+ * @return A <U>clone</U> of the established session identifier - {@code null} if
+ * not yet established
+ */
+ byte[] getSessionId();
+
+ /**
+ * Retrieve the client version for this session.
+ *
+ * @return the client version - may be {@code null}/empty if versions not yet exchanged
+ */
+ String getClientVersion();
+
+ /**
+ * Retrieve the server version for this session.
+ *
+ * @return the server version - may be {@code null}/empty if versions not yet exchanged
+ */
+ String getServerVersion();
+
+ /**
+ * @return {@code true} if session has successfully completed the authentication phase
+ */
+ boolean isAuthenticated();
+
+ /**
+ * @param version The reported client/server version
+ * @return {@code true} if version not empty and starts with either
+ * {@value #DEFAULT_SSH_VERSION_PREFIX} or {@value #FALLBACK_SSH_VERSION_PREFIX}
+ */
+ static boolean isValidVersionPrefix(String version) {
+ return GenericUtils.isNotEmpty(version)
+ && (version.startsWith(DEFAULT_SSH_VERSION_PREFIX) || version.startsWith(FALLBACK_SSH_VERSION_PREFIX));
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-common/src/main/java/org/apache/sshd/common/util/net/ConnectionEndpointsIndicator.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/net/ConnectionEndpointsIndicator.java b/sshd-common/src/main/java/org/apache/sshd/common/util/net/ConnectionEndpointsIndicator.java
new file mode 100644
index 0000000..9d56e13
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/net/ConnectionEndpointsIndicator.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.net;
+
+import java.net.SocketAddress;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ConnectionEndpointsIndicator {
+ /**
+ * @return the socket address of remote peer.
+ */
+ SocketAddress getRemoteAddress();
+
+ /**
+ * @return the socket address of local machine which is associated with this session.
+ */
+ SocketAddress getLocalAddress();
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/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
index 3fac01c..1c329ef 100644
--- 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
@@ -59,7 +59,7 @@ import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.kex.KexState;
import org.apache.sshd.common.session.ConnectionService;
-import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.session.helpers.AbstractConnectionService;
import org.apache.sshd.common.session.helpers.AbstractSession;
import org.apache.sshd.common.util.GenericUtils;
@@ -392,7 +392,7 @@ public abstract class AbstractClientSession extends AbstractSession implements C
log.debug("readIdentification({}) Server version string: {}", this, serverVersion);
}

- if (!Session.isValidVersionPrefix(serverVersion)) {
+ if (!SessionContext.isValidVersionPrefix(serverVersion)) {
throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
"Unsupported protocol version: " + serverVersion);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/client/session/forward/ExplicitPortForwardingTracker.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/forward/ExplicitPortForwardingTracker.java b/sshd-core/src/main/java/org/apache/sshd/client/session/forward/ExplicitPortForwardingTracker.java
index b8642ed..08cfefc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/forward/ExplicitPortForwardingTracker.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/forward/ExplicitPortForwardingTracker.java
@@ -24,12 +24,13 @@ import java.util.Objects;

import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.forward.PortForwardingManager;
+import org.apache.sshd.common.util.net.ConnectionEndpointsIndicator;
import org.apache.sshd.common.util.net.SshdSocketAddress;

/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public class ExplicitPortForwardingTracker extends PortForwardingTracker {
+public class ExplicitPortForwardingTracker extends PortForwardingTracker implements ConnectionEndpointsIndicator {
private final boolean localForwarding;
private final SshdSocketAddress remoteAddress;

@@ -44,6 +45,7 @@ public class ExplicitPortForwardingTracker extends PortForwardingTracker {
return localForwarding;
}

+ @Override
public SshdSocketAddress getRemoteAddress() {
return remoteAddress;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
index 3a3545c..c110eae 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
@@ -18,11 +18,10 @@
*/
package org.apache.sshd.common.io;

-import java.net.SocketAddress;
-
import org.apache.sshd.common.Closeable;
+import org.apache.sshd.common.util.net.ConnectionEndpointsIndicator;

-public interface IoSession extends PacketWriter, Closeable {
+public interface IoSession extends ConnectionEndpointsIndicator, PacketWriter, Closeable {

/**
* @return a unique identifier for this session. Every session has its own
@@ -74,16 +73,6 @@ public interface IoSession extends PacketWriter, Closeable {
Object removeAttribute(Object key);

/**
- * @return the socket address of remote peer.
- */
- SocketAddress getRemoteAddress();
-
- /**
- * @return the socket address of local machine which is associated with this session.
- */
- SocketAddress getLocalAddress();
-
- /**
* @return the {@link IoService} that created this session.
*/
IoService getService();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
index 06516da..0ecab07 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
@@ -19,6 +19,7 @@
package org.apache.sshd.common.session;

import java.io.IOException;
+import java.net.SocketAddress;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@@ -27,7 +28,6 @@ import org.apache.sshd.common.AttributeStore;
import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.FactoryManagerHolder;
-import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.Service;
import org.apache.sshd.common.auth.MutableUserHolder;
import org.apache.sshd.common.channel.ChannelListenerManager;
@@ -44,7 +44,6 @@ import org.apache.sshd.common.kex.KexFactoryManager;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.kex.KeyExchange;
import org.apache.sshd.common.mac.MacInformation;
-import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;

/**
@@ -54,7 +53,10 @@ import org.apache.sshd.common.util.buffer.Buffer;
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
*/
public interface Session
- extends KexFactoryManager,
+ extends SessionContext,
+ AttributeStore,
+ MutableUserHolder,
+ KexFactoryManager,
SessionListenerManager,
ReservedSessionMessagesManager,
ChannelListenerManager,
@@ -63,35 +65,8 @@ public interface Session
UnknownChannelReferenceHandlerManager,
FactoryManagerHolder,
PortForwardingInformationProvider,
- PropertyResolver,
- AttributeStore,
- Closeable,
- MutableUserHolder,
- PacketWriter {
-
- /**
- * Default prefix expected for the client / server identification string
- * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253 - section 4.2</A>
- */
- String DEFAULT_SSH_VERSION_PREFIX = "SSH-2.0-";
-
- /**
- * Backward compatible special prefix
- * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-5">RFC 4253 - section 5</A>
- */
- String FALLBACK_SSH_VERSION_PREFIX = "SSH-1.99-";
-
- /**
- * Maximum number of characters for any single line sent as part
- * of the initial handshake - according to
- * <A HREF="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253 - section 4.2</A>:</BR>
- *
- * <P><CODE>
- * The maximum length of the string is 255 characters,
- * including the Carriage Return and Line Feed.
- * </CODE></P>
- */
- int MAX_VERSION_LINE_LENGTH = 256;
+ PacketWriter,
+ Closeable {

/**
* Timeout status.
@@ -103,20 +78,6 @@ public interface Session
}

/**
- * Retrieve the client version for this session.
- *
- * @return the client version.
- */
- String getClientVersion();
-
- /**
- * Retrieve the server version for this session.
- *
- * @return the server version.
- */
- String getServerVersion();
-
- /**
* Retrieve one of the negotiated values during the KEX stage
*
* @param paramType The request {@link KexProposalOption} value
@@ -273,6 +234,18 @@ public interface Session
*/
IoSession getIoSession();

+ @Override
+ default SocketAddress getLocalAddress() {
+ IoSession s = getIoSession();
+ return (s == null) ? null : s.getLocalAddress();
+ }
+
+ @Override
+ default SocketAddress getRemoteAddress() {
+ IoSession s = getIoSession();
+ return (s == null) ? null : s.getRemoteAddress();
+ }
+
/**
* Check if timeout has occurred.
*
@@ -298,8 +271,6 @@ public interface Session
*/
long resetIdleTimeout();

- boolean isAuthenticated();
-
/**
* @return Timeout value in milliseconds for authentication stage
*/
@@ -320,12 +291,6 @@ public interface Session

void setAuthenticated() throws IOException;

- /**
- * @return The established session identifier - {@code null} if
- * not yet established
- */
- byte[] getSessionId();
-
KeyExchange getKex();

/**
@@ -351,16 +316,6 @@ public interface Session
}

/**
- * @param version The reported client/server version
- * @return {@code true} if version not empty and starts with either
- * {@value #DEFAULT_SSH_VERSION_PREFIX} or {@value #FALLBACK_SSH_VERSION_PREFIX}
- */
- static boolean isValidVersionPrefix(String version) {
- return GenericUtils.isNotEmpty(version)
- && (version.startsWith(DEFAULT_SSH_VERSION_PREFIX) || version.startsWith(FALLBACK_SSH_VERSION_PREFIX));
- }
-
- /**
* Attempts to use the session's attribute, if not found then tries the factory manager
*
* @param <T> The generic attribute type

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
index 1f5efbb..db3b17a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
@@ -282,7 +282,7 @@ public abstract class AbstractSession extends SessionHelper {
decoderBuffer.putBuffer(buffer);
// One of those property will be set by the constructor and the other
// one should be set by the readIdentification method
- if (clientVersion == null || serverVersion == null) {
+ if ((clientVersion == null) || (serverVersion == null)) {
if (readIdentification(decoderBuffer)) {
decoderBuffer.compact();
} else {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
index 25cbf2f..6a4574d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
@@ -60,6 +60,7 @@ import org.apache.sshd.common.random.Random;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.session.ReservedSessionMessagesHandler;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.session.UnknownChannelReferenceHandler;
import org.apache.sshd.common.util.GenericUtils;
@@ -619,7 +620,7 @@ public abstract class SessionHelper extends AbstractKexFactoryManager implements
/**
* Resolves the identification to send to the peer session by consulting
* the associated {@link FactoryManager}. If a value is set, then it is
- * <U>appended</U> to the standard {@link #DEFAULT_SSH_VERSION_PREFIX}.
+ * <U>appended</U> to the standard {@link SessionContext#DEFAULT_SSH_VERSION_PREFIX}.
* Otherwise a default value is returned consisting of the prefix and
* the core artifact name + version in <U>uppercase</U> - e.g.,'
* &quot;SSH-2.0-SSHD-CORE-1.2.3.4&quot;
@@ -630,7 +631,7 @@ public abstract class SessionHelper extends AbstractKexFactoryManager implements
protected String resolveIdentificationString(String configPropName) {
FactoryManager manager = getFactoryManager();
String ident = manager.getString(configPropName);
- return DEFAULT_SSH_VERSION_PREFIX + (GenericUtils.isEmpty(ident) ? manager.getVersion() : ident);
+ return SessionContext.DEFAULT_SSH_VERSION_PREFIX + (GenericUtils.isEmpty(ident) ? manager.getVersion() : ident);
}

/**
@@ -669,7 +670,7 @@ public abstract class SessionHelper extends AbstractKexFactoryManager implements
FactoryManager.MAX_IDENTIFICATION_SIZE, FactoryManager.DEFAULT_MAX_IDENTIFICATION_SIZE);
List<String> ident = null;
int rpos = buffer.rpos();
- for (byte[] data = new byte[MAX_VERSION_LINE_LENGTH];;) {
+ for (byte[] data = new byte[SessionContext.MAX_VERSION_LINE_LENGTH];;) {
int pos = 0; // start accumulating line from scratch
for (boolean needLf = false;;) {
if (buffer.available() == 0) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
index a5eabe1..79a166c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
@@ -27,6 +27,7 @@ import org.apache.sshd.common.channel.AbstractChannelRequestHandler;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.common.channel.PtyMode;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;

@@ -98,12 +99,12 @@ public class PuttyRequestHandler extends AbstractChannelRequestHandler {

/**
* @param clientVersion The client identification string - ignored if {@code null}/empty
- * @return {@code true} if the identification starts with the {@link Session#DEFAULT_SSH_VERSION_PREFIX}
+ * @return {@code true} if the identification starts with the {@link SessionContext#DEFAULT_SSH_VERSION_PREFIX}
* and it contains the &quot;putty&quot; string (case insensitive)
*/
public static boolean isPuttyClient(String clientVersion) {
- return (GenericUtils.length(clientVersion) > Session.DEFAULT_SSH_VERSION_PREFIX.length())
- && clientVersion.startsWith(Session.DEFAULT_SSH_VERSION_PREFIX)
+ return (GenericUtils.length(clientVersion) > SessionContext.DEFAULT_SSH_VERSION_PREFIX.length())
+ && clientVersion.startsWith(SessionContext.DEFAULT_SSH_VERSION_PREFIX)
&& clientVersion.toLowerCase().contains("putty");
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
index 04e7fd0..96053f1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
@@ -43,7 +43,7 @@ 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.session.ConnectionService;
-import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.session.helpers.AbstractSession;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
@@ -358,7 +358,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
}

String errorMessage = null;
- if (!Session.isValidVersionPrefix(clientVersion)) {
+ if (!SessionContext.isValidVersionPrefix(clientVersion)) {
errorMessage = "Unsupported protocol version: " + clientVersion;
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java b/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
index cf6779f..388bc7a 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
@@ -44,6 +44,7 @@ import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.session.ReservedSessionMessagesHandler;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
@@ -120,11 +121,11 @@ public class AbstractSessionTest extends BaseTestSupport {

@Test(expected = IllegalStateException.class)
public void testReadIdentLongLine() {
- StringBuilder sb = new StringBuilder(Session.MAX_VERSION_LINE_LENGTH + Integer.SIZE);
+ StringBuilder sb = new StringBuilder(SessionContext.MAX_VERSION_LINE_LENGTH + Integer.SIZE);
sb.append("SSH-2.0-software");
do {
sb.append("01234567890123456789012345678901234567890123456789");
- } while (sb.length() < Session.MAX_VERSION_LINE_LENGTH);
+ } while (sb.length() < SessionContext.MAX_VERSION_LINE_LENGTH);

Buffer buf = new ByteArrayBuffer(sb.toString().getBytes(StandardCharsets.UTF_8));
String ident = readIdentification(session, buf);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c649ac5a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
index 9944cde..5c3889f 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
@@ -60,6 +60,7 @@ import org.apache.sshd.common.channel.WindowClosedException;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.session.helpers.AbstractConnectionService;
import org.apache.sshd.common.session.helpers.AbstractSession;
@@ -787,11 +788,11 @@ public class ServerTest extends BaseTestSupport {
public void testIdentificationStringsOverrides() throws Exception {
String clientIdent = getCurrentTestName() + "-client";
PropertyResolverUtils.updateProperty(client, ClientFactoryManager.CLIENT_IDENTIFICATION, clientIdent);
- final String expClientIdent = Session.DEFAULT_SSH_VERSION_PREFIX + clientIdent;
+ final String expClientIdent = SessionContext.DEFAULT_SSH_VERSION_PREFIX + clientIdent;

String serverIdent = getCurrentTestName() + "-server";
PropertyResolverUtils.updateProperty(sshd, ServerFactoryManager.SERVER_IDENTIFICATION, serverIdent);
- String expServerIdent = Session.DEFAULT_SSH_VERSION_PREFIX + serverIdent;
+ String expServerIdent = SessionContext.DEFAULT_SSH_VERSION_PREFIX + serverIdent;
SessionListener listener = new SessionListener() {
@Override
public void sessionException(Session session, Throwable t) {
l***@apache.org
2018-11-18 04:55:07 UTC
Permalink
[SSHD-864] Replaced BC deprecated PEMWriter with JCAPemWriter in BouncyCastleGeneratorHostKeyProvider


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

Branch: refs/heads/master
Commit: 025df0e85655c83d99a585a620479b2a44287cb2
Parents: 895f30f
Author: Lyor Goldstein <***@apache.org>
Authored: Thu Nov 15 16:18:51 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:48 2018 +0200

----------------------------------------------------------------------
.../BouncyCastleGeneratorHostKeyProvider.java | 28 +++-
.../AbstractGeneratorHostKeyProvider.java | 4 +-
...ouncyCastleGeneratorHostKeyProviderTest.java | 140 +++++++++++++++++++
3 files changed, 166 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/025df0e8/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
index 534b033..cee48bd 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
@@ -22,12 +22,16 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyPair;

import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;

/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
@@ -37,11 +41,27 @@ public class BouncyCastleGeneratorHostKeyProvider extends AbstractGeneratorHostK
setPath(path);
}

- @SuppressWarnings("deprecation")
@Override
- protected void doWriteKeyPair(NamedResource resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException {
- try (org.bouncycastle.openssl.PEMWriter w =
- new org.bouncycastle.openssl.PEMWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
+ protected void doWriteKeyPair(NamedResource resourceKey, KeyPair kp, OutputStream outputStream)
+ throws IOException, GeneralSecurityException {
+ writePEMKeyPair(kp, outputStream);
+ }
+
+ public static void writePEMKeyPair(KeyPair kp, Path targetPath) throws IOException {
+ writePEMKeyPair(kp, targetPath, IoUtils.EMPTY_OPEN_OPTIONS);
+ }
+
+ public static void writePEMKeyPair(
+ KeyPair kp, Path targetPath, OpenOption... options)
+ throws IOException {
+ try (OutputStream os = Files.newOutputStream(targetPath, options)) {
+ writePEMKeyPair(kp, os);
+ }
+ }
+
+ public static void writePEMKeyPair(KeyPair kp, OutputStream outputStream) throws IOException {
+ try (JcaPEMWriter w = new JcaPEMWriter(
+ new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
w.writeObject(kp);
w.flush();
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/025df0e8/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
index be4ceb5..287abec 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
@@ -118,7 +118,7 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
if ((kp != null) & log.isDebugEnabled()) {
PublicKey key = kp.getPublic();
log.debug("clearLoadedKeys({}) removed key={}-{}",
- getPath(), KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+ getPath(), KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
}
}

@@ -162,7 +162,7 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
}
} catch (Throwable e) {
log.warn("resolveKeyPair({}) Failed ({}) to load: {}",
- keyPath, e.getClass().getSimpleName(), e.getMessage());
+ keyPath, e.getClass().getSimpleName(), e.getMessage());
if (log.isDebugEnabled()) {
log.debug("resolveKeyPair(" + keyPath + ") load failure details", e);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/025df0e8/sshd-common/src/test/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProviderTest.java
new file mode 100644
index 0000000..3bca2e2
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProviderTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.security.bouncycastle;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.config.keys.BuiltinIdentities;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class BouncyCastleGeneratorHostKeyProviderTest extends JUnitTestSupport {
+ private final String keyType;
+ private final int keySize;
+
+ public BouncyCastleGeneratorHostKeyProviderTest(String keyType, int keySize) {
+ this.keyType = keyType;
+ this.keySize = keySize;
+ }
+
+ @Parameters(name = "{0} / {1}")
+ public static List<Object[]> parameters() {
+ if (!SecurityUtils.isBouncyCastleRegistered()) {
+ return Collections.emptyList();
+ }
+
+ List<Object[]> params = new ArrayList<>();
+ for (Integer ks : RSA_SIZES) {
+ params.add(new Object[]{BuiltinIdentities.Constants.RSA, ks});
+ }
+ for (Integer ks : DSS_SIZES) {
+ params.add(new Object[]{BuiltinIdentities.Constants.DSA, ks});
+ }
+
+/* TODO - causes an issue where BC cannot parse its own file
+ if (SecurityUtils.isECCSupported()) {
+ for (ECCurves curve : ECCurves.VALUES) {
+ params.add(new Object[]{BuiltinIdentities.Constants.ECDSA, curve.getKeySize()});
+ }
+ }
+*/
+ return params;
+ }
+
+ @Test
+ public void testKeyReadWrite() throws IOException, GeneralSecurityException {
+ KeyPair expected;
+ if (BuiltinIdentities.Constants.RSA.equalsIgnoreCase(keyType)) {
+ expected = KeyUtils.generateKeyPair(KeyPairProvider.SSH_RSA, keySize);
+ } else if (BuiltinIdentities.Constants.DSA.equalsIgnoreCase(keyType)) {
+ expected = KeyUtils.generateKeyPair(KeyPairProvider.SSH_DSS, keySize);
+ } else if (BuiltinIdentities.Constants.ECDSA.equalsIgnoreCase(keyType)) {
+ ECCurves curve = ECCurves.fromCurveSize(keySize);
+ assertNotNull("No curve for key size=" + keySize, curve);
+ expected = KeyUtils.generateKeyPair(curve.getKeyType(), curve.getKeySize());
+ } else if (BuiltinIdentities.Constants.ED25519.equalsIgnoreCase(keyType)) {
+ KeyPairGenerator g = SecurityUtils.getKeyPairGenerator(SecurityUtils.EDDSA);
+ expected = g.generateKeyPair();
+ } else {
+ throw new InvalidKeyException("Unsupported key type: " + keyType);
+ }
+
+ PublicKey key = expected.getPublic();
+ String keyAlgorithm = key.getAlgorithm();
+ if (BuiltinIdentities.Constants.ECDSA.equalsIgnoreCase(keyAlgorithm)) {
+ keyAlgorithm = KeyUtils.EC_ALGORITHM;
+ } else if (BuiltinIdentities.Constants.ED25519.equalsIgnoreCase(keyAlgorithm)) {
+ keyAlgorithm = SecurityUtils.EDDSA;
+ }
+
+ Path dir = getTempTargetFolder();
+ dir = Files.createDirectories(dir.resolve(getClass().getSimpleName()));
+ Path file = dir.resolve(keyType + "-" + keySize + ".pem");
+ BouncyCastleGeneratorHostKeyProvider.writePEMKeyPair(expected, file);
+
+ AbstractGeneratorHostKeyProvider provider = new BouncyCastleGeneratorHostKeyProvider(file);
+ provider.setAlgorithm(keyAlgorithm);
+
+ Iterable<KeyPair> keys = provider.loadKeys(null);
+ KeyPair actual = null;
+ for (KeyPair k : keys) {
+ assertNull("Unexpected multiple keys loaded", actual);
+ actual = k;
+ }
+
+ assertKeyPairEquals(keyType + "/" + keySize, expected, actual);
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + keyType + "/" + keySize + "]";
+ }
+}
l***@apache.org
2018-11-18 04:54:59 UTC
Permalink
[SSHD-862] Provide session context argument when KeyPairProvider keys access methods are invoked


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

Branch: refs/heads/master
Commit: e05898c8095ee082dd4378d910ac0febf9c7dcac
Parents: c649ac5
Author: Lyor Goldstein <***@apache.org>
Authored: Tue Nov 13 16:51:25 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 5 ++++
.../common/keyprovider/KeyPairProvider.java | 17 ++++++++-----
.../keyprovider/MappedKeyPairProvider.java | 7 +++---
.../common/keyprovider/KeyPairProviderTest.java | 8 +++---
.../PEMGeneratorHostKeyProviderTest.java | 4 +--
.../SimpleGeneratorHostKeyProviderTest.java | 4 +--
.../server/global/OpenSshHostKeysHandler.java | 6 +++--
.../server/session/AbstractServerSession.java | 4 +--
.../java/org/apache/sshd/agent/AgentTest.java | 7 ++++--
.../java/org/apache/sshd/client/ClientTest.java | 6 ++---
.../sshd/common/auth/AuthenticationTest.java | 26 ++++++++++++--------
.../common/auth/SinglePublicKeyAuthTest.java | 5 ++--
12 files changed, 61 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 8af2a71..6751736 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -40,6 +40,8 @@ accept also an `AttributeRepository` connection context argument (propagated fro
* `SftpFileSystemProvider` and its associated helper classes have been moved to
`org.apache.sshd.client.subsystem.sftp.fs` package

+* `KeyPairProvider` accepts a `SessionContext` argument in its `getKeyTypes/loadKey` methods
+
## Behavioral changes and enhancements

* [SSHD-849](https://issues.apache.org/jira/browse/SSHD-849) - Data forwarding code makes sure all
@@ -65,3 +67,6 @@ identities both from agent and client session
* [SSHD-861](https://issues.apache.org/jira/browse/SSHD-861) - Fixed username/password encoding for `SftpFileSystem` URI(s)

* Also added `SftpFileSystemClientSessionInitializer` support in `SftpFileSystemProvider`
+
+* [SSHD-862](https://issues.apache.org/jira/browse/SSHD-862) - Provide session context argument when
+key loading methods are invoked

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
index 3ef9b0f..68c4daf 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
@@ -28,6 +28,7 @@ import java.util.stream.Collectors;

import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;

@@ -75,12 +76,12 @@ public interface KeyPairProvider extends KeyIdentityProvider {
KeyPairProvider EMPTY_KEYPAIR_PROVIDER =
new KeyPairProvider() {
@Override
- public KeyPair loadKey(String type) {
+ public KeyPair loadKey(SessionContext session, String type) {
return null;
}

@Override
- public Iterable<String> getKeyTypes() {
+ public Iterable<String> getKeyTypes(SessionContext session) {
return Collections.emptyList();
}

@@ -100,10 +101,12 @@ public interface KeyPairProvider extends KeyIdentityProvider {
* or &quot;ecdsa-sha2-nistp{256,384,521}&quot;. If there is no key of this type, return
* {@code null}
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool).
* @param type the type of key to load
* @return a valid key pair or {@code null} if this type of key is not available
*/
- default KeyPair loadKey(String type) {
+ default KeyPair loadKey(SessionContext session, String type) {
ValidateUtils.checkNotNullAndNotEmpty(type, "No key type to load");
return GenericUtils.stream(loadKeys())
.filter(key -> type.equals(KeyUtils.getKeyType(key)))
@@ -112,9 +115,11 @@ public interface KeyPairProvider extends KeyIdentityProvider {
}

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool).
* @return The available {@link Iterable} key types in preferred order - never {@code null}
*/
- default Iterable<String> getKeyTypes() {
+ default Iterable<String> getKeyTypes(SessionContext session) {
return GenericUtils.stream(loadKeys())
.map(KeyUtils::getKeyType)
.filter(GenericUtils::isNotEmpty)
@@ -148,7 +153,7 @@ public interface KeyPairProvider extends KeyIdentityProvider {
}

@Override
- public KeyPair loadKey(String type) {
+ public KeyPair loadKey(SessionContext session, String type) {
for (KeyPair kp : pairs) {
String t = KeyUtils.getKeyType(kp);
if (Objects.equals(type, t)) {
@@ -160,7 +165,7 @@ public interface KeyPairProvider extends KeyIdentityProvider {
}

@Override
- public Iterable<String> getKeyTypes() {
+ public Iterable<String> getKeyTypes(SessionContext session) {
// use a LinkedHashSet so as to preserve the order but avoid duplicates
Collection<String> types = new LinkedHashSet<>();
for (KeyPair kp : pairs) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
index bf3ec8b..d8f2350 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
@@ -28,6 +28,7 @@ import java.util.TreeMap;
import java.util.function.Function;

import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;

@@ -66,18 +67,18 @@ public class MappedKeyPairProvider implements KeyPairProvider {
}

@Override
- public KeyPair loadKey(String type) {
+ public KeyPair loadKey(SessionContext session, String type) {
return pairsMap.get(type);
}

@Override
- public Iterable<String> getKeyTypes() {
+ public Iterable<String> getKeyTypes(SessionContext session) {
return pairsMap.keySet();
}

@Override
public String toString() {
- return String.valueOf(getKeyTypes());
+ return String.valueOf(pairsMap.keySet());
}

public static Map<String, KeyPair> mapUniquePairs(Collection<? extends KeyPair> pairs) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
index 021796b..afa55cd 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
@@ -49,10 +49,10 @@ public class KeyPairProviderTest extends JUnitTestSupport {
public void testEmptyKeyProvider() {
KeyPairProvider provider = KeyPairProvider.EMPTY_KEYPAIR_PROVIDER;
assertTrue("Non empty loaded keys", GenericUtils.isEmpty(provider.loadKeys()));
- assertTrue("Non empty key type", GenericUtils.isEmpty(provider.getKeyTypes()));
+ assertTrue("Non empty key type", GenericUtils.isEmpty(provider.getKeyTypes(null)));

for (String keyType : new String[]{null, "", getCurrentTestName()}) {
- assertNull("Unexpected key-pair loaded for type='" + keyType + "'", provider.loadKey(keyType));
+ assertNull("Unexpected key-pair loaded for type='" + keyType + "'", provider.loadKey(null, keyType));
}
}

@@ -68,11 +68,11 @@ public class KeyPairProviderTest extends JUnitTestSupport {
String.CASE_INSENSITIVE_ORDER);

KeyPairProvider provider = MappedKeyPairProvider.MAP_TO_KEY_PAIR_PROVIDER.apply(pairsMap);
- assertEquals("Key types", pairsMap.keySet(), provider.getKeyTypes());
+ assertEquals("Key types", pairsMap.keySet(), provider.getKeyTypes(null));
assertEquals("Key pairs", pairsMap.values(), provider.loadKeys());

pairsMap.forEach((keyType, expected) -> {
- KeyPair actual = provider.loadKey(keyType);
+ KeyPair actual = provider.loadKey(null, keyType);
assertSame(keyType, expected, actual);
});
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
index 3be5b6d..af4a6b7 100644
--- a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
@@ -118,11 +118,11 @@ public class PEMGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

private static KeyPair validateKeyPairProvider(KeyPairProvider provider, String keyType) {
- Iterable<String> types = provider.getKeyTypes();
+ Iterable<String> types = provider.getKeyTypes(null);
KeyPair kp = null;
for (String type : types) {
if (keyType.equals(type)) {
- kp = provider.loadKey(keyType);
+ kp = provider.loadKey(null, keyType);
assertNotNull("Failed to load key for " + keyType, kp);
break;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
index dc5e9fd..ab0ff2c 100644
--- a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
@@ -110,11 +110,11 @@ public class SimpleGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

private static KeyPair validateKeyPairProvider(KeyPairProvider provider, String keyType) {
- Iterable<String> types = provider.getKeyTypes();
+ Iterable<String> types = provider.getKeyTypes(null);
KeyPair kp = null;
for (String type : types) {
if (keyType.equals(type)) {
- kp = provider.loadKey(keyType);
+ kp = provider.loadKey(null, keyType);
assertNotNull("Failed to load key for " + keyType, kp);
break;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
index 0a806aa..35a7d68 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/global/OpenSshHostKeysHandler.java
@@ -84,7 +84,9 @@ public class OpenSshHostKeysHandler extends AbstractOpenSshHostKeysHandler imple
}

@Override
- protected Result handleHostKeys(Session session, Collection<? extends PublicKey> keys, boolean wantReply, Buffer buffer) throws Exception {
+ protected Result handleHostKeys(
+ Session session, Collection<? extends PublicKey> keys, boolean wantReply, Buffer buffer)
+ throws Exception {
// according to the specification there MUST be reply required by the server
ValidateUtils.checkTrue(wantReply, "No reply required for host keys of %s", session);
Collection<? extends NamedFactory<Signature>> factories =
@@ -112,7 +114,7 @@ public class OpenSshHostKeysHandler extends AbstractOpenSshHostKeysHandler imple

KeyPair kp;
try {
- kp = ValidateUtils.checkNotNull(kpp.loadKey(keyType), "No key of type=%s available", keyType);
+ kp = ValidateUtils.checkNotNull(kpp.loadKey(session, keyType), "No key of type=%s available", keyType);
} catch (Error e) {
log.warn("handleHostKeys({}) failed ({}) to load key of type={}: {}",
session, e.getClass().getSimpleName(), keyType, e.getMessage());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
index 96053f1..69f450a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
@@ -258,7 +258,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
boolean debugEnabled = log.isDebugEnabled();
Iterable<String> provided;
try {
- provided = (kpp == null) ? null : kpp.getKeyTypes();
+ provided = (kpp == null) ? null : kpp.getKeyTypes(this);
} catch (Error e) {
log.warn("resolveAvailableSignaturesProposal({}) failed ({}) to get key types: {}",
this, e.getClass().getSimpleName(), e.getMessage());
@@ -394,7 +394,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
String keyType = getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
KeyPairProvider provider = Objects.requireNonNull(getKeyPairProvider(), "No host keys provider");
try {
- return provider.loadKey(keyType);
+ return provider.loadKey(this, keyType);
} catch (Error e) {
log.warn("getHostKey({}) failed ({}) to load key of type={}: {}",
this, e.getClass().getSimpleName(), keyType, e.getMessage());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/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 8f3e4eb..3ce0f5b 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
@@ -36,6 +36,7 @@ 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;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.Environment;
@@ -87,7 +88,8 @@ public class AgentTest extends BaseTestSupport {
assertObjectInstanceOf("Non collection initial identities", Collection.class, keys);
assertEquals("Unexpected initial identities size", 0, ((Collection<?>) keys).size());

- KeyPair k = createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
+ KeyPairProvider provider = createTestHostKeyProvider();
+ KeyPair k = provider.loadKey(null, KeyPairProvider.SSH_RSA);
client.addIdentity(k, "");
keys = client.getIdentities();
assertNotNull("No registered identities after add", keys);
@@ -112,7 +114,8 @@ public class AgentTest extends BaseTestSupport {
ProxyAgentFactory agentFactory = new ProxyAgentFactory();
LocalAgentFactory localAgentFactory = new LocalAgentFactory();
String username = getCurrentTestName();
- KeyPair pair = CommonTestSupportUtils.createTestKeyPairProvider("dsaprivkey.pem").loadKey(KeyPairProvider.SSH_DSS);
+ FileKeyPairProvider provider = CommonTestSupportUtils.createTestKeyPairProvider("dsaprivkey.pem");
+ KeyPair pair = provider.loadKey(null, KeyPairProvider.SSH_DSS);
localAgentFactory.getAgent().addIdentity(pair, username);

try (SshServer sshd1 = setupTestServer()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
index 1fa090a..11ef70e 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
@@ -1041,7 +1041,7 @@ public class ClientTest extends BaseTestSupport {
.getSession()) {
assertNotNull("Client session creation not signalled", clientSessionHolder.get());
KeyPairProvider keys = createTestHostKeyProvider();
- session.addPublicKeyIdentity(keys.loadKey(KeyPairProvider.SSH_RSA));
+ session.addPublicKeyIdentity(keys.loadKey(session, KeyPairProvider.SSH_RSA));
session.auth().verify(5L, TimeUnit.SECONDS);
} finally {
client.stop();
@@ -1055,7 +1055,7 @@ public class ClientTest extends BaseTestSupport {
provider.setAlgorithm(KeyUtils.RSA_ALGORITHM);

KeyPairProvider keys = createTestHostKeyProvider();
- KeyPair pair = keys.loadKey(KeyPairProvider.SSH_RSA);
+ KeyPair pair = keys.loadKey(null, KeyPairProvider.SSH_RSA);
sshd.setPublickeyAuthenticator((username, key, session) -> key.equals(pair.getPublic()));
client.setUserAuthFactories(Collections.singletonList(UserAuthPublicKeyFactory.INSTANCE));
client.start();
@@ -1064,7 +1064,7 @@ public class ClientTest extends BaseTestSupport {
.verify(7L, TimeUnit.SECONDS)
.getSession()) {
assertNotNull("Client session creation not signalled", clientSessionHolder.get());
- session.addPublicKeyIdentity(provider.loadKey(KeyPairProvider.SSH_RSA));
+ session.addPublicKeyIdentity(provider.loadKey(session, KeyPairProvider.SSH_RSA));
session.addPublicKeyIdentity(pair);
session.auth().verify(5L, TimeUnit.SECONDS);
} finally {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java b/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
index d7df493..5cb409c 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
@@ -276,13 +276,16 @@ public class AuthenticationTest extends BaseTestSupport {

client.start();

- try (ClientSession s = client.connect(null, TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ try (ClientSession s = client.connect(null, TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession()) {
Collection<ClientSession.ClientSessionEvent> result =
s.waitFor(EnumSet.of(ClientSession.ClientSessionEvent.CLOSED, ClientSession.ClientSessionEvent.WAIT_AUTH),
TimeUnit.SECONDS.toMillis(11L));
assertFalse("Timeout while waiting for session", result.contains(ClientSession.ClientSessionEvent.TIMEOUT));

- KeyPair pair = createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
+ KeyPairProvider provider = createTestHostKeyProvider();
+ KeyPair pair = provider.loadKey(s, KeyPairProvider.SSH_RSA);
try {
assertAuthenticationResult(UserAuthMethodFactory.PUBLIC_KEY, authPublicKey(s, getCurrentTestName(), pair), false);
} finally {
@@ -344,13 +347,16 @@ public class AuthenticationTest extends BaseTestSupport {
});
client.start();

- try (ClientSession s = client.connect(null, TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ try (ClientSession s = client.connect(null, TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession()) {
Collection<ClientSession.ClientSessionEvent> result =
- s.waitFor(EnumSet.of(ClientSession.ClientSessionEvent.CLOSED, ClientSession.ClientSessionEvent.WAIT_AUTH),
- TimeUnit.SECONDS.toMillis(11L));
+ s.waitFor(EnumSet.of(ClientSession.ClientSessionEvent.CLOSED, ClientSession.ClientSessionEvent.WAIT_AUTH),
+ TimeUnit.SECONDS.toMillis(11L));
assertFalse("Timeout while waiting for session", result.contains(ClientSession.ClientSessionEvent.TIMEOUT));

- KeyPair pair = createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
+ KeyPairProvider provider = createTestHostKeyProvider();
+ KeyPair pair = provider.loadKey(s, KeyPairProvider.SSH_RSA);
try {
assertAuthenticationResult(UserAuthMethodFactory.PUBLIC_KEY, authPublicKey(s, getCurrentTestName(), pair), false);
} finally {
@@ -587,9 +593,9 @@ public class AuthenticationTest extends BaseTestSupport {
@Test // see SSHD-618
public void testPublicKeyAuthDifferentThanKex() throws Exception {
KeyPairProvider serverKeys = KeyPairProvider.wrap(
- CommonTestSupportUtils.generateKeyPair(KeyUtils.RSA_ALGORITHM, 1024),
- CommonTestSupportUtils.generateKeyPair(KeyUtils.DSS_ALGORITHM, 512),
- CommonTestSupportUtils.generateKeyPair(KeyUtils.EC_ALGORITHM, 256));
+ CommonTestSupportUtils.generateKeyPair(KeyUtils.RSA_ALGORITHM, 1024),
+ CommonTestSupportUtils.generateKeyPair(KeyUtils.DSS_ALGORITHM, 512),
+ CommonTestSupportUtils.generateKeyPair(KeyUtils.EC_ALGORITHM, 256));
sshd.setKeyPairProvider(serverKeys);
sshd.setKeyboardInteractiveAuthenticator(KeyboardInteractiveAuthenticator.NONE);
sshd.setPasswordAuthenticator(RejectAllPasswordAuthenticator.INSTANCE);
@@ -612,7 +618,7 @@ public class AuthenticationTest extends BaseTestSupport {
String expType = kexSignature.getName();
assertEquals("Mismatched server key type", expType, keyType);

- KeyPair kp = ValidateUtils.checkNotNull(serverKeys.loadKey(keyType), "No server key for type=%s", keyType);
+ KeyPair kp = ValidateUtils.checkNotNull(serverKeys.loadKey(null, keyType), "No server key for type=%s", keyType);
assertKeyEquals("Mismatched server public keys", kp.getPublic(), serverKey);
return true;
});

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e05898c8/sshd-core/src/test/java/org/apache/sshd/common/auth/SinglePublicKeyAuthTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/auth/SinglePublicKeyAuthTest.java b/sshd-core/src/test/java/org/apache/sshd/common/auth/SinglePublicKeyAuthTest.java
index 4e97267..3685715 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/auth/SinglePublicKeyAuthTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/auth/SinglePublicKeyAuthTest.java
@@ -60,8 +60,9 @@ public class SinglePublicKeyAuthTest extends BaseTestSupport {
public SinglePublicKeyAuthTest() {
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm(KeyUtils.RSA_ALGORITHM);
- pairRsaBad = provider.loadKey(KeyPairProvider.SSH_RSA);
- pairRsaGood = createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
+ pairRsaBad = provider.loadKey(null, KeyPairProvider.SSH_RSA);
+ KeyPairProvider badKeys = createTestHostKeyProvider();
+ pairRsaGood = badKeys.loadKey(null, KeyPairProvider.SSH_RSA);
}

@Before
l***@apache.org
2018-11-18 04:54:57 UTC
Permalink
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
index a416871..f7de669 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
@@ -77,12 +77,15 @@ public class FileKeyPairProvider extends AbstractResourceKeyPairProvider<Path> {
}

@Override
- protected KeyPair doLoadKey(SessionContext session, Path resource) throws IOException, GeneralSecurityException {
+ protected KeyPair doLoadKey(SessionContext session, Path resource)
+ throws IOException, GeneralSecurityException {
return super.doLoadKey(session, (resource == null) ? null : resource.toAbsolutePath());
}

@Override
- protected InputStream openKeyPairResource(String resourceKey, Path resource) throws IOException {
+ protected InputStream openKeyPairResource(
+ SessionContext session, String resourceKey, Path resource)
+ throws IOException {
return Files.newInputStream(resource, IoUtils.EMPTY_OPEN_OPTIONS);
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
index 46b6f52..3298f20 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
@@ -19,6 +19,8 @@

package org.apache.sshd.common.keyprovider;

+import java.io.IOException;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Collection;
import java.util.Collections;
@@ -53,37 +55,11 @@ public interface KeyIdentityProvider {
*
* @param session The {@link SessionContext} for invoking this load command - may
* be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
+ * @throws IOException If failed to read/parse the keys data
+ * @throws GeneralSecurityException If failed to generate the keys
* @return an {@link Iterable} instance of available keys - ignored if {@code null}
*/
- Iterable<KeyPair> loadKeys(SessionContext session);
-
- /**
- * Creates a &quot;unified&quot; {@link Iterator} of {@link KeyPair}s out of 2 possible
- * {@link KeyIdentityProvider}
- *
- * @param session The {@link SessionContext} for invoking this load command - may
- * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
- * @param identities The registered keys identities
- * @param keys Extra available key pairs
- * @return The wrapping iterator
- * @see #resolveKeyIdentityProvider(KeyIdentityProvider, KeyIdentityProvider)
- */
- static Iterator<KeyPair> iteratorOf(
- SessionContext session, KeyIdentityProvider identities, KeyIdentityProvider keys) {
- return iteratorOf(session, resolveKeyIdentityProvider(identities, keys));
- }
-
- /**
- * Resolves a non-{@code null} iterator of the available keys
- *
- * @param session The {@link SessionContext} for invoking this load command - may
- * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
- * @param provider The {@link KeyIdentityProvider} - ignored if {@code null}
- * @return A non-{@code null} iterator - which may be empty if no provider or no keys
- */
- static Iterator<KeyPair> iteratorOf(SessionContext session, KeyIdentityProvider provider) {
- return GenericUtils.iteratorOf((provider == null) ? null : provider.loadKeys(session));
- }
+ Iterable<KeyPair> loadKeys(SessionContext session) throws IOException, GeneralSecurityException;

/**
* <P>Creates a &quot;unified&quot; {@link KeyIdentityProvider} out of 2 possible ones
@@ -159,7 +135,12 @@ public interface KeyIdentityProvider {
return Collections.emptyList();
} else if (numProviders == 1) {
KeyIdentityProvider p = GenericUtils.head(providers);
- return p.loadKeys(session);
+ try {
+ return p.loadKeys(session);
+ } catch (IOException | GeneralSecurityException e) {
+ throw new RuntimeException("Unexpected " + e.getClass().getSimpleName() + ")"
+ + " keys loading exception: " + e.getMessage(), e);
+ }
} else {
return new Iterable<KeyPair>() {
@Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
index 6b2224f..237b61f 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
@@ -18,6 +18,8 @@
*/
package org.apache.sshd.common.keyprovider;

+import java.io.IOException;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Arrays;
import java.util.Collection;
@@ -105,8 +107,11 @@ public interface KeyPairProvider extends KeyIdentityProvider {
* be {@code null} if not invoked within a session context (e.g., offline tool).
* @param type the type of key to load
* @return a valid key pair or {@code null} if this type of key is not available
+ * @throws IOException If failed to read/parse the keys data
+ * @throws GeneralSecurityException If failed to generate the keys
*/
- default KeyPair loadKey(SessionContext session, String type) {
+ default KeyPair loadKey(SessionContext session, String type)
+ throws IOException, GeneralSecurityException {
ValidateUtils.checkNotNullAndNotEmpty(type, "No key type to load");
return GenericUtils.stream(loadKeys(session))
.filter(key -> type.equals(KeyUtils.getKeyType(key)))
@@ -118,8 +123,11 @@ public interface KeyPairProvider extends KeyIdentityProvider {
* @param session The {@link SessionContext} for invoking this load command - may
* be {@code null} if not invoked within a session context (e.g., offline tool).
* @return The available {@link Iterable} key types in preferred order - never {@code null}
+ * @throws IOException If failed to read/parse the keys data
+ * @throws GeneralSecurityException If failed to generate the keys
*/
- default Iterable<String> getKeyTypes(SessionContext session) {
+ default Iterable<String> getKeyTypes(SessionContext session)
+ throws IOException, GeneralSecurityException {
return GenericUtils.stream(loadKeys(session))
.map(KeyUtils::getKeyType)
.filter(GenericUtils::isNotEmpty)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
index 9de7c17..09d5f29 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
@@ -19,6 +19,8 @@

package org.apache.sshd.common.keyprovider;

+import java.io.IOException;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Iterator;
import java.util.NoSuchElementException;
@@ -69,7 +71,13 @@ public class MultiKeyIdentityIterator implements Iterator<KeyPair> {
SessionContext session = getSessionContext();
while (provs.hasNext()) {
KeyIdentityProvider p = provs.next();
- Iterable<KeyPair> keys = (p == null) ? null : p.loadKeys(session);
+ Iterable<KeyPair> keys;
+ try {
+ keys = (p == null) ? null : p.loadKeys(session);
+ } catch (IOException | GeneralSecurityException e) {
+ throw new RuntimeException("Unexpected " + e.getClass().getSimpleName() + ")"
+ + " keys loading exception: " + e.getMessage(), e);
+ }
currentProvider = (keys == null) ? null : keys.iterator();

if ((currentProvider != null) && currentProvider.hasNext()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
index 87827bd..c937079 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/session/SessionContext.java
@@ -19,7 +19,7 @@

package org.apache.sshd.common.session;

-import org.apache.sshd.common.AttributeRepository;
+import org.apache.sshd.common.AttributeStore;
import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.auth.UsernameHolder;
import org.apache.sshd.common.util.GenericUtils;
@@ -34,7 +34,7 @@ public interface SessionContext
extends ConnectionEndpointsIndicator,
UsernameHolder,
PropertyResolver,
- AttributeRepository {
+ AttributeStore {
/**
* Default prefix expected for the client / server identification string
* @see <A HREF="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253 - section 4.2</A>

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
index a55e5d6..35f46d9 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
@@ -213,4 +213,16 @@ public final class ValidateUtils {
return constructor.apply(message);
}

+ public static <T extends Throwable> T initializeExceptionCause(T err, Throwable cause) {
+ if (cause == null) {
+ return err;
+ }
+
+ if (err.getCause() != null) {
+ return err; // already initialized - avoid IllegalStateException
+ }
+
+ err.initCause(cause);
+ return err;
+ }
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
index 1534f95..2949875 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
@@ -67,6 +67,7 @@ import org.apache.sshd.common.config.keys.loader.pem.PEMResourceParserUtils;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.random.JceRandomFactory;
import org.apache.sshd.common.random.RandomFactory;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.Buffer;
@@ -468,9 +469,10 @@ public final class SecurityUtils {
/* -------------------------------------------------------------------- */

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool).
* @param resourceKey An identifier of the key being loaded - used as
- * argument to the {@link FilePasswordProvider#getPassword(String, int)}
- * invocation
+ * argument to the {@code FilePasswordProvider#getPassword} invocation
* @param inputStream The {@link InputStream} for the <U>private</U> key
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded key is <U>guaranteed</U> not to be encrypted
@@ -478,23 +480,25 @@ public final class SecurityUtils {
* @throws IOException If failed to read/parse the input stream
* @throws GeneralSecurityException If failed to generate the keys
*/
- public static KeyPair loadKeyPairIdentity(String resourceKey, InputStream inputStream, FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
+ public static KeyPair loadKeyPairIdentity(
+ SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
KeyPairResourceParser parser = getKeyPairResourceParser();
if (parser == null) {
throw new NoSuchProviderException("No registered key-pair resource parser");
}

- Collection<KeyPair> ids = parser.loadKeyPairs(resourceKey, provider, inputStream);
+ Collection<KeyPair> ids = parser.loadKeyPairs(session, resourceKey, provider, inputStream);
int numLoaded = GenericUtils.size(ids);
if (numLoaded <= 0) {
- throw new InvalidKeyException("Unsupported private key file format: " + resourceKey);
+ return null;
}
+
if (numLoaded != 1) {
throw new InvalidKeySpecException("Multiple private key pairs N/A: " + resourceKey);
}

- return ids.iterator().next();
+ return GenericUtils.head(ids);
}

/* -------------------------------------------------------------------- */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
index 5c8befb..881adff 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
@@ -39,6 +39,7 @@ import javax.security.auth.login.FailedLoginException;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
import org.apache.sshd.common.config.keys.loader.AbstractKeyPairResourceParser;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.security.SecurityProviderRegistrar;
@@ -76,7 +77,7 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
StringBuilder writer = new StringBuilder(beginMarker.length() + endMarker.length() + lines.size() * 80);
writer.append(beginMarker).append(IoUtils.EOL);
@@ -86,20 +87,24 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa
String data = writer.toString();
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
try (InputStream bais = new ByteArrayInputStream(dataBytes)) {
- return extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, bais);
+ return extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, bais);
}
}

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ InputStream stream)
throws IOException, GeneralSecurityException {
- KeyPair kp = loadKeyPair(resourceKey, stream, passwordProvider);
+ KeyPair kp = loadKeyPair(session, resourceKey, stream, passwordProvider);
return (kp == null) ? Collections.emptyList() : Collections.singletonList(kp);
}

- public static KeyPair loadKeyPair(String resourceKey, InputStream inputStream, FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
+ public static KeyPair loadKeyPair(
+ SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
try (PEMParser r = new PEMParser(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
Object o = r.readObject();

@@ -122,7 +127,7 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa
}

for (int retryIndex = 0;; retryIndex++) {
- String password = provider.getPassword(resourceKey, retryIndex);
+ String password = provider.getPassword(session, resourceKey, retryIndex);
PEMKeyPair decoded;
try {
if (GenericUtils.isEmpty(password)) {
@@ -134,7 +139,7 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa
decoded = ((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor);
} catch (IOException | GeneralSecurityException | RuntimeException e) {
ResourceDecodeResult result =
- provider.handleDecodeAttemptResult(resourceKey, retryIndex, password, e);
+ provider.handleDecodeAttemptResult(session, resourceKey, retryIndex, password, e);
if (result == null) {
result = ResourceDecodeResult.TERMINATE;
}
@@ -151,7 +156,7 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa
}

o = decoded;
- provider.handleDecodeAttemptResult(resourceKey, retryIndex, password, null);
+ provider.handleDecodeAttemptResult(session, resourceKey, retryIndex, password, null);
break;
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
index 2f1d055..f9402eb 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
@@ -36,6 +36,7 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyEntryResolver;
import org.apache.sshd.common.config.keys.impl.AbstractPrivateKeyEntryDecoder;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.security.SecurityUtils;

import net.i2p.crypto.eddsa.EdDSAPrivateKey;
@@ -62,8 +63,9 @@ public class OpenSSHEd25519PrivateKeyEntryDecoder extends AbstractPrivateKeyEntr
}

@Override
- public EdDSAPrivateKey decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
- throws IOException, GeneralSecurityException {
+ public EdDSAPrivateKey decodePrivateKey(
+ SessionContext session, String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
+ throws IOException, GeneralSecurityException {
if (!KeyPairProvider.SSH_ED25519.equals(keyType)) {
throw new InvalidKeyException("Unsupported key type: " + keyType);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
index d30b4b8..71e3a4f 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
@@ -249,7 +249,7 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr

protected KeyPair doReadKeyPair(SessionContext session, String resourceKey, InputStream inputStream)
throws IOException, GeneralSecurityException {
- return SecurityUtils.loadKeyPairIdentity(resourceKey, inputStream, null);
+ return SecurityUtils.loadKeyPairIdentity(session, resourceKey, inputStream, null);
}

protected void writeKeyPair(KeyPair kp, Path keyPath, OpenOption... options)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
index 4f4b285..81c458f 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
@@ -40,6 +40,7 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.IoUtils;
@@ -78,7 +79,9 @@ public class BuiltinClientIdentitiesWatcherTest extends JUnitTestSupport {

ClientIdentityLoader loader = new ClientIdentityLoader() {
@Override
- public KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
+ public KeyPair loadClientIdentity(
+ SessionContext session, String location, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
BuiltinIdentities id = findIdentity(location);
assertNotNull("Invalid location: " + location, id);
return idsMap.get(id);
@@ -144,7 +147,9 @@ public class BuiltinClientIdentitiesWatcherTest extends JUnitTestSupport {
}
}

- private static void testMultipleFilesWatch(String phase, KeyIdentityProvider watcher, Collection<? extends KeyPair> expected) {
+ private static void testMultipleFilesWatch(
+ String phase, KeyIdentityProvider watcher, Collection<? extends KeyPair> expected)
+ throws IOException, GeneralSecurityException {
Iterable<KeyPair> keys = watcher.loadKeys(null);
Collection<KeyPair> actual = new ArrayList<>();
for (KeyPair kp : keys) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
index 690a381..bd43f44 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
@@ -60,7 +60,9 @@ public class ClientIdentityFileWatcherTest extends JUnitTestSupport {
KeyPair identity = CommonTestSupportUtils.getFirstKeyPair(createTestHostKeyProvider());
ClientIdentityLoader loader = new ClientIdentityLoader() {
@Override
- public KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
+ public KeyPair loadClientIdentity(
+ SessionContext session, String location, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
assertTrue("Invalid location: " + location, isValidLocation(location));
return identity;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
index d5c6aba..680a53f 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
@@ -73,7 +73,7 @@ public class OpenSSHKeyPairResourceParserTest extends JUnitTestSupport {
URL urlKeyPair = getClass().getResource(resourceKey);
assertNotNull("Missing key-pair resource: " + resourceKey, urlKeyPair);

- Collection<KeyPair> pairs = PARSER.loadKeyPairs(urlKeyPair, FilePasswordProvider.EMPTY);
+ Collection<KeyPair> pairs = PARSER.loadKeyPairs(null, urlKeyPair, FilePasswordProvider.EMPTY);
assertEquals("Mismatched pairs count", 1, GenericUtils.size(pairs));

URL urlPubKey = getClass().getResource(resourceKey + ".pub");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
index 406a273..9775e2c 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
@@ -92,7 +92,7 @@ public class PKCS8PEMResourceKeyPairParserTest extends JUnitTestSupport {
os.close();

try (ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray())) {
- KeyPair kp2 = SecurityUtils.loadKeyPairIdentity(getCurrentTestName(), bais, null);
+ KeyPair kp2 = SecurityUtils.loadKeyPairIdentity(null, getCurrentTestName(), bais, null);

assertEquals("Mismatched public key", kp.getPublic(), kp2.getPublic());
assertEquals("Mismatched private key", prv1, kp2.getPrivate());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
index 6f00621..fb9ed8c 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
@@ -19,6 +19,8 @@

package org.apache.sshd.common.keyprovider;

+import java.io.IOException;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -46,7 +48,7 @@ public class KeyPairProviderTest extends JUnitTestSupport {
}

@Test
- public void testEmptyKeyProvider() {
+ public void testEmptyKeyProvider() throws IOException, GeneralSecurityException {
KeyPairProvider provider = KeyPairProvider.EMPTY_KEYPAIR_PROVIDER;
assertTrue("Non empty loaded keys", GenericUtils.isEmpty(provider.loadKeys(null)));
assertTrue("Non empty key type", GenericUtils.isEmpty(provider.getKeyTypes(null)));
@@ -57,7 +59,7 @@ public class KeyPairProviderTest extends JUnitTestSupport {
}

@Test
- public void testMapToKeyPairProvider() {
+ public void testMapToKeyPairProvider() throws IOException, GeneralSecurityException {
PublicKey pubKey = Mockito.mock(PublicKey.class);
PrivateKey prvKey = Mockito.mock(PrivateKey.class);
String[] testKeys = {getCurrentTestName(), getClass().getSimpleName()};
@@ -71,9 +73,11 @@ public class KeyPairProviderTest extends JUnitTestSupport {
assertEquals("Key types", pairsMap.keySet(), provider.getKeyTypes(null));
assertEquals("Key pairs", pairsMap.values(), provider.loadKeys(null));

- pairsMap.forEach((keyType, expected) -> {
+ for (Map.Entry<String, KeyPair> pe : pairsMap.entrySet()) {
+ String keyType = pe.getKey();
+ KeyPair expected = pe.getValue();
KeyPair actual = provider.loadKey(null, keyType);
assertSame(keyType, expected, actual);
- });
+ }
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
index e5a4329..a1a2dca 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
@@ -19,6 +19,8 @@

package org.apache.sshd.common.keyprovider;

+import java.io.IOException;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -47,7 +49,7 @@ public class MultiKeyIdentityProviderTest extends JUnitTestSupport {
}

@Test // see SSHD-860
- public void testLazyKeyIdentityMultiProvider() {
+ public void testLazyKeyIdentityMultiProvider() throws IOException, GeneralSecurityException {
List<KeyPair> expected = new ArrayList<>();
for (int index = 1; index <= Short.SIZE; index++) {
PublicKey pub = Mockito.mock(PublicKey.class);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
index 488d2ce..e6019fe 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
@@ -67,7 +67,7 @@ public class SecurityUtilsTest extends JUnitTestSupport {
+ "." + SecurityProviderRegistrar.NAMED_PROVIDER_PROPERTY;

private static final String DEFAULT_PASSWORD = "super secret passphrase";
- private static final FilePasswordProvider TEST_PASSWORD_PROVIDER = (file, index) -> DEFAULT_PASSWORD;
+ private static final FilePasswordProvider TEST_PASSWORD_PROVIDER = (session, file, index) -> DEFAULT_PASSWORD;

public SecurityUtilsTest() {
super();
@@ -155,7 +155,7 @@ public class SecurityUtilsTest extends JUnitTestSupport {
KeyPair kpFile = testLoadPrivateKeyFile(file, pubType, prvType);
if (SecurityUtils.isBouncyCastleRegistered()) {
KeyPairResourceLoader bcLoader = SecurityUtils.getBouncycastleKeyPairResourceParser();
- Collection<KeyPair> kpList = bcLoader.loadKeyPairs(file, TEST_PASSWORD_PROVIDER);
+ Collection<KeyPair> kpList = bcLoader.loadKeyPairs(null, file, TEST_PASSWORD_PROVIDER);
assertEquals(name + ": Mismatched loaded BouncyCastle keys count", 1, GenericUtils.size(kpList));

KeyPair kpBC = kpList.iterator().next();
@@ -170,18 +170,21 @@ public class SecurityUtilsTest extends JUnitTestSupport {
}

private static KeyPair testLoadPrivateKeyResource(
- String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
+ String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
+ throws IOException, GeneralSecurityException {
return testLoadPrivateKey(name, new ClassLoadableResourceKeyPairProvider(name), pubType, prvType);
}

private static KeyPair testLoadPrivateKeyFile(
- Path file, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
+ Path file, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
+ throws IOException, GeneralSecurityException {
return testLoadPrivateKey(file.toString(), new FileKeyPairProvider(file), pubType, prvType);
}

private static KeyPair testLoadPrivateKey(
String resourceKey, AbstractResourceKeyPairProvider<?> provider,
- Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
+ Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
+ throws IOException, GeneralSecurityException {
provider.setPasswordFinder(TEST_PASSWORD_PROVIDER);
Iterable<KeyPair> iterator = provider.loadKeys(null);
List<KeyPair> pairs = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
index af4a6b7..a7a4659 100644
--- a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
@@ -21,6 +21,7 @@ package org.apache.sshd.server.keyprovider;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
@@ -51,19 +52,19 @@ public class PEMGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Test
- public void testDSA() throws IOException {
+ public void testDSA() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
testPEMGeneratorHostKeyProvider(KeyUtils.DSS_ALGORITHM, KeyPairProvider.SSH_DSS, 512, null);
}

@Test
- public void testRSA() throws IOException {
+ public void testRSA() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
testPEMGeneratorHostKeyProvider(KeyUtils.RSA_ALGORITHM, KeyPairProvider.SSH_RSA, 512, null);
}

@Test
- public void testECnistp256() throws IOException {
+ public void testECnistp256() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
Assume.assumeTrue("ECC not supported", SecurityUtils.isECCSupported());
Assume.assumeTrue(ECCurves.nistp256 + " N/A", ECCurves.nistp256.isSupported());
@@ -71,7 +72,7 @@ public class PEMGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Test
- public void testECnistp384() throws IOException {
+ public void testECnistp384() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
Assume.assumeTrue("ECC not supported", SecurityUtils.isECCSupported());
Assume.assumeTrue(ECCurves.nistp384 + " N/A", ECCurves.nistp384.isSupported());
@@ -79,14 +80,16 @@ public class PEMGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Test
- public void testECnistp521() throws IOException {
+ public void testECnistp521() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
Assume.assumeTrue("ECC not supported", SecurityUtils.isECCSupported());
Assume.assumeTrue(ECCurves.nistp521 + " N/A", ECCurves.nistp521.isSupported());
testPEMGeneratorHostKeyProvider(KeyUtils.EC_ALGORITHM, KeyPairProvider.ECDSA_SHA2_NISTP521, -1, new ECGenParameterSpec("P-521"));
}

- private Path testPEMGeneratorHostKeyProvider(String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec) throws IOException {
+ private Path testPEMGeneratorHostKeyProvider(
+ String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec)
+ throws IOException, GeneralSecurityException {
Path path = initKeyFileLocation(algorithm);
KeyPair kpWrite = invokePEMGeneratorHostKeyProvider(path, algorithm, keyType, keySize, keySpec);
assertTrue("Key file not generated: " + path, Files.exists(path, IoUtils.EMPTY_LINK_OPTIONS));
@@ -103,7 +106,9 @@ public class PEMGeneratorHostKeyProviderTest extends JUnitTestSupport {
return path;
}

- private static KeyPair invokePEMGeneratorHostKeyProvider(Path path, String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec) {
+ private static KeyPair invokePEMGeneratorHostKeyProvider(
+ Path path, String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec)
+ throws IOException, GeneralSecurityException {
AbstractGeneratorHostKeyProvider provider = SecurityUtils.createGeneratorHostKeyProvider(path.toAbsolutePath().normalize());
provider.setAlgorithm(algorithm);
provider.setOverwriteAllowed(true);
@@ -117,7 +122,8 @@ public class PEMGeneratorHostKeyProviderTest extends JUnitTestSupport {
return validateKeyPairProvider(provider, keyType);
}

- private static KeyPair validateKeyPairProvider(KeyPairProvider provider, String keyType) {
+ private static KeyPair validateKeyPairProvider(KeyPairProvider provider, String keyType)
+ throws IOException, GeneralSecurityException {
Iterable<String> types = provider.getKeyTypes(null);
KeyPair kp = null;
for (String type : types) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
index ab0ff2c..fe4a7d0 100644
--- a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
@@ -21,6 +21,7 @@ package org.apache.sshd.server.keyprovider;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
@@ -51,17 +52,17 @@ public class SimpleGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Test
- public void testDSA() throws IOException {
+ public void testDSA() throws IOException, GeneralSecurityException {
testSimpleGeneratorHostKeyProvider(KeyUtils.DSS_ALGORITHM, KeyPairProvider.SSH_DSS, 512, null);
}

@Test
- public void testRSA() throws IOException {
+ public void testRSA() throws IOException, GeneralSecurityException {
testSimpleGeneratorHostKeyProvider(KeyUtils.RSA_ALGORITHM, KeyPairProvider.SSH_RSA, 512, null);
}

@Test
- public void testECnistp256() throws IOException {
+ public void testECnistp256() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
Assume.assumeTrue("ECC not supported", SecurityUtils.isECCSupported());
Assume.assumeTrue(ECCurves.nistp256 + " N/A", ECCurves.nistp256.isSupported());
@@ -69,7 +70,7 @@ public class SimpleGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Test
- public void testECnistp384() throws IOException {
+ public void testECnistp384() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
Assume.assumeTrue("ECC not supported", SecurityUtils.isECCSupported());
Assume.assumeTrue(ECCurves.nistp384 + " N/A", ECCurves.nistp384.isSupported());
@@ -77,14 +78,16 @@ public class SimpleGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Test
- public void testECnistp521() throws IOException {
+ public void testECnistp521() throws IOException, GeneralSecurityException {
Assume.assumeTrue("BouncyCastle not registered", SecurityUtils.isBouncyCastleRegistered());
Assume.assumeTrue("ECC not supported", SecurityUtils.isECCSupported());
Assume.assumeTrue(ECCurves.nistp521 + " N/A", ECCurves.nistp521.isSupported());
testSimpleGeneratorHostKeyProvider(KeyUtils.EC_ALGORITHM, KeyPairProvider.ECDSA_SHA2_NISTP521, -1, new ECGenParameterSpec("P-521"));
}

- private Path testSimpleGeneratorHostKeyProvider(String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec) throws IOException {
+ private Path testSimpleGeneratorHostKeyProvider(
+ String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec)
+ throws IOException, GeneralSecurityException {
Path path = initKeyFileLocation(algorithm);
KeyPair kpWrite = invokeSimpleGeneratorHostKeyProvider(path, algorithm, keyType, keySize, keySpec);
assertTrue("Key file not generated: " + path, Files.exists(path, IoUtils.EMPTY_LINK_OPTIONS));
@@ -94,7 +97,9 @@ public class SimpleGeneratorHostKeyProviderTest extends JUnitTestSupport {
return path;
}

- private static KeyPair invokeSimpleGeneratorHostKeyProvider(Path path, String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec) {
+ private static KeyPair invokeSimpleGeneratorHostKeyProvider(
+ Path path, String algorithm, String keyType, int keySize, AlgorithmParameterSpec keySpec)
+ throws IOException, GeneralSecurityException {
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm(algorithm);
provider.setOverwriteAllowed(true);
@@ -109,7 +114,9 @@ public class SimpleGeneratorHostKeyProviderTest extends JUnitTestSupport {
return validateKeyPairProvider(provider, keyType);
}

- private static KeyPair validateKeyPairProvider(KeyPairProvider provider, String keyType) {
+ private static KeyPair validateKeyPairProvider(
+ KeyPairProvider provider, String keyType)
+ throws IOException, GeneralSecurityException {
Iterable<String> types = provider.getKeyTypes(null);
KeyPair kp = null;
for (String type : types) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java b/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
index a1d77ef..d920344 100644
--- a/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
+++ b/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
@@ -453,7 +453,14 @@ public final class CommonTestSupportUtils {

public static KeyPair getFirstKeyPair(KeyIdentityProvider provider) {
Objects.requireNonNull(provider, "No key pair provider");
- Iterable<? extends KeyPair> pairs = Objects.requireNonNull(provider.loadKeys(null), "No loaded keys");
+ Iterable<? extends KeyPair> pairs;
+ try {
+ pairs = Objects.requireNonNull(provider.loadKeys(null), "No loaded keys");
+ } catch (IOException | GeneralSecurityException e) {
+ throw new RuntimeException("Unexpected " + e.getClass().getSimpleName() + ")"
+ + " keys loading exception: " + e.getMessage(), e);
+ }
+
Iterator<? extends KeyPair> iter = Objects.requireNonNull(pairs.iterator(), "No keys iterator");
ValidateUtils.checkTrue(iter.hasNext(), "Empty loaded kyes iterator");
return Objects.requireNonNull(iter.next(), "No key pair in iterator");
@@ -537,7 +544,14 @@ public final class CommonTestSupportUtils {
Objects.requireNonNull(provider, "No provider");

// get the I/O out of the way
- Iterable<KeyPair> keys = Objects.requireNonNull(provider.loadKeys(null), "No keys loaded");
+ Iterable<KeyPair> keys;
+ try {
+ keys = Objects.requireNonNull(provider.loadKeys(null), "No keys loaded");
+ } catch (IOException | GeneralSecurityException e) {
+ throw new RuntimeException("Unexpected " + e.getClass().getSimpleName() + ")"
+ + " keys loading exception: " + e.getMessage(), e);
+ }
+
if (keys instanceof Collection<?>) {
ValidateUtils.checkNotNullAndNotEmpty((Collection<?>) keys, "Empty keys loaded");
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/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 6c3e9c8..6ece3d9 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
@@ -524,7 +524,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
List<KeyPair> ids = new ArrayList<>(locations.size());
boolean ignoreNonExisting = this.getBooleanProperty(IGNORE_INVALID_IDENTITIES, DEFAULT_IGNORE_INVALID_IDENTITIES);
ClientIdentityLoader loader = Objects.requireNonNull(getClientIdentityLoader(), "No ClientIdentityLoader");
- FilePasswordProvider provider = Objects.requireNonNull(getFilePasswordProvider(), "No FilePasswordProvider");
+ FilePasswordProvider provider = getFilePasswordProvider();
boolean debugEnabled = log.isDebugEnabled();
for (String l : locations) {
if (!loader.isValidLocation(l)) {
@@ -539,14 +539,14 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
}

try {
- KeyPair kp = loader.loadClientIdentity(l, provider);
+ KeyPair kp = loader.loadClientIdentity(null /* TODO use lazy-load here as well */, l, provider);
if (kp == null) {
throw new IOException("No identity loaded from " + l);
}

if (debugEnabled) {
log.debug("loadClientIdentities({}) type={}, fingerprint={}",
- l, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
+ l, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
}

ids.add(kp);
@@ -561,7 +561,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
protected ConnectFuture doConnect(
String username, SocketAddress targetAddress,
AttributeRepository context, SocketAddress localAddress,
- Collection<? extends KeyPair> identities, boolean useDefaultIdentities)
+ Iterable<? extends KeyPair> identities, boolean useDefaultIdentities)
throws IOException {
if (connector == null) {
throw new IllegalStateException("SshClient not started. Please call start() method before connecting to a server");
@@ -578,7 +578,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa

protected SshFutureListener<IoConnectFuture> createConnectCompletionListener(
ConnectFuture connectFuture, String username, SocketAddress address,
- Collection<? extends KeyPair> identities, boolean useDefaultIdentities) {
+ Iterable<? extends KeyPair> identities, boolean useDefaultIdentities) {
return new SshFutureListener<IoConnectFuture>() {
@Override
@SuppressWarnings("synthetic-access")
@@ -621,7 +621,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa

protected void onConnectOperationComplete(
IoSession ioSession, ConnectFuture connectFuture, String username,
- SocketAddress address, Collection<? extends KeyPair> identities, boolean useDefaultIdentities) {
+ SocketAddress address, Iterable<? extends KeyPair> identities, boolean useDefaultIdentities) {
AbstractClientSession session = (AbstractClientSession) AbstractSession.getSession(ioSession);
session.setUsername(username);
session.setConnectAddress(address);
@@ -630,12 +630,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
setupDefaultSessionIdentities(session);
}

- int numIds = GenericUtils.size(identities);
- if (numIds > 0) {
- if (log.isDebugEnabled()) {
- log.debug("onConnectOperationComplete({}) adding {} identities", session, numIds);
- }
-
+ if (identities != null) {
boolean traceEnabled = log.isTraceEnabled();
for (KeyPair kp : identities) {
if (traceEnabled) {
@@ -792,7 +787,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -818,7 +813,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
index d476464..a6f135c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
@@ -21,6 +21,7 @@ package org.apache.sshd.client.auth.pubkey;

import java.io.IOException;
import java.nio.channels.Channel;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.ArrayList;
@@ -84,6 +85,7 @@ public class UserAuthPublicKeyIterator extends AbstractKeyPairIterator<PublicKey
}
}

+ @SuppressWarnings("checkstyle:anoninnerlength")
protected Iterable<KeyPairIdentity> initializeSessionIdentities(
ClientSession session, SignatureFactoriesManager signatureFactories) {
return new Iterable<KeyPairIdentity>() {
@@ -94,8 +96,13 @@ public class UserAuthPublicKeyIterator extends AbstractKeyPairIterator<PublicKey
public Iterator<KeyPairIdentity> iterator() {
// Lazy load the keys the 1st time the iterator is called
if (keysHolder.get() == null) {
- KeyIdentityProvider sessionKeysProvider = ClientSession.providerOf(session);
- keysHolder.set(sessionKeysProvider.loadKeys(session));
+ try {
+ KeyIdentityProvider sessionKeysProvider = ClientSession.providerOf(session);
+ keysHolder.set(sessionKeysProvider.loadKeys(session));
+ } catch (IOException | GeneralSecurityException e) {
+ throw new RuntimeException("Unexpected " + e.getClass().getSimpleName() + ")"
+ + " keys loading exception: " + e.getMessage(), e);
+ }
}

return new Iterator<KeyPairIdentity>() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/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 b6d6235..b7b5377 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
@@ -385,21 +385,6 @@ public interface ClientSession
}

/**
- * Creates a &quot;unified&quot; {@link Iterator} of key pairs out of the registered
- * {@link KeyPair} identities and the extra available ones as a single iterator
- * of key pairs
- *
- * @param session The {@link ClientSession} - ignored if {@code null} (i.e., empty
- * iterator returned)
- * @return The wrapping iterator
- * @see ClientSession#getRegisteredIdentities()
- * @see ClientSession#getKeyPairProvider()
- */
- static Iterator<KeyPair> keyPairIteratorOf(ClientSession session) {
- return KeyIdentityProvider.iteratorOf(session, providerOf(session));
- }
-
- /**
* Creates a &quot;unified&quot; {@link Iterator} of passwords out of the registered
* passwords and the extra available ones as a single iterator of passwords
*

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
index 0ecab07..8c094cd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
@@ -24,7 +24,6 @@ import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.apache.sshd.common.AttributeRepository;
-import org.apache.sshd.common.AttributeStore;
import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.FactoryManagerHolder;
@@ -54,7 +53,6 @@ import org.apache.sshd.common.util.buffer.Buffer;
*/
public interface Session
extends SessionContext,
- AttributeStore,
MutableUserHolder,
KexFactoryManager,
SessionListenerManager,

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
index db3b17a..fc9958f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
@@ -20,8 +20,10 @@ package org.apache.sshd.common.session.helpers;

import java.io.IOException;
import java.io.InterruptedIOException;
+import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
@@ -711,7 +713,16 @@ public abstract class AbstractSession extends SessionHelper {
return doWritePacket(buffer);
} finally {
resetIdleTimeout();
- checkRekey();
+ try {
+ checkRekey();
+ } catch (GeneralSecurityException e) {
+ if (log.isDebugEnabled()) {
+ log.debug("writePacket(" + this + ") rekey security exception details", e);
+ }
+ throw ValidateUtils.initializeExceptionCause(
+ new ProtocolException("Failed (" + e.getClass().getSimpleName() + ")"
+ + " to check re-key necessity: " + e.getMessage()), e);
+ }
}
}

@@ -1101,8 +1112,9 @@ public abstract class AbstractSession extends SessionHelper {
* @return <code>true</code> if the identification has been fully read or
* <code>false</code> if more data is needed
* @throws IOException if an error occurs such as a bad protocol version
+ * @throws GeneralSecurityException If unsuccessful KEX was involved
*/
- protected abstract boolean readIdentification(Buffer buffer) throws IOException;
+ protected abstract boolean readIdentification(Buffer buffer) throws IOException, GeneralSecurityException;

/**
* Send the key exchange initialization packet.
@@ -1607,7 +1619,17 @@ public abstract class AbstractSession extends SessionHelper {

@Override
public KeyExchangeFuture reExchangeKeys() throws IOException {
- requestNewKeysExchange();
+ try {
+ requestNewKeysExchange();
+ } catch (GeneralSecurityException e) {
+ if (log.isDebugEnabled()) {
+ log.debug("reExchangeKeys(" + this + ") security exception details", e);
+ }
+ throw ValidateUtils.initializeExceptionCause(
+ new ProtocolException("Failed (" + e.getClass().getSimpleName() + ")"
+ + " to generate keys for exchange: " + e.getMessage()), e);
+ }
+
return ValidateUtils.checkNotNull(kexFutureHolder.get(), "No current KEX future on state=%s", kexState.get());
}

@@ -1616,11 +1638,12 @@ public abstract class AbstractSession extends SessionHelper {
*
* @return A {@link KeyExchangeFuture} to wait for the initiated exchange
* or {@code null} if no need to re-key or an exchange is already in progress
- * @throws IOException If failed to send the request
+ * @throws IOException If failed load the keys or send the request
+ * @throws GeneralSecurityException If failed to generate the necessary keys
* @see #isRekeyRequired()
* @see #requestNewKeysExchange()
*/
- protected KeyExchangeFuture checkRekey() throws IOException {
+ protected KeyExchangeFuture checkRekey() throws IOException, GeneralSecurityException {
return isRekeyRequired() ? requestNewKeysExchange() : null;
}

@@ -1629,9 +1652,10 @@ public abstract class AbstractSession extends SessionHelper {
*
* @return A {@link KeyExchangeFuture} to wait for the initiated exchange
* or {@code null} if an exchange is already in progress
- * @throws IOException If failed to send the request
+ * @throws IOException If failed to load the keys or send the request
+ * @throws GeneralSecurityException If failed to generate the keys
*/
- protected KeyExchangeFuture requestNewKeysExchange() throws IOException {
+ protected KeyExchangeFuture requestNewKeysExchange() throws IOException, GeneralSecurityException {
if (!kexState.compareAndSet(KexState.DONE, KexState.INIT)) {
if (log.isDebugEnabled()) {
log.debug("requestNewKeysExchange({}) KEX state not DONE: {}", this, kexState.get());
@@ -1740,7 +1764,7 @@ public abstract class AbstractSession extends SessionHelper {
return rekey;
}

- protected byte[] sendKexInit() throws IOException {
+ protected byte[] sendKexInit() throws IOException, GeneralSecurityException {
String resolvedAlgorithms = resolveAvailableSignaturesProposal();
if (GenericUtils.isEmpty(resolvedAlgorithms)) {
throw new SshException(SshConstants.SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE,
@@ -1794,10 +1818,12 @@ public abstract class AbstractSession extends SessionHelper {
/**
* @return A comma-separated list of all the signature protocols to be
* included in the proposal - {@code null}/empty if no proposal
+ * @throws IOException If failed to read/parse the keys data
+ * @throws GeneralSecurityException If failed to generate the keys
* @see #getFactoryManager()
* @see #resolveAvailableSignaturesProposal(FactoryManager)
*/
- protected String resolveAvailableSignaturesProposal() {
+ protected String resolveAvailableSignaturesProposal() throws IOException, GeneralSecurityException {
return resolveAvailableSignaturesProposal(getFactoryManager());
}

@@ -1805,8 +1831,11 @@ public abstract class AbstractSession extends SessionHelper {
* @param manager The {@link FactoryManager}
* @return A comma-separated list of all the signature protocols to be
* included in the proposal - {@code null}/empty if no proposal
+ * @throws IOException If failed to read/parse the keys data
+ * @throws GeneralSecurityException If failed to generate the keys
*/
- protected abstract String resolveAvailableSignaturesProposal(FactoryManager manager);
+ protected abstract String resolveAvailableSignaturesProposal(FactoryManager manager)
+ throws IOException, GeneralSecurityException;

/**
* Indicates the the key exchange is completed and the exchanged keys

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
index 0823a8f..4757838 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
@@ -117,9 +117,11 @@ public final class ServerIdentity {
* @see #findIdentities(Properties, LinkOption...)
* @see IdentityUtils#loadIdentities(Map, org.apache.sshd.common.config.keys.FilePasswordProvider, java.nio.file.OpenOption...)
*/
- public static Map<String, KeyPair> loadIdentities(Properties props, LinkOption... options) throws IOException, GeneralSecurityException {
+ public static Map<String, KeyPair> loadIdentities(Properties props, LinkOption... options)
+ throws IOException, GeneralSecurityException {
Map<String, Path> ids = findIdentities(props, options);
- return IdentityUtils.loadIdentities(ids, null /* server key files are never encrypted */, IoUtils.EMPTY_OPEN_OPTIONS);
+ return IdentityUtils.loadIdentities(
+ null /* server keys are not loaded in a session context */, ids, null /* server key files are never encrypted */, IoUtils.EMPTY_OPEN_OPTIONS);
}

/**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
index 69f450a..6af869e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
@@ -22,6 +22,7 @@ package org.apache.sshd.server.session;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Collection;
import java.util.List;
@@ -247,7 +248,8 @@ public abstract class AbstractServerSession extends AbstractSession implements S
}

@Override
- protected String resolveAvailableSignaturesProposal(FactoryManager proposedManager) {
+ protected String resolveAvailableSignaturesProposal(FactoryManager proposedManager)
+ throws IOException, GeneralSecurityException {
/*
* Make sure we can provide key(s) for the available signatures
*/
@@ -319,7 +321,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
}

@Override
- protected boolean readIdentification(Buffer buffer) throws IOException {
+ protected boolean readIdentification(Buffer buffer) throws IOException, GeneralSecurityException {
ServerProxyAcceptor acceptor = getServerProxyAcceptor();
int rpos = buffer.rpos();
boolean debugEnabled = log.isDebugEnabled();
@@ -395,7 +397,7 @@ public abstract class AbstractServerSession extends AbstractSession implements S
KeyPairProvider provider = Objects.requireNonNull(getKeyPairProvider(), "No host keys provider");
try {
return provider.loadKey(this, keyType);
- } catch (Error e) {
+ } catch (IOException | GeneralSecurityException | Error e) {
log.warn("getHostKey({}) failed ({}) to load key of type={}: {}",
this, e.getClass().getSimpleName(), keyType, e.getMessage());
if (log.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
index 30cb1ff..3881890 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
@@ -153,8 +153,9 @@ public class HostConfigEntryResolverTest extends BaseTestSupport {
}

@Override
- public KeyPair loadClientIdentity(String location, FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
+ public KeyPair loadClientIdentity(
+ SessionContext session, String location, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
if (isValidLocation(location)) {
return identity;
}
@@ -218,8 +219,9 @@ public class HostConfigEntryResolverTest extends BaseTestSupport {
}

@Override
- public KeyPair loadClientIdentity(String location, FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
+ public KeyPair loadClientIdentity(
+ SessionContext session, String location, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
if (isValidLocation(location)) {
return specificIdentity;
}
l***@apache.org
2018-11-18 04:54:58 UTC
Permalink
[SSHD-862] Propagate available session context to code that deals with loading private keys


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

Branch: refs/heads/master
Commit: 2b013cca86bede945a6da0fd20e6afaab6aca22a
Parents: 20be0e9
Author: Lyor Goldstein <***@apache.org>
Authored: Wed Nov 14 08:37:11 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 43 +--
.../sshd/cli/client/SshClientCliSupport.java | 2 +-
.../sshd/cli/server/SshServerCliSupport.java | 2 +-
.../sshd/client/config/keys/ClientIdentity.java | 39 +--
.../config/keys/ClientIdentityFileWatcher.java | 3 +-
.../config/keys/ClientIdentityLoader.java | 13 +-
.../config/keys/FilePasswordProvider.java | 14 +-
.../sshd/common/config/keys/IdentityUtils.java | 12 +-
.../config/keys/PrivateKeyEntryDecoder.java | 33 ++-
.../config/keys/PrivateKeyEntryResolver.java | 13 +-
.../loader/AbstractKeyPairResourceParser.java | 38 ++-
.../keys/loader/KeyPairResourceLoader.java | 67 +++--
.../keys/loader/KeyPairResourceParser.java | 7 +-
.../OpenSSHDSSPrivateKeyEntryDecoder.java | 6 +-
.../OpenSSHECDSAPrivateKeyEntryDecoder.java | 6 +-
.../openssh/OpenSSHKeyPairResourceParser.java | 32 ++-
.../openssh/OpenSSHRSAPrivateKeyDecoder.java | 6 +-
.../pem/AbstractPEMResourceKeyPairParser.java | 16 +-
.../loader/pem/DSSPEMResourceKeyPairParser.java | 6 +-
.../pem/ECDSAPEMResourceKeyPairParser.java | 6 +-
.../keys/loader/pem/PEMResourceParserUtils.java | 7 +-
.../pem/PKCS8PEMResourceKeyPairParser.java | 18 +-
.../loader/pem/RSAPEMResourceKeyPairParser.java | 6 +-
.../AbstractResourceKeyPairProvider.java | 11 +-
.../ClassLoadableResourceKeyPairProvider.java | 4 +-
.../common/keyprovider/FileKeyPairProvider.java | 7 +-
.../common/keyprovider/KeyIdentityProvider.java | 41 +--
.../common/keyprovider/KeyPairProvider.java | 12 +-
.../keyprovider/MultiKeyIdentityIterator.java | 10 +-
.../sshd/common/session/SessionContext.java | 4 +-
.../apache/sshd/common/util/ValidateUtils.java | 12 +
.../common/util/security/SecurityUtils.java | 18 +-
.../BouncyCastleKeyPairResourceParser.java | 23 +-
.../OpenSSHEd25519PrivateKeyEntryDecoder.java | 6 +-
.../AbstractGeneratorHostKeyProvider.java | 2 +-
.../BuiltinClientIdentitiesWatcherTest.java | 9 +-
.../keys/ClientIdentityFileWatcherTest.java | 4 +-
.../OpenSSHKeyPairResourceParserTest.java | 2 +-
.../pem/PKCS8PEMResourceKeyPairParserTest.java | 2 +-
.../common/keyprovider/KeyPairProviderTest.java | 12 +-
.../MultiKeyIdentityProviderTest.java | 4 +-
.../common/util/security/SecurityUtilsTest.java | 13 +-
.../PEMGeneratorHostKeyProviderTest.java | 22 +-
.../SimpleGeneratorHostKeyProviderTest.java | 23 +-
.../sshd/util/test/CommonTestSupportUtils.java | 18 +-
.../java/org/apache/sshd/client/SshClient.java | 23 +-
.../auth/pubkey/UserAuthPublicKeyIterator.java | 11 +-
.../sshd/client/session/ClientSession.java | 15 -
.../org/apache/sshd/common/session/Session.java | 2 -
.../common/session/helpers/AbstractSession.java | 49 +++-
.../sshd/server/config/keys/ServerIdentity.java | 6 +-
.../server/session/AbstractServerSession.java | 8 +-
.../hosts/HostConfigEntryResolverTest.java | 10 +-
.../sshd/common/auth/AuthenticationTest.java | 278 ++++++++++++++-----
.../common/auth/SinglePublicKeyAuthTest.java | 4 +-
.../super-secret-passphrase-RSA-AES-128-key | 30 ++
.../super-secret-passphrase-RSA-AES-128-key.pub | 1 +
.../openpgp/PGPKeyPairResourceParser.java | 19 +-
.../openpgp/PGPKeyPairResourceParserTest.java | 7 +-
.../loader/putty/AbstractPuttyKeyDecoder.java | 23 +-
.../keys/loader/putty/PuttyKeyUtilsTest.java | 18 +-
.../sftp/ApacheSshdSftpSessionFactory.java | 2 +-
62 files changed, 770 insertions(+), 390 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 57d53f6..9cc1cd4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,19 +2,19 @@

## Major code re-factoring

-* `AttributeStore` "read" methods moved to (new class) `AttributeRepository`
+* `AttributeStore` "read" methods moved to (new class) `AttributeRepository`.

- * `AttributeKey` moved to `AttributeRepository`
+ * `AttributeKey` moved to `AttributeRepository`.

- * `getAttribute` and `resolveAttribute` moved to `AttributeRepository`
+ * `getAttribute` and `resolveAttribute` moved to `AttributeRepository`.

* Added `attributeKeys` enumeration method to `AttributeRepository`.

-* `DEFAULT_PORT` moved from `SshConfigFileReader` to `SshConstants`
+* `DEFAULT_PORT` moved from `SshConfigFileReader` to `SshConstants`.

-* Moved some session "summary" related definitions from `Session` to `SessionContext` (which `Session` extends)
+* Moved some session "summary" related definitions from `Session` to `SessionContext` (which `Session` extends).

-* Added new `sessionDisconnect` method to `SessionListener`
+* Added new `sessionDisconnect` method to `SessionListener`.

* `ReservedSessionMessagesHandler#handleUnimplementedMessage` has an extra `cmd` argument
and is called both for `SSH_MSG_UNIMPLEMENTED` as well as for any other unexpected/unrecognized
@@ -35,44 +35,45 @@ accept also an `AttributeRepository` connection context argument (propagated fro
* The interface methods are also provided with a retry index that indicates the number of
times they have been re-invoked for the same resource (including on success).

+ * The available session context (if any) is also provided as an argument to the interface methods.
+
* `SshAgent#getIdentities` returns an `Iterable` rather than a `List`

* `SftpFileSystemProvider` and its associated helper classes have been moved to
-`org.apache.sshd.client.subsystem.sftp.fs` package
+`org.apache.sshd.client.subsystem.sftp.fs` package.
+
+* `KeyPairProvider` accepts a `SessionContext` argument in its `getKeyTypes/loadKey` methods.

-* `KeyPairProvider` accepts a `SessionContext` argument in its `getKeyTypes/loadKey` methods
+* `KeyIdentityProvider` accepts a `SessionContext` argument in its `loadKeys` method.

-* `KeyIdentityProvider` accepts a `SessionContext` argument in its `loadKeys` method
+* `ClientIdentityProvider` accepts a `SessionContext` argument in its `getClientIdentity` method.

-* `ClientIdentityProvider` accepts a `SessionContext` argument in its `getClientIdentity` method
+* `ClientIdentityLoader` accepts a `SessionContext` argument in its `loadClientIdentity` method.

-* `ApacheSshdSftpSessionFactory#get/setPrivateKey` has been renamed to `get/setPrivateKeyLocation`
+* `ApacheSshdSftpSessionFactory#get/setPrivateKey` has been renamed to `get/setPrivateKeyLocation`.

## Behavioral changes and enhancements

* [SSHD-849](https://issues.apache.org/jira/browse/SSHD-849) - Data forwarding code makes sure all
pending packets have been sent to the peer channel when closing the tunnel gracefully.

-* [SSHD-850](https://issues.apache.org/jira/browse/SSHD-850) - Add capability to retry a failed private key decryption
+* [SSHD-850](https://issues.apache.org/jira/browse/SSHD-850) - Add capability to retry a failed private key decryption.

-* [SSHD-857](https://issues.apache.org/jira/browse/SSHD-857) - Add session disconnect event signalling to SessionListener
+* [SSHD-857](https://issues.apache.org/jira/browse/SSHD-857) - Add session disconnect event signalling to SessionListener.

* Also calling `ReservedSessionMessagesHandler#handleUnimplementedMessage` not only for `SSH_MSG_UNIMPLEMENTED` but
also for any unexpected/unrecognized command encountered during the session message processing loop.

-* [SSHD-859](https://issues.apache.org/jira/browse/SSHD-859) - Provide client session connection context that is propagated to the SSH session
+* [SSHD-859](https://issues.apache.org/jira/browse/SSHD-859) - Provide client session connection context that is propagated to the SSH session.

* Also added connection context argument (propagated from the `ClientSessionCreator#connect` invocation)
to`connectionEstablished` and `abortEstablishedConnection` methods of `IoServiceEventListener`.

-* [SSHD-860](https://issues.apache.org/jira/browse/SSHD-860) - `UserAuthPublicKeyIterator` uses lazy loading of public key
-identities both from agent and client session
-
- * Also using lazy identity `KeyPair`(s) loading in `ClientIdentitiesWatcher`
+* [SSHD-860](https://issues.apache.org/jira/browse/SSHD-860) - Use lazy loading of public key identities.

-* [SSHD-861](https://issues.apache.org/jira/browse/SSHD-861) - Fixed username/password encoding for `SftpFileSystem` URI(s)
+* [SSHD-861](https://issues.apache.org/jira/browse/SSHD-861) - Fixed username/password encoding for `SftpFileSystem` URI(s).

* Also added `SftpFileSystemClientSessionInitializer` support in `SftpFileSystemProvider`

-* [SSHD-862](https://issues.apache.org/jira/browse/SSHD-862) - Provide session context argument when
-key loading methods are invoked
+* [SSHD-862](https://issues.apache.org/jira/browse/SSHD-862) - Provide session context argument (if available) when
+key loading methods are invoked.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
----------------------------------------------------------------------
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
index 2978524..9286324 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
@@ -346,7 +346,7 @@ public abstract class SshClientCliSupport extends CliSupport {
public static FileKeyPairProvider setupSessionIdentities(ClientFactoryManager client, Collection<? extends Path> identities,
BufferedReader stdin, PrintStream stdout, PrintStream stderr)
throws Throwable {
- client.setFilePasswordProvider((file, index) -> {
+ client.setFilePasswordProvider((session, file, index) -> {
stdout.print("Enter password for private key file=" + file + ": ");
return stdin.readLine();
});

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
----------------------------------------------------------------------
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
index eac5b7e..f716553 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
@@ -116,7 +116,7 @@ public abstract class SshServerCliSupport extends CliSupport {
for (String keyFilePath : keyFiles) {
Path path = Paths.get(keyFilePath);
try (InputStream inputStream = Files.newInputStream(path)) {
- KeyPair kp = SecurityUtils.loadKeyPairIdentity(keyFilePath, inputStream, null);
+ KeyPair kp = SecurityUtils.loadKeyPairIdentity(null, keyFilePath, inputStream, null);
pairs.add(kp);
} catch (Exception e) {
stderr.append("Failed (").append(e.getClass().getSimpleName()).append(')')

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
index 13f5c34..c92cfc0 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
@@ -38,6 +38,7 @@ import org.apache.sshd.common.config.keys.IdentityUtils;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.PublicKeyEntry;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.FileInfoExtractor;
@@ -101,7 +102,7 @@ public final class ClientIdentity {
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -114,7 +115,7 @@ public final class ClientIdentity {
*/
public static KeyPairProvider loadDefaultKeyPairProvider(
boolean strict, boolean supportedOnly, FilePasswordProvider provider, LinkOption... options)
- throws IOException, GeneralSecurityException {
+ throws IOException, GeneralSecurityException {
return loadDefaultKeyPairProvider(PublicKeyEntry.getDefaultKeysFolderPath(), strict, supportedOnly, provider, options);
}

@@ -126,7 +127,7 @@ public final class ClientIdentity {
* supported internally
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -139,7 +140,7 @@ public final class ClientIdentity {
*/
public static KeyPairProvider loadDefaultKeyPairProvider(
Path dir, boolean strict, boolean supportedOnly, FilePasswordProvider provider, LinkOption... options)
- throws IOException, GeneralSecurityException {
+ throws IOException, GeneralSecurityException {
Map<String, KeyPair> ids = loadDefaultIdentities(dir, strict, provider, options);
return IdentityUtils.createKeyPairProvider(ids, supportedOnly);
}
@@ -149,7 +150,7 @@ public final class ClientIdentity {
* access rights are excluded from consideration
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -160,8 +161,9 @@ public final class ClientIdentity {
* @see PublicKeyEntry#getDefaultKeysFolderPath()
* @see #loadDefaultIdentities(Path, boolean, FilePasswordProvider, LinkOption...)
*/
- public static Map<String, KeyPair> loadDefaultIdentities(boolean strict, FilePasswordProvider provider, LinkOption... options)
- throws IOException, GeneralSecurityException {
+ public static Map<String, KeyPair> loadDefaultIdentities(
+ boolean strict, FilePasswordProvider provider, LinkOption... options)
+ throws IOException, GeneralSecurityException {
return loadDefaultIdentities(PublicKeyEntry.getDefaultKeysFolderPath(), strict, provider, options);
}

@@ -171,7 +173,7 @@ public final class ClientIdentity {
* access rights are excluded from consideration
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -182,14 +184,17 @@ public final class ClientIdentity {
* @see #loadIdentities(Path, boolean, Collection, Function, FilePasswordProvider, LinkOption...)
* @see BuiltinIdentities
*/
- public static Map<String, KeyPair> loadDefaultIdentities(Path dir, boolean strict, FilePasswordProvider provider, LinkOption... options)
- throws IOException, GeneralSecurityException {
- return loadIdentities(dir, strict, BuiltinIdentities.NAMES, ID_GENERATOR, provider, options);
+ public static Map<String, KeyPair> loadDefaultIdentities(
+ Path dir, boolean strict, FilePasswordProvider provider, LinkOption... options)
+ throws IOException, GeneralSecurityException {
+ return loadIdentities(null, dir, strict, BuiltinIdentities.NAMES, ID_GENERATOR, provider, options);
}

/**
* Scans a folder and loads all available identity files
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param dir The {@link Path} of the folder to scan - ignored if not exists
* @param strict If {@code true} then files that do not have the required
* access rights are excluded from consideration
@@ -198,7 +203,7 @@ public final class ClientIdentity {
* holding the specified type
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link LinkOption}s to apply when checking
* for existence
@@ -210,10 +215,12 @@ public final class ClientIdentity {
* @see IdentityUtils#loadIdentities(Map, FilePasswordProvider, java.nio.file.OpenOption...)
*/
public static Map<String, KeyPair> loadIdentities(
- Path dir, boolean strict, Collection<String> types, Function<String, String> idGenerator, FilePasswordProvider provider, LinkOption... options)
+ SessionContext session, Path dir, boolean strict,
+ Collection<String> types, Function<? super String, String> idGenerator,
+ FilePasswordProvider provider, LinkOption... options)
throws IOException, GeneralSecurityException {
Map<String, Path> paths = scanIdentitiesFolder(dir, strict, types, idGenerator, options);
- return IdentityUtils.loadIdentities(paths, provider, IoUtils.EMPTY_OPEN_OPTIONS);
+ return IdentityUtils.loadIdentities(session, paths, provider, IoUtils.EMPTY_OPEN_OPTIONS);
}

/**
@@ -233,8 +240,8 @@ public final class ClientIdentity {
* @see KeyUtils#validateStrictKeyFilePermissions(Path, LinkOption...)
*/
public static Map<String, Path> scanIdentitiesFolder(
- Path dir, boolean strict, Collection<String> types, Function<String, String> idGenerator, LinkOption... options)
- throws IOException {
+ Path dir, boolean strict, Collection<String> types, Function<? super String, String> idGenerator, LinkOption... options)
+ throws IOException {
if (GenericUtils.isEmpty(types)) {
return Collections.emptyMap();
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
index 411ae1b..e2e1b82 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
@@ -123,8 +123,7 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
String location = path.toString();
ClientIdentityLoader idLoader = Objects.requireNonNull(getClientIdentityLoader(), "No client identity loader");
if (idLoader.isValidLocation(location)) {
- KeyPair kp = idLoader.loadClientIdentity(
- location, Objects.requireNonNull(getFilePasswordProvider(), "No file password provider"));
+ KeyPair kp = idLoader.loadClientIdentity(session, location, getFilePasswordProvider());
if (log.isTraceEnabled()) {
PublicKey key = (kp == null) ? null : kp.getPublic();
if (key != null) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
index 8b3a295..542697a 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
@@ -28,6 +28,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyPair;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
@@ -51,10 +52,12 @@ public interface ClientIdentityLoader {
}

@Override
- public KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
+ public KeyPair loadClientIdentity(
+ SessionContext session, String location, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
Path path = toPath(location);
try (InputStream inputStream = Files.newInputStream(path, IoUtils.EMPTY_OPEN_OPTIONS)) {
- return SecurityUtils.loadKeyPairIdentity(path.toString(), inputStream, provider);
+ return SecurityUtils.loadKeyPairIdentity(session, path.toString(), inputStream, provider);
}
}

@@ -81,6 +84,8 @@ public interface ClientIdentityLoader {
boolean isValidLocation(String location) throws IOException;

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool).
* @param location The identity key-pair location - the actual meaning (file, URL, etc.)
* depends on the implementation.
* @param provider The {@link FilePasswordProvider} to consult if the location contains
@@ -91,5 +96,7 @@ public interface ClientIdentityLoader {
* @throws GeneralSecurityException If failed to convert the contents into
* a valid identity
*/
- KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException;
+ KeyPair loadClientIdentity(
+ SessionContext session, String location, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
index 54e8465..365de50 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
@@ -22,6 +22,8 @@ package org.apache.sshd.common.config.keys;
import java.io.IOException;
import java.security.GeneralSecurityException;

+import org.apache.sshd.common.session.SessionContext;
+
/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
*/
@@ -39,9 +41,11 @@ public interface FilePasswordProvider {
/**
* An &quot;empty&quot; provider that returns {@code null} - i.e., unprotected key file
*/
- FilePasswordProvider EMPTY = (resourceKey, retryIndex) -> null;
+ FilePasswordProvider EMPTY = (session, resourceKey, retryIndex) -> null;

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param resourceKey The resource key representing the <U>private</U> file
* @param retryIndex The zero-based index of the invocation for the specific
* resource (in case invoked several times for the same resource)
@@ -49,13 +53,15 @@ public interface FilePasswordProvider {
* @throws IOException if cannot resolve password
* @see #handleDecodeAttemptResult(String, int, String, Exception)
*/
- String getPassword(String resourceKey, int retryIndex) throws IOException;
+ String getPassword(SessionContext session, String resourceKey, int retryIndex) throws IOException;

/**
* Invoked to inform the password provide about the decoding result. <b>Note:</b>
* any exception thrown from this method (including if called to inform about
* success) will be propagated instead of the original (if any was reported)
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param resourceKey The resource key representing the <U>private</U> file
* @param retryIndex The zero-based index of the invocation for the specific
* resource (in case invoked several times for the same resource). If success
@@ -68,12 +74,12 @@ public interface FilePasswordProvider {
* @throws GeneralSecurityException If not attempting to resolve a new password
*/
default ResourceDecodeResult handleDecodeAttemptResult(
- String resourceKey, int retryIndex, String password, Exception err)
+ SessionContext session, String resourceKey, int retryIndex, String password, Exception err)
throws IOException, GeneralSecurityException {
return ResourceDecodeResult.TERMINATE;
}

static FilePasswordProvider of(String password) {
- return (r, index) -> password;
+ return (session, resource, index) -> password;
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
index 9cf3859..6d9ab44 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
@@ -33,6 +33,7 @@ import java.util.TreeMap;

import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
@@ -123,11 +124,13 @@ public final class IdentityUtils {
}

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param paths A {@link Map} of the identities where key=identity type (case
* <U>insensitive</U>), value=the {@link Path} of file with the identity key
* @param provider A {@link FilePasswordProvider} - may be {@code null}
* if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String, int)} is the path of the
+ * to {@code FilePasswordProvider#getPassword} is the path of the
* file whose key is to be loaded
* @param options The {@link OpenOption}s to use when reading the key data
* @return A {@link Map} of the identities where key=identity type (case
@@ -136,8 +139,9 @@ public final class IdentityUtils {
* @throws GeneralSecurityException If failed to load the keys
* @see SecurityUtils#loadKeyPairIdentity(String, InputStream, FilePasswordProvider)
*/
- public static Map<String, KeyPair> loadIdentities(Map<String, ? extends Path> paths, FilePasswordProvider provider, OpenOption... options)
- throws IOException, GeneralSecurityException {
+ public static Map<String, KeyPair> loadIdentities(
+ SessionContext session, Map<String, ? extends Path> paths, FilePasswordProvider provider, OpenOption... options)
+ throws IOException, GeneralSecurityException {
if (GenericUtils.isEmpty(paths)) {
return Collections.emptyMap();
}
@@ -148,7 +152,7 @@ public final class IdentityUtils {
String type = pe.getKey();
Path path = pe.getValue();
try (InputStream inputStream = Files.newInputStream(path, options)) {
- KeyPair kp = SecurityUtils.loadKeyPairIdentity(path.toString(), inputStream, provider);
+ KeyPair kp = SecurityUtils.loadKeyPairIdentity(session, path.toString(), inputStream, provider);
KeyPair prev = ids.put(type, kp);
ValidateUtils.checkTrue(prev == null, "Multiple keys for type=%s", type);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java
index 8dc6113..12f6800 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java
@@ -32,6 +32,7 @@ import java.util.Collection;
import java.util.Objects;

import org.apache.sshd.common.config.keys.loader.KeyPairResourceLoader;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.NumberUtils;
import org.apache.sshd.common.util.ValidateUtils;
@@ -45,17 +46,19 @@ public interface PrivateKeyEntryDecoder<PUB extends PublicKey, PRV extends Priva
extends KeyEntryResolver<PUB, PRV>, PrivateKeyEntryResolver {

@Override
- default PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException {
+ default PrivateKey resolve(SessionContext session, String keyType, byte[] keyData) throws IOException, GeneralSecurityException {
ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type provided");
Collection<String> supported = getSupportedTypeNames();
if ((GenericUtils.size(supported) > 0) && supported.contains(keyType)) {
- return decodePrivateKey(FilePasswordProvider.EMPTY, keyData);
+ return decodePrivateKey(session, FilePasswordProvider.EMPTY, keyData);
}

throw new InvalidKeySpecException("resolve(" + keyType + ") not in listed supported types: " + supported);
}

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param passwordProvider The {@link FilePasswordProvider} to use
* in case the data is encrypted - may be {@code null} if no encrypted
* data is expected
@@ -65,24 +68,27 @@ public interface PrivateKeyEntryDecoder<PUB extends PublicKey, PRV extends Priva
* @throws IOException If failed to decode the key
* @throws GeneralSecurityException If failed to generate the key
*/
- default PRV decodePrivateKey(FilePasswordProvider passwordProvider, byte... keyData)
- throws IOException, GeneralSecurityException {
- return decodePrivateKey(passwordProvider, keyData, 0, NumberUtils.length(keyData));
+ default PRV decodePrivateKey(
+ SessionContext session, FilePasswordProvider passwordProvider, byte... keyData)
+ throws IOException, GeneralSecurityException {
+ return decodePrivateKey(session, passwordProvider, keyData, 0, NumberUtils.length(keyData));
}

- default PRV decodePrivateKey(FilePasswordProvider passwordProvider, byte[] keyData, int offset, int length)
- throws IOException, GeneralSecurityException {
+ default PRV decodePrivateKey(
+ SessionContext session, FilePasswordProvider passwordProvider, byte[] keyData, int offset, int length)
+ throws IOException, GeneralSecurityException {
if (length <= 0) {
return null;
}

try (InputStream stream = new ByteArrayInputStream(keyData, offset, length)) {
- return decodePrivateKey(passwordProvider, stream);
+ return decodePrivateKey(session, passwordProvider, stream);
}
}

- default PRV decodePrivateKey(FilePasswordProvider passwordProvider, InputStream keyData)
- throws IOException, GeneralSecurityException {
+ default PRV decodePrivateKey(
+ SessionContext session, FilePasswordProvider passwordProvider, InputStream keyData)
+ throws IOException, GeneralSecurityException {
// the actual data is preceded by a string that repeats the key type
String type = KeyEntryResolver.decodeString(keyData, KeyPairResourceLoader.MAX_KEY_TYPE_NAME_LENGTH);
if (GenericUtils.isEmpty(type)) {
@@ -94,10 +100,12 @@ public interface PrivateKeyEntryDecoder<PUB extends PublicKey, PRV extends Priva
throw new InvalidKeySpecException("Reported key type (" + type + ") not in supported list: " + supported);
}

- return decodePrivateKey(type, passwordProvider, keyData);
+ return decodePrivateKey(session, type, passwordProvider, keyData);
}

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param keyType The reported / encode key type
* @param passwordProvider The {@link FilePasswordProvider} to use
* in case the data is encrypted - may be {@code null} if no encrypted
@@ -108,7 +116,8 @@ public interface PrivateKeyEntryDecoder<PUB extends PublicKey, PRV extends Priva
* @throws IOException If failed to read from the data stream
* @throws GeneralSecurityException If failed to generate the key
*/
- PRV decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
+ PRV decodePrivateKey(
+ SessionContext session, String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
throws IOException, GeneralSecurityException;

/**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java
index 1e4c91e..581bef7 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java
@@ -24,6 +24,8 @@ import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;

+import org.apache.sshd.common.session.SessionContext;
+
/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
*/
@@ -34,7 +36,8 @@ public interface PrivateKeyEntryResolver {
*/
PrivateKeyEntryResolver IGNORING = new PrivateKeyEntryResolver() {
@Override
- public PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException {
+ public PrivateKey resolve(SessionContext session, String keyType, byte[] keyData)
+ throws IOException, GeneralSecurityException {
return null;
}

@@ -49,7 +52,8 @@ public interface PrivateKeyEntryResolver {
*/
PrivateKeyEntryResolver FAILING = new PrivateKeyEntryResolver() {
@Override
- public PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException {
+ public PrivateKey resolve(SessionContext session, String keyType, byte[] keyData)
+ throws IOException, GeneralSecurityException {
throw new InvalidKeySpecException("Failing resolver on key type=" + keyType);
}

@@ -60,11 +64,14 @@ public interface PrivateKeyEntryResolver {
};

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param keyType The {@code OpenSSH} reported key type
* @param keyData The {@code OpenSSH} encoded key data
* @return The extracted {@link PrivateKey} - ignored if {@code null}
* @throws IOException If failed to parse the key data
* @throws GeneralSecurityException If failed to generate the key
*/
- PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException;
+ PrivateKey resolve(SessionContext session, String keyType, byte[] keyData)
+ throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
index e9ad24e..0b69906 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
@@ -34,6 +34,7 @@ import java.util.Map;
import java.util.logging.Level;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.BufferUtils;
@@ -84,8 +85,9 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
}

@Override
- public Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
- throws IOException, GeneralSecurityException {
+ public Collection<KeyPair> loadKeyPairs(
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ throws IOException, GeneralSecurityException {
Collection<KeyPair> keyPairs = Collections.emptyList();
List<String> beginMarkers = getBeginners();
List<List<String>> endMarkers = getEndingMarkers();
@@ -103,8 +105,8 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean

int endIndex = markerPos.getKey();
String endLine = lines.get(endIndex);
- Collection<KeyPair> kps =
- extractKeyPairs(resourceKey, startLine, endLine, passwordProvider, lines.subList(startIndex, endIndex));
+ Collection<KeyPair> kps = extractKeyPairs(session, resourceKey,
+ startLine, endLine, passwordProvider, lines.subList(startIndex, endIndex));
if (GenericUtils.isNotEmpty(kps)) {
if (GenericUtils.isEmpty(keyPairs)) {
keyPairs = new LinkedList<>(kps);
@@ -124,6 +126,8 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* Extracts the key pairs within a <U>single</U> delimited by markers block of lines. By
* default cleans up the empty lines, joins them and converts them from BASE64
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param resourceKey A hint as to the origin of the text lines
* @param beginMarker The line containing the begin marker
* @param endMarker The line containing the end marker
@@ -136,12 +140,17 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* @see #extractKeyPairs(String, String, String, FilePasswordProvider, byte[])
*/
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ List<String> lines)
throws IOException, GeneralSecurityException {
- return extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, KeyPairResourceParser.extractDataBytes(lines));
+ return extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, KeyPairResourceParser.extractDataBytes(lines));
}

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param resourceKey A hint as to the origin of the text lines
* @param beginMarker The line containing the begin marker
* @param endMarker The line containing the end marker
@@ -154,18 +163,23 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* @see #extractKeyPairs(String, String, String, FilePasswordProvider, InputStream)
*/
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, byte[] bytes)
- throws IOException, GeneralSecurityException {
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ byte[] bytes)
+ throws IOException, GeneralSecurityException {
if (log.isTraceEnabled()) {
BufferUtils.dumpHex(getSimplifiedLogger(), Level.FINER, beginMarker, ':', 16, bytes);
}

try (InputStream bais = new ByteArrayInputStream(bytes)) {
- return extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, bais);
+ return extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, bais);
}
}

/**
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param resourceKey A hint as to the origin of the text lines
* @param beginMarker The line containing the begin marker
* @param endMarker The line containing the end marker
@@ -177,6 +191,8 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* @throws GeneralSecurityException If failed to generate the keys
*/
public abstract Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
- throws IOException, GeneralSecurityException;
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider, InputStream stream)
+ throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
index 00c53cf..5bf2597 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
@@ -39,6 +39,7 @@ import java.util.List;
import java.util.Objects;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.IoUtils;

/**
@@ -57,74 +58,95 @@ public interface KeyPairResourceLoader {
/**
* An empty loader that never fails but always returns an empty list
*/
- KeyPairResourceLoader EMPTY = (resourceKey, passwordProvider, lines) -> Collections.emptyList();
+ KeyPairResourceLoader EMPTY = (session, resourceKey, passwordProvider, lines) -> Collections.emptyList();

+ /**
+ * Loads private key data - <B>Note:</B> any non-ASCII characters are assumed to be UTF-8 encoded
+ *
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
+ * @param path The private key file {@link Path}
+ * @param passwordProvider The {@link FilePasswordProvider} to use
+ * in case the data is encrypted - may be {@code null} if no encrypted
+ * data is expected
+ * @param options The {@link OpenOption}-s to use to access the file data
+ * @return The extracted {@link KeyPair}s - may be {@code null}/empty if none.
+ * <B>Note:</B> the resource loader may decide to skip unknown lines if
+ * more than one key pair type is encoded in it
+ * @throws IOException If failed to process the lines
+ * @throws GeneralSecurityException If failed to generate the keys from the
+ * parsed data
+ */
default Collection<KeyPair> loadKeyPairs(
- Path path, FilePasswordProvider passwordProvider, OpenOption... options)
+ SessionContext session, Path path, FilePasswordProvider passwordProvider, OpenOption... options)
throws IOException, GeneralSecurityException {
- return loadKeyPairs(path, passwordProvider, StandardCharsets.UTF_8, options);
+ return loadKeyPairs(session, path, passwordProvider, StandardCharsets.UTF_8, options);
}

default Collection<KeyPair> loadKeyPairs(
- Path path, FilePasswordProvider passwordProvider, Charset cs, OpenOption... options)
+ SessionContext session, Path path, FilePasswordProvider passwordProvider, Charset cs, OpenOption... options)
throws IOException, GeneralSecurityException {
try (InputStream stream = Files.newInputStream(path, options)) {
- return loadKeyPairs(path.toString(), passwordProvider, stream, cs);
+ return loadKeyPairs(session, path.toString(), passwordProvider, stream, cs);
}
}

- default Collection<KeyPair> loadKeyPairs(URL url, FilePasswordProvider passwordProvider)
- throws IOException, GeneralSecurityException {
- return loadKeyPairs(url, passwordProvider, StandardCharsets.UTF_8);
+ default Collection<KeyPair> loadKeyPairs(
+ SessionContext session, URL url, FilePasswordProvider passwordProvider)
+ throws IOException, GeneralSecurityException {
+ return loadKeyPairs(session, url, passwordProvider, StandardCharsets.UTF_8);
}

- default Collection<KeyPair> loadKeyPairs(URL url, FilePasswordProvider passwordProvider, Charset cs)
- throws IOException, GeneralSecurityException {
+ default Collection<KeyPair> loadKeyPairs(
+ SessionContext session, URL url, FilePasswordProvider passwordProvider, Charset cs)
+ throws IOException, GeneralSecurityException {
try (InputStream stream = Objects.requireNonNull(url, "No URL").openStream()) {
- return loadKeyPairs(url.toExternalForm(), passwordProvider, stream, cs);
+ return loadKeyPairs(session, url.toExternalForm(), passwordProvider, stream, cs);
}
}

default Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, String data)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, String data)
throws IOException, GeneralSecurityException {
try (Reader reader = new StringReader((data == null) ? "" : data)) {
- return loadKeyPairs(resourceKey, passwordProvider, reader);
+ return loadKeyPairs(session, resourceKey, passwordProvider, reader);
}
}

default Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException {
- return loadKeyPairs(resourceKey, passwordProvider, stream, StandardCharsets.UTF_8);
+ return loadKeyPairs(session, resourceKey, passwordProvider, stream, StandardCharsets.UTF_8);
}

default Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, InputStream stream, Charset cs)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, InputStream stream, Charset cs)
throws IOException, GeneralSecurityException {
try (Reader reader = new InputStreamReader(
Objects.requireNonNull(stream, "No stream instance"), Objects.requireNonNull(cs, "No charset"))) {
- return loadKeyPairs(resourceKey, passwordProvider, reader);
+ return loadKeyPairs(session, resourceKey, passwordProvider, reader);
}
}

default Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, Reader r)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, Reader r)
throws IOException, GeneralSecurityException {
try (BufferedReader br = new BufferedReader(Objects.requireNonNull(r, "No reader instance"), IoUtils.DEFAULT_COPY_SIZE)) {
- return loadKeyPairs(resourceKey, passwordProvider, br);
+ return loadKeyPairs(session, resourceKey, passwordProvider, br);
}
}

default Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, BufferedReader r)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, BufferedReader r)
throws IOException, GeneralSecurityException {
- return loadKeyPairs(resourceKey, passwordProvider, IoUtils.readAllLines(r));
+ return loadKeyPairs(session, resourceKey, passwordProvider, IoUtils.readAllLines(r));
}

/**
* Loads key pairs from the given resource text lines
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param resourceKey A hint as to the origin of the text lines
* @param passwordProvider The {@link FilePasswordProvider} to use
* in case the data is encrypted - may be {@code null} if no encrypted
@@ -137,6 +159,7 @@ public interface KeyPairResourceLoader {
* @throws GeneralSecurityException If failed to generate the keys from the
* parsed data
*/
- Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ Collection<KeyPair> loadKeyPairs(
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
index f7e336a..c434f0a 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
@@ -31,6 +31,7 @@ import java.util.LinkedList;
import java.util.List;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;

@@ -45,7 +46,7 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
KeyPairResourceParser EMPTY = new KeyPairResourceParser() {
@Override
public Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
return Collections.emptyList();
}
@@ -153,7 +154,7 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
return new KeyPairResourceParser() {
@Override
public Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
Collection<KeyPair> keyPairs = Collections.emptyList();
for (KeyPairResourceParser p : parsers) {
@@ -161,7 +162,7 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
continue;
}

- Collection<KeyPair> kps = p.loadKeyPairs(resourceKey, passwordProvider, lines);
+ Collection<KeyPair> kps = p.loadKeyPairs(session, resourceKey, passwordProvider, lines);
if (GenericUtils.isEmpty(kps)) {
continue;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java
index 6188a04..fc87175 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java
@@ -41,6 +41,7 @@ import org.apache.sshd.common.config.keys.KeyEntryResolver;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.impl.AbstractPrivateKeyEntryDecoder;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -54,8 +55,9 @@ public class OpenSSHDSSPrivateKeyEntryDecoder extends AbstractPrivateKeyEntryDec
}

@Override
- public DSAPrivateKey decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
- throws IOException, GeneralSecurityException {
+ public DSAPrivateKey decodePrivateKey(
+ SessionContext session, String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
+ throws IOException, GeneralSecurityException {
if (!KeyPairProvider.SSH_DSS.equals(keyType)) { // just in case we were invoked directly
throw new InvalidKeySpecException("Unexpected key type: " + keyType);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHECDSAPrivateKeyEntryDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHECDSAPrivateKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHECDSAPrivateKeyEntryDecoder.java
index 83a0fb3..dfe01f6 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHECDSAPrivateKeyEntryDecoder.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHECDSAPrivateKeyEntryDecoder.java
@@ -43,6 +43,7 @@ import org.apache.sshd.common.config.keys.KeyEntryResolver;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.impl.AbstractPrivateKeyEntryDecoder;
import org.apache.sshd.common.config.keys.impl.ECDSAPublicKeyEntryDecoder;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -56,8 +57,9 @@ public class OpenSSHECDSAPrivateKeyEntryDecoder extends AbstractPrivateKeyEntryD
}

@Override
- public ECPrivateKey decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
- throws IOException, GeneralSecurityException {
+ public ECPrivateKey decodePrivateKey(
+ SessionContext session, String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
+ throws IOException, GeneralSecurityException {
ECCurves curve = ECCurves.fromKeyType(keyType);
if (curve == null) {
throw new InvalidKeySpecException("Not an EC curve name: " + keyType);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
index d531021..c82957d 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
@@ -48,6 +48,7 @@ import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
import org.apache.sshd.common.config.keys.loader.AbstractKeyPairResourceParser;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.BufferUtils;
@@ -98,9 +99,12 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ InputStream stream)
throws IOException, GeneralSecurityException {
- stream = validateStreamMagicMarker(resourceKey, stream);
+ stream = validateStreamMagicMarker(session, resourceKey, stream);

String cipher = KeyEntryResolver.decodeString(stream, MAX_CIPHER_NAME_LENGTH);
if (!OpenSSHParserContext.IS_NONE_CIPHER.test(cipher)) {
@@ -135,7 +139,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
OpenSSHParserContext context = new OpenSSHParserContext(cipher, kdfName, kdfOptions);
boolean traceEnabled = log.isTraceEnabled();
for (int index = 1; index <= numKeys; index++) {
- PublicKey pubKey = readPublicKey(resourceKey, context, stream);
+ PublicKey pubKey = readPublicKey(session, resourceKey, context, stream);
ValidateUtils.checkNotNull(pubKey, "Empty public key #%d in %s", index, resourceKey);
if (traceEnabled) {
log.trace("extractKeyPairs({}) read public key #{}: {} {}",
@@ -146,13 +150,13 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser

byte[] privateData = KeyEntryResolver.readRLEBytes(stream, MAX_PRIVATE_KEY_DATA_SIZE);
try (InputStream bais = new ByteArrayInputStream(privateData)) {
- return readPrivateKeys(resourceKey, context, publicKeys, passwordProvider, bais);
+ return readPrivateKeys(session, resourceKey, context, publicKeys, passwordProvider, bais);
}
}

protected PublicKey readPublicKey(
- String resourceKey, OpenSSHParserContext context, InputStream stream)
- throws IOException, GeneralSecurityException {
+ SessionContext session, String resourceKey, OpenSSHParserContext context, InputStream stream)
+ throws IOException, GeneralSecurityException {
byte[] keyData = KeyEntryResolver.readRLEBytes(stream, MAX_PUBLIC_KEY_DATA_SIZE);
try (InputStream bais = new ByteArrayInputStream(keyData)) {
String keyType = KeyEntryResolver.decodeString(bais, MAX_KEY_TYPE_NAME_LENGTH);
@@ -166,7 +170,8 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
}

protected List<KeyPair> readPrivateKeys(
- String resourceKey, OpenSSHParserContext context, Collection<? extends PublicKey> publicKeys,
+ SessionContext session, String resourceKey,
+ OpenSSHParserContext context, Collection<? extends PublicKey> publicKeys,
FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException {
if (GenericUtils.isEmpty(publicKeys)) {
@@ -190,7 +195,8 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
resourceKey, keyIndex, pubType);
}

- Map.Entry<PrivateKey, String> prvData = readPrivateKey(resourceKey, context, pubType, passwordProvider, stream);
+ Map.Entry<PrivateKey, String> prvData =
+ readPrivateKey(session, resourceKey, context, pubType, passwordProvider, stream);
PrivateKey prvKey = (prvData == null) ? null : prvData.getKey();
ValidateUtils.checkNotNull(prvKey, "Empty private key #%d in %s", keyIndex, resourceKey);

@@ -210,7 +216,9 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
}

protected SimpleImmutableEntry<PrivateKey, String> readPrivateKey(
- String resourceKey, OpenSSHParserContext context, String keyType, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ OpenSSHParserContext context, String keyType,
+ FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException {
String prvType = KeyEntryResolver.decodeString(stream, MAX_KEY_TYPE_NAME_LENGTH);
if (!Objects.equals(keyType, prvType)) {
@@ -224,7 +232,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
throw new NoSuchAlgorithmException("Unsupported key type (" + prvType + ") in " + resourceKey);
}

- PrivateKey prvKey = decoder.decodePrivateKey(prvType, passwordProvider, stream);
+ PrivateKey prvKey = decoder.decodePrivateKey(session, prvType, passwordProvider, stream);
if (prvKey == null) {
throw new InvalidKeyException("Cannot parse key type (" + prvType + ") in " + resourceKey);
}
@@ -233,7 +241,9 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
return new SimpleImmutableEntry<>(prvKey, comment);
}

- protected <S extends InputStream> S validateStreamMagicMarker(String resourceKey, S stream) throws IOException {
+ protected <S extends InputStream> S validateStreamMagicMarker(
+ SessionContext session, String resourceKey, S stream)
+ throws IOException {
byte[] actual = new byte[AUTH_MAGIC_BYTES.length];
IoUtils.readFully(stream, actual);
if (!Arrays.equals(AUTH_MAGIC_BYTES, actual)) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHRSAPrivateKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHRSAPrivateKeyDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHRSAPrivateKeyDecoder.java
index 72e003f..b77257d 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHRSAPrivateKeyDecoder.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHRSAPrivateKeyDecoder.java
@@ -41,6 +41,7 @@ import org.apache.sshd.common.config.keys.KeyEntryResolver;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.impl.AbstractPrivateKeyEntryDecoder;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -55,8 +56,9 @@ public class OpenSSHRSAPrivateKeyDecoder extends AbstractPrivateKeyEntryDecoder<
}

@Override
- public RSAPrivateKey decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
- throws IOException, GeneralSecurityException {
+ public RSAPrivateKey decodePrivateKey(
+ SessionContext session, String keyType, FilePasswordProvider passwordProvider, InputStream keyData)
+ throws IOException, GeneralSecurityException {
if (!KeyPairProvider.SSH_RSA.equals(keyType)) { // just in case we were invoked directly
throw new InvalidKeySpecException("Unexpected key type: " + keyType);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
index 6ac9e2f..a324339 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
@@ -39,6 +39,7 @@ import org.apache.sshd.common.config.keys.loader.AbstractKeyPairResourceParser;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
import org.apache.sshd.common.config.keys.loader.PrivateKeyEncryptionContext;
import org.apache.sshd.common.config.keys.loader.PrivateKeyObfuscator;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.BufferUtils;
@@ -73,7 +74,10 @@ public abstract class AbstractPEMResourceKeyPairParser

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ List<String> lines)
throws IOException, GeneralSecurityException {
if (GenericUtils.isEmpty(lines)) {
return Collections.emptyList();
@@ -133,7 +137,7 @@ public abstract class AbstractPEMResourceKeyPairParser
}

for (int retryIndex = 0;; retryIndex++) {
- String password = passwordProvider.getPassword(resourceKey, retryIndex);
+ String password = passwordProvider.getPassword(session, resourceKey, retryIndex);
Collection<KeyPair> keys;
try {
if (GenericUtils.isEmpty(password)) {
@@ -146,11 +150,11 @@ public abstract class AbstractPEMResourceKeyPairParser
byte[] encryptedData = KeyPairResourceParser.extractDataBytes(dataLines);
byte[] decodedData = applyPrivateKeyCipher(encryptedData, encContext, false);
try (InputStream bais = new ByteArrayInputStream(decodedData)) {
- keys = extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, bais);
+ keys = extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, bais);
}
} catch (IOException | GeneralSecurityException | RuntimeException e) {
ResourceDecodeResult result =
- passwordProvider.handleDecodeAttemptResult(resourceKey, retryIndex, password, e);
+ passwordProvider.handleDecodeAttemptResult(session, resourceKey, retryIndex, password, e);
if (result == null) {
result = ResourceDecodeResult.TERMINATE;
}
@@ -166,12 +170,12 @@ public abstract class AbstractPEMResourceKeyPairParser
}
}

- passwordProvider.handleDecodeAttemptResult(resourceKey, retryIndex, password, null);
+ passwordProvider.handleDecodeAttemptResult(session, resourceKey, retryIndex, password, null);
return keys;
}
}

- return super.extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, dataLines);
+ return super.extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, dataLines);
}

protected byte[] applyPrivateKeyCipher(

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
index c68a815..39c84a6 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
@@ -36,6 +36,7 @@ import java.util.List;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.NoCloseInputStream;
import org.apache.sshd.common.util.io.der.ASN1Object;
import org.apache.sshd.common.util.io.der.ASN1Type;
@@ -68,7 +69,10 @@ public class DSSPEMResourceKeyPairParser extends AbstractPEMResourceKeyPairParse

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ InputStream stream)
throws IOException, GeneralSecurityException {
KeyPair kp = decodeDSSKeyPair(SecurityUtils.getKeyFactory(KeyUtils.DSS_ALGORITHM), stream, false);
return Collections.singletonList(kp);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
index 768c30f..19c15e2 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
@@ -41,6 +41,7 @@ import java.util.Map;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.NoCloseInputStream;
import org.apache.sshd.common.util.io.der.ASN1Object;
import org.apache.sshd.common.util.io.der.ASN1Type;
@@ -72,7 +73,10 @@ public class ECDSAPEMResourceKeyPairParser extends AbstractPEMResourceKeyPairPar

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ InputStream stream)
throws IOException, GeneralSecurityException {
Map.Entry<ECPublicKeySpec, ECPrivateKeySpec> spec = decodeECPrivateKeySpec(stream, false);
if (!SecurityUtils.isECCSupported()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
index b6749da..d3aba1e 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
@@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;

@@ -43,11 +44,11 @@ public final class PEMResourceParserUtils {
public static final KeyPairResourceParser PROXY = new KeyPairResourceParser() {
@Override
public Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
- throws IOException, GeneralSecurityException {
+ SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ throws IOException, GeneralSecurityException {
@SuppressWarnings("synthetic-access")
KeyPairResourceParser proxy = PROXY_HOLDER.get();
- return (proxy == null) ? Collections.<KeyPair>emptyList() : proxy.loadKeyPairs(resourceKey, passwordProvider, lines);
+ return (proxy == null) ? Collections.emptyList() : proxy.loadKeyPairs(session, resourceKey, passwordProvider, lines);
}

@Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
index 1967719..90f033b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
@@ -35,6 +35,7 @@ import java.util.List;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.IoUtils;
@@ -65,27 +66,28 @@ public class PKCS8PEMResourceKeyPairParser extends AbstractPEMResourceKeyPairPar

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ InputStream stream)
throws IOException, GeneralSecurityException {
// Save the data before getting the algorithm OID since we will need it
byte[] encBytes = IoUtils.toByteArray(stream);
List<Integer> oidAlgorithm = getPKCS8AlgorithmIdentifier(encBytes);
- PrivateKey prvKey = decodePEMPrivateKeyPKCS8(oidAlgorithm, encBytes, passwordProvider);
+ PrivateKey prvKey = decodePEMPrivateKeyPKCS8(oidAlgorithm, encBytes);
PublicKey pubKey = ValidateUtils.checkNotNull(KeyUtils.recoverPublicKey(prvKey),
"Failed to recover public key of OID=%s", oidAlgorithm);
KeyPair kp = new KeyPair(pubKey, prvKey);
return Collections.singletonList(kp);
}

- public static PrivateKey decodePEMPrivateKeyPKCS8(
- List<Integer> oidAlgorithm, byte[] keyBytes, FilePasswordProvider passwordProvider)
- throws GeneralSecurityException {
+ public static PrivateKey decodePEMPrivateKeyPKCS8(List<Integer> oidAlgorithm, byte[] keyBytes)
+ throws GeneralSecurityException {
ValidateUtils.checkNotNullAndNotEmpty(oidAlgorithm, "No PKCS8 algorithm OID");
- return decodePEMPrivateKeyPKCS8(GenericUtils.join(oidAlgorithm, '.'), keyBytes, passwordProvider);
+ return decodePEMPrivateKeyPKCS8(GenericUtils.join(oidAlgorithm, '.'), keyBytes);
}

- public static PrivateKey decodePEMPrivateKeyPKCS8(
- String oid, byte[] keyBytes, FilePasswordProvider passwordProvider)
+ public static PrivateKey decodePEMPrivateKeyPKCS8(String oid, byte[] keyBytes)
throws GeneralSecurityException {
KeyPairPEMResourceParser parser =
PEMResourceParserUtils.getPEMResourceParserByOid(

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
index 988c210..8badd63 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
@@ -37,6 +37,7 @@ import java.util.List;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.NoCloseInputStream;
import org.apache.sshd.common.util.io.der.ASN1Object;
import org.apache.sshd.common.util.io.der.ASN1Type;
@@ -69,7 +70,10 @@ public class RSAPEMResourceKeyPairParser extends AbstractPEMResourceKeyPairParse

@Override
public Collection<KeyPair> extractKeyPairs(
- String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, String resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ InputStream stream)
throws IOException, GeneralSecurityException {
KeyPair kp = decodeRSAKeyPair(SecurityUtils.getKeyFactory(KeyUtils.RSA_ALGORITHM), stream, false);
return Collections.singletonList(kp);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
index 194daf5..7fbee1b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
@@ -166,16 +166,17 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair

protected KeyPair doLoadKey(SessionContext session, String resourceKey, R resource, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
- try (InputStream inputStream = openKeyPairResource(resourceKey, resource)) {
+ try (InputStream inputStream = openKeyPairResource(session, resourceKey, resource)) {
return doLoadKey(session, resourceKey, inputStream, provider);
}
}

- protected abstract InputStream openKeyPairResource(String resourceKey, R resource) throws IOException;
+ protected abstract InputStream openKeyPairResource(SessionContext session, String resourceKey, R resource) throws IOException;

- protected KeyPair doLoadKey(SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
- return SecurityUtils.loadKeyPairIdentity(resourceKey, inputStream, provider);
+ protected KeyPair doLoadKey(
+ SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
+ return SecurityUtils.loadKeyPairIdentity(session, resourceKey, inputStream, provider);
}

protected class KeyPairIterator implements Iterator<KeyPair> {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2b013cca/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
index 3132abd..54b4e30 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
@@ -90,7 +90,9 @@ public class ClassLoadableResourceKeyPairProvider extends AbstractResourceKeyPai
}

@Override
- protected InputStream openKeyPairResource(String resourceKey, String resource) throws IOException {
+ protected InputStream openKeyPairResource(
+ SessionContext session, String resourceKey, String resource)
+ throws IOException {
ClassLoader cl = resolveClassLoader();
if (cl == null) {
throw new StreamCorruptedException("No resource loader for " + resource);
l***@apache.org
2018-11-18 04:55:05 UTC
Permalink
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
index 9775e2c..445de2e 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
@@ -31,6 +31,7 @@ import java.util.List;

import org.apache.commons.ssl.PEMItem;
import org.apache.commons.ssl.PEMUtil;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
@@ -92,7 +93,7 @@ public class PKCS8PEMResourceKeyPairParserTest extends JUnitTestSupport {
os.close();

try (ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray())) {
- KeyPair kp2 = SecurityUtils.loadKeyPairIdentity(null, getCurrentTestName(), bais, null);
+ KeyPair kp2 = SecurityUtils.loadKeyPairIdentity(null, NamedResource.ofName(getCurrentTestName()), bais, null);

assertEquals("Mismatched public key", kp.getPublic(), kp2.getPublic());
assertEquals("Mismatched private key", prv1, kp2.getPrivate());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/test/java/org/apache/sshd/common/file/root/RootedFileSystemProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/file/root/RootedFileSystemProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/file/root/RootedFileSystemProviderTest.java
index db2f1be..5e07ba0 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/file/root/RootedFileSystemProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/file/root/RootedFileSystemProviderTest.java
@@ -37,6 +37,7 @@ import java.util.Objects;
import java.util.Random;
import java.util.TreeSet;

+import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.util.test.CommonTestSupportUtils;
import org.apache.sshd.util.test.NoIoTestCase;
import org.junit.BeforeClass;
@@ -231,7 +232,7 @@ public class RootedFileSystemProviderTest extends AssertableFile {

@Test
public void testResolveRoot() throws IOException {
- Path root = fileSystem.getRootDirectories().iterator().next();
+ Path root = GenericUtils.head(fileSystem.getRootDirectories());
Path dir = root.resolve("tsd");
FileHelper.createDirectory(dir);
Path f1 = FileHelper.createFile(dir.resolve("test.txt"));

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
index e6019fe..a1b525c 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
@@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
@@ -44,6 +45,7 @@ import org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider;
import org.apache.sshd.common.keyprovider.ClassLoadableResourceKeyPairProvider;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.util.test.JUnitTestSupport;
import org.apache.sshd.util.test.NoIoTestCase;
import org.junit.AfterClass;
@@ -158,7 +160,7 @@ public class SecurityUtilsTest extends JUnitTestSupport {
Collection<KeyPair> kpList = bcLoader.loadKeyPairs(null, file, TEST_PASSWORD_PROVIDER);
assertEquals(name + ": Mismatched loaded BouncyCastle keys count", 1, GenericUtils.size(kpList));

- KeyPair kpBC = kpList.iterator().next();
+ KeyPair kpBC = GenericUtils.head(kpList);
assertTrue(name + ": Mismatched BouncyCastle vs. file values", KeyUtils.compareKeyPairs(kpFile, kpBC));
}

@@ -172,20 +174,22 @@ public class SecurityUtilsTest extends JUnitTestSupport {
private static KeyPair testLoadPrivateKeyResource(
String name, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
throws IOException, GeneralSecurityException {
- return testLoadPrivateKey(name, new ClassLoadableResourceKeyPairProvider(name), pubType, prvType);
+ return testLoadPrivateKey(
+ NamedResource.ofName(name), new ClassLoadableResourceKeyPairProvider(name), pubType, prvType);
}

private static KeyPair testLoadPrivateKeyFile(
Path file, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
throws IOException, GeneralSecurityException {
- return testLoadPrivateKey(file.toString(), new FileKeyPairProvider(file), pubType, prvType);
+ return testLoadPrivateKey(new PathResource(file), new FileKeyPairProvider(file), pubType, prvType);
}

private static KeyPair testLoadPrivateKey(
- String resourceKey, AbstractResourceKeyPairProvider<?> provider,
+ NamedResource resourceKey, AbstractResourceKeyPairProvider<?> provider,
Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType)
throws IOException, GeneralSecurityException {
provider.setPasswordFinder(TEST_PASSWORD_PROVIDER);
+
Iterable<KeyPair> iterator = provider.loadKeys(null);
List<KeyPair> pairs = new ArrayList<>();
for (KeyPair kp : iterator) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
index 66ecb05..7cd690c 100644
--- a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
@@ -27,6 +27,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.concurrent.atomic.AtomicInteger;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.util.test.JUnitTestSupport;
import org.apache.sshd.util.test.NoIoTestCase;
@@ -69,13 +70,13 @@ public class AbstractGeneratorHostKeyProviderTest extends JUnitTestSupport {

@Override
protected KeyPair doReadKeyPair(
- SessionContext session, String resourceKey, InputStream inputStream)
+ SessionContext session, NamedResource resourceKey, InputStream inputStream)
throws IOException, GeneralSecurityException {
return null;
}

@Override
- protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream)
+ protected void doWriteKeyPair(NamedResource resourceKey, KeyPair kp, OutputStream outputStream)
throws IOException, GeneralSecurityException {
writes.incrementAndGet();
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/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 6ece3d9..fba078c 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
@@ -26,6 +26,7 @@ import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.ArrayList;
@@ -37,6 +38,7 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;

import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.client.auth.AuthenticationIdentitiesProvider;
@@ -67,6 +69,7 @@ import org.apache.sshd.common.AttributeRepository;
import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
@@ -81,7 +84,7 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.session.helpers.AbstractSession;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.common.util.net.SshdSocketAddress;

/**
@@ -511,12 +514,19 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
int port = hostConfig.getPort();
ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port);

- Collection<KeyPair> keys = loadClientIdentities(hostConfig.getIdentities(), IoUtils.EMPTY_LINK_OPTIONS);
+ Collection<String> hostIds = hostConfig.getIdentities();
+ Collection<PathResource> idFiles = GenericUtils.isEmpty(hostIds)
+ ? Collections.emptyList()
+ : hostIds.stream()
+ .map(l -> Paths.get(l))
+ .map(PathResource::new)
+ .collect(Collectors.toCollection(() -> new ArrayList<>(hostIds.size())));
+ Collection<KeyPair> keys = loadClientIdentities(idFiles);
return doConnect(hostConfig.getUsername(), new InetSocketAddress(host, port),
context, localAddress, keys, !hostConfig.isIdentitiesOnly());
}

- protected List<KeyPair> loadClientIdentities(Collection<String> locations, LinkOption... options) throws IOException {
+ protected List<KeyPair> loadClientIdentities(Collection<? extends NamedResource> locations) throws IOException {
if (GenericUtils.isEmpty(locations)) {
return Collections.emptyList();
}
@@ -526,7 +536,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
ClientIdentityLoader loader = Objects.requireNonNull(getClientIdentityLoader(), "No ClientIdentityLoader");
FilePasswordProvider provider = getFilePasswordProvider();
boolean debugEnabled = log.isDebugEnabled();
- for (String l : locations) {
+ for (NamedResource l : locations) {
if (!loader.isValidLocation(l)) {
if (ignoreNonExisting) {
if (debugEnabled) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwardingFilter.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwardingFilter.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwardingFilter.java
index 04c05bd..9100f4e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwardingFilter.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwardingFilter.java
@@ -978,7 +978,7 @@ public class DefaultForwardingFilter
if (after.size() > 1) {
throw new IOException("Multiple local addresses have been bound for " + address + "[" + bindAddress + "]");
}
- return (InetSocketAddress) after.iterator().next();
+ return (InetSocketAddress) GenericUtils.head(after);
} catch (IOException bindErr) {
Set<SocketAddress> after = acceptor.getBoundAddresses();
if (GenericUtils.isEmpty(after)) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
index ea8f74a..c5a6918 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
@@ -308,7 +308,8 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa

acceptor.bind(new InetSocketAddress(inetAddress, port));
if (port == 0) {
- port = ((InetSocketAddress) acceptor.getBoundAddresses().iterator().next()).getPort();
+ SocketAddress selectedAddress = GenericUtils.head(acceptor.getBoundAddresses());
+ port = ((InetSocketAddress) selectedAddress).getPort();
log.info("start() listen on auto-allocated port=" + port);
}
}
@@ -316,7 +317,8 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
} else {
acceptor.bind(new InetSocketAddress(port));
if (port == 0) {
- port = ((InetSocketAddress) acceptor.getBoundAddresses().iterator().next()).getPort();
+ SocketAddress selectedAddress = GenericUtils.head(acceptor.getBoundAddresses());
+ port = ((InetSocketAddress) selectedAddress).getPort();
log.info("start() listen on auto-allocated port=" + port);
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
index 3881890..1a767c6 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
@@ -29,6 +29,7 @@ import java.security.KeyPair;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

@@ -36,6 +37,7 @@ import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.config.keys.ClientIdentityLoader;
import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
@@ -148,13 +150,13 @@ public class HostConfigEntryResolverTest extends BaseTestSupport {
String clientIdentity = getCurrentTestName();
client.setClientIdentityLoader(new ClientIdentityLoader() {
@Override
- public boolean isValidLocation(String location) throws IOException {
- return clientIdentity.equals(location);
+ public boolean isValidLocation(NamedResource location) throws IOException {
+ return Objects.equals(clientIdentity, location.getName());
}

@Override
public KeyPair loadClientIdentity(
- SessionContext session, String location, FilePasswordProvider provider)
+ SessionContext session, NamedResource location, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
if (isValidLocation(location)) {
return identity;
@@ -214,13 +216,13 @@ public class HostConfigEntryResolverTest extends BaseTestSupport {

client.setClientIdentityLoader(new ClientIdentityLoader() {
@Override
- public boolean isValidLocation(String location) throws IOException {
- return clientIdentity.equals(location);
+ public boolean isValidLocation(NamedResource location) throws IOException {
+ return Objects.equals(clientIdentity, location.getName());
}

@Override
public KeyPair loadClientIdentity(
- SessionContext session, String location, FilePasswordProvider provider)
+ SessionContext session, NamedResource location, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
if (isValidLocation(location)) {
return specificIdentity;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java b/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
index b8b2e04..e55d150 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/auth/AuthenticationTest.java
@@ -45,6 +45,7 @@ import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.AttributeRepository;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
@@ -61,6 +62,7 @@ import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.io.resource.URLResource;
import org.apache.sshd.common.util.net.SshdSocketAddress;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.ServerAuthenticationManager;
@@ -894,12 +896,19 @@ public class AuthenticationTest extends BaseTestSupport {
String keyLocation = "super-secret-passphrase-RSA-AES-128-key";
FilePasswordProvider passwordProvider = new FilePasswordProvider() {
@Override
+ @SuppressWarnings("synthetic-access")
public String getPassword(
- SessionContext session, String resourceKey, int retryIndex)
+ SessionContext session, NamedResource resourceKey, int retryIndex)
throws IOException {
assertSame("Mismatched session context", s, session);
assertEquals("Mismatched retry index", 0, retryIndex);
- assertEquals("Mismatched location", keyLocation, resourceKey);
+
+ String name = resourceKey.getName();
+ int pos = name.lastIndexOf('/');
+ if (pos >= 0) {
+ name = name.substring(pos + 1);
+ }
+ assertEquals("Mismatched location", keyLocation, name);

Boolean passwordRequested = session.getAttribute(PASSWORD_ATTR);
assertNull("Password already requested", passwordRequested);
@@ -915,10 +924,11 @@ public class AuthenticationTest extends BaseTestSupport {
assertNotNull("Missing key file " + keyLocation, location);

KeyPair kp;
- try (InputStream keyData = location.openStream()) {
- kp = SecurityUtils.loadKeyPairIdentity(session, keyLocation, keyData, passwordProvider);
+ URLResource resourceKey = new URLResource(location);
+ try (InputStream keyData = resourceKey.openInputStream()) {
+ kp = SecurityUtils.loadKeyPairIdentity(session, resourceKey, keyData, passwordProvider);
}
- assertNotNull("No identity loaded from " + keyLocation, kp);
+ assertNotNull("No identity loaded from " + resourceKey, kp);
return Collections.singletonList(kp);
}
});

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
index b543328..e32f3d8 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
@@ -43,6 +43,7 @@ import org.apache.sshd.common.io.IoInputStream;
import org.apache.sshd.common.io.IoOutputStream;
import org.apache.sshd.common.io.IoReadFuture;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.server.SshServer;
@@ -152,14 +153,17 @@ public class WindowTest extends BaseTestSupport {
PropertyResolverUtils.updateProperty(client, FactoryManager.WINDOW_SIZE, 1024);
client.start();

- try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession()) {
session.addPasswordIdentity(getCurrentTestName());
session.auth().verify(5L, TimeUnit.SECONDS);

try (ChannelShell channel = session.createShellChannel()) {
channel.open().verify(5L, TimeUnit.SECONDS);

- try (Channel serverChannel = sshd.getActiveSessions().iterator().next().getService(ServerConnectionService.class).getChannels().iterator().next()) {
+ try (Channel serverChannel = GenericUtils.head(GenericUtils.head(sshd.getActiveSessions())
+ .getService(ServerConnectionService.class).getChannels())) {
Window clientLocal = channel.getLocalWindow();
Window clientRemote = channel.getRemoteWindow();
Window serverLocal = serverChannel.getLocalWindow();
@@ -168,8 +172,10 @@ public class WindowTest extends BaseTestSupport {
final String message = "0123456789";
final int nbMessages = 500;

- try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(channel.getInvertedIn(), StandardCharsets.UTF_8));
- BufferedReader reader = new BufferedReader(new InputStreamReader(channel.getInvertedOut(), StandardCharsets.UTF_8))) {
+ try (BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(channel.getInvertedIn(), StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(channel.getInvertedOut(), StandardCharsets.UTF_8))) {

for (int i = 0; i < nbMessages; i++) {
writer.write(message);
@@ -200,7 +206,9 @@ public class WindowTest extends BaseTestSupport {

client.start();

- try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession()) {
session.addPasswordIdentity(getCurrentTestName());
session.auth().verify(5L, TimeUnit.SECONDS);

@@ -214,7 +222,8 @@ public class WindowTest extends BaseTestSupport {
channel.setOut(outPos);
channel.open().verify(7L, TimeUnit.SECONDS);

- try (Channel serverChannel = sshd.getActiveSessions().iterator().next().getService(ServerConnectionService.class).getChannels().iterator().next()) {
+ try (Channel serverChannel = GenericUtils.head(GenericUtils.head(sshd.getActiveSessions())
+ .getService(ServerConnectionService.class).getChannels())) {
Window clientLocal = channel.getLocalWindow();
Window clientRemote = channel.getRemoteWindow();
Window serverLocal = serverChannel.getLocalWindow();
@@ -223,8 +232,10 @@ public class WindowTest extends BaseTestSupport {
final String message = "0123456789";
final int nbMessages = 500;

- try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(inPos, StandardCharsets.UTF_8));
- BufferedReader reader = new BufferedReader(new InputStreamReader(outPis, StandardCharsets.UTF_8))) {
+ try (BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(inPos, StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(outPis, StandardCharsets.UTF_8))) {
for (int i = 0; i < nbMessages; i++) {
writer.write(message);
writer.write('\n');
@@ -254,7 +265,9 @@ public class WindowTest extends BaseTestSupport {

client.start();

- try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port)
+ .verify(7L, TimeUnit.SECONDS)
+ .getSession()) {
session.addPasswordIdentity(getCurrentTestName());
session.auth().verify(5L, TimeUnit.SECONDS);

@@ -262,7 +275,8 @@ public class WindowTest extends BaseTestSupport {
channel.setStreaming(ClientChannel.Streaming.Async);
channel.open().verify(5L, TimeUnit.SECONDS);

- try (Channel serverChannel = sshd.getActiveSessions().iterator().next().getService(ServerConnectionService.class).getChannels().iterator().next()) {
+ try (Channel serverChannel = GenericUtils.head(GenericUtils.head(sshd.getActiveSessions())
+ .getService(ServerConnectionService.class).getChannels())) {
Window clientLocal = channel.getLocalWindow();
Window clientRemote = channel.getRemoteWindow();
Window serverLocal = serverChannel.getLocalWindow();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
index 5c3889f..11b0927 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
@@ -333,11 +333,11 @@ public class ServerTest extends BaseTestSupport {
assertTrue("No changes in activated channels", channelListener.waitForActiveChannelsChange(5L, TimeUnit.SECONDS));
assertTrue("No changes in open channels", channelListener.waitForOpenChannelsChange(5L, TimeUnit.SECONDS));

- try (AbstractSession serverSession = sshd.getActiveSessions().iterator().next()) {
+ try (AbstractSession serverSession = GenericUtils.head(sshd.getActiveSessions())) {
AbstractConnectionService service = serverSession.getService(AbstractConnectionService.class);
Collection<? extends Channel> channels = service.getChannels();

- try (Channel channel = channels.iterator().next()) {
+ try (Channel channel = GenericUtils.head(channels)) {
final long maxTimeoutValue = idleTimeoutValue + disconnectTimeoutValue + TimeUnit.SECONDS.toMillis(3L);
final long maxWaitNanos = TimeUnit.MILLISECONDS.toNanos(maxTimeoutValue);
Window wRemote = channel.getRemoteWindow();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParser.java b/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParser.java
index 1390fcf..e6ae158 100644
--- a/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParser.java
+++ b/sshd-openpgp/src/main/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParser.java
@@ -56,6 +56,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
@@ -103,7 +104,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
List<String> lines)
@@ -128,7 +129,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)
@@ -186,7 +187,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
}
}

- public List<KeyPair> extractKeyPairs(String resourceKey, Collection<? extends Subkey> subKeys)
+ public List<KeyPair> extractKeyPairs(NamedResource resourceKey, Collection<? extends Subkey> subKeys)
throws IOException, GeneralSecurityException {
if (GenericUtils.isEmpty(subKeys)) {
return Collections.emptyList();
@@ -249,7 +250,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
return kpList;
}

- public PublicKey extractPublicKey(String resourceKey, Subkey sk) throws IOException, GeneralSecurityException {
+ public PublicKey extractPublicKey(NamedResource resourceKey, Subkey sk) throws IOException, GeneralSecurityException {
if (sk == null) {
return null;
}
@@ -268,7 +269,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
}
}

- public RSAPublicKey extractRSAPublicKey(String resourceKey, RSAPublicBCPGKey bcKey) throws GeneralSecurityException {
+ public RSAPublicKey extractRSAPublicKey(NamedResource resourceKey, RSAPublicBCPGKey bcKey) throws GeneralSecurityException {
if (bcKey == null) {
return null;
}
@@ -278,7 +279,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
return generatePublicKey(KeyUtils.RSA_ALGORITHM, RSAPublicKey.class, new RSAPublicKeySpec(n, e));
}

- public PublicKey extractECPublicKey(String resourceKey, ECPublicBCPGKey bcKey) throws GeneralSecurityException {
+ public PublicKey extractECPublicKey(NamedResource resourceKey, ECPublicBCPGKey bcKey) throws GeneralSecurityException {
if (bcKey == null) {
return null;
} else if (bcKey instanceof EdDSAPublicBCPGKey) {
@@ -290,7 +291,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
}
}

- public ECPublicKey extractECDSAPublicKey(String resourceKey, ECDSAPublicBCPGKey bcKey) throws GeneralSecurityException {
+ public ECPublicKey extractECDSAPublicKey(NamedResource resourceKey, ECDSAPublicBCPGKey bcKey) throws GeneralSecurityException {
if (bcKey == null) {
return null;
}
@@ -326,7 +327,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
return generatePublicKey(KeyUtils.EC_ALGORITHM, ECPublicKey.class, new ECPublicKeySpec(w, paramSpec));
}

- public PublicKey extractEdDSAPublicKey(String resourceKey, EdDSAPublicBCPGKey bcKey) throws GeneralSecurityException {
+ public PublicKey extractEdDSAPublicKey(NamedResource resourceKey, EdDSAPublicBCPGKey bcKey) throws GeneralSecurityException {
if (bcKey == null) {
return null;
}
@@ -338,7 +339,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
throw new NoSuchAlgorithmException("Unsupported EdDSA public key type: " + bcKey.getClass().getSimpleName());
}

- public DSAPublicKey extractDSSPublicKey(String resourceKey, DSAPublicBCPGKey bcKey) throws GeneralSecurityException {
+ public DSAPublicKey extractDSSPublicKey(NamedResource resourceKey, DSAPublicBCPGKey bcKey) throws GeneralSecurityException {
if (bcKey == null) {
return null;
}
@@ -357,7 +358,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
return keyType.cast(pubKey);
}

- public PrivateKey extractPrivateKey(String resourceKey, Subkey sk, PublicKey pubKey)
+ public PrivateKey extractPrivateKey(NamedResource resourceKey, Subkey sk, PublicKey pubKey)
throws IOException, GeneralSecurityException, PGPException {
if (sk == null) {
return null;
@@ -378,7 +379,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
}
}

- public ECPrivateKey extractECDSAPrivateKey(String resourceKey, ECPublicKey pubKey, ECSecretBCPGKey bcKey)
+ public ECPrivateKey extractECDSAPrivateKey(NamedResource resourceKey, ECPublicKey pubKey, ECSecretBCPGKey bcKey)
throws GeneralSecurityException {
if (bcKey == null) {
return null;
@@ -393,7 +394,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
return generatePrivateKey(KeyUtils.EC_ALGORITHM, ECPrivateKey.class, new ECPrivateKeySpec(x, params));
}

- public PrivateKey extractEdDSAPrivateKey(String resourceKey, PublicKey pubKey, EdSecretBCPGKey bcKey)
+ public PrivateKey extractEdDSAPrivateKey(NamedResource resourceKey, PublicKey pubKey, EdSecretBCPGKey bcKey)
throws GeneralSecurityException {
if (bcKey == null) {
return null;
@@ -406,7 +407,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
throw new NoSuchAlgorithmException("Unsupported EdDSA private key type: " + bcKey.getClass().getSimpleName());
}

- public RSAPrivateKey extractRSAPrivateKey(String resourceKey, RSAPublicKey pubKey, RSASecretBCPGKey bcKey)
+ public RSAPrivateKey extractRSAPrivateKey(NamedResource resourceKey, RSAPublicKey pubKey, RSASecretBCPGKey bcKey)
throws GeneralSecurityException {
if (bcKey == null) {
return null;
@@ -424,7 +425,7 @@ public class PGPKeyPairResourceParser extends AbstractKeyPairResourceParser {
bcKey.getCrtCoefficient()));
}

- public DSAPrivateKey extractDSSPrivateKey(String resourceKey, DSAPublicKey pubKey, DSASecretBCPGKey bcKey)
+ public DSAPrivateKey extractDSSPrivateKey(NamedResource resourceKey, DSAPublicKey pubKey, DSASecretBCPGKey bcKey)
throws GeneralSecurityException {
if (bcKey == null) {
return null;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java b/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
index 27bbfef..cd13da5 100644
--- a/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
+++ b/sshd-openpgp/src/test/java/org/apache/sshd/common/config/keys/loader/openpgp/PGPKeyPairResourceParserTest.java
@@ -31,6 +31,7 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
import org.apache.sshd.common.config.keys.KeyUtils;
@@ -70,7 +71,7 @@ public class PGPKeyPairResourceParserTest extends JUnitTestSupport {
this.passwordProvider = new FilePasswordProvider() {
@Override
@SuppressWarnings("synthetic-access")
- public String getPassword(SessionContext session, String resourceKey, int retryIndex) throws IOException {
+ public String getPassword(SessionContext session, NamedResource resourceKey, int retryIndex) throws IOException {
switch (result) {
case IGNORE:
case TERMINATE:
@@ -94,7 +95,7 @@ public class PGPKeyPairResourceParserTest extends JUnitTestSupport {
@Override
@SuppressWarnings("synthetic-access")
public ResourceDecodeResult handleDecodeAttemptResult(
- SessionContext session, String resourceKey, int retryIndex, String password, Exception err)
+ SessionContext session, NamedResource resourceKey, int retryIndex, String password, Exception err)
throws IOException, GeneralSecurityException {
if (err == null) {
return null;
@@ -142,7 +143,7 @@ public class PGPKeyPairResourceParserTest extends JUnitTestSupport {

Collection<KeyPair> keys;
try {
- keys = PGPKeyPairResourceParser.INSTANCE.loadKeyPairs(null, resourceName, passwordProvider, stream);
+ keys = PGPKeyPairResourceParser.INSTANCE.loadKeyPairs(null, NamedResource.ofName(resourceName), passwordProvider, stream);
} catch (Exception e) {
if (result != ResourceDecodeResult.TERMINATE) {
fail("Mismatched result mode for " + e.getClass().getSimpleName() + "[" + e.getMessage() + "]");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
index 8faed0b..4a72a01 100644
--- a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
@@ -36,6 +36,7 @@ import java.util.List;

import javax.security.auth.login.FailedLoginException;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
import org.apache.sshd.common.config.keys.impl.AbstractIdentityResourceLoader;
@@ -59,7 +60,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}

@Override
- public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ public boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException {
if (!PuttyKeyPairResourceParser.super.canExtractKeyPairs(resourceKey, lines)) {
return false;
@@ -86,7 +87,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends

@Override
public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
List<String> pubLines = Collections.emptyList();
List<String> prvLines = Collections.emptyList();
@@ -124,7 +125,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}

public static List<String> extractDataLines(
- String resourceKey, List<String> lines, int startIndex, String hdrName, String hdrValue, List<String> curLines)
+ NamedResource resourceKey, List<String> lines, int startIndex, String hdrName, String hdrValue, List<String> curLines)
throws IOException {
if (GenericUtils.size(curLines) > 0) {
throw new StreamCorruptedException("Duplicate " + hdrName + " in " + resourceKey);
@@ -147,7 +148,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}

public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
List<String> pubLines, List<String> prvLines, String prvEncryption,
FilePasswordProvider passwordProvider)
throws IOException, GeneralSecurityException {
@@ -157,7 +158,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}

public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String pubData, String prvData, String prvEncryption,
FilePasswordProvider passwordProvider)
throws IOException, GeneralSecurityException {
@@ -225,7 +226,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}
}

- public Collection<KeyPair> loadKeyPairs(String resourceKey, byte[] pubData, byte[] prvData)
+ public Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, byte[] pubData, byte[] prvData)
throws IOException, GeneralSecurityException {
ValidateUtils.checkNotNullAndNotEmpty(pubData, "No public key data in %s", resourceKey);
ValidateUtils.checkNotNullAndNotEmpty(prvData, "No private key data in %s", resourceKey);
@@ -235,7 +236,7 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}
}

- public Collection<KeyPair> loadKeyPairs(String resourceKey, InputStream pubData, InputStream prvData)
+ public Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, InputStream pubData, InputStream prvData)
throws IOException, GeneralSecurityException {
try (PuttyKeyReader pubReader =
new PuttyKeyReader(ValidateUtils.checkNotNull(pubData, "No public key data in %s", resourceKey));
@@ -245,6 +246,6 @@ public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends
}
}

- public abstract Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
+ public abstract Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
index 366aead..78aedc2 100644
--- a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
@@ -33,6 +33,7 @@ import java.security.spec.DSAPublicKeySpec;
import java.util.Collection;
import java.util.Collections;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.security.SecurityUtils;
@@ -48,7 +49,7 @@ public class DSSPuttyKeyDecoder extends AbstractPuttyKeyDecoder<DSAPublicKey, DS
}

@Override
- public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
+ public Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
throws IOException, GeneralSecurityException {
pubReader.skip(); // skip version


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
index f5860f1..4ae9922 100644
--- a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
@@ -36,6 +36,7 @@ import java.security.spec.InvalidKeySpecException;
import java.util.Collection;
import java.util.Collections;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.util.buffer.BufferUtils;
@@ -54,7 +55,7 @@ public class ECDSAPuttyKeyDecoder extends AbstractPuttyKeyDecoder<ECPublicKey, E
}

@Override
- public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
+ public Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
throws IOException, GeneralSecurityException {
if (!SecurityUtils.isECCSupported()) {
throw new NoSuchAlgorithmException("ECC not supported for " + resourceKey);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
index f610983..e461cc3 100644
--- a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
@@ -28,6 +28,7 @@ import java.security.spec.InvalidKeySpecException;
import java.util.Collection;
import java.util.Collections;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderUtils;
@@ -48,7 +49,7 @@ public class EdDSAPuttyKeyDecoder extends AbstractPuttyKeyDecoder<EdDSAPublicKey
}

@Override
- public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
+ public Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
throws IOException, GeneralSecurityException {
if (!SecurityUtils.isEDDSACurveSupported()) {
throw new NoSuchAlgorithmException(SecurityUtils.EDDSA + " provider not supported for " + resourceKey);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
index f098b0f..28570df 100644
--- a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
@@ -37,6 +37,7 @@ import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.IdentityResourceLoader;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
import org.apache.sshd.common.digest.BuiltinDigests;
@@ -112,7 +113,7 @@ public interface PuttyKeyPairResourceParser<PUB extends PublicKey, PRV extends P
String NO_PRIVATE_KEY_ENCRYPTION_VALUE = "none";

@Override
- default boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ default boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException {
if (GenericUtils.isEmpty(lines)) {
return false;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
index 0a55d55..d99b8a0 100644
--- a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
@@ -34,6 +34,7 @@ import java.security.spec.RSAPublicKeySpec;
import java.util.Collection;
import java.util.Collections;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.security.SecurityUtils;
@@ -49,7 +50,7 @@ public class RSAPuttyKeyDecoder extends AbstractPuttyKeyDecoder<RSAPublicKey, RS
}

@Override
- public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
+ public Collection<KeyPair> loadKeyPairs(NamedResource resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
throws IOException, GeneralSecurityException {
pubReader.skip(); // skip version


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java b/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
index 795e053..0e0580a 100644
--- a/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
+++ b/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
@@ -97,7 +98,8 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {
}

List<String> lines = IoUtils.readAllLines(url);
- assertTrue(resource + " - can extract key pair", parser.canExtractKeyPairs(resource, lines));
+ NamedResource resourceKey = NamedResource.ofName(resource);
+ assertTrue(resource + " - can extract key pair", parser.canExtractKeyPairs(resourceKey, lines));

for (PuttyKeyPairResourceParser<?, ?> other : PuttyKeyUtils.BY_KEY_TYPE.values()) {
if (parser == other) {
@@ -105,7 +107,7 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {
}

assertFalse(other.getClass().getSimpleName() + "/" + resource + " - unexpected extraction capability",
- other.canExtractKeyPairs(resource, lines));
+ other.canExtractKeyPairs(resourceKey, lines));
}
}
}
@@ -117,7 +119,7 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {

Collection<KeyPair> keys = parser.loadKeyPairs(null, url, null);
assertEquals("Mismatched loaded keys count from " + regularFile, 1, GenericUtils.size(keys));
- assertLoadedKeyPair(regularFile, keys.iterator().next());
+ assertLoadedKeyPair(regularFile, GenericUtils.head(keys));
}

@Test
@@ -130,7 +132,7 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {
Collection<KeyPair> keys = parser.loadKeyPairs(null, url, (s, r, index) -> PASSWORD);
assertEquals("Mismatched loaded keys count from " + encryptedFile, 1, GenericUtils.size(keys));

- assertLoadedKeyPair(encryptedFile, keys.iterator().next());
+ assertLoadedKeyPair(encryptedFile, GenericUtils.head(keys));
}

@Test
@@ -146,7 +148,7 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {
AtomicInteger retriesCount = new AtomicInteger(0);
FilePasswordProvider provider = new FilePasswordProvider() {
@Override
- public String getPassword(SessionContext session, String resourceKey, int retryIndex) throws IOException {
+ public String getPassword(SessionContext session, NamedResource resourceKey, int retryIndex) throws IOException {
assertSame("Mismatched session context", mockSession, session);

switch (result) {
@@ -171,7 +173,7 @@ public class PuttyKeyUtilsTest extends JUnitTestSupport {

@Override
public ResourceDecodeResult handleDecodeAttemptResult(
- SessionContext session, String resourceKey, int retryIndex, String password, Exception err)
+ SessionContext session, NamedResource resourceKey, int retryIndex, String password, Exception err)
throws IOException, GeneralSecurityException {
assertSame("Mismatched session context", mockSession, session);
if (err == null) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java b/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
index 6ede1e3..5754a2a 100644
--- a/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
+++ b/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
@@ -200,15 +200,18 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
}
}

- validateHashResult(file, file.checkFileName(srcPath, algorithms, 0L, 0L, hashBlockSize), algorithms.get(0), expectedHash);
+ String hashAlgo = algorithms.get(0);
+ validateHashResult(file, file.checkFileName(srcPath, algorithms, 0L, 0L, hashBlockSize), hashAlgo, expectedHash);
try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Read)) {
- validateHashResult(hndl, hndl.checkFileHandle(fileHandle, algorithms, 0L, 0L, hashBlockSize), algorithms.get(0), expectedHash);
+ validateHashResult(hndl, hndl.checkFileHandle(fileHandle, algorithms, 0L, 0L, hashBlockSize), hashAlgo, expectedHash);
}
}
}
}

- private void validateHashResult(NamedResource hasher, Map.Entry<String, ? extends Collection<byte[]>> result, String expectedAlgorithm, byte[] expectedHash) {
+ private void validateHashResult(
+ NamedResource hasher, Map.Entry<String, ? extends Collection<byte[]>> result,
+ String expectedAlgorithm, byte[] expectedHash) {
String name = hasher.getName();
assertNotNull("No result for hash=" + name, result);
assertEquals("Mismatched hash algorithms for " + name, expectedAlgorithm, result.getKey());
@@ -217,7 +220,7 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
Collection<byte[]> values = result.getValue();
assertEquals("Mismatched hash values count for " + name, 1, GenericUtils.size(values));

- byte[] actualHash = values.iterator().next();
+ byte[] actualHash = GenericUtils.head(values);
if (!Arrays.equals(expectedHash, actualHash)) {
fail("Mismatched hashes for " + name
+ ": expected=" + BufferUtils.toHex(':', expectedHash)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
----------------------------------------------------------------------
diff --git a/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java b/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
index 478d3cc..b2d29b0 100644
--- a/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
+++ b/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/ApacheSshdSftpSessionFactory.java
@@ -20,7 +20,6 @@
package org.apache.sshd.spring.integration.sftp;

import java.io.IOException;
-import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PublicKey;
@@ -367,11 +366,8 @@ public class ApacheSshdSftpSessionFactory
}

FilePasswordProvider provider = resolveFilePasswordProvider(session, keyResource, keyPassword);
- Collection<KeyPair> keyPairs;
- try (InputStream inputStream = keyResource.getInputStream()) {
- keyPairs = PEMResourceParserUtils.PROXY.loadKeyPairs(session, keyResource.toString(), provider, inputStream);
- }
-
+ SpringIoResource location = new SpringIoResource(keyResource);
+ Collection<KeyPair> keyPairs = PEMResourceParserUtils.PROXY.loadKeyPairs(session, location, provider);
int numLoaded = GenericUtils.size(keyPairs);
if (numLoaded <= 0) {
if (debugEnabled) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/SpringIoResource.java
----------------------------------------------------------------------
diff --git a/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/SpringIoResource.java b/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/SpringIoResource.java
new file mode 100644
index 0000000..7ab4ade
--- /dev/null
+++ b/sshd-spring-sftp/src/main/java/org/apache/sshd/spring/integration/sftp/SpringIoResource.java
@@ -0,0 +1,51 @@
+/*
+ * 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.spring.integration.sftp;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.sshd.common.util.io.resource.AbstractIoResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SpringIoResource extends AbstractIoResource<Resource> {
+ public SpringIoResource(Resource r) {
+ super(Resource.class, r);
+ }
+
+ public Resource getResource() {
+ return getResourceValue();
+ }
+
+ @Override
+ public String getName() {
+ Resource r = getResource();
+ return r.getFilename();
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ Resource r = getResource();
+ return r.getInputStream();
+ }
+}
l***@apache.org
2018-11-18 04:55:03 UTC
Permalink
[SSHD-862] Provide SessionContext argument when loading client keys identities


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

Branch: refs/heads/master
Commit: 210f638e34ced6ce6322dc788dd01d8818b1da3d
Parents: e05898c
Author: Lyor Goldstein <***@apache.org>
Authored: Tue Nov 13 17:21:42 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:47 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 4 ++
.../sshd/cli/server/SshServerCliSupport.java | 4 +-
.../auth/AuthenticationIdentitiesProvider.java | 3 +-
.../keys/BuiltinClientIdentitiesWatcher.java | 11 +++--
.../config/keys/ClientIdentitiesWatcher.java | 13 +++---
.../config/keys/ClientIdentityFileWatcher.java | 7 ++--
.../config/keys/ClientIdentityProvider.java | 8 +++-
.../sshd/common/config/keys/KeyRandomArt.java | 22 +++++++---
.../AbstractResourceKeyPairProvider.java | 31 ++++++++------
.../ClassLoadableResourceKeyPairProvider.java | 5 ++-
.../common/keyprovider/FileKeyPairProvider.java | 9 ++--
.../common/keyprovider/KeyIdentityProvider.java | 44 +++++++++++---------
.../common/keyprovider/KeyPairProvider.java | 8 ++--
.../keyprovider/MappedKeyPairProvider.java | 2 +-
.../keyprovider/MultiKeyIdentityIterator.java | 13 +++++-
.../keyprovider/MultiKeyIdentityProvider.java | 6 ++-
.../AbstractGeneratorHostKeyProvider.java | 30 +++++++------
.../SimpleGeneratorHostKeyProvider.java | 8 +++-
.../BuiltinClientIdentitiesWatcherTest.java | 2 +-
.../keys/ClientIdentityFileWatcherTest.java | 7 ++--
.../client/config/keys/ClientIdentityTest.java | 2 +-
.../common/config/keys/KeyRandomArtTest.java | 2 +-
.../common/keyprovider/KeyPairProviderTest.java | 4 +-
.../MultiKeyIdentityProviderTest.java | 5 ++-
.../common/util/security/SecurityUtilsTest.java | 2 +-
.../AbstractGeneratorHostKeyProviderTest.java | 14 ++++---
.../sshd/util/test/CommonTestSupportUtils.java | 4 +-
.../keys/LazyClientIdentityIteratorTest.java | 7 ++--
.../auth/pubkey/UserAuthPublicKeyIterator.java | 2 +-
.../sshd/client/session/ClientSession.java | 4 +-
.../server/session/ServerUserAuthService.java | 2 +-
.../hosts/HostConfigEntryResolverTest.java | 3 +-
.../signature/SignatureFactoriesTest.java | 11 ++---
.../sshd/server/auth/WelcomeBannerTest.java | 5 ++-
.../server/config/keys/ServerIdentityTest.java | 2 +-
35 files changed, 186 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 6751736..a07e953 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -42,6 +42,10 @@ accept also an `AttributeRepository` connection context argument (propagated fro

* `KeyPairProvider` accepts a `SessionContext` argument in its `getKeyTypes/loadKey` methods

+* `KeyIdentityProvider` accepts a `SessionContext` argument in its `loadKeys` method
+
+* `ClientIdentityProvider` accepts a `SessionContext` argument in its `getClientIdentity` method
+
## Behavioral changes and enhancements

* [SSHD-849](https://issues.apache.org/jira/browse/SSHD-849) - Data forwarding code makes sure all

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
----------------------------------------------------------------------
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
index 6cdffc8..eac5b7e 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
@@ -92,8 +92,8 @@ public abstract class SshServerCliSupport extends CliSupport {
hostKeyProvider.setKeySize(hostKeySize);
}

- List<KeyPair> keys = ValidateUtils.checkNotNullAndNotEmpty(hostKeyProvider.loadKeys(),
- "Failed to load keys from %s", hostKeyFile);
+ List<KeyPair> keys = ValidateUtils.checkNotNullAndNotEmpty(
+ hostKeyProvider.loadKeys(null), "Failed to load keys from %s", hostKeyFile);
KeyPair kp = keys.get(0);
PublicKey pubKey = kp.getPublic();
String keyAlgorithm = pubKey.getAlgorithm();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java b/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
index ee7c856..6ac1a93 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
@@ -26,6 +26,7 @@ import java.util.List;
import org.apache.sshd.client.auth.password.PasswordIdentityProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.helper.LazyMatchingTypeIterable;

/**
@@ -82,7 +83,7 @@ public interface AuthenticationIdentitiesProvider extends KeyIdentityProvider, P
static AuthenticationIdentitiesProvider wrapIdentities(Iterable<?> identities) {
return new AuthenticationIdentitiesProvider() {
@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return LazyMatchingTypeIterable.lazySelectMatchingTypes(identities, KeyPair.class);
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
index ab9929b..bb3f738 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
@@ -32,6 +32,7 @@ import org.apache.sshd.common.NamedResource;
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.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;

/**
@@ -69,18 +70,20 @@ public class BuiltinClientIdentitiesWatcher extends ClientIdentitiesWatcher {
}

@Override
- public Iterable<KeyPair> loadKeys() {
- return isSupportedOnly() ? loadKeys(this::isSupported) : super.loadKeys();
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
+ return isSupportedOnly()
+ ? loadKeys(session, p -> isSupported(session, p))
+ : super.loadKeys(session);
}

- private boolean isSupported(KeyPair kp) {
+ protected boolean isSupported(SessionContext session, KeyPair kp) {
BuiltinIdentities id = BuiltinIdentities.fromKeyPair(kp);
if ((id != null) && id.isSupported()) {
return true;
}
if (log.isDebugEnabled()) {
log.debug("loadKeys - remove unsupported identity={}, key-type={}, key={}",
- id, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
+ id, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
}
return false;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
index 05660f7..eed14e9 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
@@ -31,6 +31,7 @@ import java.util.function.Supplier;
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.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;

/**
@@ -69,17 +70,17 @@ public class ClientIdentitiesWatcher extends AbstractKeyPairProvider implements
}

@Override
- public Iterable<KeyPair> loadKeys() {
- return loadKeys(null);
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
+ return loadKeys(session, null);
}

- protected Iterable<KeyPair> loadKeys(Predicate<? super KeyPair> filter) {
- return ClientIdentityProvider.lazyKeysLoader(providers, this::doGetKeyPair, filter);
+ protected Iterable<KeyPair> loadKeys(SessionContext session, Predicate<? super KeyPair> filter) {
+ return ClientIdentityProvider.lazyKeysLoader(providers, p -> doGetKeyPair(session, p), filter);
}

- protected KeyPair doGetKeyPair(ClientIdentityProvider p) {
+ protected KeyPair doGetKeyPair(SessionContext session, ClientIdentityProvider p) {
try {
- KeyPair kp = p.getClientIdentity();
+ KeyPair kp = p.getClientIdentity(session);
if (kp == null) {
if (log.isDebugEnabled()) {
log.debug("loadKeys({}) no key loaded", p);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
index dc2128f..411ae1b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
@@ -31,6 +31,7 @@ import java.util.function.Supplier;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.io.ModifiableFileWatcher;
@@ -84,7 +85,7 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
}

@Override
- public KeyPair getClientIdentity() throws IOException, GeneralSecurityException {
+ public KeyPair getClientIdentity(SessionContext session) throws IOException, GeneralSecurityException {
if (!checkReloadRequired()) {
return identityHolder.get();
}
@@ -95,7 +96,7 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
return identityHolder.get();
}

- KeyPair id = reloadClientIdentity(path);
+ KeyPair id = reloadClientIdentity(session, path);
if (!KeyUtils.compareKeyPairs(kp, id)) {
if (log.isDebugEnabled()) {
log.debug("getClientIdentity({}) identity {}", path, (kp == null) ? "loaded" : "re-loaded");
@@ -107,7 +108,7 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
return identityHolder.get();
}

- protected KeyPair reloadClientIdentity(Path path) throws IOException, GeneralSecurityException {
+ protected KeyPair reloadClientIdentity(SessionContext session, Path path) throws IOException, GeneralSecurityException {
if (isStrict()) {
Map.Entry<String, Object> violation =
KeyUtils.validateStrictKeyFilePermissions(path, IoUtils.EMPTY_LINK_OPTIONS);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
index 6bd4c07..8c52d4f 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
@@ -28,6 +28,8 @@ import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

+import org.apache.sshd.common.session.SessionContext;
+
/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
*/
@@ -36,6 +38,8 @@ public interface ClientIdentityProvider {
/**
* Provides a {@link KeyPair} representing the client identity
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool).
* @return The client identity - may be {@code null} if no currently
* available identity from this provider. <B>Note:</B> the provider
* may return a <U>different</U> value every time this method is called
@@ -43,7 +47,7 @@ public interface ClientIdentityProvider {
* @throws IOException If failed to load the identity
* @throws GeneralSecurityException If failed to parse the identity
*/
- KeyPair getClientIdentity() throws IOException, GeneralSecurityException;
+ KeyPair getClientIdentity(SessionContext session) throws IOException, GeneralSecurityException;

/**
* Wraps a {@link KeyPair} into a {@link ClientIdentityProvider} that
@@ -53,7 +57,7 @@ public interface ClientIdentityProvider {
* @return The wrapping provider
*/
static ClientIdentityProvider of(KeyPair kp) {
- return () -> kp;
+ return session -> kp;
}

/**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java
index b59dbd0..cf0b1c9 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java
@@ -34,6 +34,7 @@ import java.util.Objects;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.digest.Digest;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;

@@ -197,6 +198,8 @@ public class KeyRandomArt {
/**
* Creates the combined representation of the random art entries for the provided keys
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param separator The separator to use between the arts - if empty char
* ('\0') then no separation is done
* @param provider The {@link KeyIdentityProvider} - ignored if {@code null}
@@ -205,14 +208,18 @@ public class KeyRandomArt {
* @throws Exception If failed to extract or combine the entries
* @see #combine(Appendable, char, KeyIdentityProvider)
*/
- public static String combine(char separator, KeyIdentityProvider provider) throws Exception {
- return combine(new StringBuilder(4 * (FLDSIZE_X + 4) * (FLDSIZE_Y + 3)), separator, provider).toString();
+ public static String combine(
+ SessionContext session, char separator, KeyIdentityProvider provider)
+ throws Exception {
+ return combine(session, new StringBuilder(4 * (FLDSIZE_X + 4) * (FLDSIZE_Y + 3)), separator, provider).toString();
}

/**
* Appends the combined random art entries for the provided keys
*
* @param <A> The {@link Appendable} output writer
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param sb The writer
* @param separator The separator to use between the arts - if empty char
* ('\0') then no separation is done
@@ -223,21 +230,24 @@ public class KeyRandomArt {
* @see #generate(KeyIdentityProvider)
* @see #combine(Appendable, char, Collection)
*/
- public static <A extends Appendable> A combine(A sb, char separator, KeyIdentityProvider provider) throws Exception {
- return combine(sb, separator, generate(provider));
+ public static <A extends Appendable> A combine(
+ SessionContext session, A sb, char separator, KeyIdentityProvider provider) throws Exception {
+ return combine(sb, separator, generate(session, provider));
}

/**
* Extracts and generates random art entries for all key in the provider
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param provider The {@link KeyIdentityProvider} - ignored if {@code null}
* or has no keys to provide
* @return The extracted {@link KeyRandomArt}s
* @throws Exception If failed to extract the entries
* @see KeyIdentityProvider#loadKeys()
*/
- public static Collection<KeyRandomArt> generate(KeyIdentityProvider provider) throws Exception {
- Iterable<KeyPair> keys = (provider == null) ? null : provider.loadKeys();
+ public static Collection<KeyRandomArt> generate(SessionContext session, KeyIdentityProvider provider) throws Exception {
+ Iterable<KeyPair> keys = (provider == null) ? null : provider.loadKeys(session);
Iterator<KeyPair> iter = (keys == null) ? null : keys.iterator();
if ((iter == null) || (!iter.hasNext())) {
return Collections.emptyList();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
index e4e941d..194daf5 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
@@ -35,6 +35,7 @@ import java.util.TreeSet;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
@@ -109,15 +110,16 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
}
}

- protected Iterable<KeyPair> loadKeys(final Collection<? extends R> resources) {
+ protected Iterable<KeyPair> loadKeys(SessionContext session, Collection<? extends R> resources) {
if (GenericUtils.isEmpty(resources)) {
return Collections.emptyList();
} else {
- return () -> new KeyPairIterator(resources);
+ return () -> new KeyPairIterator(session, resources);
}
}

- protected KeyPair doLoadKey(R resource) throws IOException, GeneralSecurityException {
+ protected KeyPair doLoadKey(SessionContext session, R resource)
+ throws IOException, GeneralSecurityException {
String resourceKey = ValidateUtils.checkNotNullAndNotEmpty(Objects.toString(resource, null), "No resource string value");
KeyPair kp;
synchronized (cacheMap) {
@@ -129,12 +131,12 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
if (log.isTraceEnabled()) {
PublicKey key = kp.getPublic();
log.trace("doLoadKey({}) use cached key {}-{}",
- resourceKey, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+ resourceKey, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
}
return kp;
}

- kp = doLoadKey(resourceKey, resource, getPasswordFinder());
+ kp = doLoadKey(session, resourceKey, resource, getPasswordFinder());
if (kp != null) {
boolean reusedKey;
synchronized (cacheMap) {
@@ -150,8 +152,8 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
if (log.isDebugEnabled()) {
PublicKey key = kp.getPublic();
log.debug("doLoadKey({}) {} {}-{}",
- resourceKey, reusedKey ? "re-loaded" : "loaded",
- KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+ resourceKey, reusedKey ? "re-loaded" : "loaded",
+ KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
}
} else {
if (log.isDebugEnabled()) {
@@ -162,26 +164,29 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
return kp;
}

- protected KeyPair doLoadKey(String resourceKey, R resource, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
+ protected KeyPair doLoadKey(SessionContext session, String resourceKey, R resource, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
try (InputStream inputStream = openKeyPairResource(resourceKey, resource)) {
- return doLoadKey(resourceKey, inputStream, provider);
+ return doLoadKey(session, resourceKey, inputStream, provider);
}
}

protected abstract InputStream openKeyPairResource(String resourceKey, R resource) throws IOException;

- protected KeyPair doLoadKey(String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ protected KeyPair doLoadKey(SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
return SecurityUtils.loadKeyPairIdentity(resourceKey, inputStream, provider);
}

protected class KeyPairIterator implements Iterator<KeyPair> {
+ protected final SessionContext session;
private final Iterator<? extends R> iterator;
private KeyPair nextKeyPair;
private boolean nextKeyPairSet;

- protected KeyPairIterator(Collection<? extends R> resources) {
- iterator = resources.iterator();
+ protected KeyPairIterator(SessionContext session, Collection<? extends R> resources) {
+ this.session = session;
+ this.iterator = resources.iterator();
}

@Override
@@ -211,7 +216,7 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
while (iterator.hasNext()) {
R r = iterator.next();
try {
- nextKeyPair = doLoadKey(r);
+ nextKeyPair = doLoadKey(session, r);
} catch (Throwable e) {
log.warn("Failed (" + e.getClass().getSimpleName() + ")"
+ " to load key resource=" + r + ": " + e.getMessage());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
index 6e8da54..3132abd 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
@@ -26,6 +26,7 @@ import java.security.KeyPair;
import java.util.Collection;
import java.util.Collections;

+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.threads.ThreadUtils;

@@ -84,8 +85,8 @@ public class ClassLoadableResourceKeyPairProvider extends AbstractResourceKeyPai
}

@Override
- public Iterable<KeyPair> loadKeys() {
- return loadKeys(getResources());
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
+ return loadKeys(session, getResources());
}

@Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
index fa52eb2..a416871 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Objects;

+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.io.IoUtils;

@@ -71,13 +72,13 @@ public class FileKeyPairProvider extends AbstractResourceKeyPairProvider<Path> {
}

@Override
- public Iterable<KeyPair> loadKeys() {
- return loadKeys(getPaths());
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
+ return loadKeys(session, getPaths());
}

@Override
- protected KeyPair doLoadKey(Path resource) throws IOException, GeneralSecurityException {
- return super.doLoadKey((resource == null) ? null : resource.toAbsolutePath());
+ protected KeyPair doLoadKey(SessionContext session, Path resource) throws IOException, GeneralSecurityException {
+ return super.doLoadKey(session, (resource == null) ? null : resource.toAbsolutePath());
}

@Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
index f03b68b..46b6f52 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java
@@ -23,8 +23,8 @@ import java.security.KeyPair;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
-import java.util.function.Function;

+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;

/**
@@ -38,7 +38,7 @@ public interface KeyIdentityProvider {
*/
KeyIdentityProvider EMPTY_KEYS_PROVIDER = new KeyIdentityProvider() {
@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return Collections.emptyList();
}

@@ -49,40 +49,40 @@ public interface KeyIdentityProvider {
};

/**
- * Invokes {@link KeyIdentityProvider#loadKeys()} and returns the result - ignores
- * {@code null} providers (i.e., returns an empty iterable instance)
- */
- Function<KeyIdentityProvider, Iterable<KeyPair>> LOADER = p ->
- (p == null) ? Collections.<KeyPair>emptyList() : p.loadKeys();
-
- /**
* Load available keys.
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @return an {@link Iterable} instance of available keys - ignored if {@code null}
*/
- Iterable<KeyPair> loadKeys();
+ Iterable<KeyPair> loadKeys(SessionContext session);

/**
* Creates a &quot;unified&quot; {@link Iterator} of {@link KeyPair}s out of 2 possible
* {@link KeyIdentityProvider}
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param identities The registered keys identities
* @param keys Extra available key pairs
* @return The wrapping iterator
* @see #resolveKeyIdentityProvider(KeyIdentityProvider, KeyIdentityProvider)
*/
- static Iterator<KeyPair> iteratorOf(KeyIdentityProvider identities, KeyIdentityProvider keys) {
- return iteratorOf(resolveKeyIdentityProvider(identities, keys));
+ static Iterator<KeyPair> iteratorOf(
+ SessionContext session, KeyIdentityProvider identities, KeyIdentityProvider keys) {
+ return iteratorOf(session, resolveKeyIdentityProvider(identities, keys));
}

/**
* Resolves a non-{@code null} iterator of the available keys
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param provider The {@link KeyIdentityProvider} - ignored if {@code null}
* @return A non-{@code null} iterator - which may be empty if no provider or no keys
*/
- static Iterator<KeyPair> iteratorOf(KeyIdentityProvider provider) {
- return GenericUtils.iteratorOf((provider == null) ? null : provider.loadKeys());
+ static Iterator<KeyPair> iteratorOf(SessionContext session, KeyIdentityProvider provider) {
+ return GenericUtils.iteratorOf((provider == null) ? null : provider.loadKeys(session));
}

/**
@@ -94,12 +94,14 @@ public interface KeyIdentityProvider {
* <LI>If both are the same instance then use it.</U>
* <LI>Otherwise, returns a wrapper that groups both providers.</LI>
* </UL>
+ *
* @param identities The registered key pair identities
* @param keys The extra available key pairs
* @return The resolved provider
* @see #multiProvider(KeyIdentityProvider...)
*/
- static KeyIdentityProvider resolveKeyIdentityProvider(KeyIdentityProvider identities, KeyIdentityProvider keys) {
+ static KeyIdentityProvider resolveKeyIdentityProvider(
+ KeyIdentityProvider identities, KeyIdentityProvider keys) {
if ((keys == null) || (identities == keys)) {
return identities;
} else if (identities == null) {
@@ -124,6 +126,8 @@ public interface KeyIdentityProvider {
/**
* Wraps a group of {@link KeyIdentityProvider} into a single one
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param providers The providers - ignored if {@code null}/empty (i.e., returns
* {@link #EMPTY_KEYS_PROVIDER})
* @return The wrapping provider
@@ -143,22 +147,24 @@ public interface KeyIdentityProvider {
/**
* Wraps a group of {@link KeyIdentityProvider} into an {@link Iterable} of {@link KeyPair}s
*
+ * @param session The {@link SessionContext} for invoking this load command - may
+ * be {@code null} if not invoked within a session context (e.g., offline tool or session unknown).
* @param providers The group of providers - ignored if {@code null}/empty (i.e., returns an
* empty iterable instance)
* @return The wrapping iterable
*/
- static Iterable<KeyPair> iterableOf(Collection<? extends KeyIdentityProvider> providers) {
+ static Iterable<KeyPair> iterableOf(SessionContext session, Collection<? extends KeyIdentityProvider> providers) {
int numProviders = GenericUtils.size(providers);
if (numProviders <= 0) {
return Collections.emptyList();
} else if (numProviders == 1) {
KeyIdentityProvider p = GenericUtils.head(providers);
- return p.loadKeys();
+ return p.loadKeys(session);
} else {
return new Iterable<KeyPair>() {
@Override
public Iterator<KeyPair> iterator() {
- return new MultiKeyIdentityIterator(providers);
+ return new MultiKeyIdentityIterator(session, providers);
}

@Override
@@ -188,6 +194,6 @@ public interface KeyIdentityProvider {
* @return The provider wrapper
*/
static KeyIdentityProvider wrapKeyPairs(Iterable<KeyPair> pairs) {
- return (pairs == null) ? EMPTY_KEYS_PROVIDER : () -> pairs;
+ return (pairs == null) ? EMPTY_KEYS_PROVIDER : session -> pairs;
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
index 68c4daf..6b2224f 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
@@ -86,7 +86,7 @@ public interface KeyPairProvider extends KeyIdentityProvider {
}

@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return Collections.emptyList();
}

@@ -108,7 +108,7 @@ public interface KeyPairProvider extends KeyIdentityProvider {
*/
default KeyPair loadKey(SessionContext session, String type) {
ValidateUtils.checkNotNullAndNotEmpty(type, "No key type to load");
- return GenericUtils.stream(loadKeys())
+ return GenericUtils.stream(loadKeys(session))
.filter(key -> type.equals(KeyUtils.getKeyType(key)))
.findFirst()
.orElse(null);
@@ -120,7 +120,7 @@ public interface KeyPairProvider extends KeyIdentityProvider {
* @return The available {@link Iterable} key types in preferred order - never {@code null}
*/
default Iterable<String> getKeyTypes(SessionContext session) {
- return GenericUtils.stream(loadKeys())
+ return GenericUtils.stream(loadKeys(session))
.map(KeyUtils::getKeyType)
.filter(GenericUtils::isNotEmpty)
.collect(Collectors.toSet());
@@ -148,7 +148,7 @@ public interface KeyPairProvider extends KeyIdentityProvider {
static KeyPairProvider wrap(Iterable<KeyPair> pairs) {
return (pairs == null) ? EMPTY_KEYPAIR_PROVIDER : new KeyPairProvider() {
@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return pairs;
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
index d8f2350..ca4fd5e 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MappedKeyPairProvider.java
@@ -62,7 +62,7 @@ public class MappedKeyPairProvider implements KeyPairProvider {
}

@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return pairsMap.values();
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
index 5ba5386..9de7c17 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityIterator.java
@@ -23,6 +23,8 @@ import java.security.KeyPair;
import java.util.Iterator;
import java.util.NoSuchElementException;

+import org.apache.sshd.common.session.SessionContext;
+
/**
* Iterates over several {@link KeyIdentityProvider}-s exhausting their
* keys one by one (lazily).
@@ -32,16 +34,22 @@ import java.util.NoSuchElementException;
public class MultiKeyIdentityIterator implements Iterator<KeyPair> {
protected Iterator<KeyPair> currentProvider;
protected boolean finished;
+ private final SessionContext sessionContext;
private final Iterator<? extends KeyIdentityProvider> providers;

- public MultiKeyIdentityIterator(Iterable<? extends KeyIdentityProvider> providers) {
+ public MultiKeyIdentityIterator(SessionContext session, Iterable<? extends KeyIdentityProvider> providers) {
this.providers = (providers == null) ? null : providers.iterator();
+ this.sessionContext = session;
}

public Iterator<? extends KeyIdentityProvider> getProviders() {
return providers;
}

+ public SessionContext getSessionContext() {
+ return sessionContext;
+ }
+
@Override
public boolean hasNext() {
if (finished) {
@@ -58,9 +66,10 @@ public class MultiKeyIdentityIterator implements Iterator<KeyPair> {
return true;
}

+ SessionContext session = getSessionContext();
while (provs.hasNext()) {
KeyIdentityProvider p = provs.next();
- Iterable<KeyPair> keys = (p == null) ? null : p.loadKeys();
+ Iterable<KeyPair> keys = (p == null) ? null : p.loadKeys(session);
currentProvider = (keys == null) ? null : keys.iterator();

if ((currentProvider != null) && currentProvider.hasNext()) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProvider.java
index 18304ff..97b94a5 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProvider.java
@@ -23,6 +23,8 @@ import java.security.KeyPair;
import java.util.Collections;
import java.util.Iterator;

+import org.apache.sshd.common.session.SessionContext;
+
/**
* Aggregates several {@link KeyIdentityProvider}-s into a single logical
* one that (lazily) exposes the keys from each aggregated provider
@@ -37,11 +39,11 @@ public class MultiKeyIdentityProvider implements KeyIdentityProvider {
}

@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return new Iterable<KeyPair>() {
@Override
public Iterator<KeyPair> iterator() {
- return (providers == null) ? Collections.emptyIterator() : new MultiKeyIdentityIterator(providers);
+ return (providers == null) ? Collections.emptyIterator() : new MultiKeyIdentityIterator(session, providers);
}

@Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
index f43f5c0..d30b4b8 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
@@ -39,6 +39,7 @@ import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.BuiltinIdentities;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.security.SecurityUtils;

@@ -120,20 +121,20 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
}

@Override // co-variant return
- public synchronized List<KeyPair> loadKeys() {
+ public synchronized List<KeyPair> loadKeys(SessionContext session) {
Path keyPath = getPath();
KeyPair kp;
synchronized (keyPairHolder) {
kp = keyPairHolder.get();
if (kp == null) {
try {
- kp = resolveKeyPair(keyPath);
+ kp = resolveKeyPair(session, keyPath);
if (kp != null) {
keyPairHolder.set(kp);
}
} catch (Throwable t) {
log.warn("loadKeys({}) Failed ({}) to resolve: {}",
- keyPath, t.getClass().getSimpleName(), t.getMessage());
+ keyPath, t.getClass().getSimpleName(), t.getMessage());
if (log.isDebugEnabled()) {
log.debug("loadKeys(" + keyPath + ") resolution failure details", t);
}
@@ -148,12 +149,12 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
}
}

- protected KeyPair resolveKeyPair(Path keyPath) throws IOException, GeneralSecurityException {
+ protected KeyPair resolveKeyPair(SessionContext session, Path keyPath) throws IOException, GeneralSecurityException {
String alg = getAlgorithm();
KeyPair kp;
if (keyPath != null) {
try {
- kp = loadFromFile(alg, keyPath);
+ kp = loadFromFile(session, alg, keyPath);
if (kp != null) {
return kp;
}
@@ -203,13 +204,13 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
return kp;
}

- protected KeyPair loadFromFile(String alg, Path keyPath) throws IOException, GeneralSecurityException {
+ protected KeyPair loadFromFile(SessionContext session, String alg, Path keyPath) throws IOException, GeneralSecurityException {
LinkOption[] options = IoUtils.getLinkOptions(true);
if ((!Files.exists(keyPath, options)) || (!Files.isRegularFile(keyPath, options))) {
return null;
}

- KeyPair kp = readKeyPair(keyPath, IoUtils.EMPTY_OPEN_OPTIONS);
+ KeyPair kp = readKeyPair(session, keyPath, IoUtils.EMPTY_OPEN_OPTIONS);
if (kp == null) {
return null;
}
@@ -225,7 +226,7 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
if (Objects.equals(alg, keyAlgorithm)) {
if (log.isDebugEnabled()) {
log.debug("resolveKeyPair({}) loaded key={}-{}",
- keyPath, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
+ keyPath, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
}
return kp;
}
@@ -233,23 +234,26 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
// Not same algorithm - start again
if (log.isDebugEnabled()) {
log.debug("resolveKeyPair({}) mismatched loaded key algorithm: expected={}, loaded={}",
- keyPath, alg, keyAlgorithm);
+ keyPath, alg, keyAlgorithm);
}
Files.deleteIfExists(keyPath);
return null;
}

- protected KeyPair readKeyPair(Path keyPath, OpenOption... options) throws IOException, GeneralSecurityException {
+ protected KeyPair readKeyPair(SessionContext session, Path keyPath, OpenOption... options)
+ throws IOException, GeneralSecurityException {
try (InputStream inputStream = Files.newInputStream(keyPath, options)) {
- return doReadKeyPair(keyPath.toString(), inputStream);
+ return doReadKeyPair(session, keyPath.toString(), inputStream);
}
}

- protected KeyPair doReadKeyPair(String resourceKey, InputStream inputStream) throws IOException, GeneralSecurityException {
+ protected KeyPair doReadKeyPair(SessionContext session, String resourceKey, InputStream inputStream)
+ throws IOException, GeneralSecurityException {
return SecurityUtils.loadKeyPairIdentity(resourceKey, inputStream, null);
}

- protected void writeKeyPair(KeyPair kp, Path keyPath, OpenOption... options) throws IOException, GeneralSecurityException {
+ protected void writeKeyPair(KeyPair kp, Path keyPath, OpenOption... options)
+ throws IOException, GeneralSecurityException {
if ((!Files.exists(keyPath)) || isOverwriteAllowed()) {
try (OutputStream os = Files.newOutputStream(keyPath, options)) {
doWriteKeyPair(keyPath.toString(), kp, os);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
index 7f2888e..b40edcb 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
@@ -28,6 +28,8 @@ import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.spec.InvalidKeySpecException;

+import org.apache.sshd.common.session.SessionContext;
+
/**
* TODO Add javadoc
*
@@ -43,7 +45,8 @@ public class SimpleGeneratorHostKeyProvider extends AbstractGeneratorHostKeyProv
}

@Override
- protected KeyPair doReadKeyPair(String resourceKey, InputStream inputStream) throws IOException, GeneralSecurityException {
+ protected KeyPair doReadKeyPair(SessionContext session, String resourceKey, InputStream inputStream)
+ throws IOException, GeneralSecurityException {
try (ObjectInputStream r = new ObjectInputStream(inputStream)) {
try {
return (KeyPair) r.readObject();
@@ -54,7 +57,8 @@ public class SimpleGeneratorHostKeyProvider extends AbstractGeneratorHostKeyProv
}

@Override
- protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException {
+ protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream)
+ throws IOException, GeneralSecurityException {
try (ObjectOutputStream w = new ObjectOutputStream(outputStream)) {
w.writeObject(kp);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
index 19375ec..4f4b285 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
@@ -145,7 +145,7 @@ public class BuiltinClientIdentitiesWatcherTest extends JUnitTestSupport {
}

private static void testMultipleFilesWatch(String phase, KeyIdentityProvider watcher, Collection<? extends KeyPair> expected) {
- Iterable<KeyPair> keys = watcher.loadKeys();
+ Iterable<KeyPair> keys = watcher.loadKeys(null);
Collection<KeyPair> actual = new ArrayList<>();
for (KeyPair kp : keys) {
actual.add(kp);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
index 144a3b0..690a381 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
@@ -33,6 +33,7 @@ import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.util.test.CommonTestSupportUtils;
import org.apache.sshd.util.test.JUnitTestSupport;
@@ -78,10 +79,10 @@ public class ClientIdentityFileWatcherTest extends JUnitTestSupport {
AtomicInteger reloadCount = new AtomicInteger(0);
ClientIdentityProvider idProvider = new ClientIdentityFileWatcher(idFile, loader, FilePasswordProvider.EMPTY, false) {
@Override
- protected KeyPair reloadClientIdentity(Path path) throws IOException, GeneralSecurityException {
+ protected KeyPair reloadClientIdentity(SessionContext session, Path path) throws IOException, GeneralSecurityException {
assertEquals("Mismatched client identity path", idFile, path);
reloadCount.incrementAndGet();
- return super.reloadClientIdentity(path);
+ return super.reloadClientIdentity(session, path);
}
};
Files.deleteIfExists(idFile);
@@ -114,7 +115,7 @@ public class ClientIdentityFileWatcherTest extends JUnitTestSupport {
private static void testIdentityReload(
String phase, Number reloadCount, ClientIdentityProvider provider, KeyPair expectedIdentity, int expectedCount)
throws Exception {
- KeyPair actualIdentity = provider.getClientIdentity();
+ KeyPair actualIdentity = provider.getClientIdentity(null);
assertSame(phase + ": mismatched identity", expectedIdentity, actualIdentity);
assertEquals(phase + ": mismatched re-load count", expectedCount, reloadCount.intValue());
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java
index bc2f02c..c8acfa5 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java
@@ -90,7 +90,7 @@ public class ClientIdentityTest extends JUnitTestSupport {
KeyIdentityProvider provider = IdentityUtils.createKeyPairProvider(ids, true /* supported only */);
assertNotNull("No provider generated", provider);

- Iterable<KeyPair> keys = provider.loadKeys();
+ Iterable<KeyPair> keys = provider.loadKeys(null);
for (KeyPair kp : keys) {
assertTrue("Unexpected loaded key: " + kp, pairs.remove(kp));
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java
index eedbfe7..42b39e1 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java
@@ -90,7 +90,7 @@ public class KeyRandomArtTest extends JUnitTestSupport {

@AfterClass
public static void dumpAllArts() throws Exception {
- KeyRandomArt.combine(System.out, ' ', () -> KEYS);
+ KeyRandomArt.combine(null, System.out, ' ', session -> KEYS);
}

@Test

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
index afa55cd..6f00621 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
@@ -48,7 +48,7 @@ public class KeyPairProviderTest extends JUnitTestSupport {
@Test
public void testEmptyKeyProvider() {
KeyPairProvider provider = KeyPairProvider.EMPTY_KEYPAIR_PROVIDER;
- assertTrue("Non empty loaded keys", GenericUtils.isEmpty(provider.loadKeys()));
+ assertTrue("Non empty loaded keys", GenericUtils.isEmpty(provider.loadKeys(null)));
assertTrue("Non empty key type", GenericUtils.isEmpty(provider.getKeyTypes(null)));

for (String keyType : new String[]{null, "", getCurrentTestName()}) {
@@ -69,7 +69,7 @@ public class KeyPairProviderTest extends JUnitTestSupport {

KeyPairProvider provider = MappedKeyPairProvider.MAP_TO_KEY_PAIR_PROVIDER.apply(pairsMap);
assertEquals("Key types", pairsMap.keySet(), provider.getKeyTypes(null));
- assertEquals("Key pairs", pairsMap.values(), provider.loadKeys());
+ assertEquals("Key pairs", pairsMap.values(), provider.loadKeys(null));

pairsMap.forEach((keyType, expected) -> {
KeyPair actual = provider.loadKey(null, keyType);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
index 5a24da2..e5a4329 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/MultiKeyIdentityProviderTest.java
@@ -28,6 +28,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.util.test.JUnitTestSupport;
import org.junit.FixMethodOrder;
import org.junit.Test;
@@ -66,7 +67,7 @@ public class MultiKeyIdentityProviderTest extends JUnitTestSupport {
KeyIdentityProvider multiProvider = KeyIdentityProvider.multiProvider(providers);
assertObjectInstanceOf(MultiKeyIdentityProvider.class.getSimpleName(), MultiKeyIdentityProvider.class, multiProvider);

- Iterable<KeyPair> keys = multiProvider.loadKeys();
+ Iterable<KeyPair> keys = multiProvider.loadKeys(null);
Iterator<KeyPair> iter = keys.iterator();
for (int index = 0, count = expected.size(); index < count; index++) {
KeyPair kpExpected = expected.get(index);
@@ -82,7 +83,7 @@ public class MultiKeyIdentityProviderTest extends JUnitTestSupport {
private static KeyIdentityProvider wrapKeyPairs(AtomicInteger position, Iterable<KeyPair> keys) {
return new KeyIdentityProvider() {
@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return new Iterable<KeyPair>() {
@Override
public Iterator<KeyPair> iterator() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
index cdb4967..488d2ce 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
@@ -183,7 +183,7 @@ public class SecurityUtilsTest extends JUnitTestSupport {
String resourceKey, AbstractResourceKeyPairProvider<?> provider,
Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
provider.setPasswordFinder(TEST_PASSWORD_PROVIDER);
- Iterable<KeyPair> iterator = provider.loadKeys();
+ Iterable<KeyPair> iterator = provider.loadKeys(null);
List<KeyPair> pairs = new ArrayList<>();
for (KeyPair kp : iterator) {
pairs.add(kp);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
index 2978a18..66ecb05 100644
--- a/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
@@ -27,6 +27,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.concurrent.atomic.AtomicInteger;

+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.util.test.JUnitTestSupport;
import org.apache.sshd.util.test.NoIoTestCase;
import org.junit.FixMethodOrder;
@@ -41,20 +42,20 @@ public class AbstractGeneratorHostKeyProviderTest extends JUnitTestSupport {
super();
}

- @SuppressWarnings("synthetic-access")
@Test
+ @SuppressWarnings("synthetic-access")
public void testOverwriteKey() throws Exception {
Path tempDir = assertHierarchyTargetFolderExists(getTempTargetFolder());
Path keyPairFile = tempDir.resolve(getCurrentTestName() + ".key");
Files.deleteIfExists(keyPairFile);

TestProvider provider = new TestProvider(keyPairFile);
- provider.loadKeys();
+ provider.loadKeys(null);
assertEquals("Mismatched generate write count", 1, provider.getWriteCount());

provider = new TestProvider(keyPairFile);
provider.setOverwriteAllowed(false);
- provider.loadKeys();
+ provider.loadKeys(null);
assertEquals("Mismatched load write count", 0, provider.getWriteCount());
}

@@ -67,12 +68,15 @@ public class AbstractGeneratorHostKeyProviderTest extends JUnitTestSupport {
}

@Override
- protected KeyPair doReadKeyPair(String resourceKey, InputStream inputStream) throws IOException, GeneralSecurityException {
+ protected KeyPair doReadKeyPair(
+ SessionContext session, String resourceKey, InputStream inputStream)
+ throws IOException, GeneralSecurityException {
return null;
}

@Override
- protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException {
+ protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream)
+ throws IOException, GeneralSecurityException {
writes.incrementAndGet();
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java b/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
index 6558c07..a1d77ef 100644
--- a/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
+++ b/sshd-common/src/test/java/org/apache/sshd/util/test/CommonTestSupportUtils.java
@@ -453,7 +453,7 @@ public final class CommonTestSupportUtils {

public static KeyPair getFirstKeyPair(KeyIdentityProvider provider) {
Objects.requireNonNull(provider, "No key pair provider");
- Iterable<? extends KeyPair> pairs = Objects.requireNonNull(provider.loadKeys(), "No loaded keys");
+ Iterable<? extends KeyPair> pairs = Objects.requireNonNull(provider.loadKeys(null), "No loaded keys");
Iterator<? extends KeyPair> iter = Objects.requireNonNull(pairs.iterator(), "No keys iterator");
ValidateUtils.checkTrue(iter.hasNext(), "Empty loaded kyes iterator");
return Objects.requireNonNull(iter.next(), "No key pair in iterator");
@@ -537,7 +537,7 @@ public final class CommonTestSupportUtils {
Objects.requireNonNull(provider, "No provider");

// get the I/O out of the way
- Iterable<KeyPair> keys = Objects.requireNonNull(provider.loadKeys(), "No keys loaded");
+ Iterable<KeyPair> keys = Objects.requireNonNull(provider.loadKeys(null), "No keys loaded");
if (keys instanceof Collection<?>) {
ValidateUtils.checkNotNullAndNotEmpty((Collection<?>) keys, "Empty keys loaded");
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java b/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
index d6137a8..32f2712 100644
--- a/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
+++ b/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
@@ -27,6 +27,7 @@ import java.util.Iterator;
import java.util.List;

import org.apache.sshd.client.config.keys.ClientIdentityProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.util.test.JUnitTestSupport;
import org.junit.FixMethodOrder;
import org.junit.Test;
@@ -56,7 +57,7 @@ public class LazyClientIdentityIteratorTest extends JUnitTestSupport {
Iterable<KeyPair> ids = ClientIdentityProvider.lazyKeysLoader(
providers, p -> {
try {
- return p.getClientIdentity();
+ return p.getClientIdentity(null);
} catch (Exception e) {
throw new RuntimeException("Unexpected " + e.getClass().getSimpleName() + ": " + e.getMessage(), e);
}
@@ -93,7 +94,7 @@ public class LazyClientIdentityIteratorTest extends JUnitTestSupport {
}

@Override
- public KeyPair getClientIdentity() {
+ public KeyPair getClientIdentity(SessionContext session) {
loadCount++;
return getKeyPair();
}
@@ -101,7 +102,7 @@ public class LazyClientIdentityIteratorTest extends JUnitTestSupport {
@Override
public String toString() {
return getClass().getSimpleName()
- + "[" + getClientIdentity() + "]"
+ + "[" + getKeyPair() + "]"
+ ": loadCount=" + getLoadCount();
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
index 73e34ee..d476464 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
@@ -95,7 +95,7 @@ public class UserAuthPublicKeyIterator extends AbstractKeyPairIterator<PublicKey
// Lazy load the keys the 1st time the iterator is called
if (keysHolder.get() == null) {
KeyIdentityProvider sessionKeysProvider = ClientSession.providerOf(session);
- keysHolder.set(sessionKeysProvider.loadKeys());
+ keysHolder.set(sessionKeysProvider.loadKeys(session));
}

return new Iterator<KeyPairIdentity>() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/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 63343cb..b6d6235 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
@@ -381,7 +381,7 @@ public interface ClientSession
return (session == null)
? KeyIdentityProvider.EMPTY_KEYS_PROVIDER
: KeyIdentityProvider.resolveKeyIdentityProvider(
- session.getRegisteredIdentities(), session.getKeyPairProvider());
+ session.getRegisteredIdentities(), session.getKeyPairProvider());
}

/**
@@ -396,7 +396,7 @@ public interface ClientSession
* @see ClientSession#getKeyPairProvider()
*/
static Iterator<KeyPair> keyPairIteratorOf(ClientSession session) {
- return KeyIdentityProvider.iteratorOf(providerOf(session));
+ return KeyIdentityProvider.iteratorOf(session, providerOf(session));
}

/**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
index ae038ae..d6f6d51 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -437,7 +437,7 @@ public class ServerUserAuthService extends AbstractCloseable implements Service,

if (ServerAuthenticationManager.AUTO_WELCOME_BANNER_VALUE.equalsIgnoreCase(message)) {
try {
- return KeyRandomArt.combine(' ', session.getKeyPairProvider());
+ return KeyRandomArt.combine(session, ' ', session.getKeyPairProvider());
} catch (Exception e) {
if (e instanceof IOException) {
throw (IOException) e;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
index 0679fa3..30cb1ff 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
@@ -43,6 +43,7 @@ import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.net.SshdSocketAddress;
import org.apache.sshd.server.SshServer;
@@ -231,7 +232,7 @@ public class HostConfigEntryResolverTest extends BaseTestSupport {
Collection<KeyPair> clientIdentities = Collections.singletonList(defaultIdentity);
KeyPairProvider provider = new AbstractKeyPairProvider() {
@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return clientIdentities;
}
};

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
index 164c2f1..7ae6c96 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
@@ -39,6 +39,7 @@ import org.apache.sshd.common.config.keys.impl.DSSPublicKeyEntryDecoder;
import org.apache.sshd.common.config.keys.impl.ECDSAPublicKeyEntryDecoder;
import org.apache.sshd.common.config.keys.impl.RSAPublicKeyDecoder;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.SshServer;
@@ -164,8 +165,8 @@ public class SignatureFactoriesTest extends BaseTestSupport implements OptionalF
}

protected void testKeyPairProvider(
- final String keyName, final int keySize, final PublicKeyEntryDecoder<?, ?> decoder, List<NamedFactory<Signature>> signatures)
- throws Exception {
+ String keyName, int keySize, PublicKeyEntryDecoder<?, ?> decoder, List<NamedFactory<Signature>> signatures)
+ throws Exception {
testKeyPairProvider(keyName, () -> {
try {
KeyPair kp = decoder.generateKeyPair(keySize);
@@ -178,12 +179,12 @@ public class SignatureFactoriesTest extends BaseTestSupport implements OptionalF
}

protected void testKeyPairProvider(
- final String keyName, final Factory<Iterable<KeyPair>> keyPairFactory, List<NamedFactory<Signature>> signatures)
+ String keyName, Factory<Iterable<KeyPair>> keyPairFactory, List<NamedFactory<Signature>> signatures)
throws Exception {
- final Iterable<KeyPair> iter = keyPairFactory.create();
+ Iterable<KeyPair> iter = keyPairFactory.create();
testKeyPairProvider(new KeyPairProvider() {
@Override
- public Iterable<KeyPair> loadKeys() {
+ public Iterable<KeyPair> loadKeys(SessionContext session) {
return iter;
}
}, signatures);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
index e417aa9..4ae73b6 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
@@ -98,8 +98,9 @@ public class WelcomeBannerTest extends BaseTestSupport {
@Test // see SSHD-686
public void testAutoGeneratedBanner() throws Exception {
KeyPairProvider keys = sshd.getKeyPairProvider();
- PropertyResolverUtils.updateProperty(sshd, ServerAuthenticationManager.WELCOME_BANNER, ServerAuthenticationManager.AUTO_WELCOME_BANNER_VALUE);
- testBanner(KeyRandomArt.combine(' ', keys));
+ PropertyResolverUtils.updateProperty(sshd,
+ ServerAuthenticationManager.WELCOME_BANNER, ServerAuthenticationManager.AUTO_WELCOME_BANNER_VALUE);
+ testBanner(KeyRandomArt.combine(null, ' ', keys));
}

@Test

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/210f638e/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
index 5e3bb7b..1665dc9 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
@@ -92,7 +92,7 @@ public class ServerIdentityTest extends BaseTestSupport {
KeyPairProvider provider = IdentityUtils.createKeyPairProvider(ids, true /* supported only */);
assertNotNull("No provider generated", provider);

- Iterable<KeyPair> keys = provider.loadKeys();
+ Iterable<KeyPair> keys = provider.loadKeys(null);
for (KeyPair kp : keys) {
assertTrue("Unexpected loaded key: " + kp, pairs.remove(kp));
}
l***@apache.org
2018-11-18 04:55:06 UTC
Permalink
[SSHD-864] Use a 'NamedResource' instead of plain old string in order to provide key file(s) location information


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

Branch: refs/heads/master
Commit: 895f30f135d4e730dca56d842cc110a04e31a404
Parents: 2b013cc
Author: Lyor Goldstein <***@apache.org>
Authored: Thu Nov 15 13:53:20 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Sun Nov 18 06:54:48 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 10 ++-
README.md | 7 ++
.../sshd/cli/server/SshServerCliSupport.java | 6 +-
.../config/keys/ClientIdentityFileWatcher.java | 3 +-
.../config/keys/ClientIdentityLoader.java | 22 ++++---
.../org/apache/sshd/common/NamedResource.java | 20 ++++++
.../config/keys/FilePasswordProvider.java | 5 +-
.../sshd/common/config/keys/IdentityUtils.java | 7 +-
.../loader/AbstractKeyPairResourceParser.java | 11 ++--
.../keys/loader/KeyPairResourceLoader.java | 37 +++++++----
.../keys/loader/KeyPairResourceParser.java | 11 ++--
.../openssh/OpenSSHKeyPairResourceParser.java | 11 ++--
.../pem/AbstractPEMResourceKeyPairParser.java | 3 +-
.../loader/pem/DSSPEMResourceKeyPairParser.java | 3 +-
.../pem/ECDSAPEMResourceKeyPairParser.java | 3 +-
.../keys/loader/pem/PEMResourceParserUtils.java | 5 +-
.../pem/PKCS8PEMResourceKeyPairParser.java | 3 +-
.../loader/pem/RSAPEMResourceKeyPairParser.java | 3 +-
.../AbstractResourceKeyPairProvider.java | 32 ++++++++--
.../ClassLoadableResourceKeyPairProvider.java | 22 ++-----
.../common/keyprovider/FileKeyPairProvider.java | 17 ++---
.../util/io/resource/AbstractIoResource.java | 57 +++++++++++++++++
.../util/io/resource/ClassLoaderResource.java | 67 ++++++++++++++++++++
.../common/util/io/resource/IoResource.java | 63 ++++++++++++++++++
.../common/util/io/resource/PathResource.java | 60 ++++++++++++++++++
.../io/resource/ResourceStreamProvider.java | 35 ++++++++++
.../common/util/io/resource/URIResource.java | 45 +++++++++++++
.../common/util/io/resource/URLResource.java | 50 +++++++++++++++
.../common/util/security/SecurityUtils.java | 3 +-
.../BouncyCastleGeneratorHostKeyProvider.java | 3 +-
.../BouncyCastleKeyPairResourceParser.java | 10 ++-
.../AbstractGeneratorHostKeyProvider.java | 18 ++++--
.../SimpleGeneratorHostKeyProvider.java | 5 +-
.../BuiltinClientIdentitiesWatcherTest.java | 12 ++--
.../keys/ClientIdentityFileWatcherTest.java | 7 +-
.../pem/PKCS8PEMResourceKeyPairParserTest.java | 3 +-
.../file/root/RootedFileSystemProviderTest.java | 3 +-
.../common/util/security/SecurityUtilsTest.java | 12 ++--
.../AbstractGeneratorHostKeyProviderTest.java | 5 +-
.../java/org/apache/sshd/client/SshClient.java | 18 ++++--
.../common/forward/DefaultForwardingFilter.java | 2 +-
.../java/org/apache/sshd/server/SshServer.java | 6 +-
.../hosts/HostConfigEntryResolverTest.java | 14 ++--
.../sshd/common/auth/AuthenticationTest.java | 20 ++++--
.../apache/sshd/common/channel/WindowTest.java | 34 +++++++---
.../java/org/apache/sshd/server/ServerTest.java | 4 +-
.../openpgp/PGPKeyPairResourceParser.java | 29 +++++----
.../openpgp/PGPKeyPairResourceParserTest.java | 7 +-
.../loader/putty/AbstractPuttyKeyDecoder.java | 17 ++---
.../keys/loader/putty/DSSPuttyKeyDecoder.java | 3 +-
.../keys/loader/putty/ECDSAPuttyKeyDecoder.java | 3 +-
.../keys/loader/putty/EdDSAPuttyKeyDecoder.java | 3 +-
.../putty/PuttyKeyPairResourceParser.java | 3 +-
.../keys/loader/putty/RSAPuttyKeyDecoder.java | 3 +-
.../keys/loader/putty/PuttyKeyUtilsTest.java | 14 ++--
.../helpers/AbstractCheckFileExtensionTest.java | 11 ++--
.../sftp/ApacheSshdSftpSessionFactory.java | 8 +--
.../integration/sftp/SpringIoResource.java | 51 +++++++++++++++
58 files changed, 759 insertions(+), 190 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 9cc1cd4..1b1d0df 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -37,6 +37,8 @@ accept also an `AttributeRepository` connection context argument (propagated fro

* The available session context (if any) is also provided as an argument to the interface methods.

+ * The interface methods use a `NamedResource` as the resource key instead of a plain string.
+
* `SshAgent#getIdentities` returns an `Iterable` rather than a `List`

* `SftpFileSystemProvider` and its associated helper classes have been moved to
@@ -48,7 +50,10 @@ accept also an `AttributeRepository` connection context argument (propagated fro

* `ClientIdentityProvider` accepts a `SessionContext` argument in its `getClientIdentity` method.

-* `ClientIdentityLoader` accepts a `SessionContext` argument in its `loadClientIdentity` method.
+* `ClientIdentityLoader`
+ * Accepts a `SessionContext` argument in its `loadClientIdentity` method.
+
+ * Uses a `NamedResource` as the identity location indicator instead of a plain old string.

* `ApacheSshdSftpSessionFactory#get/setPrivateKey` has been renamed to `get/setPrivateKeyLocation`.

@@ -77,3 +82,6 @@ pending packets have been sent to the peer channel when closing the tunnel grace

* [SSHD-862](https://issues.apache.org/jira/browse/SSHD-862) - Provide session context argument (if available) when
key loading methods are invoked.
+
+* [SSHD-864](https://issues.apache.org/jira/browse/SSHD-864) - Using a `NamedResource` instead of plain old string
+in order to provide key file(s) location information

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 1231528..3b291a0 100644
--- a/README.md
+++ b/README.md
@@ -257,6 +257,13 @@ it will start a loop where it prompts for the password, attempts to decode the k
the outcome - success or failure. If failure is signaled, then the provider can decide whether to retry using a new password, abort (with exception)
or ignore. If the provider chooses to ignore the failure, then the code will make a best effort to proceed without the (undecoded) key.

+The methods are provided with a `NamedResource` that provides an indication of the key source "name" that is being attempted. This name can
+be used in order to prompt the user interactively and provide a useful "hint" as to the password that needs to be provided. Furthermore, the
+vast majority of the provided `NamedResource`-s also implement `IoResource` - which means that the code can find out what type of resource
+is being attempted - e.g., a file [Path](https://docs.oracle.com/javase/8/docs/api/index.html?java/nio/file/Path.html),
+a [URL](https://docs.oracle.com/javase/8/docs/api/java/net/URL.html), a [URI](https://docs.oracle.com/javase/8/docs/api/java/net/URI.html),
+etc. - and modify it's behavior accordingly.
+
### UserInteraction

This interface is required for full support of `keyboard-interactive` authentication protocol as described in [RFC 4256](https://www.ietf.org/rfc/rfc4256.txt).

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
----------------------------------------------------------------------
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
index f716553..2521ea1 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
@@ -47,6 +47,7 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.common.util.threads.ThreadUtils;
import org.apache.sshd.server.ServerAuthenticationManager;
@@ -115,8 +116,9 @@ public abstract class SshServerCliSupport extends CliSupport {
List<KeyPair> pairs = new ArrayList<>(keyFiles.size());
for (String keyFilePath : keyFiles) {
Path path = Paths.get(keyFilePath);
- try (InputStream inputStream = Files.newInputStream(path)) {
- KeyPair kp = SecurityUtils.loadKeyPairIdentity(null, keyFilePath, inputStream, null);
+ PathResource location = new PathResource(path);
+ try (InputStream inputStream = location.openInputStream()) {
+ KeyPair kp = SecurityUtils.loadKeyPairIdentity(null, location, inputStream, null);
pairs.add(kp);
} catch (Exception e) {
stderr.append("Failed (").append(e.getClass().getSimpleName()).append(')')

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
index e2e1b82..ca81e47 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
@@ -35,6 +35,7 @@ import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.io.ModifiableFileWatcher;
+import org.apache.sshd.common.util.io.resource.PathResource;

/**
* A {@link ClientIdentityProvider} that watches a given key file re-loading
@@ -120,7 +121,7 @@ public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements
}
}

- String location = path.toString();
+ PathResource location = new PathResource(path);
ClientIdentityLoader idLoader = Objects.requireNonNull(getClientIdentityLoader(), "No client identity loader");
if (idLoader.isValidLocation(location)) {
KeyPair kp = idLoader.loadClientIdentity(session, location, getFilePasswordProvider());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
index 542697a..1d941ac 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
@@ -26,11 +26,14 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
+import java.util.Objects;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -46,18 +49,19 @@ public interface ClientIdentityLoader {
*/
ClientIdentityLoader DEFAULT = new ClientIdentityLoader() {
@Override
- public boolean isValidLocation(String location) throws IOException {
+ public boolean isValidLocation(NamedResource location) throws IOException {
Path path = toPath(location);
return Files.exists(path, IoUtils.EMPTY_LINK_OPTIONS);
}

@Override
public KeyPair loadClientIdentity(
- SessionContext session, String location, FilePasswordProvider provider)
+ SessionContext session, NamedResource location, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
Path path = toPath(location);
- try (InputStream inputStream = Files.newInputStream(path, IoUtils.EMPTY_OPEN_OPTIONS)) {
- return SecurityUtils.loadKeyPairIdentity(session, path.toString(), inputStream, provider);
+ PathResource resource = new PathResource(path);
+ try (InputStream inputStream = resource.openInputStream()) {
+ return SecurityUtils.loadKeyPairIdentity(session, resource, inputStream, provider);
}
}

@@ -66,8 +70,10 @@ public interface ClientIdentityLoader {
return "DEFAULT";
}

- private Path toPath(String location) {
- Path path = Paths.get(ValidateUtils.checkNotNullAndNotEmpty(location, "No location"));
+ private Path toPath(NamedResource location) {
+ Objects.requireNonNull(location, "No location provided");
+
+ Path path = Paths.get(ValidateUtils.checkNotNullAndNotEmpty(location.getName(), "No location value for %s", location));
path = path.toAbsolutePath();
path = path.normalize();
return path;
@@ -81,7 +87,7 @@ public interface ClientIdentityLoader {
* the validity depends on the implementation
* @throws IOException If failed to validate the location
*/
- boolean isValidLocation(String location) throws IOException;
+ boolean isValidLocation(NamedResource location) throws IOException;

/**
* @param session The {@link SessionContext} for invoking this load command - may
@@ -97,6 +103,6 @@ public interface ClientIdentityLoader {
* a valid identity
*/
KeyPair loadClientIdentity(
- SessionContext session, String location, FilePasswordProvider provider)
+ SessionContext session, NamedResource location, FilePasswordProvider provider)
throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/NamedResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/NamedResource.java b/sshd-common/src/main/java/org/apache/sshd/common/NamedResource.java
index 813f53d..048d23f 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/NamedResource.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/NamedResource.java
@@ -101,4 +101,24 @@ public interface NamedResource {
.findFirst()
.orElse(null);
}
+
+ /**
+ * Wraps a name value inside a {@link NamedResource}
+ *
+ * @param name The name value to wrap
+ * @return The wrapper instance
+ */
+ static NamedResource ofName(String name) {
+ return new NamedResource() {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+ };
+ }
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
index 365de50..037cc61 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
@@ -22,6 +22,7 @@ package org.apache.sshd.common.config.keys;
import java.io.IOException;
import java.security.GeneralSecurityException;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.session.SessionContext;

/**
@@ -53,7 +54,7 @@ public interface FilePasswordProvider {
* @throws IOException if cannot resolve password
* @see #handleDecodeAttemptResult(String, int, String, Exception)
*/
- String getPassword(SessionContext session, String resourceKey, int retryIndex) throws IOException;
+ String getPassword(SessionContext session, NamedResource resourceKey, int retryIndex) throws IOException;

/**
* Invoked to inform the password provide about the decoding result. <b>Note:</b>
@@ -74,7 +75,7 @@ public interface FilePasswordProvider {
* @throws GeneralSecurityException If not attempting to resolve a new password
*/
default ResourceDecodeResult handleDecodeAttemptResult(
- SessionContext session, String resourceKey, int retryIndex, String password, Exception err)
+ SessionContext session, NamedResource resourceKey, int retryIndex, String password, Exception err)
throws IOException, GeneralSecurityException {
return ResourceDecodeResult.TERMINATE;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
index 6d9ab44..0212806 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
@@ -21,7 +21,6 @@ package org.apache.sshd.common.config.keys;

import java.io.IOException;
import java.io.InputStream;
-import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -36,6 +35,7 @@ import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -151,8 +151,9 @@ public final class IdentityUtils {
for (Map.Entry<String, ? extends Path> pe : paths.entrySet()) {
String type = pe.getKey();
Path path = pe.getValue();
- try (InputStream inputStream = Files.newInputStream(path, options)) {
- KeyPair kp = SecurityUtils.loadKeyPairIdentity(session, path.toString(), inputStream, provider);
+ PathResource location = new PathResource(path);
+ try (InputStream inputStream = location.openInputStream()) {
+ KeyPair kp = SecurityUtils.loadKeyPairIdentity(session, location, inputStream, provider);
KeyPair prev = ids.put(type, kp);
ValidateUtils.checkTrue(prev == null, "Multiple keys for type=%s", type);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
index 0b69906..7c4bf89 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java
@@ -33,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.logging.Level;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
@@ -79,14 +80,14 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
}

@Override
- public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ public boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException {
return KeyPairResourceParser.containsMarkerLine(lines, getBeginners());
}

@Override
public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
Collection<KeyPair> keyPairs = Collections.emptyList();
List<String> beginMarkers = getBeginners();
@@ -140,7 +141,7 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* @see #extractKeyPairs(String, String, String, FilePasswordProvider, byte[])
*/
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
List<String> lines)
@@ -163,7 +164,7 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* @see #extractKeyPairs(String, String, String, FilePasswordProvider, InputStream)
*/
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
byte[] bytes)
@@ -191,7 +192,7 @@ public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean
* @throws GeneralSecurityException If failed to generate the keys
*/
public abstract Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
index 5bf2597..5f76cc6 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java
@@ -28,7 +28,6 @@ import java.io.StringReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
@@ -38,9 +37,13 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.common.util.io.resource.IoResource;
+import org.apache.sshd.common.util.io.resource.PathResource;
+import org.apache.sshd.common.util.io.resource.URLResource;

/**
* Loads {@link KeyPair}s from text resources
@@ -86,9 +89,7 @@ public interface KeyPairResourceLoader {
default Collection<KeyPair> loadKeyPairs(
SessionContext session, Path path, FilePasswordProvider passwordProvider, Charset cs, OpenOption... options)
throws IOException, GeneralSecurityException {
- try (InputStream stream = Files.newInputStream(path, options)) {
- return loadKeyPairs(session, path.toString(), passwordProvider, stream, cs);
- }
+ return loadKeyPairs(session, new PathResource(path, options), passwordProvider, cs);
}

default Collection<KeyPair> loadKeyPairs(
@@ -100,13 +101,25 @@ public interface KeyPairResourceLoader {
default Collection<KeyPair> loadKeyPairs(
SessionContext session, URL url, FilePasswordProvider passwordProvider, Charset cs)
throws IOException, GeneralSecurityException {
- try (InputStream stream = Objects.requireNonNull(url, "No URL").openStream()) {
- return loadKeyPairs(session, url.toExternalForm(), passwordProvider, stream, cs);
+ return loadKeyPairs(session, new URLResource(url), passwordProvider, cs);
+ }
+
+ default Collection<KeyPair> loadKeyPairs(
+ SessionContext session, IoResource<?> resource, FilePasswordProvider passwordProvider)
+ throws IOException, GeneralSecurityException {
+ return loadKeyPairs(session, resource, passwordProvider, StandardCharsets.UTF_8);
+ }
+
+ default Collection<KeyPair> loadKeyPairs(
+ SessionContext session, IoResource<?> resource, FilePasswordProvider passwordProvider, Charset cs)
+ throws IOException, GeneralSecurityException {
+ try (InputStream stream = Objects.requireNonNull(resource, "No resource data").openInputStream()) {
+ return loadKeyPairs(session, resource, passwordProvider, stream, cs);
}
}

default Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, String data)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, String data)
throws IOException, GeneralSecurityException {
try (Reader reader = new StringReader((data == null) ? "" : data)) {
return loadKeyPairs(session, resourceKey, passwordProvider, reader);
@@ -114,13 +127,13 @@ public interface KeyPairResourceLoader {
}

default Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, InputStream stream)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException {
return loadKeyPairs(session, resourceKey, passwordProvider, stream, StandardCharsets.UTF_8);
}

default Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, InputStream stream, Charset cs)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, InputStream stream, Charset cs)
throws IOException, GeneralSecurityException {
try (Reader reader = new InputStreamReader(
Objects.requireNonNull(stream, "No stream instance"), Objects.requireNonNull(cs, "No charset"))) {
@@ -129,7 +142,7 @@ public interface KeyPairResourceLoader {
}

default Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, Reader r)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, Reader r)
throws IOException, GeneralSecurityException {
try (BufferedReader br = new BufferedReader(Objects.requireNonNull(r, "No reader instance"), IoUtils.DEFAULT_COPY_SIZE)) {
return loadKeyPairs(session, resourceKey, passwordProvider, br);
@@ -137,7 +150,7 @@ public interface KeyPairResourceLoader {
}

default Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, BufferedReader r)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, BufferedReader r)
throws IOException, GeneralSecurityException {
return loadKeyPairs(session, resourceKey, passwordProvider, IoUtils.readAllLines(r));
}
@@ -160,6 +173,6 @@ public interface KeyPairResourceLoader {
* parsed data
*/
Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
index c434f0a..8a725d1 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java
@@ -30,6 +30,7 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
@@ -46,13 +47,13 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
KeyPairResourceParser EMPTY = new KeyPairResourceParser() {
@Override
public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
return Collections.emptyList();
}

@Override
- public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ public boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException {
return false;
}
@@ -71,7 +72,7 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
* @throws GeneralSecurityException If failed to extract information regarding
* the possibility to extract the key pairs
*/
- boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException;

/**
@@ -154,7 +155,7 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
return new KeyPairResourceParser() {
@Override
public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
Collection<KeyPair> keyPairs = Collections.emptyList();
for (KeyPairResourceParser p : parsers) {
@@ -178,7 +179,7 @@ public interface KeyPairResourceParser extends KeyPairResourceLoader {
}

@Override
- public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ public boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException {
for (KeyPairResourceParser p : parsers) {
if (p.canExtractKeyPairs(resourceKey, lines)) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
index c82957d..3c7871b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java
@@ -42,6 +42,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyEntryResolver;
import org.apache.sshd.common.config.keys.KeyUtils;
@@ -99,7 +100,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)
@@ -155,7 +156,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
}

protected PublicKey readPublicKey(
- SessionContext session, String resourceKey, OpenSSHParserContext context, InputStream stream)
+ SessionContext session, NamedResource resourceKey, OpenSSHParserContext context, InputStream stream)
throws IOException, GeneralSecurityException {
byte[] keyData = KeyEntryResolver.readRLEBytes(stream, MAX_PUBLIC_KEY_DATA_SIZE);
try (InputStream bais = new ByteArrayInputStream(keyData)) {
@@ -170,7 +171,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
}

protected List<KeyPair> readPrivateKeys(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
OpenSSHParserContext context, Collection<? extends PublicKey> publicKeys,
FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException {
@@ -216,7 +217,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
}

protected SimpleImmutableEntry<PrivateKey, String> readPrivateKey(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
OpenSSHParserContext context, String keyType,
FilePasswordProvider passwordProvider, InputStream stream)
throws IOException, GeneralSecurityException {
@@ -242,7 +243,7 @@ public class OpenSSHKeyPairResourceParser extends AbstractKeyPairResourceParser
}

protected <S extends InputStream> S validateStreamMagicMarker(
- SessionContext session, String resourceKey, S stream)
+ SessionContext session, NamedResource resourceKey, S stream)
throws IOException {
byte[] actual = new byte[AUTH_MAGIC_BYTES.length];
IoUtils.readFully(stream, actual);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
index a324339..39e546b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java
@@ -33,6 +33,7 @@ import java.util.List;
import javax.security.auth.login.CredentialException;
import javax.security.auth.login.FailedLoginException;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
import org.apache.sshd.common.config.keys.loader.AbstractKeyPairResourceParser;
@@ -74,7 +75,7 @@ public abstract class AbstractPEMResourceKeyPairParser

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
List<String> lines)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
index 39c84a6..df645e1 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/DSSPEMResourceKeyPairParser.java
@@ -34,6 +34,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.session.SessionContext;
@@ -69,7 +70,7 @@ public class DSSPEMResourceKeyPairParser extends AbstractPEMResourceKeyPairParse

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
index 19c15e2..2669e19 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/ECDSAPEMResourceKeyPairParser.java
@@ -38,6 +38,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
@@ -73,7 +74,7 @@ public class ECDSAPEMResourceKeyPairParser extends AbstractPEMResourceKeyPairPar

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
index d3aba1e..a0f3f99 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PEMResourceParserUtils.java
@@ -31,6 +31,7 @@ import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
import org.apache.sshd.common.session.SessionContext;
@@ -44,7 +45,7 @@ public final class PEMResourceParserUtils {
public static final KeyPairResourceParser PROXY = new KeyPairResourceParser() {
@Override
public Collection<KeyPair> loadKeyPairs(
- SessionContext session, String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
throws IOException, GeneralSecurityException {
@SuppressWarnings("synthetic-access")
KeyPairResourceParser proxy = PROXY_HOLDER.get();
@@ -52,7 +53,7 @@ public final class PEMResourceParserUtils {
}

@Override
- public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ public boolean canExtractKeyPairs(NamedResource resourceKey, List<String> lines)
throws IOException, GeneralSecurityException {
@SuppressWarnings("synthetic-access")
KeyPairResourceParser proxy = PROXY_HOLDER.get();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
index 90f033b..c755ea8 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
@@ -33,6 +33,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.session.SessionContext;
@@ -66,7 +67,7 @@ public class PKCS8PEMResourceKeyPairParser extends AbstractPEMResourceKeyPairPar

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
index 8badd63..b830063 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/RSAPEMResourceKeyPairParser.java
@@ -35,6 +35,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.session.SessionContext;
@@ -70,7 +71,7 @@ public class RSAPEMResourceKeyPairParser extends AbstractPEMResourceKeyPairParse

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
index 7fbee1b..fd33ec2 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java
@@ -21,6 +21,7 @@ package org.apache.sshd.common.keyprovider;

import java.io.IOException;
import java.io.InputStream;
+import java.io.StreamCorruptedException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PublicKey;
@@ -33,11 +34,14 @@ import java.util.Objects;
import java.util.TreeMap;
import java.util.TreeSet;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.resource.IoResource;
+import org.apache.sshd.common.util.io.resource.ResourceStreamProvider;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -118,9 +122,16 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
}
}

+ protected IoResource<?> getIoResource(SessionContext session, R resource) {
+ return IoResource.forResource(resource);
+ }
+
protected KeyPair doLoadKey(SessionContext session, R resource)
throws IOException, GeneralSecurityException {
- String resourceKey = ValidateUtils.checkNotNullAndNotEmpty(Objects.toString(resource, null), "No resource string value");
+ IoResource<?> ioResource =
+ ValidateUtils.checkNotNull(getIoResource(session, resource), "No I/O resource available for %s", resource);
+ String resourceKey =
+ ValidateUtils.checkNotNullAndNotEmpty(ioResource.getName(), "No resource string value for %s", resource);
KeyPair kp;
synchronized (cacheMap) {
// check if lucky enough to have already loaded this file
@@ -136,7 +147,7 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
return kp;
}

- kp = doLoadKey(session, resourceKey, resource, getPasswordFinder());
+ kp = doLoadKey(session, ioResource, resource, getPasswordFinder());
if (kp != null) {
boolean reusedKey;
synchronized (cacheMap) {
@@ -164,17 +175,26 @@ public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPair
return kp;
}

- protected KeyPair doLoadKey(SessionContext session, String resourceKey, R resource, FilePasswordProvider provider)
- throws IOException, GeneralSecurityException {
+ protected KeyPair doLoadKey(
+ SessionContext session, NamedResource resourceKey, R resource, FilePasswordProvider provider)
+ throws IOException, GeneralSecurityException {
try (InputStream inputStream = openKeyPairResource(session, resourceKey, resource)) {
return doLoadKey(session, resourceKey, inputStream, provider);
}
}

- protected abstract InputStream openKeyPairResource(SessionContext session, String resourceKey, R resource) throws IOException;
+ protected InputStream openKeyPairResource(
+ SessionContext session, NamedResource resourceKey, R resource)
+ throws IOException {
+ if (resourceKey instanceof ResourceStreamProvider) {
+ return ((ResourceStreamProvider) resourceKey).openInputStream();
+ }
+
+ throw new StreamCorruptedException("Cannot open resource data for " + resource);
+ }

protected KeyPair doLoadKey(
- SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ SessionContext session, NamedResource resourceKey, InputStream inputStream, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
return SecurityUtils.loadKeyPairIdentity(session, resourceKey, inputStream, provider);
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
index 54b4e30..0f8a70b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java
@@ -18,16 +18,14 @@
*/
package org.apache.sshd.common.keyprovider;

-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StreamCorruptedException;
import java.security.KeyPair;
import java.util.Collection;
import java.util.Collections;

import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.resource.ClassLoaderResource;
+import org.apache.sshd.common.util.io.resource.IoResource;
import org.apache.sshd.common.util.threads.ThreadUtils;

/**
@@ -90,20 +88,8 @@ public class ClassLoadableResourceKeyPairProvider extends AbstractResourceKeyPai
}

@Override
- protected InputStream openKeyPairResource(
- SessionContext session, String resourceKey, String resource)
- throws IOException {
- ClassLoader cl = resolveClassLoader();
- if (cl == null) {
- throw new StreamCorruptedException("No resource loader for " + resource);
- }
-
- InputStream input = cl.getResourceAsStream(resource);
- if (input == null) {
- throw new FileNotFoundException("Cannot find resource " + resource);
- }
-
- return input;
+ protected IoResource<?> getIoResource(SessionContext session, String resource) {
+ return new ClassLoaderResource(resolveClassLoader(), resource);
}

protected ClassLoader resolveClassLoader() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
index f7de669..613e0cf 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
@@ -19,8 +19,6 @@
package org.apache.sshd.common.keyprovider;

import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
@@ -31,7 +29,8 @@ import java.util.Objects;

import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.common.util.io.resource.IoResource;
+import org.apache.sshd.common.util.io.resource.PathResource;

/**
* This host key provider loads private keys from the specified files. The
@@ -77,15 +76,13 @@ public class FileKeyPairProvider extends AbstractResourceKeyPairProvider<Path> {
}

@Override
- protected KeyPair doLoadKey(SessionContext session, Path resource)
- throws IOException, GeneralSecurityException {
- return super.doLoadKey(session, (resource == null) ? null : resource.toAbsolutePath());
+ protected IoResource<Path> getIoResource(SessionContext session, Path resource) {
+ return (resource == null) ? null : new PathResource(resource);
}

@Override
- protected InputStream openKeyPairResource(
- SessionContext session, String resourceKey, Path resource)
- throws IOException {
- return Files.newInputStream(resource, IoUtils.EMPTY_OPEN_OPTIONS);
+ protected KeyPair doLoadKey(SessionContext session, Path resource)
+ throws IOException, GeneralSecurityException {
+ return super.doLoadKey(session, (resource == null) ? null : resource.toAbsolutePath());
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/AbstractIoResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/AbstractIoResource.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/AbstractIoResource.java
new file mode 100644
index 0000000..50e2ccd
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/AbstractIoResource.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.util.Objects;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractIoResource<T> implements IoResource<T> {
+ private final Class<T> resourceType;
+ private final T resourceValue;
+
+ protected AbstractIoResource(Class<T> resourceType, T resourceValue) {
+ this.resourceType = Objects.requireNonNull(resourceType, "No resource type specified");
+ this.resourceValue = Objects.requireNonNull(resourceValue, "No resource value provided");
+ }
+
+ @Override
+ public Class<T> getResourceType() {
+ return resourceType;
+ }
+
+ @Override
+ public T getResourceValue() {
+ return resourceValue;
+ }
+
+ @Override
+ public String getName() {
+ return Objects.toString(getResourceValue(), null);
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ClassLoaderResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ClassLoaderResource.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ClassLoaderResource.java
new file mode 100644
index 0000000..7dec40a
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ClassLoaderResource.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StreamCorruptedException;
+
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.threads.ThreadUtils;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClassLoaderResource extends AbstractIoResource<ClassLoader> {
+ private final String resourceName;
+
+ public ClassLoaderResource(ClassLoader loader, String resourceName) {
+ super(ClassLoader.class, (loader == null) ? ThreadUtils.resolveDefaultClassLoader(ClassLoaderResource.class) : loader);
+ this.resourceName = ValidateUtils.checkNotNullAndNotEmpty(resourceName, "No resource name provided");
+ }
+
+ public ClassLoader getResourceLoader() {
+ return getResourceValue();
+ }
+
+ @Override
+ public String getName() {
+ return resourceName;
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ String name = getName();
+ ClassLoader cl = getResourceLoader();
+ if (cl == null) {
+ throw new StreamCorruptedException("No resource loader for " + name);
+ }
+
+ InputStream input = cl.getResourceAsStream(name);
+ if (input == null) {
+ throw new FileNotFoundException("Cannot find resource " + name);
+ }
+
+ return input;
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/IoResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/IoResource.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/IoResource.java
new file mode 100644
index 0000000..0031544
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/IoResource.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.apache.sshd.common.NamedResource;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface IoResource<T> extends NamedResource, ResourceStreamProvider {
+ /**
+ * @return The type of resource being represented
+ */
+ Class<T> getResourceType();
+
+ /**
+ * @return The resource value serving as basis for the provided data stream
+ */
+ T getResourceValue();
+
+ /**
+ * Attempts to find the best wrapper for the resource
+ *
+ * @param resource The resource object - ignored if {@code null}
+ * @return The best wrapper out of the supported ones ({@code null} if no initial resource)
+ * @throws UnsupportedOperationException if no match found
+ */
+ static IoResource<?> forResource(Object resource) {
+ if (resource == null) {
+ return null;
+ } else if (resource instanceof Path) {
+ return new PathResource((Path) resource);
+ } else if (resource instanceof URL) {
+ return new URLResource((URL) resource);
+ } else if (resource instanceof URI) {
+ return new URIResource((URI) resource);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported resource type " + resource.getClass().getSimpleName() + ": " + resource);
+ }
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/PathResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/PathResource.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/PathResource.java
new file mode 100644
index 0000000..a11380b
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/PathResource.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+
+import org.apache.sshd.common.util.io.IoUtils;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class PathResource extends AbstractIoResource<Path> {
+ private final OpenOption[] openOptions;
+
+ public PathResource(Path path) {
+ super(Path.class, path);
+ this.openOptions = IoUtils.EMPTY_OPEN_OPTIONS;
+ }
+
+ public PathResource(Path path, OpenOption... openOptions) {
+ super(Path.class, path);
+ // Use a clone to avoid shared instance modification
+ this.openOptions = (openOptions == null) ? IoUtils.EMPTY_OPEN_OPTIONS : openOptions.clone();
+ }
+
+ public Path getPath() {
+ return getResourceValue();
+ }
+
+ public OpenOption[] getOpenOptions() {
+ // Use a clone to avoid shared instance modification
+ return (openOptions.length <= 0) ? openOptions : openOptions.clone();
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ return Files.newInputStream(getPath(), getOpenOptions());
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ResourceStreamProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ResourceStreamProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ResourceStreamProvider.java
new file mode 100644
index 0000000..6e17c5c
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/ResourceStreamProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FunctionalInterface
+public interface ResourceStreamProvider {
+ /**
+ * Return an {@link InputStream} for the resource's data
+ */
+ InputStream openInputStream() throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URIResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URIResource.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URIResource.java
new file mode 100644
index 0000000..a43f9e5
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URIResource.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class URIResource extends AbstractIoResource<URI> {
+ public URIResource(URI uri) {
+ super(URI.class, uri);
+ }
+
+ public URI getURI() {
+ return getResourceValue();
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ URI uri = getURI();
+ URL url = uri.toURL();
+ return url.openStream();
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URLResource.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URLResource.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URLResource.java
new file mode 100644
index 0000000..761012b
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/resource/URLResource.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.util.io.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class URLResource extends AbstractIoResource<URL> {
+ public URLResource(URL url) {
+ super(URL.class, url);
+ }
+
+ public URL getURL() {
+ return getResourceValue();
+ }
+
+ @Override
+ public String getName() {
+ URL url = getURL();
+ // URL#toString() may involve a DNS lookup
+ return url.toExternalForm();
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ URL url = getURL();
+ return url.openStream();
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
index 2949875..cac845e 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
@@ -57,6 +57,7 @@ import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
import javax.crypto.spec.DHParameterSpec;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
@@ -481,7 +482,7 @@ public final class SecurityUtils {
* @throws GeneralSecurityException If failed to generate the keys
*/
public static KeyPair loadKeyPairIdentity(
- SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ SessionContext session, NamedResource resourceKey, InputStream inputStream, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
KeyPairResourceParser parser = getKeyPairResourceParser();
if (parser == null) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
index 3716719..534b033 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java
@@ -26,6 +26,7 @@ import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyPair;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;

/**
@@ -38,7 +39,7 @@ public class BouncyCastleGeneratorHostKeyProvider extends AbstractGeneratorHostK

@SuppressWarnings("deprecation")
@Override
- protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException {
+ protected void doWriteKeyPair(NamedResource resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException {
try (org.bouncycastle.openssl.PEMWriter w =
new org.bouncycastle.openssl.PEMWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
w.writeObject(kp);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
index 881adff..7709606 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java
@@ -36,6 +36,7 @@ import java.util.List;
import javax.security.auth.login.CredentialException;
import javax.security.auth.login.FailedLoginException;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.FilePasswordProvider.ResourceDecodeResult;
import org.apache.sshd.common.config.keys.loader.AbstractKeyPairResourceParser;
@@ -77,7 +78,10 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines)
+ SessionContext session, NamedResource resourceKey,
+ String beginMarker, String endMarker,
+ FilePasswordProvider passwordProvider,
+ List<String> lines)
throws IOException, GeneralSecurityException {
StringBuilder writer = new StringBuilder(beginMarker.length() + endMarker.length() + lines.size() * 80);
writer.append(beginMarker).append(IoUtils.EOL);
@@ -93,7 +97,7 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa

@Override
public Collection<KeyPair> extractKeyPairs(
- SessionContext session, String resourceKey,
+ SessionContext session, NamedResource resourceKey,
String beginMarker, String endMarker,
FilePasswordProvider passwordProvider,
InputStream stream)
@@ -103,7 +107,7 @@ public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourcePa
}

public static KeyPair loadKeyPair(
- SessionContext session, String resourceKey, InputStream inputStream, FilePasswordProvider provider)
+ SessionContext session, NamedResource resourceKey, InputStream inputStream, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
try (PEMParser r = new PEMParser(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
Object o = r.readObject();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
index 71e3a4f..be4ceb5 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
@@ -35,12 +35,14 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.config.keys.BuiltinIdentities;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.common.util.security.SecurityUtils;

/**
@@ -242,12 +244,13 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr

protected KeyPair readKeyPair(SessionContext session, Path keyPath, OpenOption... options)
throws IOException, GeneralSecurityException {
- try (InputStream inputStream = Files.newInputStream(keyPath, options)) {
- return doReadKeyPair(session, keyPath.toString(), inputStream);
+ PathResource location = new PathResource(keyPath, options);
+ try (InputStream inputStream = location.openInputStream()) {
+ return doReadKeyPair(session, location, inputStream);
}
}

- protected KeyPair doReadKeyPair(SessionContext session, String resourceKey, InputStream inputStream)
+ protected KeyPair doReadKeyPair(SessionContext session, NamedResource resourceKey, InputStream inputStream)
throws IOException, GeneralSecurityException {
return SecurityUtils.loadKeyPairIdentity(session, resourceKey, inputStream, null);
}
@@ -255,8 +258,9 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
protected void writeKeyPair(KeyPair kp, Path keyPath, OpenOption... options)
throws IOException, GeneralSecurityException {
if ((!Files.exists(keyPath)) || isOverwriteAllowed()) {
+ PathResource location = new PathResource(keyPath); // The options are for write (!!)
try (OutputStream os = Files.newOutputStream(keyPath, options)) {
- doWriteKeyPair(keyPath.toString(), kp, os);
+ doWriteKeyPair(location, kp, os);
} catch (Throwable e) {
log.warn("writeKeyPair({}) failed ({}) to write key {}: {}",
keyPath, e.getClass().getSimpleName(), e.getMessage());
@@ -266,11 +270,13 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
}
} else {
log.error("Overwriting key ({}) is disabled: using throwaway {}: {}",
- keyPath, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint((kp == null) ? null : kp.getPublic()));
+ keyPath, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint((kp == null) ? null : kp.getPublic()));
}
}

- protected abstract void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException;
+ protected abstract void doWriteKeyPair(
+ NamedResource resourceKey, KeyPair kp, OutputStream outputStream)
+ throws IOException, GeneralSecurityException;

protected KeyPair generateKeyPair(String algorithm) throws GeneralSecurityException {
KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator(algorithm);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
index b40edcb..c0ccd16 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProvider.java
@@ -28,6 +28,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.spec.InvalidKeySpecException;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.session.SessionContext;

/**
@@ -45,7 +46,7 @@ public class SimpleGeneratorHostKeyProvider extends AbstractGeneratorHostKeyProv
}

@Override
- protected KeyPair doReadKeyPair(SessionContext session, String resourceKey, InputStream inputStream)
+ protected KeyPair doReadKeyPair(SessionContext session, NamedResource resourceKey, InputStream inputStream)
throws IOException, GeneralSecurityException {
try (ObjectInputStream r = new ObjectInputStream(inputStream)) {
try {
@@ -57,7 +58,7 @@ public class SimpleGeneratorHostKeyProvider extends AbstractGeneratorHostKeyProv
}

@Override
- protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream)
+ protected void doWriteKeyPair(NamedResource resourceKey, KeyPair kp, OutputStream outputStream)
throws IOException, GeneralSecurityException {
try (ObjectOutputStream w = new ObjectOutputStream(outputStream)) {
w.writeObject(kp);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
index 81c458f..64573c4 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcherTest.java
@@ -35,6 +35,7 @@ import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.BuiltinIdentities;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
@@ -80,7 +81,7 @@ public class BuiltinClientIdentitiesWatcherTest extends JUnitTestSupport {
ClientIdentityLoader loader = new ClientIdentityLoader() {
@Override
public KeyPair loadClientIdentity(
- SessionContext session, String location, FilePasswordProvider provider)
+ SessionContext session, NamedResource location, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
BuiltinIdentities id = findIdentity(location);
assertNotNull("Invalid location: " + location, id);
@@ -88,18 +89,19 @@ public class BuiltinClientIdentitiesWatcherTest extends JUnitTestSupport {
}

@Override
- public boolean isValidLocation(String location) throws IOException {
+ public boolean isValidLocation(NamedResource location) throws IOException {
return findIdentity(location) != null;
}

- private BuiltinIdentities findIdentity(String location) {
- if (GenericUtils.isEmpty(location)) {
+ private BuiltinIdentities findIdentity(NamedResource location) {
+ String idPath = (location == null) ? null : location.getName();
+ if (GenericUtils.isEmpty(idPath)) {
return null;
}

for (Map.Entry<BuiltinIdentities, Path> le : locationsMap.entrySet()) {
Path path = le.getValue();
- if (String.CASE_INSENSITIVE_ORDER.compare(location, path.toString()) == 0) {
+ if (String.CASE_INSENSITIVE_ORDER.compare(idPath, path.toString()) == 0) {
return le.getKey();
}
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/895f30f1/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
index bd43f44..2cf3828 100644
--- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcherTest.java
@@ -32,6 +32,7 @@ import java.util.Date;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

+import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.IoUtils;
@@ -61,15 +62,15 @@ public class ClientIdentityFileWatcherTest extends JUnitTestSupport {
ClientIdentityLoader loader = new ClientIdentityLoader() {
@Override
public KeyPair loadClientIdentity(
- SessionContext session, String location, FilePasswordProvider provider)
+ SessionContext session, NamedResource location, FilePasswordProvider provider)
throws IOException, GeneralSecurityException {
assertTrue("Invalid location: " + location, isValidLocation(location));
return identity;
}

@Override
- public boolean isValidLocation(String location) throws IOException {
- return Objects.equals(location, toString());
+ public boolean isValidLocation(NamedResource location) throws IOException {
+ return Objects.equals(location.getName(), toString());
}

@Override

Loading...