1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.provider.sftp;
18
19 import com.jcraft.jsch.JSch;
20 import com.jcraft.jsch.JSchException;
21 import com.jcraft.jsch.Session;
22 import com.jcraft.jsch.UserInfo;
23 import com.jcraft.jsch.Proxy;
24 import com.jcraft.jsch.ProxyHTTP;
25 import com.jcraft.jsch.ProxySOCKS5;
26 import org.apache.commons.vfs.FileSystemException;
27 import org.apache.commons.vfs.FileSystemOptions;
28 import org.apache.commons.vfs.util.Os;
29
30 import java.io.File;
31 import java.util.Properties;
32
33 /***
34 * Create a HttpClient instance
35 *
36 * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
37 * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
38 */
39 public class SftpClientFactory
40 {
41 private static final String SSH_DIR_NAME = ".ssh";
42
43 private SftpClientFactory()
44 {
45 }
46
47 /***
48 * Creates a new connection to the server.
49 */
50 public static Session createConnection(String hostname, int port, char[] username, char[] password, FileSystemOptions fileSystemOptions) throws FileSystemException
51 {
52 JSch jsch = new JSch();
53
54 File sshDir = null;
55
56
57 File knownHostsFile = SftpFileSystemConfigBuilder.getInstance().getKnownHosts(fileSystemOptions);
58 File[] identities = SftpFileSystemConfigBuilder.getInstance().getIdentities(fileSystemOptions);
59
60 if (knownHostsFile != null)
61 {
62 try
63 {
64 jsch.setKnownHosts(knownHostsFile.getAbsolutePath());
65 }
66 catch (JSchException e)
67 {
68 throw new FileSystemException("vfs.provider.sftp/known-hosts.error", knownHostsFile.getAbsolutePath(), e);
69 }
70 }
71 else
72 {
73 if (sshDir == null)
74 {
75 sshDir = findSshDir();
76 }
77
78 knownHostsFile = new File(sshDir, "known_hosts");
79 if (knownHostsFile.isFile() && knownHostsFile.canRead())
80 {
81 try
82 {
83 jsch.setKnownHosts(knownHostsFile.getAbsolutePath());
84 }
85 catch (JSchException e)
86 {
87 throw new FileSystemException("vfs.provider.sftp/known-hosts.error", knownHostsFile.getAbsolutePath(), e);
88 }
89 }
90 }
91
92 if (identities != null)
93 {
94 for (int iterIdentities = 0; iterIdentities < identities.length; iterIdentities++)
95 {
96 final File privateKeyFile = identities[iterIdentities];
97 try
98 {
99 jsch.addIdentity(privateKeyFile.getAbsolutePath());
100 }
101 catch (final JSchException e)
102 {
103 throw new FileSystemException("vfs.provider.sftp/load-private-key.error", privateKeyFile, e);
104 }
105 }
106 }
107 else
108 {
109 if (sshDir == null)
110 {
111 sshDir = findSshDir();
112 }
113
114
115 final File privateKeyFile = new File(sshDir, "id_rsa");
116 if (privateKeyFile.isFile() && privateKeyFile.canRead())
117 {
118 try
119 {
120 jsch.addIdentity(privateKeyFile.getAbsolutePath());
121 }
122 catch (final JSchException e)
123 {
124 throw new FileSystemException("vfs.provider.sftp/load-private-key.error", privateKeyFile, e);
125 }
126 }
127 }
128
129 Session session;
130 try
131 {
132 session = jsch.getSession(new String(username),
133 hostname,
134 port);
135 if (password != null)
136 {
137 session.setPassword(new String(password));
138 }
139
140 Integer timeout = SftpFileSystemConfigBuilder.getInstance().getTimeout(fileSystemOptions);
141 if (timeout != null)
142 {
143 session.setTimeout(timeout.intValue());
144 }
145
146 UserInfo userInfo = SftpFileSystemConfigBuilder.getInstance().getUserInfo(fileSystemOptions);
147 if (userInfo != null)
148 {
149 session.setUserInfo(userInfo);
150 }
151
152 Properties config = new Properties();
153
154
155 String strictHostKeyChecking = SftpFileSystemConfigBuilder.getInstance().getStrictHostKeyChecking(fileSystemOptions);
156 if (strictHostKeyChecking != null)
157 {
158 config.setProperty("StrictHostKeyChecking", strictHostKeyChecking);
159 }
160
161
162 String compression = SftpFileSystemConfigBuilder.getInstance().getCompression(fileSystemOptions);
163 if (compression != null)
164 {
165 config.setProperty("compression.s2c", compression);
166 config.setProperty("compression.c2s", compression);
167 }
168
169 String proxyHost = SftpFileSystemConfigBuilder.getInstance().getProxyHost(fileSystemOptions);
170 if (proxyHost != null)
171 {
172 int proxyPort = SftpFileSystemConfigBuilder.getInstance().getProxyPort(fileSystemOptions);
173 SftpFileSystemConfigBuilder.ProxyType proxyType = SftpFileSystemConfigBuilder.getInstance().getProxyType(fileSystemOptions);
174 Proxy proxy = null;
175 if (SftpFileSystemConfigBuilder.PROXY_HTTP.equals(proxyType))
176 {
177 if (proxyPort != 0)
178 {
179 proxy = new ProxyHTTP(proxyHost, proxyPort);
180 }
181 else
182 {
183 proxy = new ProxyHTTP(proxyHost);
184 }
185 }
186 else if (SftpFileSystemConfigBuilder.PROXY_SOCKS5.equals(proxyType))
187 {
188 if (proxyPort != 0)
189 {
190 proxy = new ProxySOCKS5(proxyHost, proxyPort);
191 }
192 else
193 {
194 proxy = new ProxySOCKS5(proxyHost);
195 }
196 }
197
198 if (proxy != null)
199 {
200 session.setProxy(proxy);
201 }
202 }
203
204
205 if (config.size() > 0)
206 {
207 session.setConfig(config);
208 }
209
210 session.connect();
211 }
212 catch (final Exception exc)
213 {
214 throw new FileSystemException("vfs.provider.sftp/connect.error", new Object[]{hostname}, exc);
215 }
216
217
218 return session;
219 }
220
221 /***
222 * Finds the .ssh directory.
223 * <p>The lookup order is:</p>
224 * <ol>
225 * <li>The system property <code>vfs.sftp.sshdir</code> (the override
226 * mechanism)</li>
227 * <li><code>{user.home}/.ssh</code></li>
228 * <li>On Windows only: C:\cygwin\home\{user.name}\.ssh</li>
229 * <li>The current directory, as a last resort.</li>
230 * <ol>
231 * <p/>
232 * Windows Notes:
233 * The default installation directory for Cygwin is <code>C:\cygwin</code>.
234 * On my set up (Gary here), I have Cygwin in C:\bin\cygwin, not the default.
235 * Also, my .ssh directory was created in the {user.home} directory.
236 * </p>
237 *
238 * @return The .ssh directory
239 */
240 private static File findSshDir()
241 {
242 String sshDirPath;
243 sshDirPath = System.getProperty("vfs.sftp.sshdir");
244 if (sshDirPath != null)
245 {
246 File sshDir = new File(sshDirPath);
247 if (sshDir.exists())
248 {
249 return sshDir;
250 }
251 }
252
253 File sshDir = new File(System.getProperty("user.home"), SSH_DIR_NAME);
254 if (sshDir.exists())
255 {
256 return sshDir;
257 }
258
259 if (Os.isFamily(Os.OS_FAMILY_WINDOWS))
260 {
261
262 final String userName = System.getProperty("user.name");
263 sshDir = new File("C://cygwin//home//" + userName + "//" + SSH_DIR_NAME);
264 if (sshDir.exists())
265 {
266 return sshDir;
267 }
268 }
269 return new File("");
270 }
271 }