2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
5
This program and the accompanying materials are made available
6
under the terms of the Eclipse Distribution License v1.0 which
7
accompanies this distribution, is reproduced below, and is
8
available at http://www.eclipse.org/org/documents/edl-v10.php
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
19
- Redistributions in binary form must reproduce the above
20
copyright notice, this list of conditions and the following
21
disclaimer in the documentation and/or other materials provided
22
with the distribution.
24
- Neither the name of the Eclipse Foundation, Inc. nor the
25
names of its contributors may be used to endorse or promote
26
products derived from this software without specific prior
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
using System.Collections.Generic;
54
namespace NGit.Transport
57
/// The base session factory that loads known hosts and private keys from
58
/// <code>$HOME/.ssh</code>.
61
/// The base session factory that loads known hosts and private keys from
62
/// <code>$HOME/.ssh</code>.
64
/// This is the default implementation used by JGit and provides most of the
65
/// compatibility necessary to match OpenSSH, a popular implementation of SSH
68
/// The factory does not provide UI behavior. Override the method
69
/// <see cref="Configure(Host, NSch.Session)">Configure(Host, NSch.Session)</see>
70
/// to supply appropriate
71
/// <see cref="NSch.UserInfo">NSch.UserInfo</see>
74
public abstract class JschConfigSessionFactory : SshSessionFactory
76
private readonly IDictionary<string, JSch> byIdentityFile = new Dictionary<string
79
private JSch defaultJSch;
81
private OpenSshConfig config;
83
/// <exception cref="NGit.Errors.TransportException"></exception>
84
public override RemoteSession GetSession(URIish uri, CredentialsProvider credentialsProvider
89
string user = uri.GetUser();
90
string pass = uri.GetPass();
91
string host = uri.GetHost();
92
int port = uri.GetPort();
97
config = OpenSshConfig.Get(fs);
99
OpenSshConfig.Host hc = config.Lookup(host);
100
host = hc.GetHostName();
109
Session session = CreateSession(hc, user, host, port, fs);
112
session.SetPassword(pass);
114
string strictHostKeyCheckingPolicy = hc.GetStrictHostKeyChecking();
115
if (strictHostKeyCheckingPolicy != null)
117
session.SetConfig("StrictHostKeyChecking", strictHostKeyCheckingPolicy);
119
string pauth = hc.GetPreferredAuthentications();
122
session.SetConfig("PreferredAuthentications", pauth);
124
if (credentialsProvider != null && (!hc.IsBatchMode() || !credentialsProvider.IsInteractive
127
session.SetUserInfo(new CredentialsProviderUserInfo(session, credentialsProvider)
130
Configure(hc, session);
131
if (!session.IsConnected())
133
session.Connect(tms);
135
return new JschSession(session, uri);
137
catch (JSchException je)
139
Exception c = je.InnerException;
140
if (c is UnknownHostException)
142
throw new TransportException(uri, JGitText.Get().unknownHost);
144
if (c is ConnectException)
146
throw new TransportException(uri, c.Message);
148
throw new TransportException(uri, je.Message, je);
153
/// <summary>Create a new remote session for the requested address.</summary>
154
/// <remarks>Create a new remote session for the requested address.</remarks>
155
/// <param name="hc">host configuration</param>
156
/// <param name="user">login to authenticate as.</param>
157
/// <param name="host">server name to connect to.</param>
158
/// <param name="port">port number of the SSH daemon (typically 22).</param>
159
/// <param name="fs">
160
/// the file system abstraction which will be necessary to
161
/// perform certain file system operations.
163
/// <returns>new session instance, but otherwise unconfigured.</returns>
164
/// <exception cref="NSch.JSchException">the session could not be created.</exception>
165
protected internal virtual Session CreateSession(OpenSshConfig.Host hc, string user
166
, string host, int port, FS fs)
168
return GetJSch(hc, fs).GetSession(user, host, port);
172
/// Provide additional configuration for the session based on the host
176
/// Provide additional configuration for the session based on the host
177
/// information. This method could be used to supply
178
/// <see cref="NSch.UserInfo">NSch.UserInfo</see>
181
/// <param name="hc">host configuration</param>
182
/// <param name="session">session to configure</param>
183
protected internal abstract void Configure(OpenSshConfig.Host hc, Session session
186
/// <summary>Obtain the JSch used to create new sessions.</summary>
187
/// <remarks>Obtain the JSch used to create new sessions.</remarks>
188
/// <param name="hc">host configuration</param>
189
/// <param name="fs">
190
/// the file system abstraction which will be necessary to
191
/// perform certain file system operations.
193
/// <returns>the JSch instance to use.</returns>
194
/// <exception cref="NSch.JSchException">the user configuration could not be created.
196
protected internal virtual JSch GetJSch(OpenSshConfig.Host hc, FS fs)
198
if (defaultJSch == null)
200
defaultJSch = CreateDefaultJSch(fs);
201
foreach (object name in defaultJSch.GetIdentityNames())
203
byIdentityFile.Put((string)name, defaultJSch);
206
FilePath identityFile = hc.GetIdentityFile();
207
if (identityFile == null)
211
string identityKey = identityFile.GetAbsolutePath();
212
JSch jsch = byIdentityFile.Get(identityKey);
216
jsch.SetHostKeyRepository(defaultJSch.GetHostKeyRepository());
217
jsch.AddIdentity(identityKey);
218
byIdentityFile.Put(identityKey, jsch);
223
/// <param name="fs">
224
/// the file system abstraction which will be necessary to
225
/// perform certain file system operations.
227
/// <returns>the new default JSch implementation.</returns>
228
/// <exception cref="NSch.JSchException">known host keys cannot be loaded.</exception>
229
protected internal virtual JSch CreateDefaultJSch(FS fs)
231
JSch jsch = new JSch();
232
KnownHosts(jsch, fs);
233
Identities(jsch, fs);
237
/// <exception cref="NSch.JSchException"></exception>
238
private static void KnownHosts(JSch sch, FS fs)
240
FilePath home = fs.UserHome();
245
FilePath known_hosts = new FilePath(new FilePath(home, ".ssh"), "known_hosts");
248
FileInputStream @in = new FileInputStream(known_hosts);
251
sch.SetKnownHosts(@in);
258
catch (FileNotFoundException)
266
// Oh well. They don't have a known hosts in home.
267
// Oh well. They don't have a known hosts in home.
268
private static void Identities(JSch sch, FS fs)
270
FilePath home = fs.UserHome();
275
FilePath sshdir = new FilePath(home, ".ssh");
276
if (sshdir.IsDirectory())
278
LoadIdentity(sch, new FilePath(sshdir, "identity"));
279
LoadIdentity(sch, new FilePath(sshdir, "id_rsa"));
280
LoadIdentity(sch, new FilePath(sshdir, "id_dsa"));
284
private static void LoadIdentity(JSch sch, FilePath priv)
290
sch.AddIdentity(priv.GetAbsolutePath());
292
catch (JSchException)
297
// Instead, pretend the key doesn't exist.