1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.common.util.secure;
17
18 import java.io.File;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.Properties;
24
25 import org.apache.commons.io.FileUtils;
26 import org.apache.commons.lang3.StringUtils;
27 import org.kuali.common.util.LocationUtils;
28 import org.kuali.common.util.PropertyUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import org.springframework.util.Assert;
32
33 public class SSHUtils {
34
35 private static final Logger logger = LoggerFactory.getLogger(SSHUtils.class);
36
37 private static final String FS = File.separator;
38 private static final String IDENTITY_FILE = "IdentityFile";
39 private static final String TILDE = "~";
40 private static final String USER_HOME = FileUtils.getUserDirectoryPath();
41 private static final String SSHDIR = USER_HOME + FS + ".ssh";
42 private static final String IDENTITY = SSHDIR + FS + "identity";
43 private static final String ID_DSA = SSHDIR + FS + "id_dsa";
44 private static final String ID_RSA = SSHDIR + FS + "id_rsa";
45 private static final String ID_ECDSA = SSHDIR + FS + "id_ecdsa";
46 private static final int PORT_NUMBER_LOWEST = 1;
47 private static final int PORT_NUMBER_HIGHEST = 65535;
48
49 public static final String STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
50 public static final String NO = "no";
51 public static final List<String> PRIVATE_KEY_DEFAULTS = Arrays.asList(IDENTITY, ID_DSA, ID_RSA, ID_ECDSA);
52 public static final File DEFAULT_CONFIG_FILE = new File(SSHDIR + FS + "config");
53 public static final int DEFAULT_PORT = 22;
54 public static final File DEFAULT_KNOWN_HOSTS = new File(SSHDIR + FS + "known_hosts");
55
56
57
58
59 public static final boolean isValidPort(int port) {
60 return port >= PORT_NUMBER_LOWEST && port <= PORT_NUMBER_HIGHEST;
61 }
62
63 public static final void addPort(List<String> args, String portOption, int port, int defaultPort) {
64 if (port != defaultPort) {
65 Assert.isTrue(SSHUtils.isValidPort(port));
66 logger.debug("port={}", port);
67 args.add(portOption);
68 args.add(Integer.toString(port));
69 }
70 }
71
72 public static final void addOptions(List<String> args, Properties options) {
73 if (options == null) {
74 return;
75 }
76 List<String> keys = PropertyUtils.getSortedKeys(options);
77 for (String key : keys) {
78 String value = options.getProperty(key);
79 logger.debug("Adding option [-o {}={}]", key, value);
80 args.add("-o");
81 args.add(key + "=" + value);
82 }
83 }
84
85 public static final void addConfigFile(List<String> args, File configFile, File defaultConfigFile) {
86 if (configFile == null) {
87 return;
88 }
89 String defaultPath = LocationUtils.getCanonicalPath(defaultConfigFile);
90 String configFilePath = LocationUtils.getCanonicalPath(configFile);
91 if (!StringUtils.equals(defaultPath, configFilePath)) {
92 logger.debug("SSH config=[{}]", configFilePath);
93 args.add("-F");
94 args.add(configFilePath);
95 }
96 }
97
98 public static final void addIdentityFile(List<String> args, File identityFile) {
99 if (identityFile != null) {
100 String path = LocationUtils.getCanonicalPath(identityFile);
101 logger.debug("Private key=[{}]", path);
102 args.add("-i");
103 args.add(path);
104 }
105 }
106
107
108
109
110
111 public static final List<File> getPrivateKeys(File config) {
112 List<String> paths = getFilenames(config);
113 return getExistingAndReadable(paths);
114 }
115
116
117
118
119
120 public static final List<File> getDefaultPrivateKeys() {
121 return getPrivateKeys(DEFAULT_CONFIG_FILE);
122 }
123
124 public static final Properties getDefaultOptions() {
125 Properties options = new Properties();
126 options.setProperty(STRICT_HOST_KEY_CHECKING, NO);
127 return options;
128 }
129
130 public static final List<File> getExistingAndReadable(List<String> filenames) {
131 List<File> files = new ArrayList<File>();
132 for (String filename : filenames) {
133 File file = new File(filename);
134 if (file.exists() && file.canRead()) {
135 files.add(file);
136 }
137 }
138 return files;
139 }
140
141 public static final List<String> getFilenames(File config) {
142 if (config.exists() && config.canRead()) {
143 List<String> lines = LocationUtils.readLines(config);
144 List<String> identityFileLines = getIdentityFileLines(lines);
145 return getFilenames(identityFileLines);
146 } else {
147 return Collections.<String> emptyList();
148 }
149 }
150
151 public static final List<String> getIdentityFileLines(List<String> lines) {
152 List<String> identityFileLines = new ArrayList<String>();
153 for (String line : lines) {
154 String trimmed = StringUtils.trim(line);
155 if (StringUtils.startsWith(trimmed, IDENTITY_FILE)) {
156 identityFileLines.add(trimmed);
157 }
158 }
159 return identityFileLines;
160 }
161
162 public static final List<String> getFilenames(List<String> identityFileLines) {
163 List<String> filenames = new ArrayList<String>();
164 for (String identityFileLine : identityFileLines) {
165 String originalFilename = StringUtils.substring(identityFileLine, IDENTITY_FILE.length());
166 String resolvedFilename = StringUtils.replace(originalFilename, TILDE, USER_HOME);
167 String trimmed = StringUtils.trim(resolvedFilename);
168 filenames.add(trimmed);
169 }
170 return filenames;
171 }
172 }