/*
 * Copyright (C) 2018, Sasa Zivkov <sasa.zivkov@sap.com>
 * Copyright (C) 2016, Mark Ingram <markdingram@gmail.com>
 * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
 * Copyright (C) 2008-2009, Google Inc.
 * Copyright (C) 2009, Google, Inc.
 * Copyright (C) 2009, JetBrains s.r.o.
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> 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;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.ConfigRepository;
import com.jcraft.jsch.ConfigRepository.Config;
import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.HostKeyRepository;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * The base session factory that loads known hosts and private keys from
 * <code>$HOME/.ssh</code>.
 * <p>
 * This is the default implementation used by JGit and provides most of the
 * compatibility necessary to match OpenSSH, a popular implementation of SSH
 * used by C Git.
 * <p>
 * The factory does not provide UI behavior. Override the method
 * {@link #configure(org.eclipse.jgit.transport.OpenSshConfig.Host, Session)} to
 * supply appropriate {@link com.jcraft.jsch.UserInfo} to the session.
 */
public abstract class JschConfigSessionFactory extends SshSessionFactory {

	private static final Logger LOG = LoggerFactory
			.getLogger(JschConfigSessionFactory.class);

	/**
	 * We use different Jsch instances for hosts that have an IdentityFile
	 * configured in ~/.ssh/config. Jsch by default would cache decrypted keys
	 * only per session, which results in repeated password prompts. Using
	 * different Jsch instances, we can cache the keys on these instances so
	 * that they will be re-used for successive sessions, and thus the user is
	 * prompted for a key password only once while Eclipse runs.
	 */
	private final Map<String, JSch> byIdentityFile = new HashMap<>();

	private JSch defaultJSch;

	private OpenSshConfig config;

	/** {@inheritDoc} */
	@Override
	public synchronized RemoteSession getSession(URIish uri,
			CredentialsProvider credentialsProvider, FS fs, int tms)
			throws TransportException {

		String user = uri.getUser();
		final String pass = uri.getPass();
		String host = uri.getHost();
		int port = uri.getPort();

		try {
			if (config == null)
				config = OpenSshConfig.get(fs);

			final OpenSshConfig.Host hc = config.lookup(host);
			if (port <= 0)
				port = hc.getPort();
			if (user == null)
				user = hc.getUser();

			Session session = createSession(credentialsProvider, fs, user,
					pass, host, port, hc);

			int retries = 0;
			while (!session.isConnected()) {
				try {
					retries++;
					session.connect(tms);
				} catch (JSchException e) {
					session.disconnect();
					session = null;
					// Make sure our known_hosts is not outdated
					knownHosts(getJSch(hc, fs), fs);

					if (isAuthenticationCanceled(e)) {
						throw e;
					} else if (isAuthenticationFailed(e)
							&& credentialsProvider != null) {
						// if authentication failed maybe credentials changed at
						// the remote end therefore reset credentials and retry
						if (retries < 3) {
							credentialsProvider.reset(uri);
							session = createSession(credentialsProvider, fs,
									user, pass, host, port, hc);
						} else
							throw e;
					} else if (retries >= hc.getConnectionAttempts()) {
						throw e;
					} else {
						try {
							Thread.sleep(1000);
							session = createSession(credentialsProvider, fs,
									user, pass, host, port, hc);
						} catch (InterruptedException e1) {
							throw new TransportException(
									JGitText.get().transportSSHRetryInterrupt,
									e1);
						}
					}
				}
			}

			return new JschSession(session, uri);

		} catch (JSchException je) {
			final Throwable c = je.getCause();
			if (c instanceof UnknownHostException) {
				throw new TransportException(uri, JGitText.get().unknownHost,
						je);
			}
			if (c instanceof ConnectException) {
				throw new TransportException(uri, c.getMessage(), je);
			}
			throw new TransportException(uri, je.getMessage(), je);
		}

	}

	private static boolean isAuthenticationFailed(JSchException e) {
		return e.getCause() == null && e.getMessage().equals("Auth fail"); //$NON-NLS-1$
	}

	private static boolean isAuthenticationCanceled(JSchException e) {
		return e.getCause() == null && e.getMessage().equals("Auth cancel"); //$NON-NLS-1$
	}

	// Package visibility for tests
	Session createSession(CredentialsProvider credentialsProvider,
			FS fs, String user, final String pass, String host, int port,
			final OpenSshConfig.Host hc) throws JSchException {
		final Session session = createSession(hc, user, host, port, fs);
		// Jsch will have overridden the explicit user by the one from the SSH
		// config file...
		setUserName(session, user);
		// Jsch will also have overridden the port.
		if (port > 0 && port != session.getPort()) {
			session.setPort(port);
		}
		// We retry already in getSession() method. JSch must not retry
		// on its own.
		session.setConfig("MaxAuthTries", "1"); //$NON-NLS-1$ //$NON-NLS-2$
		if (pass != null)
			session.setPassword(pass);
		final String strictHostKeyCheckingPolicy = hc
				.getStrictHostKeyChecking();
		if (strictHostKeyCheckingPolicy != null)
			session.setConfig("StrictHostKeyChecking", //$NON-NLS-1$
					strictHostKeyCheckingPolicy);
		final String pauth = hc.getPreferredAuthentications();
		if (pauth != null)
			session.setConfig("PreferredAuthentications", pauth); //$NON-NLS-1$
		if (credentialsProvider != null
				&& (!hc.isBatchMode() || !credentialsProvider.isInteractive())) {
			session.setUserInfo(new CredentialsProviderUserInfo(session,
					credentialsProvider));
		}
		safeConfig(session, hc.getConfig());
		if (hc.getConfig().getValue("HostKeyAlgorithms") == null) { //$NON-NLS-1$
			setPreferredKeyTypesOrder(session);
		}
		configure(hc, session);
		return session;
	}

	private void safeConfig(Session session, Config cfg) {
		// Ensure that Jsch checks all configured algorithms, not just its
		// built-in ones. Otherwise it may propose an algorithm for which it
		// doesn't have an implementation, and then run into an NPE if that
		// algorithm ends up being chosen.
		copyConfigValueToSession(session, cfg, "Ciphers", "CheckCiphers"); //$NON-NLS-1$ //$NON-NLS-2$
		copyConfigValueToSession(session, cfg, "KexAlgorithms", "CheckKexes"); //$NON-NLS-1$ //$NON-NLS-2$
		copyConfigValueToSession(session, cfg, "HostKeyAlgorithms", //$NON-NLS-1$
				"CheckSignatures"); //$NON-NLS-1$
	}

	private static void setPreferredKeyTypesOrder(Session session) {
		HostKeyRepository hkr = session.getHostKeyRepository();
		List<String> known = Stream.of(hkr.getHostKey(hostName(session), null))
				.map(HostKey::getType)
				.collect(toList());

		if (!known.isEmpty()) {
			String serverHostKey = "server_host_key"; //$NON-NLS-1$
			String current = session.getConfig(serverHostKey);
			if (current == null) {
				session.setConfig(serverHostKey, String.join(",", known)); //$NON-NLS-1$
				return;
			}

			String knownFirst = Stream.concat(
							known.stream(),
							Stream.of(current.split(",")) //$NON-NLS-1$
									.filter(s -> !known.contains(s)))
					.collect(joining(",")); //$NON-NLS-1$
			session.setConfig(serverHostKey, knownFirst);
		}
	}

	private static String hostName(Session s) {
		if (s.getPort() == SshConstants.SSH_DEFAULT_PORT) {
			return s.getHost();
		}
		return String.format("[%s]:%d", s.getHost(), //$NON-NLS-1$
				Integer.valueOf(s.getPort()));
	}

	private void copyConfigValueToSession(Session session, Config cfg,
			String from, String to) {
		String value = cfg.getValue(from);
		if (value != null) {
			session.setConfig(to, value);
		}
	}

	private void setUserName(Session session, String userName) {
		// Jsch 0.1.54 picks up the user name from the ssh config, even if an
		// explicit user name was given! We must correct that if ~/.ssh/config
		// has a different user name.
		if (userName == null || userName.isEmpty()
				|| userName.equals(session.getUserName())) {
			return;
		}
		try {
			Class<?>[] parameterTypes = { String.class };
			Method method = Session.class.getDeclaredMethod("setUserName", //$NON-NLS-1$
					parameterTypes);
			method.setAccessible(true);
			method.invoke(session, userName);
		} catch (NullPointerException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException
				| NoSuchMethodException | SecurityException e) {
			LOG.error(MessageFormat.format(JGitText.get().sshUserNameError,
					userName, session.getUserName()), e);
		}
	}

	/**
	 * Create a new remote session for the requested address.
	 *
	 * @param hc
	 *            host configuration
	 * @param user
	 *            login to authenticate as.
	 * @param host
	 *            server name to connect to.
	 * @param port
	 *            port number of the SSH daemon (typically 22).
	 * @param fs
	 *            the file system abstraction which will be necessary to
	 *            perform certain file system operations.
	 * @return new session instance, but otherwise unconfigured.
	 * @throws com.jcraft.jsch.JSchException
	 *             the session could not be created.
	 */
	protected Session createSession(final OpenSshConfig.Host hc,
			final String user, final String host, final int port, FS fs)
			throws JSchException {
		return getJSch(hc, fs).getSession(user, host, port);
	}

	/**
	 * Provide additional configuration for the JSch instance. This method could
	 * be overridden to supply a preferred
	 * {@link com.jcraft.jsch.IdentityRepository}.
	 *
	 * @param jsch
	 *            jsch instance
	 * @since 4.5
	 */
	protected void configureJSch(JSch jsch) {
		// No additional configuration required.
	}

	/**
	 * Provide additional configuration for the session based on the host
	 * information. This method could be used to supply
	 * {@link com.jcraft.jsch.UserInfo}.
	 *
	 * @param hc
	 *            host configuration
	 * @param session
	 *            session to configure
	 */
	protected abstract void configure(OpenSshConfig.Host hc, Session session);

	/**
	 * Obtain the JSch used to create new sessions.
	 *
	 * @param hc
	 *            host configuration
	 * @param fs
	 *            the file system abstraction which will be necessary to
	 *            perform certain file system operations.
	 * @return the JSch instance to use.
	 * @throws com.jcraft.jsch.JSchException
	 *             the user configuration could not be created.
	 */
	protected JSch getJSch(OpenSshConfig.Host hc, FS fs) throws JSchException {
		if (defaultJSch == null) {
			defaultJSch = createDefaultJSch(fs);
			if (defaultJSch.getConfigRepository() == null) {
				defaultJSch.setConfigRepository(
						new JschBugFixingConfigRepository(config));
			}
			for (Object name : defaultJSch.getIdentityNames())
				byIdentityFile.put((String) name, defaultJSch);
		}

		final File identityFile = hc.getIdentityFile();
		if (identityFile == null)
			return defaultJSch;

		final String identityKey = identityFile.getAbsolutePath();
		JSch jsch = byIdentityFile.get(identityKey);
		if (jsch == null) {
			jsch = new JSch();
			configureJSch(jsch);
			if (jsch.getConfigRepository() == null) {
				jsch.setConfigRepository(defaultJSch.getConfigRepository());
			}
			jsch.setHostKeyRepository(defaultJSch.getHostKeyRepository());
			jsch.addIdentity(identityKey);
			byIdentityFile.put(identityKey, jsch);
		}
		return jsch;
	}

	/**
	 * Create default instance of jsch
	 *
	 * @param fs
	 *            the file system abstraction which will be necessary to perform
	 *            certain file system operations.
	 * @return the new default JSch implementation.
	 * @throws com.jcraft.jsch.JSchException
	 *             known host keys cannot be loaded.
	 */
	protected JSch createDefaultJSch(FS fs) throws JSchException {
		final JSch jsch = new JSch();
		JSch.setConfig("ssh-rsa", JSch.getConfig("signature.rsa")); //$NON-NLS-1$ //$NON-NLS-2$
		JSch.setConfig("ssh-dss", JSch.getConfig("signature.dss")); //$NON-NLS-1$ //$NON-NLS-2$
		configureJSch(jsch);
		knownHosts(jsch, fs);
		identities(jsch, fs);
		return jsch;
	}

	private static void knownHosts(JSch sch, FS fs) throws JSchException {
		final File home = fs.userHome();
		if (home == null)
			return;
		final File known_hosts = new File(new File(home, ".ssh"), "known_hosts"); //$NON-NLS-1$ //$NON-NLS-2$
		try (FileInputStream in = new FileInputStream(known_hosts)) {
			sch.setKnownHosts(in);
		} catch (FileNotFoundException none) {
			// Oh well. They don't have a known hosts in home.
		} catch (IOException err) {
			// Oh well. They don't have a known hosts in home.
		}
	}

	private static void identities(JSch sch, FS fs) {
		final File home = fs.userHome();
		if (home == null)
			return;
		final File sshdir = new File(home, ".ssh"); //$NON-NLS-1$
		if (sshdir.isDirectory()) {
			loadIdentity(sch, new File(sshdir, "identity")); //$NON-NLS-1$
			loadIdentity(sch, new File(sshdir, "id_rsa")); //$NON-NLS-1$
			loadIdentity(sch, new File(sshdir, "id_dsa")); //$NON-NLS-1$
		}
	}

	private static void loadIdentity(JSch sch, File priv) {
		if (priv.isFile()) {
			try {
				sch.addIdentity(priv.getAbsolutePath());
			} catch (JSchException e) {
				// Instead, pretend the key doesn't exist.
			}
		}
	}

	private static class JschBugFixingConfigRepository
			implements ConfigRepository {

		private final ConfigRepository base;

		public JschBugFixingConfigRepository(ConfigRepository base) {
			this.base = base;
		}

		@Override
		public Config getConfig(String host) {
			return new JschBugFixingConfig(base.getConfig(host));
		}

		/**
		 * A {@link com.jcraft.jsch.ConfigRepository.Config} that transforms
		 * some values from the config file into the format Jsch 0.1.54 expects.
		 * This is a work-around for bugs in Jsch.
		 * <p>
		 * Additionally, this config hides the IdentityFile config entries from
		 * Jsch; we manage those ourselves. Otherwise Jsch would cache passwords
		 * (or rather, decrypted keys) only for a single session, resulting in
		 * multiple password prompts for user operations that use several Jsch
		 * sessions.
		 */
		private static class JschBugFixingConfig implements Config {

			private static final String[] NO_IDENTITIES = {};

			private final Config real;

			public JschBugFixingConfig(Config delegate) {
				real = delegate;
			}

			@Override
			public String getHostname() {
				return real.getHostname();
			}

			@Override
			public String getUser() {
				return real.getUser();
			}

			@Override
			public int getPort() {
				return real.getPort();
			}

			@Override
			public String getValue(String key) {
				String k = key.toUpperCase(Locale.ROOT);
				if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
					return null;
				}
				String result = real.getValue(key);
				if (result != null) {
					if ("SERVERALIVEINTERVAL".equals(k) //$NON-NLS-1$
							|| "CONNECTTIMEOUT".equals(k)) { //$NON-NLS-1$
						// These values are in seconds. Jsch 0.1.54 passes them
						// on as is to java.net.Socket.setSoTimeout(), which
						// expects milliseconds. So convert here to
						// milliseconds.
						try {
							int timeout = Integer.parseInt(result);
							result = Long.toString(
									TimeUnit.SECONDS.toMillis(timeout));
						} catch (NumberFormatException e) {
							// Ignore
						}
					}
				}
				return result;
			}

			@Override
			public String[] getValues(String key) {
				String k = key.toUpperCase(Locale.ROOT);
				if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
					return NO_IDENTITIES;
				}
				return real.getValues(key);
			}
		}
	}

	/**
	 * Set the {@link OpenSshConfig} to use. Intended for use in tests.
	 *
	 * @param config
	 *            to use
	 */
	synchronized void setConfig(OpenSshConfig config) {
		this.config = config;
	}
}
