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 }