aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.ssh.apache
diff options
context:
space:
mode:
authorThomas Wolf <thomas.wolf@paranor.ch>2021-10-27 14:03:10 +0200
committerThomas Wolf <thomas.wolf@paranor.ch>2021-11-10 13:57:01 -0500
commite7838b9c080011817ddb59c53298237a9c24a7a6 (patch)
tree885bd217ebe1f0226c156aa2676272cfa1e9cc43 /org.eclipse.jgit.ssh.apache
parentb84738c3693081d3ed9e8e1ba4a5db6e5ac3abf8 (diff)
downloadjgit-e7838b9c080011817ddb59c53298237a9c24a7a6.tar.gz
jgit-e7838b9c080011817ddb59c53298237a9c24a7a6.zip
[sshd agent] Introduce ConnectorDescriptor
Once a factory supports different SSH agents on the same platform, which is planned for Windows once we use Apache MINA sshd 2.8.0, client code may need to have a way to specify which SSH agent shall be used when the SSH config doesn't define anything. Add a mechanism by which a ConnectorFactory can tell what Connectors it may provide. Client code can use this to set the identityAgent parameter of ConnectorFactory.create() to the wanted default if it would be null otherwise. A ConnectorDescriptor is a pair of strings: an internal name, and a display name. The latter is included because client code might want to communicate agent names to the user, be it in error messages or in some chooser dialog where a user could define which of several alternative SSH agents should be used as default. The internal name is intended to be used in the IdentityAgent directive in ~/.ssh/config. Also make the ConnectorFactory discovered via the ServiceLoader accessible and overrideable. Provide static get/setDefault() methods, similar to the SshSessionFactory itself. Change-Id: Ie3d077395d32dfddc72bc8627e92b23636938182 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.jgit.ssh.apache')
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/agent/ConnectorFactoryProvider.java26
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java6
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java116
3 files changed, 136 insertions, 12 deletions
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/agent/ConnectorFactoryProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/agent/ConnectorFactoryProvider.java
index 9984f99763..aba7a76459 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/agent/ConnectorFactoryProvider.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/agent/ConnectorFactoryProvider.java
@@ -19,7 +19,7 @@ import org.eclipse.jgit.transport.sshd.agent.ConnectorFactory;
*/
public final class ConnectorFactoryProvider {
- private static final ConnectorFactory FACTORY = loadDefaultFactory();
+ private static volatile ConnectorFactory INSTANCE = loadDefaultFactory();
private static ConnectorFactory loadDefaultFactory() {
ServiceLoader<ConnectorFactory> loader = ServiceLoader
@@ -35,17 +35,27 @@ public final class ConnectorFactoryProvider {
}
- private ConnectorFactoryProvider() {
- // No instantiation
- }
-
/**
- * Retrieves the default {@link ConnectorFactory} obtained via the
- * {@link ServiceLoader}.
+ * Retrieves the currently set default {@link ConnectorFactory}.
*
* @return the {@link ConnectorFactory}, or {@code null} if none.
*/
public static ConnectorFactory getDefaultFactory() {
- return FACTORY;
+ return INSTANCE;
+ }
+
+ /**
+ * Sets the default {@link ConnectorFactory}.
+ *
+ * @param factory
+ * {@link ConnectorFactory} to use, or {@code null} to use the
+ * factory discovered via the {@link ServiceLoader}.
+ */
+ public static void setDefaultFactory(ConnectorFactory factory) {
+ INSTANCE = factory == null ? loadDefaultFactory() : factory;
+ }
+
+ private ConnectorFactoryProvider() {
+ // No instantiation
}
}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java
index 3364180099..58cf8e1ddd 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java
@@ -56,7 +56,6 @@ import org.eclipse.jgit.internal.transport.sshd.JGitUserInteraction;
import org.eclipse.jgit.internal.transport.sshd.OpenSshServerKeyDatabase;
import org.eclipse.jgit.internal.transport.sshd.PasswordProviderWrapper;
import org.eclipse.jgit.internal.transport.sshd.SshdText;
-import org.eclipse.jgit.internal.transport.sshd.agent.ConnectorFactoryProvider;
import org.eclipse.jgit.internal.transport.sshd.agent.JGitSshAgentFactory;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.SshConfigStore;
@@ -456,12 +455,15 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable {
/**
* Gets a {@link ConnectorFactory}. If this returns {@code null}, SSH agents
* are not supported.
+ * <p>
+ * The default implementation uses {@link ConnectorFactory#getDefault()}
+ * </p>
*
* @return the factory, or {@code null} if no SSH agent support is desired
* @since 6.0
*/
protected ConnectorFactory getConnectorFactory() {
- return ConnectorFactoryProvider.getDefaultFactory();
+ return ConnectorFactory.getDefault();
}
/**
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java
index b351d89ef5..da98ea7fe0 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/agent/ConnectorFactory.java
@@ -11,8 +11,10 @@ package org.eclipse.jgit.transport.sshd.agent;
import java.io.File;
import java.io.IOException;
+import java.util.Collection;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.internal.transport.sshd.agent.ConnectorFactoryProvider;
/**
* A factory for creating {@link Connector}s. This is a service provider
@@ -25,13 +27,44 @@ import org.eclipse.jgit.annotations.NonNull;
public interface ConnectorFactory {
/**
+ * Retrieves the currently set default {@link ConnectorFactory}. This is the
+ * factory that is used unless overridden by the
+ * {@link org.eclipse.jgit.transport.sshd.SshdSessionFactory}.
+ *
+ * @return the current default factory; may be {@code null} if none is set
+ * and the {@link java.util.ServiceLoader} cannot find any suitable
+ * implementation
+ */
+ static ConnectorFactory getDefault() {
+ return ConnectorFactoryProvider.getDefaultFactory();
+ }
+
+ /**
+ * Sets a default {@link ConnectorFactory}. This is the factory that is used
+ * unless overridden by the
+ * {@link org.eclipse.jgit.transport.sshd.SshdSessionFactory}.
+ * <p>
+ * If no default factory is set programmatically, an implementation is
+ * discovered via the {@link java.util.ServiceLoader}.
+ * </p>
+ *
+ * @param factory
+ * {@link ConnectorFactory} to set, or {@code null} to revert to
+ * the default behavior of using the
+ * {@link java.util.ServiceLoader}.
+ */
+ static void setDefault(ConnectorFactory factory) {
+ ConnectorFactoryProvider.setDefaultFactory(factory);
+ }
+
+ /**
* Creates a new {@link Connector}.
*
* @param identityAgent
* identifies the wanted agent connection; if {@code null}, the
* factory is free to provide a {@link Connector} to a default
- * agent. The value will typically come from the IdentityAgent
- * setting in ~/.ssh/config.
+ * agent. The value will typically come from the
+ * {@code IdentityAgent} setting in {@code ~/.ssh/config}.
* @param homeDir
* the current local user's home directory as configured in the
* {@link org.eclipse.jgit.transport.sshd.SshdSessionFactory}
@@ -58,4 +91,83 @@ public interface ConnectorFactory {
*/
String getName();
+ /**
+ * {@link ConnectorDescriptor}s describe available {@link Connector}s a
+ * {@link ConnectorFactory} may provide.
+ * <p>
+ * A {@link ConnectorFactory} may support connecting to different SSH
+ * agents. Agents are identified by name; a user can choose a specific agent
+ * for instance via the {@code IdentityAgent} setting in
+ * {@code ~/.ssh/config}.
+ * </p>
+ * <p>
+ * OpenSSH knows two built-in names: "none" for not using any agent, and
+ * "SSH_AUTH_SOCK" for using an agent that communicates over a Unix domain
+ * socket given by the value of environment variable {@code SSH_AUTH_SOCK}.
+ * Other agents can be specified in OpenSSH by specifying the socket file
+ * directly. (The "standard" OpenBSD OpenSSH knows only this communication
+ * mechanism.) "SSH_AUTH_SOCK" is also the default in OpenBSD OpenSSH if
+ * nothing is configured.
+ * </p>
+ * <p>
+ * A particular {@link ConnectorFactory} may support more communication
+ * mechanisms or different agents. For instance, a factory on Windows might
+ * support Pageant, Win32-OpenSSH, or even git bash ssh-agent, and might
+ * accept internal names like "pageant", "openssh", "SSH_AUTH_SOCK" in
+ * {@link ConnectorFactory#create(String, File)} to choose among them.
+ * </p>
+ * The {@link ConnectorDescriptor} interface and the
+ * {@link ConnectorFactory#getSupportedConnectors()} and
+ * {@link ConnectorFactory#getDefaultConnector()} methods provide a way for
+ * code using a {@link ConnectorFactory} to learn what the factory supports
+ * and thus implement some way by which a user can influence the default
+ * behavior if {@code IdentityAgent} is not set or
+ * {@link ConnectorFactory#create(String, File)} is called with
+ * {@code identityAgent == null}.
+ */
+ interface ConnectorDescriptor {
+
+ /**
+ * Retrieves the internal name of a supported {@link Connector}. The
+ * internal name is the one a user can specify for instance in the
+ * {@code IdentityAgent} setting in {@code ~/.ssh/config} to select the
+ * connector.
+ *
+ * @return the internal name; not empty
+ */
+ @NonNull
+ String getIdentityAgent();
+
+ /**
+ * Retrieves a display name for a {@link Connector}, suitable for
+ * showing in a UI.
+ *
+ * @return the display name; properly localized and not empty
+ */
+ @NonNull
+ String getDisplayName();
+ }
+
+ /**
+ * Tells which kinds of SSH agents this {@link ConnectorFactory} supports.
+ * <p>
+ * An implementation of this method should document the possible values it
+ * returns.
+ * </p>
+ *
+ * @return an immutable collection of {@link ConnectorDescriptor}s,
+ * including {@link #getDefaultConnector()} and not including a
+ * descriptor for internal name "none"
+ */
+ @NonNull
+ Collection<ConnectorDescriptor> getSupportedConnectors();
+
+ /**
+ * Tells what kind of {@link Connector} this {@link ConnectorFactory}
+ * creates if {@link ConnectorFactory#create(String, File)} is called with
+ * {@code identityAgent == null}.
+ *
+ * @return a {@link ConnectorDescriptor} for the default connector
+ */
+ ConnectorDescriptor getDefaultConnector();
}