PageRenderTime 64ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/SharpSSH/jsch/Session.cs

https://bitbucket.org/sign42/sharpssh
C# | 1856 lines | 1580 code | 182 blank | 94 comment | 255 complexity | 75d56596e1ea5e0464560fb64b2a1635 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. //using System;
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using System.Runtime.CompilerServices;
  6. using System.Threading;
  7. using Tamir.SharpSsh.java;
  8. using Tamir.SharpSsh.java.lang;
  9. using Tamir.SharpSsh.java.net;
  10. namespace Tamir.SharpSsh.jsch
  11. {
  12. public class Session : JavaRunnable
  13. {
  14. private static String version = "SharpSSH-" + SshBase.Version.ToString() + "-JSCH-0.1.28";
  15. // http://ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-01.txt
  16. internal const int SSH_MSG_DISCONNECT = 1;
  17. internal const int SSH_MSG_IGNORE = 2;
  18. internal const int SSH_MSG_UNIMPLEMENTED = 3;
  19. internal const int SSH_MSG_DEBUG = 4;
  20. internal const int SSH_MSG_SERVICE_REQUEST = 5;
  21. internal const int SSH_MSG_SERVICE_ACCEPT = 6;
  22. internal const int SSH_MSG_KEXINIT = 20;
  23. internal const int SSH_MSG_NEWKEYS = 21;
  24. internal const int SSH_MSG_KEXDH_INIT = 30;
  25. internal const int SSH_MSG_KEXDH_REPLY = 31;
  26. internal const int SSH_MSG_KEX_DH_GEX_GROUP = 31;
  27. internal const int SSH_MSG_KEX_DH_GEX_INIT = 32;
  28. internal const int SSH_MSG_KEX_DH_GEX_REPLY = 33;
  29. internal const int SSH_MSG_KEX_DH_GEX_REQUEST = 34;
  30. internal const int SSH_MSG_USERAUTH_REQUEST = 50;
  31. internal const int SSH_MSG_USERAUTH_FAILURE = 51;
  32. internal const int SSH_MSG_USERAUTH_SUCCESS = 52;
  33. internal const int SSH_MSG_USERAUTH_BANNER = 53;
  34. internal const int SSH_MSG_USERAUTH_INFO_REQUEST = 60;
  35. internal const int SSH_MSG_USERAUTH_INFO_RESPONSE = 61;
  36. internal const int SSH_MSG_USERAUTH_PK_OK = 60;
  37. internal const int SSH_MSG_GLOBAL_REQUEST = 80;
  38. internal const int SSH_MSG_REQUEST_SUCCESS = 81;
  39. internal const int SSH_MSG_REQUEST_FAILURE = 82;
  40. internal const int SSH_MSG_CHANNEL_OPEN = 90;
  41. internal const int SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91;
  42. internal const int SSH_MSG_CHANNEL_OPEN_FAILURE = 92;
  43. internal const int SSH_MSG_CHANNEL_WINDOW_ADJUST = 93;
  44. internal const int SSH_MSG_CHANNEL_DATA = 94;
  45. internal const int SSH_MSG_CHANNEL_EXTENDED_DATA = 95;
  46. internal const int SSH_MSG_CHANNEL_EOF = 96;
  47. internal const int SSH_MSG_CHANNEL_CLOSE = 97;
  48. internal const int SSH_MSG_CHANNEL_REQUEST = 98;
  49. internal const int SSH_MSG_CHANNEL_SUCCESS = 99;
  50. internal const int SSH_MSG_CHANNEL_FAILURE = 100;
  51. private byte[] V_S; // server version
  52. private byte[] V_C = ("SSH-2.0-" + version).GetBytes(); // client version
  53. private byte[] I_C; // the payload of the client's SSH_MSG_KEXINIT
  54. private byte[] I_S; // the payload of the server's SSH_MSG_KEXINIT
  55. private byte[] K_S; // the host key
  56. private byte[] session_id;
  57. private byte[] IVc2s;
  58. private byte[] IVs2c;
  59. private byte[] Ec2s;
  60. private byte[] Es2c;
  61. private byte[] MACc2s;
  62. private byte[] MACs2c;
  63. private int seqi = 0;
  64. private int seqo = 0;
  65. private Cipher s2ccipher;
  66. private Cipher c2scipher;
  67. private MAC s2cmac;
  68. private MAC c2smac;
  69. private byte[] mac_buf;
  70. private Compression deflater;
  71. private Compression inflater;
  72. private IO io;
  73. private Socket socket;
  74. private int timeout = 0;
  75. private bool _isConnected = false;
  76. private bool isAuthed = false;
  77. private JavaThread connectThread = null;
  78. internal bool x11_forwarding = false;
  79. internal Stream In = null;
  80. internal Stream Out = null;
  81. internal static Random random;
  82. internal Buffer buf;
  83. internal Packet packet;
  84. internal SocketFactory socket_factory = null;
  85. private Hashtable config = null;
  86. private IProxy proxy = null;
  87. private UserInfo userinfo;
  88. internal String host = "127.0.0.1";
  89. internal int port = 22;
  90. internal String username = null;
  91. internal String password = null;
  92. internal JSch jsch;
  93. internal Session(JSch jsch)
  94. {
  95. ;
  96. this.jsch = jsch;
  97. buf = new Buffer();
  98. packet = new Packet(buf);
  99. }
  100. public void connect()
  101. {
  102. connect(timeout);
  103. }
  104. public void connect(int connectTimeout)
  105. {
  106. if (_isConnected)
  107. {
  108. throw new JSchException("session is already connected");
  109. }
  110. io = new IO();
  111. if (random == null)
  112. {
  113. try
  114. {
  115. var c = Type.GetType(getConfig("random"));
  116. random = (Random) Activator.CreateInstance(c);
  117. }
  118. catch (Exception e)
  119. {
  120. Console.Error.WriteLine("connect: random " + e);
  121. }
  122. }
  123. Packet.setRandom(random);
  124. try
  125. {
  126. int i, j;
  127. int pad = 0;
  128. if (proxy == null)
  129. {
  130. proxy = jsch.getProxy(host);
  131. if (proxy != null)
  132. {
  133. lock (proxy)
  134. {
  135. proxy.Close();
  136. }
  137. }
  138. }
  139. if (proxy == null)
  140. {
  141. Stream In;
  142. Stream Out;
  143. if (socket_factory == null)
  144. {
  145. socket = Util.createSocket(host, port, connectTimeout);
  146. In = socket.getInputStream();
  147. Out = socket.getOutputStream();
  148. }
  149. else
  150. {
  151. socket = socket_factory.createSocket(host, port);
  152. In = socket_factory.getInputStream(socket);
  153. Out = socket_factory.getOutputStream(socket);
  154. }
  155. //if(timeout>0){ socket.setSoTimeout(timeout); }
  156. socket.setTcpNoDelay(true);
  157. io.setInputStream(In);
  158. io.setOutputStream(Out);
  159. }
  160. else
  161. {
  162. lock (proxy)
  163. {
  164. proxy.Connect(socket_factory, host, port, connectTimeout);
  165. io.setInputStream(proxy.InputStream);
  166. io.setOutputStream(proxy.OutputStream);
  167. socket = proxy.Socket;
  168. }
  169. }
  170. if (connectTimeout > 0 && socket != null)
  171. {
  172. socket.setSoTimeout(connectTimeout);
  173. }
  174. _isConnected = true;
  175. while (true)
  176. {
  177. i = 0;
  178. j = 0;
  179. while (i < buf.buffer.Length)
  180. {
  181. j = io.getByte();
  182. if (j < 0) break;
  183. buf.buffer[i] = (byte) j;
  184. i++;
  185. if (j == 10) break;
  186. }
  187. if (j < 0)
  188. {
  189. throw new JSchException("connection is closed by foreign host");
  190. }
  191. if (buf.buffer[i - 1] == 10)
  192. {
  193. // 0x0a
  194. i--;
  195. if (buf.buffer[i - 1] == 13)
  196. {
  197. // 0x0d
  198. i--;
  199. }
  200. }
  201. if (i > 4 && (i != buf.buffer.Length) &&
  202. (buf.buffer[0] != 'S' || buf.buffer[1] != 'S' ||
  203. buf.buffer[2] != 'H' || buf.buffer[3] != '-'))
  204. {
  205. //System.err.println(new String(buf.buffer, 0, i);
  206. continue;
  207. }
  208. if (i == buf.buffer.Length ||
  209. i < 7 || // SSH-1.99 or SSH-2.0
  210. (buf.buffer[4] == '1' && buf.buffer[6] != '9') // SSH-1.5
  211. )
  212. {
  213. throw new JSchException("invalid server's version String");
  214. }
  215. break;
  216. }
  217. V_S = new byte[i];
  218. Array.Copy(buf.buffer, 0, V_S, 0, i);
  219. {
  220. // Some Cisco devices will miss to read '\n' if it is sent separately.
  221. byte[] foo = new byte[V_C.Length + 1];
  222. Array.Copy(V_C, 0, foo, 0, V_C.Length);
  223. foo[foo.Length - 1] = (byte) '\n';
  224. io.put(foo, 0, foo.Length);
  225. }
  226. buf = read(buf);
  227. //System.Console.WriteLine("read: 20 ? "+buf.buffer[5]);
  228. if (buf.buffer[5] != SSH_MSG_KEXINIT)
  229. {
  230. throw new JSchException("invalid protocol: " + buf.buffer[5]);
  231. }
  232. KeyExchange kex = receive_kexinit(buf);
  233. while (true)
  234. {
  235. buf = read(buf);
  236. if (kex.getState() == buf.buffer[5])
  237. {
  238. bool result = kex.next(buf);
  239. if (!result)
  240. {
  241. //System.Console.WriteLine("verify: "+result);
  242. in_kex = false;
  243. throw new JSchException("verify: " + result);
  244. }
  245. }
  246. else
  247. {
  248. in_kex = false;
  249. throw new JSchException("invalid protocol(kex): " + buf.buffer[5]);
  250. }
  251. if (kex.getState() == KeyExchange.STATE_END)
  252. {
  253. break;
  254. }
  255. }
  256. try
  257. {
  258. checkHost(host, kex);
  259. }
  260. catch (JSchException ee)
  261. {
  262. in_kex = false;
  263. throw ee;
  264. }
  265. send_newkeys();
  266. // receive SSH_MSG_NEWKEYS(21)
  267. buf = read(buf);
  268. //System.Console.WriteLine("read: 21 ? "+buf.buffer[5]);
  269. if (buf.buffer[5] == SSH_MSG_NEWKEYS)
  270. {
  271. receive_newkeys(buf, kex);
  272. }
  273. else
  274. {
  275. in_kex = false;
  276. throw new JSchException("invalid protocol(newkyes): " + buf.buffer[5]);
  277. }
  278. bool auth = false;
  279. bool auth_cancel = false;
  280. UserAuthNone usn = new UserAuthNone(userinfo);
  281. auth = usn.start(this);
  282. String methods = null;
  283. if (!auth)
  284. {
  285. methods = usn.getMethods();
  286. if (methods != null)
  287. {
  288. methods = methods.ToLower();
  289. }
  290. else
  291. {
  292. // methods: publickey,password,keyboard-interactive
  293. methods = "publickey,password,keyboard-interactive";
  294. }
  295. }
  296. while (true)
  297. {
  298. while (!auth && methods != null && methods.Length > 0)
  299. {
  300. UserAuth us = null;
  301. if (methods.StartsWith("publickey"))
  302. {
  303. lock (jsch.identities)
  304. {
  305. if (jsch.identities.Count > 0)
  306. {
  307. us = new UserAuthPublicKey(userinfo);
  308. }
  309. }
  310. }
  311. else if (methods.StartsWith("keyboard-interactive"))
  312. {
  313. if (userinfo is UIKeyboardInteractive)
  314. {
  315. us = new UserAuthKeyboardInteractive(userinfo);
  316. }
  317. }
  318. else if (methods.StartsWith("password"))
  319. {
  320. us = new UserAuthPassword(userinfo);
  321. }
  322. if (us != null)
  323. {
  324. try
  325. {
  326. auth = us.start(this);
  327. auth_cancel = false;
  328. }
  329. catch (JSchAuthCancelException ee)
  330. {
  331. auth_cancel = true;
  332. }
  333. catch (JSchPartialAuthException ee)
  334. {
  335. methods = ee.getMethods();
  336. auth_cancel = false;
  337. continue;
  338. }
  339. catch (Exception ee)
  340. {
  341. Console.WriteLine("ee: " + ee);
  342. }
  343. }
  344. if (!auth)
  345. {
  346. int comma = methods.IndexOf(",");
  347. if (comma == -1) break;
  348. methods = methods.Substring(comma + 1);
  349. }
  350. }
  351. break;
  352. }
  353. if (connectTimeout > 0 || timeout > 0)
  354. {
  355. socket.setSoTimeout(timeout);
  356. }
  357. if (auth)
  358. {
  359. isAuthed = true;
  360. connectThread = new JavaThread(this);
  361. connectThread.Name("Connect thread " + host + " session");
  362. connectThread.Start();
  363. return;
  364. }
  365. if (auth_cancel)
  366. throw new JSchException("Auth cancel");
  367. throw new JSchException("Auth fail");
  368. }
  369. catch (Exception e)
  370. {
  371. in_kex = false;
  372. if (_isConnected)
  373. {
  374. try
  375. {
  376. packet.reset();
  377. buf.putByte((byte) SSH_MSG_DISCONNECT);
  378. buf.putInt(3);
  379. buf.putString(new JavaString(e.ToString()).GetBytes());
  380. buf.putString(new JavaString("en").GetBytes());
  381. write(packet);
  382. disconnect();
  383. }
  384. catch (Exception ee)
  385. {
  386. }
  387. }
  388. _isConnected = false;
  389. if (e is JSchException) throw (JSchException) e;
  390. throw new JSchException("Session.connect: " + e);
  391. }
  392. }
  393. private KeyExchange receive_kexinit(Buffer buf)
  394. {
  395. int j = buf.getInt();
  396. if (j != buf.getLength())
  397. {
  398. // packet was compressed and
  399. buf.getByte(); // j is the size of deflated packet.
  400. I_S = new byte[buf.index - 5];
  401. }
  402. else
  403. {
  404. I_S = new byte[j - 1 - buf.getByte()];
  405. }
  406. Array.Copy(buf.buffer, buf.s, I_S, 0, I_S.Length);
  407. send_kexinit();
  408. String[] guess = KeyExchange.guess(I_S, I_C);
  409. if (guess == null)
  410. {
  411. throw new JSchException("Algorithm negotiation fail");
  412. }
  413. if (!isAuthed &&
  414. (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].Equals("none") ||
  415. (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].Equals("none"))))
  416. {
  417. throw new JSchException("NONE Cipher should not be chosen before authentification is successed.");
  418. }
  419. KeyExchange kex = null;
  420. try
  421. {
  422. var c = Type.GetType(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));
  423. kex = (KeyExchange) Activator.CreateInstance(c);
  424. }
  425. catch (Exception e)
  426. {
  427. Console.Error.WriteLine("kex: " + e);
  428. }
  429. kex._guess = guess;
  430. kex.init(this, V_S, V_C, I_S, I_C);
  431. return kex;
  432. }
  433. private bool in_kex = false;
  434. public void rekey()
  435. {
  436. send_kexinit();
  437. }
  438. private void send_kexinit()
  439. {
  440. if (in_kex) return;
  441. in_kex = true;
  442. packet.reset();
  443. buf.putByte((byte) SSH_MSG_KEXINIT);
  444. lock (random)
  445. {
  446. random.fill(buf.buffer, buf.index, 16);
  447. buf.skip(16);
  448. }
  449. buf.putString(getConfig("kex").GetBytes());
  450. buf.putString(getConfig("server_host_key").GetBytes());
  451. buf.putString(getConfig("cipher.c2s").GetBytes());
  452. buf.putString(getConfig("cipher.s2c").GetBytes());
  453. buf.putString(getConfig("mac.c2s").GetBytes());
  454. buf.putString(getConfig("mac.s2c").GetBytes());
  455. buf.putString(getConfig("compression.c2s").GetBytes());
  456. buf.putString(getConfig("compression.s2c").GetBytes());
  457. buf.putString(getConfig("lang.c2s").GetBytes());
  458. buf.putString(getConfig("lang.s2c").GetBytes());
  459. buf.putByte((byte) 0);
  460. buf.putInt(0);
  461. buf.setOffSet(5);
  462. I_C = new byte[buf.getLength()];
  463. buf.getByte(I_C);
  464. write(packet);
  465. }
  466. private void send_newkeys()
  467. {
  468. // send SSH_MSG_NEWKEYS(21)
  469. packet.reset();
  470. buf.putByte((byte) SSH_MSG_NEWKEYS);
  471. write(packet);
  472. }
  473. private void checkHost(String host, KeyExchange kex)
  474. {
  475. String shkc = getConfig("StrictHostKeyChecking");
  476. byte[] K_S = kex.getHostKey();
  477. String key_type = kex.getKeyType();
  478. String key_fprint = kex.getFingerPrint();
  479. hostkey = new HostKey(host, K_S);
  480. HostKeyRepository hkr = jsch.getHostKeyRepository();
  481. int i = 0;
  482. lock (hkr)
  483. {
  484. i = hkr.check(host, K_S);
  485. }
  486. bool insert = false;
  487. if ((shkc.Equals("ask") || shkc.Equals("yes")) &&
  488. i == HostKeyRepository.CHANGED)
  489. {
  490. String file = null;
  491. lock (hkr)
  492. {
  493. file = hkr.getKnownHostsRepositoryID();
  494. }
  495. if (file == null)
  496. {
  497. file = "known_hosts";
  498. }
  499. String message =
  500. "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n" +
  501. "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n" +
  502. "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n" +
  503. "It is also possible that the " + key_type + " host key has just been changed.\n" +
  504. "The fingerprint for the " + key_type + " key sent by the remote host is\n" +
  505. key_fprint + ".\n" +
  506. "Please contact your system administrator.\n" +
  507. "Add correct host key in " + file + " to get rid of this message.";
  508. bool b = false;
  509. if (userinfo != null)
  510. {
  511. b = userinfo.promptYesNo(message +
  512. "\nDo you want to delete the old key and insert the new key?");
  513. }
  514. if (!b)
  515. {
  516. throw new JSchException("HostKey has been changed: " + host);
  517. }
  518. else
  519. {
  520. lock (hkr)
  521. {
  522. hkr.remove(host,
  523. (key_type.Equals("DSA") ? "ssh-dss" : "ssh-rsa"),
  524. null);
  525. insert = true;
  526. }
  527. }
  528. }
  529. if ((shkc.Equals("ask") || shkc.Equals("yes")) &&
  530. (i != HostKeyRepository.OK) && !insert)
  531. {
  532. if (shkc.Equals("yes"))
  533. {
  534. throw new JSchException("reject HostKey: " + host);
  535. }
  536. if (userinfo != null)
  537. {
  538. bool foo = userinfo.promptYesNo(
  539. "The authenticity of host '" + host + "' can't be established.\n" +
  540. key_type + " key fingerprint is " + key_fprint + ".\n" +
  541. "Are you sure you want to continue connecting?"
  542. );
  543. if (!foo)
  544. {
  545. throw new JSchException("reject HostKey: " + host);
  546. }
  547. insert = true;
  548. }
  549. else
  550. {
  551. if (i == HostKeyRepository.NOT_INCLUDED)
  552. throw new JSchException("UnknownHostKey: " + host + ". " + key_type + " key fingerprint is " + key_fprint);
  553. else throw new JSchException("HostKey has been changed: " + host);
  554. }
  555. }
  556. if (shkc.Equals("no") &&
  557. HostKeyRepository.NOT_INCLUDED == i)
  558. {
  559. insert = true;
  560. }
  561. if (insert)
  562. {
  563. lock (hkr)
  564. {
  565. hkr.add(host, K_S, userinfo);
  566. }
  567. }
  568. }
  569. public Channel openChannel(String type)
  570. {
  571. if (!_isConnected)
  572. {
  573. throw new JSchException("session is down");
  574. }
  575. try
  576. {
  577. Channel channel = Channel.getChannel(type);
  578. addChannel(channel);
  579. channel.init();
  580. return channel;
  581. }
  582. catch (Exception e)
  583. {
  584. Console.WriteLine(e);
  585. }
  586. return null;
  587. }
  588. // encode will bin invoked in write with synchronization.
  589. public void encode(Packet packet)
  590. {
  591. if (deflater != null)
  592. {
  593. packet.buffer.index = deflater.compress(packet.buffer.buffer,
  594. 5, packet.buffer.index);
  595. }
  596. if (c2scipher != null)
  597. {
  598. packet.padding(c2scipher.getIVSize());
  599. int pad = packet.buffer.buffer[4];
  600. lock (random)
  601. {
  602. random.fill(packet.buffer.buffer, packet.buffer.index - pad, pad);
  603. }
  604. }
  605. else
  606. {
  607. packet.padding(8);
  608. }
  609. byte[] mac = null;
  610. if (c2smac != null)
  611. {
  612. c2smac.update(seqo);
  613. c2smac.update(packet.buffer.buffer, 0, packet.buffer.index);
  614. mac = c2smac.doFinal();
  615. }
  616. if (c2scipher != null)
  617. {
  618. byte[] buf = packet.buffer.buffer;
  619. c2scipher.update(buf, 0, packet.buffer.index, buf, 0);
  620. }
  621. if (mac != null)
  622. {
  623. packet.buffer.putByte(mac);
  624. }
  625. }
  626. private int[] uncompress_len = new int[1];
  627. private int cipher_size = 8;
  628. public Buffer read(Buffer buf)
  629. {
  630. int j = 0;
  631. while (true)
  632. {
  633. buf.reset();
  634. io.getByte(buf.buffer, buf.index, cipher_size);
  635. buf.index += cipher_size;
  636. if (s2ccipher != null)
  637. {
  638. s2ccipher.update(buf.buffer, 0, cipher_size, buf.buffer, 0);
  639. }
  640. j = Util.ToInt32(buf.buffer, 0);
  641. j = j - 4 - cipher_size + 8;
  642. if (j < 0 || (buf.index + j) > buf.buffer.Length)
  643. {
  644. throw new IOException("invalid data");
  645. }
  646. if (j > 0)
  647. {
  648. io.getByte(buf.buffer, buf.index, j);
  649. buf.index += (j);
  650. if (s2ccipher != null)
  651. {
  652. s2ccipher.update(buf.buffer, cipher_size, j, buf.buffer, cipher_size);
  653. }
  654. }
  655. if (s2cmac != null)
  656. {
  657. s2cmac.update(seqi);
  658. s2cmac.update(buf.buffer, 0, buf.index);
  659. byte[] result = s2cmac.doFinal();
  660. io.getByte(mac_buf, 0, mac_buf.Length);
  661. if (result.Length != mac_buf.Length) throw new IOException("MAC Error");
  662. for (int i = 0; i < result.Length; i++)
  663. {
  664. if (result[i] != mac_buf[i])
  665. {
  666. throw new IOException("MAC Error");
  667. }
  668. }
  669. }
  670. seqi++;
  671. if (inflater != null)
  672. {
  673. //inflater.uncompress(buf);
  674. int pad = buf.buffer[4];
  675. uncompress_len[0] = buf.index - 5 - pad;
  676. byte[] foo = inflater.uncompress(buf.buffer, 5, uncompress_len);
  677. if (foo != null)
  678. {
  679. buf.buffer = foo;
  680. buf.index = 5 + uncompress_len[0];
  681. }
  682. else
  683. {
  684. Console.Error.WriteLine("fail in inflater");
  685. break;
  686. }
  687. }
  688. int type = buf.buffer[5] & 0xff;
  689. //System.Console.WriteLine("read: "+type);
  690. if (type == SSH_MSG_DISCONNECT)
  691. {
  692. buf.rewind();
  693. buf.getInt();
  694. buf.getShort();
  695. int reason_code = buf.getInt();
  696. byte[] description = buf.getString();
  697. byte[] language_tag = buf.getString();
  698. /*
  699. System.Console.Error.WriteLine("SSH_MSG_DISCONNECT:"+
  700. " "+reason_code+
  701. " "+new String(description)+
  702. " "+new String(language_tag));
  703. */
  704. throw new JSchException("SSH_MSG_DISCONNECT:" +
  705. " " + reason_code +
  706. " " + new JavaString(description) +
  707. " " + new JavaString(language_tag));
  708. //break;
  709. }
  710. else if (type == SSH_MSG_IGNORE)
  711. {
  712. }
  713. else if (type == SSH_MSG_DEBUG)
  714. {
  715. buf.rewind();
  716. buf.getInt();
  717. buf.getShort();
  718. }
  719. else if (type == SSH_MSG_CHANNEL_WINDOW_ADJUST)
  720. {
  721. buf.rewind();
  722. buf.getInt();
  723. buf.getShort();
  724. Channel c = Channel.getChannel(buf.getInt(), this);
  725. if (c == null)
  726. {
  727. }
  728. else
  729. {
  730. c.addRemoteWindowSize(buf.getInt());
  731. }
  732. }
  733. else
  734. {
  735. break;
  736. }
  737. }
  738. buf.rewind();
  739. return buf;
  740. }
  741. internal byte[] getSessionId()
  742. {
  743. return session_id;
  744. }
  745. private void receive_newkeys(Buffer buf, KeyExchange kex)
  746. {
  747. updateKeys(kex);
  748. in_kex = false;
  749. }
  750. private void updateKeys(KeyExchange kex)
  751. {
  752. byte[] K = kex.getK();
  753. byte[] H = kex.getH();
  754. HASH hash = kex.getHash();
  755. String[] guess = kex._guess;
  756. if (session_id == null)
  757. {
  758. session_id = new byte[H.Length];
  759. Array.Copy(H, 0, session_id, 0, H.Length);
  760. }
  761. /*
  762. Initial IV client to server: HASH (K || H || "A" || session_id)
  763. Initial IV server to client: HASH (K || H || "B" || session_id)
  764. Encryption key client to server: HASH (K || H || "C" || session_id)
  765. Encryption key server to client: HASH (K || H || "D" || session_id)
  766. Integrity key client to server: HASH (K || H || "E" || session_id)
  767. Integrity key server to client: HASH (K || H || "F" || session_id)
  768. */
  769. buf.reset();
  770. buf.putMPInt(K);
  771. buf.putByte(H);
  772. buf.putByte((byte) 0x41);
  773. buf.putByte(session_id);
  774. hash.update(buf.buffer, 0, buf.index);
  775. IVc2s = hash.digest();
  776. int j = buf.index - session_id.Length - 1;
  777. buf.buffer[j]++;
  778. hash.update(buf.buffer, 0, buf.index);
  779. IVs2c = hash.digest();
  780. buf.buffer[j]++;
  781. hash.update(buf.buffer, 0, buf.index);
  782. Ec2s = hash.digest();
  783. buf.buffer[j]++;
  784. hash.update(buf.buffer, 0, buf.index);
  785. Es2c = hash.digest();
  786. buf.buffer[j]++;
  787. hash.update(buf.buffer, 0, buf.index);
  788. MACc2s = hash.digest();
  789. buf.buffer[j]++;
  790. hash.update(buf.buffer, 0, buf.index);
  791. MACs2c = hash.digest();
  792. try
  793. {
  794. var c = Type.GetType(getConfig(guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC]));
  795. s2ccipher = (Cipher) (Activator.CreateInstance(c));
  796. while (s2ccipher.getBlockSize() > Es2c.Length)
  797. {
  798. buf.reset();
  799. buf.putMPInt(K);
  800. buf.putByte(H);
  801. buf.putByte(Es2c);
  802. hash.update(buf.buffer, 0, buf.index);
  803. byte[] foo = hash.digest();
  804. byte[] bar = new byte[Es2c.Length + foo.Length];
  805. Array.Copy(Es2c, 0, bar, 0, Es2c.Length);
  806. Array.Copy(foo, 0, bar, Es2c.Length, foo.Length);
  807. Es2c = bar;
  808. }
  809. s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c);
  810. cipher_size = s2ccipher.getIVSize();
  811. c = Type.GetType(getConfig(guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC]));
  812. s2cmac = (MAC) (Activator.CreateInstance(c));
  813. s2cmac.init(MACs2c);
  814. mac_buf = new byte[s2cmac.getBlockSize()];
  815. c = Type.GetType(getConfig(guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS]));
  816. c2scipher = (Cipher) (Activator.CreateInstance(c));
  817. while (c2scipher.getBlockSize() > Ec2s.Length)
  818. {
  819. buf.reset();
  820. buf.putMPInt(K);
  821. buf.putByte(H);
  822. buf.putByte(Ec2s);
  823. hash.update(buf.buffer, 0, buf.index);
  824. byte[] foo = hash.digest();
  825. byte[] bar = new byte[Ec2s.Length + foo.Length];
  826. Array.Copy(Ec2s, 0, bar, 0, Ec2s.Length);
  827. Array.Copy(foo, 0, bar, Ec2s.Length, foo.Length);
  828. Ec2s = bar;
  829. }
  830. c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s);
  831. c = Type.GetType(getConfig(guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS]));
  832. c2smac = (MAC) (Activator.CreateInstance(c));
  833. c2smac.init(MACc2s);
  834. if (!guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS].Equals("none"))
  835. {
  836. String foo = getConfig(guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS]);
  837. if (foo != null)
  838. {
  839. try
  840. {
  841. c = Type.GetType(foo);
  842. deflater = (Compression)(Activator.CreateInstance(c));
  843. int level = 6;
  844. try
  845. {
  846. level = Int32.Parse(getConfig("compression_level"));
  847. }
  848. catch (Exception ee)
  849. {
  850. }
  851. deflater.init(Compression.DEFLATER, level);
  852. }
  853. catch (Exception ee)
  854. {
  855. Console.Error.WriteLine(foo + " isn't accessible.");
  856. }
  857. }
  858. }
  859. else
  860. {
  861. if (deflater != null)
  862. {
  863. deflater = null;
  864. }
  865. }
  866. if (!guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC].Equals("none"))
  867. {
  868. String foo = getConfig(guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC]);
  869. if (foo != null)
  870. {
  871. try
  872. {
  873. c = Type.GetType(foo);
  874. inflater = (Compression)(Activator.CreateInstance(c));
  875. inflater.init(Compression.INFLATER, 0);
  876. }
  877. catch (Exception ee)
  878. {
  879. Console.Error.WriteLine(foo + " isn't accessible.");
  880. }
  881. }
  882. }
  883. else
  884. {
  885. if (inflater != null)
  886. {
  887. inflater = null;
  888. }
  889. }
  890. }
  891. catch (Exception e)
  892. {
  893. Console.Error.WriteLine("updatekeys: " + e);
  894. }
  895. }
  896. public void write(Packet packet, Channel c, int length)
  897. {
  898. while (true)
  899. {
  900. if (in_kex)
  901. {
  902. try
  903. {
  904. Thread.Sleep(10);
  905. }
  906. catch (ThreadInterruptedException e)
  907. {
  908. }
  909. ;
  910. continue;
  911. }
  912. lock (c)
  913. {
  914. if (c.rwsize >= length)
  915. {
  916. c.rwsize -= length;
  917. break;
  918. }
  919. }
  920. if (c._close || !c.isConnected())
  921. {
  922. throw new IOException("channel is broken");
  923. }
  924. bool sendit = false;
  925. int s = 0;
  926. byte command = 0;
  927. int recipient = -1;
  928. lock (c)
  929. {
  930. if (c.rwsize > 0)
  931. {
  932. int len = c.rwsize;
  933. if (len > length)
  934. {
  935. len = length;
  936. }
  937. if (len != length)
  938. {
  939. s = packet.shift(len, (c2smac != null ? c2smac.getBlockSize() : 0));
  940. }
  941. command = packet.buffer.buffer[5];
  942. recipient = c.getRecipient();
  943. length -= len;
  944. c.rwsize -= len;
  945. sendit = true;
  946. }
  947. }
  948. if (sendit)
  949. {
  950. _write(packet);
  951. if (length == 0)
  952. {
  953. return;
  954. }
  955. packet.unshift(command, recipient, s, length);
  956. lock (c)
  957. {
  958. if (c.rwsize >= length)
  959. {
  960. c.rwsize -= length;
  961. break;
  962. }
  963. }
  964. }
  965. try
  966. {
  967. Thread.Sleep(100);
  968. }
  969. catch (ThreadInterruptedException e)
  970. {
  971. }
  972. ;
  973. }
  974. _write(packet);
  975. }
  976. public void write(Packet packet)
  977. {
  978. while (in_kex)
  979. {
  980. byte command = packet.buffer.buffer[5];
  981. if (command == SSH_MSG_KEXINIT ||
  982. command == SSH_MSG_NEWKEYS ||
  983. command == SSH_MSG_KEXDH_INIT ||
  984. command == SSH_MSG_KEXDH_REPLY ||
  985. command == SSH_MSG_DISCONNECT ||
  986. command == SSH_MSG_KEX_DH_GEX_GROUP ||
  987. command == SSH_MSG_KEX_DH_GEX_INIT ||
  988. command == SSH_MSG_KEX_DH_GEX_REPLY ||
  989. command == SSH_MSG_KEX_DH_GEX_REQUEST)
  990. {
  991. break;
  992. }
  993. try
  994. {
  995. Thread.Sleep(10);
  996. }
  997. catch (ThreadInterruptedException e)
  998. {
  999. }
  1000. ;
  1001. }
  1002. _write(packet);
  1003. }
  1004. [MethodImpl(MethodImplOptions.Synchronized)]
  1005. private void _write(Packet packet)
  1006. {
  1007. encode(packet);
  1008. if (io != null)
  1009. {
  1010. io.put(packet);
  1011. seqo++;
  1012. }
  1013. }
  1014. private JavaRunnable thread;
  1015. public void run()
  1016. {
  1017. thread = this;
  1018. byte[] foo;
  1019. Buffer buf = new Buffer();
  1020. Packet packet = new Packet(buf);
  1021. int i = 0;
  1022. Channel channel;
  1023. int[] start = new int[1];
  1024. int[] length = new int[1];
  1025. KeyExchange kex = null;
  1026. try
  1027. {
  1028. while (_isConnected &&
  1029. thread != null)
  1030. {
  1031. buf = read(buf);
  1032. int msgType = buf.buffer[5] & 0xff;
  1033. if (kex != null && kex.getState() == msgType)
  1034. {
  1035. bool result = kex.next(buf);
  1036. if (!result)
  1037. {
  1038. throw new JSchException("verify: " + result);
  1039. }
  1040. continue;
  1041. }
  1042. switch (msgType)
  1043. {
  1044. case SSH_MSG_KEXINIT:
  1045. //System.Console.WriteLine("KEXINIT");
  1046. kex = receive_kexinit(buf);
  1047. break;
  1048. case SSH_MSG_NEWKEYS:
  1049. //System.Console.WriteLine("NEWKEYS");
  1050. send_newkeys();
  1051. receive_newkeys(buf, kex);
  1052. kex = null;
  1053. break;
  1054. case SSH_MSG_CHANNEL_DATA:
  1055. buf.getInt();
  1056. buf.getByte();
  1057. buf.getByte();
  1058. i = buf.getInt();
  1059. channel = Channel.getChannel(i, this);
  1060. foo = buf.getString(start, length);
  1061. if (channel == null)
  1062. {
  1063. break;
  1064. }
  1065. try
  1066. {
  1067. channel.write(foo, start[0], length[0]);
  1068. }
  1069. catch (Exception e)
  1070. {
  1071. //System.Console.WriteLine(e);
  1072. try
  1073. {
  1074. channel.disconnect();
  1075. }
  1076. catch (Exception ee)
  1077. {
  1078. }
  1079. break;
  1080. }
  1081. int len = length[0];
  1082. channel.setLocalWindowSize(channel.lwsize - len);
  1083. if (channel.lwsize < channel.lwsize_max/2)
  1084. {
  1085. packet.reset();
  1086. buf.putByte((byte) SSH_MSG_CHANNEL_WINDOW_ADJUST);
  1087. buf.putInt(channel.getRecipient());
  1088. buf.putInt(channel.lwsize_max - channel.lwsize);
  1089. write(packet);
  1090. channel.setLocalWindowSize(channel.lwsize_max);
  1091. }
  1092. break;
  1093. case SSH_MSG_CHANNEL_EXTENDED_DATA:
  1094. buf.getInt();
  1095. buf.getShort();
  1096. i = buf.getInt();
  1097. channel = Channel.getChannel(i, this);
  1098. buf.getInt(); // data_type_code == 1
  1099. foo = buf.getString(start, length);
  1100. //System.Console.WriteLine("stderr: "+new String(foo,start[0],length[0]));
  1101. if (channel == null)
  1102. {
  1103. break;
  1104. }
  1105. //channel.write(foo, start[0], length[0]);
  1106. channel.write_ext(foo, start[0], length[0]);
  1107. len = length[0];
  1108. channel.setLocalWindowSize(channel.lwsize - len);
  1109. if (channel.lwsize < channel.lwsize_max/2)
  1110. {
  1111. packet.reset();
  1112. buf.putByte((byte) SSH_MSG_CHANNEL_WINDOW_ADJUST);
  1113. buf.putInt(channel.getRecipient());
  1114. buf.putInt(channel.lwsize_max - channel.lwsize);
  1115. write(packet);
  1116. channel.setLocalWindowSize(channel.lwsize_max);
  1117. }
  1118. break;
  1119. case SSH_MSG_CHANNEL_WINDOW_ADJUST:
  1120. buf.getInt();
  1121. buf.getShort();
  1122. i = buf.getInt();
  1123. channel = Channel.getChannel(i, this);
  1124. if (channel == null)
  1125. {
  1126. break;
  1127. }
  1128. channel.addRemoteWindowSize(buf.getInt());
  1129. break;
  1130. case SSH_MSG_CHANNEL_EOF:
  1131. buf.getInt();
  1132. buf.getShort();
  1133. i = buf.getInt();
  1134. channel = Channel.getChannel(i, this);
  1135. if (channel != null)
  1136. {
  1137. //channel._eof_remote=true;
  1138. //channel.eof();
  1139. channel.eof_remote();
  1140. }
  1141. /*
  1142. packet.reset();
  1143. buf.putByte((byte)SSH_MSG_CHANNEL_EOF);
  1144. buf.putInt(channel.getRecipient());
  1145. write(packet);
  1146. */
  1147. break;
  1148. case SSH_MSG_CHANNEL_CLOSE:
  1149. buf.getInt();
  1150. buf.getShort();
  1151. i = buf.getInt();
  1152. channel = Channel.getChannel(i, this);
  1153. if (channel != null)
  1154. {
  1155. // channel.close();
  1156. channel.disconnect();
  1157. }
  1158. /*
  1159. if(Channel.pool.Count==0){
  1160. thread=null;
  1161. }
  1162. */
  1163. break;
  1164. case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
  1165. buf.getInt();
  1166. buf.getShort();
  1167. i = buf.getInt();
  1168. channel = Channel.getChannel(i, this);
  1169. if (channel == null)
  1170. {
  1171. //break;
  1172. }
  1173. channel.setRecipient(buf.getInt());
  1174. channel.setRemoteWindowSize(buf.getInt());
  1175. channel.setRemotePacketSize(buf.getInt());
  1176. break;
  1177. case SSH_MSG_CHANNEL_OPEN_FAILURE:
  1178. buf.getInt();
  1179. buf.getShort();
  1180. i = buf.getInt();
  1181. channel = Channel.getChannel(i, this);
  1182. if (channel == null)
  1183. {
  1184. //break;
  1185. }
  1186. int reason_code = buf.getInt();
  1187. //foo=buf.getString(); // additional textual information
  1188. //foo=buf.getString(); // language tag
  1189. channel.exitstatus = reason_code;
  1190. channel._close = true;
  1191. channel._eof_remote = true;
  1192. channel.setRecipient(0);
  1193. break;
  1194. case SSH_MSG_CHANNEL_REQUEST:
  1195. buf.getInt();
  1196. buf.getShort();
  1197. i = buf.getInt();
  1198. foo = buf.getString();
  1199. bool reply = (buf.getByte() != 0);
  1200. channel = Channel.getChannel(i, this);
  1201. if (channel != null)
  1202. {
  1203. byte reply_type = (byte) SSH_MSG_CHANNEL_FAILURE;
  1204. if ((new JavaString(foo)).Equals("exit-status"))
  1205. {
  1206. i = buf.getInt(); // exit-status
  1207. channel.setExitStatus(i);
  1208. // System.Console.WriteLine("exit-stauts: "+i);
  1209. // channel.close();
  1210. reply_type = (byte) SSH_MSG_CHANNEL_SUCCESS;
  1211. }
  1212. if (reply)
  1213. {
  1214. packet.reset();
  1215. buf.putByte(reply_type);
  1216. buf.putInt(channel.getRecipient());
  1217. write(packet);
  1218. }
  1219. }
  1220. else
  1221. {
  1222. }
  1223. break;
  1224. case SSH_MSG_CHANNEL_OPEN:
  1225. buf.getInt();
  1226. buf.getShort();

Large files files are truncated, but you can click here to view the full file