001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.vfs.provider.sftp;
018:
019: import com.jcraft.jsch.JSch;
020: import com.jcraft.jsch.JSchException;
021: import com.jcraft.jsch.Session;
022: import com.jcraft.jsch.UserInfo;
023: import com.jcraft.jsch.Proxy;
024: import com.jcraft.jsch.ProxyHTTP;
025: import com.jcraft.jsch.ProxySOCKS5;
026: import org.apache.commons.vfs.FileSystemException;
027: import org.apache.commons.vfs.FileSystemOptions;
028: import org.apache.commons.vfs.util.Os;
029:
030: import java.io.File;
031: import java.util.Properties;
032:
033: /**
034: * Create a HttpClient instance
035: *
036: * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
037: * @version $Revision: 480428 $ $Date: 2006-11-28 22:15:24 -0800 (Tue, 28 Nov 2006) $
038: */
039: public class SftpClientFactory {
040: private static final String SSH_DIR_NAME = ".ssh";
041:
042: private SftpClientFactory() {
043: }
044:
045: /**
046: * Creates a new connection to the server.
047: */
048: public static Session createConnection(String hostname, int port,
049: char[] username, char[] password,
050: FileSystemOptions fileSystemOptions)
051: throws FileSystemException {
052: JSch jsch = new JSch();
053:
054: File sshDir = null;
055:
056: // new style - user passed
057: File knownHostsFile = SftpFileSystemConfigBuilder.getInstance()
058: .getKnownHosts(fileSystemOptions);
059: File[] identities = SftpFileSystemConfigBuilder.getInstance()
060: .getIdentities(fileSystemOptions);
061:
062: if (knownHostsFile != null) {
063: try {
064: jsch.setKnownHosts(knownHostsFile.getAbsolutePath());
065: } catch (JSchException e) {
066: throw new FileSystemException(
067: "vfs.provider.sftp/known-hosts.error",
068: knownHostsFile.getAbsolutePath(), e);
069: }
070: } else {
071: if (sshDir == null) {
072: sshDir = findSshDir();
073: }
074: // Load the known hosts file
075: knownHostsFile = new File(sshDir, "known_hosts");
076: if (knownHostsFile.isFile() && knownHostsFile.canRead()) {
077: try {
078: jsch
079: .setKnownHosts(knownHostsFile
080: .getAbsolutePath());
081: } catch (JSchException e) {
082: throw new FileSystemException(
083: "vfs.provider.sftp/known-hosts.error",
084: knownHostsFile.getAbsolutePath(), e);
085: }
086: }
087: }
088:
089: if (identities != null) {
090: for (int iterIdentities = 0; iterIdentities < identities.length; iterIdentities++) {
091: final File privateKeyFile = identities[iterIdentities];
092: try {
093: jsch.addIdentity(privateKeyFile.getAbsolutePath());
094: } catch (final JSchException e) {
095: throw new FileSystemException(
096: "vfs.provider.sftp/load-private-key.error",
097: privateKeyFile, e);
098: }
099: }
100: } else {
101: if (sshDir == null) {
102: sshDir = findSshDir();
103: }
104:
105: // Load the private key (rsa-key only)
106: final File privateKeyFile = new File(sshDir, "id_rsa");
107: if (privateKeyFile.isFile() && privateKeyFile.canRead()) {
108: try {
109: jsch.addIdentity(privateKeyFile.getAbsolutePath());
110: } catch (final JSchException e) {
111: throw new FileSystemException(
112: "vfs.provider.sftp/load-private-key.error",
113: privateKeyFile, e);
114: }
115: }
116: }
117:
118: Session session;
119: try {
120: session = jsch.getSession(new String(username), hostname,
121: port);
122: if (password != null) {
123: session.setPassword(new String(password));
124: }
125:
126: Integer timeout = SftpFileSystemConfigBuilder.getInstance()
127: .getTimeout(fileSystemOptions);
128: if (timeout != null) {
129: session.setTimeout(timeout.intValue());
130: }
131:
132: UserInfo userInfo = SftpFileSystemConfigBuilder
133: .getInstance().getUserInfo(fileSystemOptions);
134: if (userInfo != null) {
135: session.setUserInfo(userInfo);
136: }
137:
138: Properties config = new Properties();
139:
140: //set StrictHostKeyChecking property
141: String strictHostKeyChecking = SftpFileSystemConfigBuilder
142: .getInstance().getStrictHostKeyChecking(
143: fileSystemOptions);
144: if (strictHostKeyChecking != null) {
145: config.setProperty("StrictHostKeyChecking",
146: strictHostKeyChecking);
147: }
148:
149: //set compression property
150: String compression = SftpFileSystemConfigBuilder
151: .getInstance().getCompression(fileSystemOptions);
152: if (compression != null) {
153: config.setProperty("compression.s2c", compression);
154: config.setProperty("compression.c2s", compression);
155: }
156:
157: String proxyHost = SftpFileSystemConfigBuilder
158: .getInstance().getProxyHost(fileSystemOptions);
159: if (proxyHost != null) {
160: int proxyPort = SftpFileSystemConfigBuilder
161: .getInstance().getProxyPort(fileSystemOptions);
162: SftpFileSystemConfigBuilder.ProxyType proxyType = SftpFileSystemConfigBuilder
163: .getInstance().getProxyType(fileSystemOptions);
164: Proxy proxy = null;
165: if (SftpFileSystemConfigBuilder.PROXY_HTTP
166: .equals(proxyType)) {
167: if (proxyPort != 0) {
168: proxy = new ProxyHTTP(proxyHost, proxyPort);
169: } else {
170: proxy = new ProxyHTTP(proxyHost);
171: }
172: } else if (SftpFileSystemConfigBuilder.PROXY_SOCKS5
173: .equals(proxyType)) {
174: if (proxyPort != 0) {
175: proxy = new ProxySOCKS5(proxyHost, proxyPort);
176: } else {
177: proxy = new ProxySOCKS5(proxyHost);
178: }
179: }
180:
181: if (proxy != null) {
182: session.setProxy(proxy);
183: }
184: }
185:
186: //set properties for the session
187: if (config.size() > 0) {
188: session.setConfig(config);
189: }
190:
191: session.connect();
192: } catch (final Exception exc) {
193: throw new FileSystemException(
194: "vfs.provider.sftp/connect.error",
195: new Object[] { hostname }, exc);
196: }
197:
198: return session;
199: }
200:
201: /**
202: * Finds the .ssh directory.
203: * <p>The lookup order is:</p>
204: * <ol>
205: * <li>The system property <code>vfs.sftp.sshdir</code> (the override
206: * mechanism)</li>
207: * <li><code>{user.home}/.ssh</code></li>
208: * <li>On Windows only: C:\cygwin\home\{user.name}\.ssh</li>
209: * <li>The current directory, as a last resort.</li>
210: * <ol>
211: * <p/>
212: * Windows Notes:
213: * The default installation directory for Cygwin is <code>C:\cygwin</code>.
214: * On my set up (Gary here), I have Cygwin in C:\bin\cygwin, not the default.
215: * Also, my .ssh directory was created in the {user.home} directory.
216: * </p>
217: *
218: * @return The .ssh directory
219: */
220: private static File findSshDir() {
221: String sshDirPath;
222: sshDirPath = System.getProperty("vfs.sftp.sshdir");
223: if (sshDirPath != null) {
224: File sshDir = new File(sshDirPath);
225: if (sshDir.exists()) {
226: return sshDir;
227: }
228: }
229:
230: File sshDir = new File(System.getProperty("user.home"),
231: SSH_DIR_NAME);
232: if (sshDir.exists()) {
233: return sshDir;
234: }
235:
236: if (Os.isFamily(Os.OS_FAMILY_WINDOWS)) {
237: // TODO - this may not be true
238: final String userName = System.getProperty("user.name");
239: sshDir = new File("C:\\cygwin\\home\\" + userName + "\\"
240: + SSH_DIR_NAME);
241: if (sshDir.exists()) {
242: return sshDir;
243: }
244: }
245: return new File("");
246: }
247: }
|