/*
 * Copyright (C) 2018, 2019 Thomas Wolf <thomas.wolf@paranor.ch> 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.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import org.apache.sshd.client.ClientBuilder;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.auth.UserAuthFactory;
import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory;
import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory;
import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
import org.apache.sshd.common.compression.BuiltinCompressions;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.config.keys.loader.openssh.kdf.BCryptKdfOptions;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
import org.eclipse.jgit.internal.transport.sshd.CachingKeyPairProvider;
import org.eclipse.jgit.internal.transport.sshd.GssApiWithMicAuthFactory;
import org.eclipse.jgit.internal.transport.sshd.JGitPasswordAuthFactory;
import org.eclipse.jgit.internal.transport.sshd.JGitServerKeyVerifier;
import org.eclipse.jgit.internal.transport.sshd.JGitSshClient;
import org.eclipse.jgit.internal.transport.sshd.JGitSshConfig;
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.transport.CredentialsProvider;
import org.eclipse.jgit.transport.SshConfigStore;
import org.eclipse.jgit.transport.SshConstants;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.FS;

/**
 * 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
 */
public class SshdSessionFactory extends SshSessionFactory implements Closeable {

	private final AtomicBoolean closing = new AtomicBoolean();

	private final Set<SshdSession> sessions = new HashSet<>();

	private final Map<Tuple, HostConfigEntryResolver> defaultHostConfigEntryResolver = new ConcurrentHashMap<>();

	private final Map<Tuple, ServerKeyDatabase> defaultServerKeyDatabase = new ConcurrentHashMap<>();

	private final Map<Tuple, Iterable<KeyPair>> defaultKeys = new ConcurrentHashMap<>();

	private final KeyCache keyCache;

	private final ProxyDataFactory proxies;

	private File sshDirectory;

	private File homeDirectory;

	/**
	 * Creates a new {@link SshdSessionFactory} without key cache and a
	 * {@link DefaultProxyDataFactory}.
	 */
	public SshdSessionFactory() {
		this(null, new DefaultProxyDataFactory());
	}

	/**
	 * Creates a new {@link SshdSessionFactory} using the given {@link KeyCache}
	 * and {@link ProxyDataFactory}. The {@code keyCache} is used for all sessions
	 * created through this session factory; cached keys are destroyed when the
	 * session factory is {@link #close() closed}.
	 * <p>
	 * Caching ssh keys in memory for an extended period of time is generally
	 * considered bad practice, but there may be circumstances where using a
	 * {@link KeyCache} is still the right choice, for instance to avoid that a
	 * user gets prompted several times for the same password for the same key.
	 * In general, however, it is preferable <em>not</em> to use a key cache but
	 * to use a {@link #createKeyPasswordProvider(CredentialsProvider)
	 * KeyPasswordProvider} that has access to some secure storage and can save
	 * and retrieve passwords from there without user interaction. Another
	 * approach is to use an ssh agent.
	 * </p>
	 * <p>
	 * Note that the underlying ssh library (Apache MINA sshd) may or may not
	 * keep ssh keys in memory for unspecified periods of time irrespective of
	 * the use of a {@link KeyCache}.
	 * </p>
	 *
	 * @param keyCache
	 *            {@link KeyCache} to use for caching ssh keys, or {@code null}
	 *            to not use a key cache
	 * @param proxies
	 *            {@link ProxyDataFactory} to use, or {@code null} to not use a
	 *            proxy database (in which case connections through proxies will
	 *            not be possible)
	 */
	public SshdSessionFactory(KeyCache keyCache, ProxyDataFactory proxies) {
		super();
		this.keyCache = keyCache;
		this.proxies = proxies;
		// sshd limits the number of BCrypt KDF rounds to 255 by default.
		// Decrypting such a key takes about two seconds on my machine.
		// I consider this limit too low. The time increases linearly with the
		// number of rounds.
		BCryptKdfOptions.setMaxAllowedRounds(16384);
	}

	/** A simple general map key. */
	private static final class Tuple {
		private Object[] objects;

		public Tuple(Object[] objects) {
			this.objects = objects;
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == this) {
				return true;
			}
			if (obj != null && obj.getClass() == Tuple.class) {
				Tuple other = (Tuple) obj;
				return Arrays.equals(objects, other.objects);
			}
			return false;
		}

		@Override
		public int hashCode() {
			return Arrays.hashCode(objects);
		}
	}

	// We can't really use a single client. Clients need to be stopped
	// properly, and we don't really know when to do that. Instead we use
	// a dedicated SshClient instance per session. We need a bit of caching to
	// avoid re-loading the ssh config and keys repeatedly.

	@Override
	public SshdSession getSession(URIish uri,
			CredentialsProvider credentialsProvider, FS fs, int tms)
			throws TransportException {
		SshdSession session = null;
		try {
			session = new SshdSession(uri, () -> {
				File home = getHomeDirectory();
				if (home == null) {
					// Always use the detected filesystem for the user home!
					// It makes no sense to have different "user home"
					// directories depending on what file system a repository
					// is.
					home = FS.DETECTED.userHome();
				}
				File sshDir = getSshDirectory();
				if (sshDir == null) {
					sshDir = new File(home, SshConstants.SSH_DIR);
				}
				HostConfigEntryResolver configFile = getHostConfigEntryResolver(
						home, sshDir);
				KeyIdentityProvider defaultKeysProvider = toKeyIdentityProvider(
						getDefaultKeys(sshDir));
				KeyPasswordProvider passphrases = createKeyPasswordProvider(
						credentialsProvider);
				SshClient client = ClientBuilder.builder()
						.factory(JGitSshClient::new)
						.filePasswordProvider(
								createFilePasswordProvider(passphrases))
						.hostConfigEntryResolver(configFile)
						.serverKeyVerifier(new JGitServerKeyVerifier(
								getServerKeyDatabase(home, sshDir)))
						.compressionFactories(
								new ArrayList<>(BuiltinCompressions.VALUES))
						.build();
				client.setUserInteraction(
						new JGitUserInteraction(credentialsProvider));
				client.setUserAuthFactories(getUserAuthFactories());
				client.setKeyIdentityProvider(defaultKeysProvider);
				// JGit-specific things:
				JGitSshClient jgitClient = (JGitSshClient) client;
				jgitClient.setKeyCache(getKeyCache());
				jgitClient.setCredentialsProvider(credentialsProvider);
				jgitClient.setProxyDatabase(proxies);
				String defaultAuths = getDefaultPreferredAuthentications();
				if (defaultAuths != null) {
					jgitClient.setAttribute(
							JGitSshClient.PREFERRED_AUTHENTICATIONS,
							defaultAuths);
				}
				// Other things?
				return client;
			});
			session.addCloseListener(s -> unregister(s));
			register(session);
			session.connect(Duration.ofMillis(tms));
			return session;
		} catch (Exception e) {
			unregister(session);
			throw new TransportException(uri, e.getMessage(), e);
		}
	}

	@Override
	public void close() {
		closing.set(true);
		boolean cleanKeys = false;
		synchronized (this) {
			cleanKeys = sessions.isEmpty();
		}
		if (cleanKeys) {
			KeyCache cache = getKeyCache();
			if (cache != null) {
				cache.close();
			}
		}
	}

	private void register(SshdSession newSession) throws IOException {
		if (newSession == null) {
			return;
		}
		if (closing.get()) {
			throw new IOException(SshdText.get().sshClosingDown);
		}
		synchronized (this) {
			sessions.add(newSession);
		}
	}

	private void unregister(SshdSession oldSession) {
		boolean cleanKeys = false;
		synchronized (this) {
			sessions.remove(oldSession);
			cleanKeys = closing.get() && sessions.isEmpty();
		}
		if (cleanKeys) {
			KeyCache cache = getKeyCache();
			if (cache != null) {
				cache.close();
			}
		}
	}

	/**
	 * Set a global directory to use as the user's home directory
	 *
	 * @param homeDir
	 *            to use
	 */
	public void setHomeDirectory(@NonNull File homeDir) {
		if (homeDir.isAbsolute()) {
			homeDirectory = homeDir;
		} else {
			homeDirectory = homeDir.getAbsoluteFile();
		}
	}

	/**
	 * Retrieves the global user home directory
	 *
	 * @return the directory, or {@code null} if not set
	 */
	public File getHomeDirectory() {
		return homeDirectory;
	}

	/**
	 * Set a global directory to use as the .ssh directory
	 *
	 * @param sshDir
	 *            to use
	 */
	public void setSshDirectory(@NonNull File sshDir) {
		if (sshDir.isAbsolute()) {
			sshDirectory = sshDir;
		} else {
			sshDirectory = sshDir.getAbsoluteFile();
		}
	}

	/**
	 * Retrieves the global .ssh directory
	 *
	 * @return the directory, or {@code null} if not set
	 */
	public File getSshDirectory() {
		return sshDirectory;
	}

	/**
	 * Obtain a {@link HostConfigEntryResolver} to read the ssh config file and
	 * to determine host entries for connections.
	 *
	 * @param homeDir
	 *            home directory to use for ~ replacement
	 * @param sshDir
	 *            to use for looking for the config file
	 * @return the resolver
	 */
	@NonNull
	private HostConfigEntryResolver getHostConfigEntryResolver(
			@NonNull File homeDir, @NonNull File sshDir) {
		return defaultHostConfigEntryResolver.computeIfAbsent(
				new Tuple(new Object[] { homeDir, sshDir }),
				t -> new JGitSshConfig(createSshConfigStore(homeDir,
						getSshConfig(sshDir), getLocalUserName())));
	}

	/**
	 * Determines the ssh config file. The default implementation returns
	 * ~/.ssh/config. If the file does not exist and is created later it will be
	 * picked up. To not use a config file at all, return {@code null}.
	 *
	 * @param sshDir
	 *            representing ~/.ssh/
	 * @return the file (need not exist), or {@code null} if no config file
	 *         shall be used
	 * @since 5.5
	 */
	protected File getSshConfig(@NonNull File sshDir) {
		return new File(sshDir, SshConstants.CONFIG);
	}

	/**
	 * Obtains a {@link SshConfigStore}, or {@code null} if not SSH config is to
	 * be used. The default implementation returns {@code null} if
	 * {@code configFile == null} and otherwise an OpenSSH-compatible store
	 * reading host entries from the given file.
	 *
	 * @param homeDir
	 *            may be used for ~-replacements by the returned config store
	 * @param configFile
	 *            to use, or {@code null} if none
	 * @param localUserName
	 *            user name of the current user on the local OS
	 * @return A {@link SshConfigStore}, or {@code null} if none is to be used
	 *
	 * @since 5.8
	 */
	protected SshConfigStore createSshConfigStore(@NonNull File homeDir,
			File configFile, String localUserName) {
		return configFile == null ? null
				: new OpenSshConfigFile(homeDir, configFile, localUserName);
	}

	/**
	 * Obtains a {@link ServerKeyDatabase} to verify server host keys. The
	 * default implementation returns a {@link ServerKeyDatabase} that
	 * recognizes the two openssh standard files {@code ~/.ssh/known_hosts} and
	 * {@code ~/.ssh/known_hosts2} as well as any files configured via the
	 * {@code UserKnownHostsFile} option in the ssh config file.
	 *
	 * @param homeDir
	 *            home directory to use for ~ replacement
	 * @param sshDir
	 *            representing ~/.ssh/
	 * @return the {@link ServerKeyDatabase}
	 * @since 5.5
	 */
	@NonNull
	protected ServerKeyDatabase getServerKeyDatabase(@NonNull File homeDir,
			@NonNull File sshDir) {
		return defaultServerKeyDatabase.computeIfAbsent(
				new Tuple(new Object[] { homeDir, sshDir }),
				t -> createServerKeyDatabase(homeDir, sshDir));

	}

	/**
	 * Creates a {@link ServerKeyDatabase} to verify server host keys. The
	 * default implementation returns a {@link ServerKeyDatabase} that
	 * recognizes the two openssh standard files {@code ~/.ssh/known_hosts} and
	 * {@code ~/.ssh/known_hosts2} as well as any files configured via the
	 * {@code UserKnownHostsFile} option in the ssh config file.
	 *
	 * @param homeDir
	 *            home directory to use for ~ replacement
	 * @param sshDir
	 *            representing ~/.ssh/
	 * @return the {@link ServerKeyDatabase}
	 * @since 5.8
	 */
	@NonNull
	protected ServerKeyDatabase createServerKeyDatabase(@NonNull File homeDir,
			@NonNull File sshDir) {
		return new OpenSshServerKeyDatabase(true,
				getDefaultKnownHostsFiles(sshDir));
	}

	/**
	 * Gets the list of default user known hosts files. The default returns
	 * ~/.ssh/known_hosts and ~/.ssh/known_hosts2. The ssh config
	 * {@code UserKnownHostsFile} overrides this default.
	 *
	 * @param sshDir
	 * @return the possibly empty list of default known host file paths.
	 */
	@NonNull
	protected List<Path> getDefaultKnownHostsFiles(@NonNull File sshDir) {
		return Arrays.asList(sshDir.toPath().resolve(SshConstants.KNOWN_HOSTS),
				sshDir.toPath().resolve(SshConstants.KNOWN_HOSTS + '2'));
	}

	/**
	 * 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
	 *            to look in for keys
	 * @return an {@link Iterable} over the default keys
	 * @since 5.3
	 */
	@NonNull
	protected Iterable<KeyPair> getDefaultKeys(@NonNull File sshDir) {
		List<Path> defaultIdentities = getDefaultIdentities(sshDir);
		return defaultKeys.computeIfAbsent(
				new Tuple(defaultIdentities.toArray(new Path[0])),
				t -> new CachingKeyPairProvider(defaultIdentities,
						getKeyCache()));
	}

	/**
	 * Converts an {@link Iterable} of {link KeyPair}s into a
	 * {@link KeyIdentityProvider}.
	 *
	 * @param keys
	 *            to provide via the returned {@link KeyIdentityProvider}
	 * @return a {@link KeyIdentityProvider} that provides the given
	 *         {@code keys}
	 */
	private KeyIdentityProvider toKeyIdentityProvider(Iterable<KeyPair> keys) {
		if (keys instanceof KeyIdentityProvider) {
			return (KeyIdentityProvider) keys;
		}
		return (session) -> keys;
	}

	/**
	 * Gets a list of default identities, i.e., private key files that shall
	 * always be tried for public key authentication. Typically those are
	 * ~/.ssh/id_dsa, ~/.ssh/id_rsa, and so on. The default implementation
	 * returns the files defined in {@link SshConstants#DEFAULT_IDENTITIES}.
	 *
	 * @param sshDir
	 *            the directory that represents ~/.ssh/
	 * @return a possibly empty list of paths containing default identities
	 *         (private keys)
	 */
	@NonNull
	protected List<Path> getDefaultIdentities(@NonNull File sshDir) {
		return Arrays
				.asList(SshConstants.DEFAULT_IDENTITIES).stream()
				.map(s -> new File(sshDir, s).toPath()).filter(Files::exists)
				.collect(Collectors.toList());
	}

	/**
	 * Obtains the {@link KeyCache} to use to cache loaded keys.
	 *
	 * @return the {@link KeyCache}, or {@code null} if none.
	 */
	protected final KeyCache getKeyCache() {
		return keyCache;
	}

	/**
	 * Creates a {@link KeyPasswordProvider} for a new session.
	 *
	 * @param provider
	 *            the {@link CredentialsProvider} to delegate to for user
	 *            interactions
	 * @return a new {@link KeyPasswordProvider}
	 */
	@NonNull
	protected KeyPasswordProvider createKeyPasswordProvider(
			CredentialsProvider provider) {
		return new IdentityPasswordProvider(provider);
	}

	/**
	 * Creates a {@link FilePasswordProvider} for a new session.
	 *
	 * @param provider
	 *            the {@link KeyPasswordProvider} to delegate to
	 * @return a new {@link FilePasswordProvider}
	 */
	@NonNull
	private FilePasswordProvider createFilePasswordProvider(
			KeyPasswordProvider provider) {
		return new PasswordProviderWrapper(provider);
	}

	/**
	 * Gets the user authentication mechanisms (or rather, factories for them).
	 * By default this returns gssapi-with-mic, public-key, password, and
	 * keyboard-interactive, in that order. The order is only significant if the
	 * ssh config does <em>not</em> set {@code PreferredAuthentications}; if it
	 * is set, the order defined there will be taken.
	 *
	 * @return the non-empty list of factories.
	 */
	@NonNull
	private List<UserAuthFactory> getUserAuthFactories() {
		// About the order of password and keyboard-interactive, see upstream
		// bug https://issues.apache.org/jira/projects/SSHD/issues/SSHD-866 .
		// Password auth doesn't have this problem.
		return Collections.unmodifiableList(
				Arrays.asList(GssApiWithMicAuthFactory.INSTANCE,
						UserAuthPublicKeyFactory.INSTANCE,
						JGitPasswordAuthFactory.INSTANCE,
						UserAuthKeyboardInteractiveFactory.INSTANCE));
	}

	/**
	 * Gets the list of default preferred authentication mechanisms. If
	 * {@code null} is returned the openssh default list will be in effect. If
	 * the ssh config defines {@code PreferredAuthentications} the value from
	 * the ssh config takes precedence.
	 *
	 * @return a comma-separated list of mechanism names, or {@code null} if
	 *         none
	 */
	protected String getDefaultPreferredAuthentications() {
		return null;
	}
}
