001/**
002 * Copyright 2010-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.common.util.secure.channel;
017
018import java.io.File;
019import java.util.ArrayList;
020import java.util.Arrays;
021import java.util.Collections;
022import java.util.List;
023import java.util.Properties;
024
025import org.apache.commons.io.FileUtils;
026import org.apache.commons.lang3.StringUtils;
027import org.kuali.common.util.LocationUtils;
028import org.kuali.common.util.PropertyUtils;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031import org.springframework.util.Assert;
032
033/**
034 * @deprecated
035 */
036@Deprecated
037public class SSHUtils {
038
039        private static final Logger logger = LoggerFactory.getLogger(SSHUtils.class);
040
041        private static final String FS = File.separator;
042        private static final String IDENTITY_FILE = "IdentityFile";
043        private static final String TILDE = "~";
044        private static final String USER_HOME = FileUtils.getUserDirectoryPath();
045        private static final String SSHDIR = USER_HOME + FS + ".ssh";
046        private static final String IDENTITY = SSHDIR + FS + "identity";
047        private static final String ID_DSA = SSHDIR + FS + "id_dsa";
048        private static final String ID_RSA = SSHDIR + FS + "id_rsa";
049        private static final String ID_ECDSA = SSHDIR + FS + "id_ecdsa";
050        private static final int PORT_NUMBER_LOWEST = 1;
051        private static final int PORT_NUMBER_HIGHEST = 65535;
052
053        public static final String STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
054        public static final String NO = "no";
055        public static final List<String> PRIVATE_KEY_DEFAULTS = Arrays.asList(IDENTITY, ID_DSA, ID_RSA, ID_ECDSA);
056        public static final File DEFAULT_CONFIG_FILE = new File(SSHDIR + FS + "config");
057        public static final int DEFAULT_PORT = 22;
058        public static final File DEFAULT_KNOWN_HOSTS = new File(SSHDIR + FS + "known_hosts");
059
060        /**
061         * Return true if <code>port &gt;= 1</code> and <code>port &lt;= 65535</code>, false otherwise.
062         */
063        public static final boolean isValidPort(int port) {
064                return port >= PORT_NUMBER_LOWEST && port <= PORT_NUMBER_HIGHEST;
065        }
066
067        public static final void addPort(List<String> args, String portOption, int port, int defaultPort) {
068                if (port != defaultPort) {
069                        Assert.isTrue(SSHUtils.isValidPort(port));
070                        logger.debug("port={}", port);
071                        args.add(portOption);
072                        args.add(Integer.toString(port));
073                }
074        }
075
076        public static final void addOptions(List<String> args, Properties options) {
077                if (options == null) {
078                        return;
079                }
080                List<String> keys = PropertyUtils.getSortedKeys(options);
081                for (String key : keys) {
082                        String value = options.getProperty(key);
083                        logger.debug("Adding option [-o {}={}]", key, value);
084                        args.add("-o");
085                        args.add(key + "=" + value);
086                }
087        }
088
089        public static final void addConfigFile(List<String> args, File configFile, File defaultConfigFile) {
090                if (configFile == null) {
091                        return;
092                }
093                String defaultPath = LocationUtils.getCanonicalPath(defaultConfigFile);
094                String configFilePath = LocationUtils.getCanonicalPath(configFile);
095                if (!StringUtils.equals(defaultPath, configFilePath)) {
096                        logger.debug("SSH config=[{}]", configFilePath);
097                        args.add("-F");
098                        args.add(configFilePath);
099                }
100        }
101
102        public static final void addIdentityFile(List<String> args, File identityFile) {
103                if (identityFile != null) {
104                        String path = LocationUtils.getCanonicalPath(identityFile);
105                        logger.debug("Private key=[{}]", path);
106                        args.add("-i");
107                        args.add(path);
108                }
109        }
110
111        /**
112         * Return a non-null list containing any private keys found by examining default private key locations in <code>~/.ssh</code> and
113         * parsing <code>config</code>. Any files returned by this method are guaranteed to exist and be readable.
114         */
115        public static final List<File> getPrivateKeys(File config) {
116                List<String> paths = getFilenames(config);
117                return getExistingAndReadable(paths);
118        }
119
120        /**
121         * Return a non-null list containing any private keys found by examining default private key locations in <code>~/.ssh</code> and
122         * parsing <code>~/.ssh/config</code>. Any files returned by this method are guaranteed to exist and be readable.
123         */
124        public static final List<File> getDefaultPrivateKeys() {
125                return getPrivateKeys(DEFAULT_CONFIG_FILE);
126        }
127
128        public static final Properties getDefaultOptions() {
129                Properties options = new Properties();
130                options.setProperty(STRICT_HOST_KEY_CHECKING, NO);
131                return options;
132        }
133
134        public static final List<File> getExistingAndReadable(List<String> filenames) {
135                List<File> files = new ArrayList<File>();
136                for (String filename : filenames) {
137                        File file = new File(filename);
138                        if (file.exists() && file.canRead()) {
139                                files.add(file);
140                        }
141                }
142                return files;
143        }
144
145        public static final List<String> getFilenames(File config) {
146                if (config.exists() && config.canRead()) {
147                        List<String> lines = LocationUtils.readLines(config);
148                        List<String> identityFileLines = getIdentityFileLines(lines);
149                        return getFilenames(identityFileLines);
150                } else {
151                        return Collections.<String> emptyList();
152                }
153        }
154
155        public static final List<String> getIdentityFileLines(List<String> lines) {
156                List<String> identityFileLines = new ArrayList<String>();
157                for (String line : lines) {
158                        String trimmed = StringUtils.trim(line);
159                        if (StringUtils.startsWith(trimmed, IDENTITY_FILE)) {
160                                identityFileLines.add(trimmed);
161                        }
162                }
163                return identityFileLines;
164        }
165
166        public static final List<String> getFilenames(List<String> identityFileLines) {
167                List<String> filenames = new ArrayList<String>();
168                for (String identityFileLine : identityFileLines) {
169                        String originalFilename = StringUtils.substring(identityFileLine, IDENTITY_FILE.length());
170                        String resolvedFilename = StringUtils.replace(originalFilename, TILDE, USER_HOME);
171                        String trimmed = StringUtils.trim(resolvedFilename);
172                        filenames.add(trimmed);
173                }
174                return filenames;
175        }
176}