2
Copyright (c) 2006-2010 ymnk, JCraft,Inc. All rights reserved.
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
7
1. Redistributions of source code must retain the above copyright notice,
8
this list of conditions and the following disclaimer.
10
2. Redistributions in binary form must reproduce the above copyright
11
notice, this list of conditions and the following disclaimer in
12
the documentation and/or other materials provided with the distribution.
14
3. The names of the authors may not be used to endorse or promote products
15
derived from this software without specific prior written permission.
17
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
This code is based on jsch (http://www.jcraft.com/jsch).
29
All credit should go to the authors of jsch.
33
using System.Collections;
41
public class KnownHosts : HostKeyRepository
43
private static readonly string _known_hosts = "known_hosts";
45
private JSch jsch = null;
47
private string known_hosts = null;
49
private ArrayList pool = null;
51
private MAC hmacsha1 = null;
53
internal KnownHosts(JSch jsch) : base()
56
pool = new ArrayList();
59
/// <exception cref="NSch.JSchException"></exception>
60
internal virtual void SetKnownHosts(string foo)
65
FileInputStream fis = new FileInputStream(foo);
68
catch (FileNotFoundException)
73
/// <exception cref="NSch.JSchException"></exception>
74
internal virtual void SetKnownHosts(InputStream foo)
77
StringBuilder sb = new StringBuilder();
83
InputStream fis = foo;
87
byte[] buf = new byte[1024];
106
if (j == unchecked((int)(0x0d)))
110
if (j == unchecked((int)(0x0a)))
114
if (buf.Length <= bufl)
116
if (bufl > 1024 * 10)
121
byte[] newbuf = new byte[buf.Length * 2];
122
System.Array.Copy(buf, 0, newbuf, 0, buf.Length);
125
buf[bufl++] = unchecked((byte)j);
131
if (i == ' ' || i == '\t')
138
AddInvalidLine(Util.Byte2str(buf, 0, bufl));
145
AddInvalidLine(Util.Byte2str(buf, 0, bufl));
152
if (i == unchecked((int)(0x20)) || i == '\t')
158
host = sb.ToString();
159
if (j >= bufl || host.Length == 0)
161
AddInvalidLine(Util.Byte2str(buf, 0, bufl));
169
if (i == unchecked((int)(0x20)) || i == '\t')
175
if (sb.ToString().Equals("ssh-dss"))
177
type = HostKey.SSHDSS;
181
if (sb.ToString().Equals("ssh-rsa"))
183
type = HostKey.SSHRSA;
192
AddInvalidLine(Util.Byte2str(buf, 0, bufl));
199
if (i == unchecked((int)(0x0d)))
203
if (i == unchecked((int)(0x0a)))
212
AddInvalidLine(Util.Byte2str(buf, 0, bufl));
215
//System.err.println(host);
216
//System.err.println("|"+key+"|");
218
hk = new KnownHosts.HashedHostKey(this, host, type, Util.FromBase64(Util.Str2byte
219
(key), 0, key.Length));
227
throw new JSchException("KnownHosts: invalid format");
232
if (e is JSchException)
234
throw (JSchException)e;
238
throw new JSchException(e.ToString(), (Exception)e);
240
throw new JSchException(e.ToString());
244
/// <exception cref="NSch.JSchException"></exception>
245
private void AddInvalidLine(string line)
247
HostKey hk = new HostKey(line, HostKey.UNKNOWN, null);
251
internal virtual string GetKnownHostsFile()
256
public override string GetKnownHostsRepositoryID()
261
public override int Check(string host, byte[] key)
263
int result = NOT_INCLUDED;
268
int type = GetType(key);
272
for (int i = 0; i < pool.Count; i++)
274
hk = (HostKey)(pool[i]);
275
if (hk.IsMatched(host) && hk.type == type)
277
if (Util.Array_equals(hk.key, key))
288
if (result == NOT_INCLUDED && host.StartsWith("[") && host.IndexOf("]:") > 1)
290
return Check(Sharpen.Runtime.Substring(host, 1, host.IndexOf("]:")), key);
295
public override void Add(HostKey hostkey, UserInfo userinfo)
297
int type = hostkey.type;
298
string host = hostkey.GetHost();
299
byte[] key = hostkey.key;
303
for (int i = 0; i < pool.Count; i++)
305
hk = (HostKey)(pool[i]);
306
if (hk.IsMatched(host) && hk.type == type)
313
string bar = GetKnownHostsRepositoryID();
317
FilePath goo = new FilePath(bar);
321
if (userinfo != null)
323
foo = userinfo.PromptYesNo(bar + " does not exist.\n" + "Are you sure you want to create it?"
325
goo = goo.GetParentFile();
326
if (foo && goo != null && !goo.Exists())
328
foo = userinfo.PromptYesNo("The parent directory " + goo + " does not exist.\n" +
329
"Are you sure you want to create it?");
334
userinfo.ShowMessage(goo + " has not been created.");
339
userinfo.ShowMessage(goo + " has been succesfully created.\nPlease check its access permission."
358
System.Console.Error.WriteLine("sync known_hosts: " + e);
364
public override HostKey[] GetHostKey()
366
return GetHostKey(null, null);
369
public override HostKey[] GetHostKey(string host, string type)
374
for (int i = 0; i < pool.Count; i++)
376
HostKey hk = (HostKey)pool[i];
377
if (hk.type == HostKey.UNKNOWN)
381
if (host == null || (hk.IsMatched(host) && (type == null || hk.GetType().Equals(type
391
HostKey[] foo = new HostKey[count];
393
for (int i_1 = 0; i_1 < pool.Count; i_1++)
395
HostKey hk = (HostKey)pool[i_1];
396
if (hk.type == HostKey.UNKNOWN)
400
if (host == null || (hk.IsMatched(host) && (type == null || hk.GetType().Equals(type
410
public override void Remove(string host, string type)
412
Remove(host, type, null);
415
public override void Remove(string host, string type, byte[] key)
420
for (int i = 0; i < pool.Count; i++)
422
HostKey hk = (HostKey)(pool[i]);
423
if (host == null || (hk.IsMatched(host) && (type == null || (hk.GetType().Equals(
424
type) && (key == null || Util.Array_equals(key, hk.key))))))
426
string hosts = hk.GetHost();
427
if (hosts.Equals(host) || ((hk is KnownHosts.HashedHostKey) && ((KnownHosts.HashedHostKey
430
pool.RemoveElement(hk);
434
hk.host = DeleteSubString(hosts, host);
452
/// <exception cref="System.IO.IOException"></exception>
453
protected internal virtual void Sync()
455
if (known_hosts != null)
461
/// <exception cref="System.IO.IOException"></exception>
462
protected internal virtual void Sync(string foo)
470
FileOutputStream fos = new FileOutputStream(foo);
476
private static readonly byte[] space = new byte[] { unchecked((byte)unchecked((int
479
private static readonly byte[] cr = Util.Str2byte("\n");
481
/// <exception cref="System.IO.IOException"></exception>
482
internal virtual void Dump(OutputStream @out)
489
for (int i = 0; i < pool.Count; i++)
491
hk = (HostKey)(pool[i]);
493
string host = hk.GetHost();
494
string type = hk.GetType();
495
if (type.Equals("UNKNOWN"))
497
@out.Write(Util.Str2byte(host));
501
@out.Write(Util.Str2byte(host));
503
@out.Write(Util.Str2byte(type));
505
@out.Write(Util.Str2byte(hk.GetKey()));
512
System.Console.Error.WriteLine(e);
516
private int GetType(byte[] key)
520
return HostKey.SSHDSS;
524
return HostKey.SSHRSA;
526
return HostKey.UNKNOWN;
529
private string DeleteSubString(string hosts, string host)
532
int hostlen = host.Length;
533
int hostslen = hosts.Length;
537
j = hosts.IndexOf(',', i);
542
if (!host.Equals(Sharpen.Runtime.Substring(hosts, i, j)))
547
return Sharpen.Runtime.Substring(hosts, 0, i) + Sharpen.Runtime.Substring(hosts,
550
if (hosts.EndsWith(host) && hostslen - i == hostlen)
552
return Sharpen.Runtime.Substring(hosts, 0, (hostlen == hostslen) ? 0 : hostslen -
558
private MAC GetHMACSHA1()
562
if (hmacsha1 == null)
566
Type c = Sharpen.Runtime.GetType(JSch.GetConfig("hmac-sha1"));
567
hmacsha1 = (MAC)(System.Activator.CreateInstance(c));
571
System.Console.Error.WriteLine("hmacsha1: " + e);
578
/// <exception cref="NSch.JSchException"></exception>
579
internal virtual HostKey CreateHashedHostKey(string host, byte[] key)
581
KnownHosts.HashedHostKey hhk = new KnownHosts.HashedHostKey(this, host, key);
586
internal class HashedHostKey : HostKey
588
private static readonly string HASH_MAGIC = "|1|";
590
private static readonly string HASH_DELIM = "|";
592
private bool hashed = false;
594
internal byte[] salt = null;
596
internal byte[] hash = null;
598
/// <exception cref="NSch.JSchException"></exception>
599
public HashedHostKey(KnownHosts _enclosing, string host, byte[] key) : this(_enclosing, host,
602
this._enclosing = _enclosing;
605
/// <exception cref="NSch.JSchException"></exception>
606
public HashedHostKey(KnownHosts _enclosing, string host, int type, byte[] key) :
607
base(host, type, key)
609
this._enclosing = _enclosing;
610
if (this.host.StartsWith(KnownHosts.HashedHostKey.HASH_MAGIC) && Sharpen.Runtime.Substring
611
(this.host, KnownHosts.HashedHostKey.HASH_MAGIC.Length).IndexOf(KnownHosts.HashedHostKey
614
string data = Sharpen.Runtime.Substring(this.host, KnownHosts.HashedHostKey.HASH_MAGIC
616
string _salt = Sharpen.Runtime.Substring(data, 0, data.IndexOf(KnownHosts.HashedHostKey
618
string _hash = Sharpen.Runtime.Substring(data, data.IndexOf(KnownHosts.HashedHostKey
620
this.salt = Util.FromBase64(Util.Str2byte(_salt), 0, _salt.Length);
621
this.hash = Util.FromBase64(Util.Str2byte(_hash), 0, _hash.Length);
622
if (this.salt.Length != 20 || this.hash.Length != 20)
624
// block size of hmac-sha1
633
internal override bool IsMatched(string _host)
637
return base.IsMatched(_host);
639
MAC macsha1 = this._enclosing.GetHMACSHA1();
644
macsha1.Init(this.salt);
645
byte[] foo = Util.Str2byte(_host);
646
macsha1.Update(foo, 0, foo.Length);
647
byte[] bar = new byte[macsha1.GetBlockSize()];
648
macsha1.DoFinal(bar, 0);
649
return Util.Array_equals(this.hash, bar);
654
System.Console.Out.WriteLine(e);
659
internal virtual bool IsHashed()
664
internal virtual void Hash()
670
MAC macsha1 = this._enclosing.GetHMACSHA1();
671
if (this.salt == null)
673
Random random = Session.random;
676
this.salt = new byte[macsha1.GetBlockSize()];
677
random.Fill(this.salt, 0, this.salt.Length);
684
macsha1.Init(this.salt);
685
byte[] foo = Util.Str2byte(this.host);
686
macsha1.Update(foo, 0, foo.Length);
687
this.hash = new byte[macsha1.GetBlockSize()];
688
macsha1.DoFinal(this.hash, 0);
694
this.host = KnownHosts.HashedHostKey.HASH_MAGIC + Util.Byte2str(Util.ToBase64(this
695
.salt, 0, this.salt.Length)) + KnownHosts.HashedHostKey.HASH_DELIM + Util.Byte2str
696
(Util.ToBase64(this.hash, 0, this.hash.Length));
700
private readonly KnownHosts _enclosing;