View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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          // new style - user passed
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              // Load the known hosts file
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             // Load the private key (rsa-key only)
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             //set StrictHostKeyChecking property
155             String strictHostKeyChecking = SftpFileSystemConfigBuilder.getInstance().getStrictHostKeyChecking(fileSystemOptions);
156             if (strictHostKeyChecking != null)
157             {
158                 config.setProperty("StrictHostKeyChecking", strictHostKeyChecking);
159             }
160 
161             //set compression property
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             //set properties for the session
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             // TODO - this may not be true
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 }