From 4c7801a48c0fef26e6c513a583b1e030e09fe849 Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Fri, 20 Sep 2024 21:59:49 +0200 Subject: [PATCH] ssh: add a factory for KeyPasswordProvider Introduce a global default factory to create KeyPasswordProvider. Previously, their creation was tied to the SSH session, but for SSH signatures, we will need to be able to create KeyPasswordProviders without having an SSH session. Change-Id: If4a69c4d4c4e8de390cb1ef3b65966d0e39c24ff Signed-off-by: Thomas Wolf --- .../sshd/KeyPasswordProviderFactory.java | 69 +++++++++++++++++++ .../transport/sshd/SshdSessionFactory.java | 22 ++++-- 2 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyPasswordProviderFactory.java diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyPasswordProviderFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyPasswordProviderFactory.java new file mode 100644 index 0000000000..0537300b24 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyPasswordProviderFactory.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024, Thomas Wolf and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.transport.sshd; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.transport.CredentialsProvider; + +/** + * Maintains a static singleton instance of a factory to create a + * {@link KeyPasswordProvider} from a {@link CredentialsProvider}. + * + * @since 7.1 + */ +public final class KeyPasswordProviderFactory { + + /** + * Creates a {@link KeyPasswordProvider} from a {@link CredentialsProvider}. + */ + @FunctionalInterface + public interface KeyPasswordProviderCreator + extends Function { + // Nothing + } + + private static final KeyPasswordProviderCreator DEFAULT = IdentityPasswordProvider::new; + + private static AtomicReference INSTANCE = new AtomicReference<>( + DEFAULT); + + private KeyPasswordProviderFactory() { + // No instantiation + } + + /** + * Retrieves the currently set {@link KeyPasswordProviderCreator}. + * + * @return the {@link KeyPasswordProviderCreator} + */ + @NonNull + public static KeyPasswordProviderCreator getInstance() { + return INSTANCE.get(); + } + + /** + * Sets a new {@link KeyPasswordProviderCreator}. + * + * @param provider + * to set; if {@code null}, sets a default provider. + * @return the previously set {@link KeyPasswordProviderCreator} + */ + @NonNull + public static KeyPasswordProviderCreator setInstance( + KeyPasswordProviderCreator provider) { + if (provider == null) { + return INSTANCE.getAndSet(DEFAULT); + } + return INSTANCE.getAndSet(provider); + } +} 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 2c3cbe55c9..4a2eb9c3dd 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, 2022 Thomas Wolf and others + * Copyright (C) 2018, 2024 Thomas Wolf and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -210,7 +210,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { home, sshDir); KeyIdentityProvider defaultKeysProvider = toKeyIdentityProvider( getDefaultKeys(sshDir)); - Supplier keyPasswordProvider = () -> createKeyPasswordProvider( + Supplier keyPasswordProvider = newKeyPasswordProvider( credentialsProvider); SshClient client = ClientBuilder.builder() .factory(JGitSshClient::new) @@ -574,12 +574,24 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { * @param provider * the {@link CredentialsProvider} to delegate to for user * interactions - * @return a new {@link KeyPasswordProvider} + * @return a new {@link KeyPasswordProvider}, or {@code null} to use the + * global {@link KeyPasswordProviderFactory} */ - @NonNull protected KeyPasswordProvider createKeyPasswordProvider( CredentialsProvider provider) { - return new IdentityPasswordProvider(provider); + return null; + } + + private Supplier newKeyPasswordProvider( + CredentialsProvider credentials) { + return () -> { + KeyPasswordProvider provider = createKeyPasswordProvider( + credentials); + if (provider != null) { + return provider; + } + return KeyPasswordProviderFactory.getInstance().apply(credentials); + }; } /** -- 2.39.5