diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java | 435 |
1 files changed, 0 insertions, 435 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java deleted file mode 100644 index 38f3a2ac77..0000000000 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2008, 2014, Google Inc. - * and other copyright owners as documented in the project's IP log. - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.eclipse.jgit.transport; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.jgit.errors.InvalidPatternException; -import org.eclipse.jgit.fnmatch.FileNameMatcher; -import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.util.FS; -import org.eclipse.jgit.util.StringUtils; - -/** - * Simple configuration parser for the OpenSSH ~/.ssh/config file. - * <p> - * Since JSch does not (currently) have the ability to parse an OpenSSH - * configuration file this is a simple parser to read that file and make the - * critical options available to {@link SshSessionFactory}. - */ -public class OpenSshConfig { - /** IANA assigned port number for SSH. */ - static final int SSH_PORT = 22; - - /** - * Obtain the user's configuration data. - * <p> - * The configuration file is always returned to the caller, even if no file - * exists in the user's home directory at the time the call was made. Lookup - * requests are cached and are automatically updated if the user modifies - * the configuration file since the last time it was cached. - * - * @param fs - * the file system abstraction which will be necessary to - * perform certain file system operations. - * @return a caching reader of the user's configuration file. - */ - public static OpenSshConfig get(FS fs) { - File home = fs.userHome(); - if (home == null) - home = new File(".").getAbsoluteFile(); //$NON-NLS-1$ - - final File config = new File(new File(home, ".ssh"), Constants.CONFIG); //$NON-NLS-1$ - final OpenSshConfig osc = new OpenSshConfig(home, config); - osc.refresh(); - return osc; - } - - /** The user's home directory, as key files may be relative to here. */ - private final File home; - - /** The .ssh/config file we read and monitor for updates. */ - private final File configFile; - - /** Modification time of {@link #configFile} when {@link #hosts} loaded. */ - private long lastModified; - - /** Cached entries read out of the configuration file. */ - private Map<String, Host> hosts; - - OpenSshConfig(final File h, final File cfg) { - home = h; - configFile = cfg; - hosts = Collections.emptyMap(); - } - - /** - * Locate the configuration for a specific host request. - * - * @param hostName - * the name the user has supplied to the SSH tool. This may be a - * real host name, or it may just be a "Host" block in the - * configuration file. - * @return r configuration for the requested name. Never null. - */ - public Host lookup(final String hostName) { - final Map<String, Host> cache = refresh(); - Host h = cache.get(hostName); - if (h == null) - h = new Host(); - if (h.patternsApplied) - return h; - - for (final Map.Entry<String, Host> e : cache.entrySet()) { - if (!isHostPattern(e.getKey())) - continue; - if (!isHostMatch(e.getKey(), hostName)) - continue; - h.copyFrom(e.getValue()); - } - - if (h.hostName == null) - h.hostName = hostName; - if (h.user == null) - h.user = OpenSshConfig.userName(); - if (h.port == 0) - h.port = OpenSshConfig.SSH_PORT; - if (h.connectionAttempts == 0) - h.connectionAttempts = 1; - h.patternsApplied = true; - return h; - } - - private synchronized Map<String, Host> refresh() { - final long mtime = configFile.lastModified(); - if (mtime != lastModified) { - try { - final FileInputStream in = new FileInputStream(configFile); - try { - hosts = parse(in); - } finally { - in.close(); - } - } catch (FileNotFoundException none) { - hosts = Collections.emptyMap(); - } catch (IOException err) { - hosts = Collections.emptyMap(); - } - lastModified = mtime; - } - return hosts; - } - - private Map<String, Host> parse(final InputStream in) throws IOException { - final Map<String, Host> m = new LinkedHashMap<String, Host>(); - final BufferedReader br = new BufferedReader(new InputStreamReader(in)); - final List<Host> current = new ArrayList<Host>(4); - String line; - - while ((line = br.readLine()) != null) { - line = line.trim(); - if (line.length() == 0 || line.startsWith("#")) //$NON-NLS-1$ - continue; - - final String[] parts = line.split("[ \t]*[= \t]", 2); //$NON-NLS-1$ - final String keyword = parts[0].trim(); - final String argValue = parts[1].trim(); - - if (StringUtils.equalsIgnoreCase("Host", keyword)) { //$NON-NLS-1$ - current.clear(); - for (final String pattern : argValue.split("[ \t]")) { //$NON-NLS-1$ - final String name = dequote(pattern); - Host c = m.get(name); - if (c == null) { - c = new Host(); - m.put(name, c); - } - current.add(c); - } - continue; - } - - if (current.isEmpty()) { - // We received an option outside of a Host block. We - // don't know who this should match against, so skip. - // - continue; - } - - if (StringUtils.equalsIgnoreCase("HostName", keyword)) { //$NON-NLS-1$ - for (final Host c : current) - if (c.hostName == null) - c.hostName = dequote(argValue); - } else if (StringUtils.equalsIgnoreCase("User", keyword)) { //$NON-NLS-1$ - for (final Host c : current) - if (c.user == null) - c.user = dequote(argValue); - } else if (StringUtils.equalsIgnoreCase("Port", keyword)) { //$NON-NLS-1$ - try { - final int port = Integer.parseInt(dequote(argValue)); - for (final Host c : current) - if (c.port == 0) - c.port = port; - } catch (NumberFormatException nfe) { - // Bad port number. Don't set it. - } - } else if (StringUtils.equalsIgnoreCase("IdentityFile", keyword)) { //$NON-NLS-1$ - for (final Host c : current) - if (c.identityFile == null) - c.identityFile = toFile(dequote(argValue)); - } else if (StringUtils.equalsIgnoreCase( - "PreferredAuthentications", keyword)) { //$NON-NLS-1$ - for (final Host c : current) - if (c.preferredAuthentications == null) - c.preferredAuthentications = nows(dequote(argValue)); - } else if (StringUtils.equalsIgnoreCase("BatchMode", keyword)) { //$NON-NLS-1$ - for (final Host c : current) - if (c.batchMode == null) - c.batchMode = yesno(dequote(argValue)); - } else if (StringUtils.equalsIgnoreCase( - "StrictHostKeyChecking", keyword)) { //$NON-NLS-1$ - String value = dequote(argValue); - for (final Host c : current) - if (c.strictHostKeyChecking == null) - c.strictHostKeyChecking = value; - } else if (StringUtils.equalsIgnoreCase( - "ConnectionAttempts", keyword)) { //$NON-NLS-1$ - try { - final int connectionAttempts = Integer.parseInt(dequote(argValue)); - if (connectionAttempts > 0) { - for (final Host c : current) - if (c.connectionAttempts == 0) - c.connectionAttempts = connectionAttempts; - } - } catch (NumberFormatException nfe) { - // ignore bad values - } - } - } - - return m; - } - - private static boolean isHostPattern(final String s) { - return s.indexOf('*') >= 0 || s.indexOf('?') >= 0; - } - - private static boolean isHostMatch(final String pattern, final String name) { - final FileNameMatcher fn; - try { - fn = new FileNameMatcher(pattern, null); - } catch (InvalidPatternException e) { - return false; - } - fn.append(name); - return fn.isMatch(); - } - - private static String dequote(final String value) { - if (value.startsWith("\"") && value.endsWith("\"")) //$NON-NLS-1$ //$NON-NLS-2$ - return value.substring(1, value.length() - 1); - return value; - } - - private static String nows(final String value) { - final StringBuilder b = new StringBuilder(); - for (int i = 0; i < value.length(); i++) { - if (!Character.isSpaceChar(value.charAt(i))) - b.append(value.charAt(i)); - } - return b.toString(); - } - - private static Boolean yesno(final String value) { - if (StringUtils.equalsIgnoreCase("yes", value)) //$NON-NLS-1$ - return Boolean.TRUE; - return Boolean.FALSE; - } - - private File toFile(final String path) { - if (path.startsWith("~/")) //$NON-NLS-1$ - return new File(home, path.substring(2)); - File ret = new File(path); - if (ret.isAbsolute()) - return ret; - return new File(home, path); - } - - static String userName() { - return AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return System.getProperty("user.name"); //$NON-NLS-1$ - } - }); - } - - /** - * Configuration of one "Host" block in the configuration file. - * <p> - * If returned from {@link OpenSshConfig#lookup(String)} some or all of the - * properties may not be populated. The properties which are not populated - * should be defaulted by the caller. - * <p> - * When returned from {@link OpenSshConfig#lookup(String)} any wildcard - * entries which appear later in the configuration file will have been - * already merged into this block. - */ - public static class Host { - boolean patternsApplied; - - String hostName; - - int port; - - File identityFile; - - String user; - - String preferredAuthentications; - - Boolean batchMode; - - String strictHostKeyChecking; - - int connectionAttempts; - - void copyFrom(final Host src) { - if (hostName == null) - hostName = src.hostName; - if (port == 0) - port = src.port; - if (identityFile == null) - identityFile = src.identityFile; - if (user == null) - user = src.user; - if (preferredAuthentications == null) - preferredAuthentications = src.preferredAuthentications; - if (batchMode == null) - batchMode = src.batchMode; - if (strictHostKeyChecking == null) - strictHostKeyChecking = src.strictHostKeyChecking; - if (connectionAttempts == 0) - connectionAttempts = src.connectionAttempts; - } - - /** - * @return the value StrictHostKeyChecking property, the valid values - * are "yes" (unknown hosts are not accepted), "no" (unknown - * hosts are always accepted), and "ask" (user should be asked - * before accepting the host) - */ - public String getStrictHostKeyChecking() { - return strictHostKeyChecking; - } - - /** - * @return the real IP address or host name to connect to; never null. - */ - public String getHostName() { - return hostName; - } - - /** - * @return the real port number to connect to; never 0. - */ - public int getPort() { - return port; - } - - /** - * @return path of the private key file to use for authentication; null - * if the caller should use default authentication strategies. - */ - public File getIdentityFile() { - return identityFile; - } - - /** - * @return the real user name to connect as; never null. - */ - public String getUser() { - return user; - } - - /** - * @return the preferred authentication methods, separated by commas if - * more than one authentication method is preferred. - */ - public String getPreferredAuthentications() { - return preferredAuthentications; - } - - /** - * @return true if batch (non-interactive) mode is preferred for this - * host connection. - */ - public boolean isBatchMode() { - return batchMode != null && batchMode.booleanValue(); - } - - /** - * @return the number of tries (one per second) to connect before - * exiting. The argument must be an integer. This may be useful - * in scripts if the connection sometimes fails. The default is - * 1. - * @since 3.4 - */ - public int getConnectionAttempts() { - return connectionAttempts; - } - } -} |