@ -47,6 +47,7 @@ import java.io.File;
import java.io.IOException ;
import java.io.IOException ;
import java.nio.file.Files ;
import java.nio.file.Files ;
import java.nio.file.Path ;
import java.nio.file.Path ;
import java.security.KeyPair ;
import java.time.Duration ;
import java.time.Duration ;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Arrays ;
@ -68,7 +69,6 @@ import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.common.NamedFactory ;
import org.apache.sshd.common.NamedFactory ;
import org.apache.sshd.common.compression.BuiltinCompressions ;
import org.apache.sshd.common.compression.BuiltinCompressions ;
import org.apache.sshd.common.config.keys.FilePasswordProvider ;
import org.apache.sshd.common.config.keys.FilePasswordProvider ;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider ;
import org.apache.sshd.common.keyprovider.KeyPairProvider ;
import org.apache.sshd.common.keyprovider.KeyPairProvider ;
import org.eclipse.jgit.annotations.NonNull ;
import org.eclipse.jgit.annotations.NonNull ;
import org.eclipse.jgit.errors.TransportException ;
import org.eclipse.jgit.errors.TransportException ;
@ -89,7 +89,9 @@ import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.FS ;
import org.eclipse.jgit.util.FS ;
/ * *
/ * *
* A { @link SshSessionFactory } that uses Apache MINA sshd .
* A { @link SshSessionFactory } that uses Apache MINA sshd . Classes from Apache
* MINA sshd are kept private to avoid API evolution problems when Apache MINA
* sshd interfaces change .
*
*
* @since 5 . 2
* @since 5 . 2
* /
* /
@ -103,7 +105,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
private final Map < Tuple , ServerKeyVerifier > defaultServerKeyVerifier = new ConcurrentHashMap < > ( ) ;
private final Map < Tuple , ServerKeyVerifier > defaultServerKeyVerifier = new ConcurrentHashMap < > ( ) ;
private final Map < Tuple , FileKeyPairProvider > defaultKeys = new ConcurrentHashMap < > ( ) ;
private final Map < Tuple , Iterable < KeyPair > > defaultKeys = new ConcurrentHashMap < > ( ) ;
private final KeyCache keyCache ;
private final KeyCache keyCache ;
@ -209,8 +211,8 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
}
}
HostConfigEntryResolver configFile = getHostConfigEntryResolver (
HostConfigEntryResolver configFile = getHostConfigEntryResolver (
home , sshDir ) ;
home , sshDir ) ;
KeyPairProvider defaultKeysProvider = getDefaultKeys Provider(
KeyPairProvider defaultKeysProvider = toKeyPair Provider(
sshDir ) ;
getDefaultKeys ( sshDir ) ) ;
KeyPasswordProvider passphrases = createKeyPasswordProvider (
KeyPasswordProvider passphrases = createKeyPasswordProvider (
credentialsProvider ) ;
credentialsProvider ) ;
SshClient client = ClientBuilder . builder ( )
SshClient client = ClientBuilder . builder ( )
@ -395,14 +397,38 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
}
}
/ * *
/ * *
* Determines a { @link KeyPairProvider } to use to load the default keys .
* Determines the default keys . The default implementation will lazy load
* the { @link # getDefaultIdentities ( File ) default identity files } .
* < p >
* Subclasses may override and return an { @link Iterable } of whatever keys
* are appropriate . If the returned iterable lazily loads keys , it should be
* an instance of
* { @link org . apache . sshd . common . keyprovider . AbstractResourceKeyPairProvider
* AbstractResourceKeyPairProvider } so that the session can later pass it
* the { @link # createKeyPasswordProvider ( CredentialsProvider ) password
* provider } wrapped as a { @link FilePasswordProvider } via
* { @link org . apache . sshd . common . keyprovider . AbstractResourceKeyPairProvider # setPasswordFinder ( FilePasswordProvider )
* AbstractResourceKeyPairProvider # setPasswordFinder ( FilePasswordProvider ) }
* so that encrypted , password - protected keys can be loaded .
* < / p >
* < p >
* The default implementation uses exactly this mechanism ; class
* { @link CachingKeyPairProvider } may serve as a model for a customized
* lazy - loading { @link Iterable } implementation
* < / p >
* < p >
* If the { @link Iterable } returned has the keys already pre - loaded or
* otherwise doesn ' t need to decrypt encrypted keys , it can be any
* { @link Iterable } , for instance a simple { @link java . util . List List } .
* < / p >
*
*
* @param sshDir
* @param sshDir
* to look in for keys
* to look in for keys
* @return the { @link KeyPairProvider }
* @return an { @link Iterable } over the default keys
* @since 5 . 3
* /
* /
@NonNull
@NonNull
private KeyPairProvider getDefaultKeysProvider ( @NonNull File sshDir ) {
protected Iterable < KeyPair > getDefaultKeys ( @NonNull File sshDir ) {
List < Path > defaultIdentities = getDefaultIdentities ( sshDir ) ;
List < Path > defaultIdentities = getDefaultIdentities ( sshDir ) ;
return defaultKeys . computeIfAbsent (
return defaultKeys . computeIfAbsent (
new Tuple ( defaultIdentities . toArray ( new Path [ 0 ] ) ) ,
new Tuple ( defaultIdentities . toArray ( new Path [ 0 ] ) ) ,
@ -410,6 +436,21 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
getKeyCache ( ) ) ) ;
getKeyCache ( ) ) ) ;
}
}
/ * *
* Converts an { @link Iterable } of { link KeyPair } s into a
* { @link KeyPairProvider } .
*
* @param keys
* to provide via the returned { @link KeyPairProvider }
* @return a { @link KeyPairProvider } that provides the given { @code keys }
* /
private KeyPairProvider toKeyPairProvider ( Iterable < KeyPair > keys ) {
if ( keys instanceof KeyPairProvider ) {
return ( KeyPairProvider ) keys ;
}
return ( ) - > keys ;
}
/ * *
/ * *
* Gets a list of default identities , i . e . , private key files that shall
* Gets a list of default identities , i . e . , private key files that shall
* always be tried for public key authentication . Typically those are
* always be tried for public key authentication . Typically those are