SSH1Connection.cs
上传用户:szltgg
上传日期:2019-05-16
资源大小:604k
文件大小:23k
源码类别:

Telnet服务器

开发平台:

C#

  1. /* ---------------------------------------------------------------------------
  2.  *
  3.  * Copyright (c) Granados Networks, Inc.    All Rights Reserved..
  4.  * 
  5.  * This file is a part of the Granados SSH Client Library that is subject to
  6.  * the license included in the distributed package.
  7.  * You may not use this file except in compliance with the license.
  8.  * 
  9.  * ---------------------------------------------------------------------------
  10.  */
  11. using System;
  12. using System.IO;
  13. using System.Security.Cryptography;
  14. using System.Net.Sockets;
  15. using System.Text;
  16. using System.Diagnostics;
  17. using Granados.PKI;
  18. using Granados.SSHC;
  19. using Granados.Toolkit;
  20. namespace Granados.SSHCV1
  21. {
  22. public sealed class SSH1Connection : SSHConnection {
  23. private const int AUTH_NOT_REQUIRED = 0;
  24. private const int AUTH_REQUIRED = 1;
  25. private SSH1ConnectionInfo _cInfo;
  26. private int _shellID;
  27. private SSH1PacketBuilder _packetBuilder;
  28. private bool _executingShell;
  29. public SSH1Connection(SSHConnectionParameter param, ISSHConnectionEventReceiver er, string serverversion, string clientversion) : base(param, er) {
  30. _cInfo = new SSH1ConnectionInfo();
  31. _cInfo._serverVersionString = serverversion;
  32. _cInfo._clientVersionString = clientversion;
  33. _shellID = -1;
  34. _packetBuilder = new SSH1PacketBuilder(new SynchronizedSSH1PacketHandler());
  35. }
  36. public override SSHConnectionInfo ConnectionInfo {
  37. get {
  38. return _cInfo;
  39. }
  40. }
  41. internal override IByteArrayHandler PacketBuilder {
  42. get {
  43. return _packetBuilder;
  44. }
  45. }
  46. public override int ChannelCount {
  47. get {
  48. return base.ChannelCount + 1; //'1' is for the shell
  49. }
  50. }
  51. internal override AuthenticationResult Connect(AbstractSocket s) {
  52. _stream = s;
  53. // Phase2 receives server keys
  54. ReceiveServerKeys();
  55. if(_param.KeyCheck!=null && !_param.KeyCheck(_cInfo)) {
  56. _stream.Close();
  57. return AuthenticationResult.Failure;
  58. }
  59. // Phase3 generates session key
  60. byte[] session_key = GenerateSessionKey();
  61. // Phase4 establishes the session key
  62. try {
  63. _packetBuilder.SetSignal(false);
  64. SendSessionKey(session_key);
  65. InitCipher(session_key);
  66. }
  67. finally {
  68. _packetBuilder.SetSignal(true);
  69. }
  70. ReceiveKeyConfirmation();
  71. // Phase5 user authentication
  72. SendUserName(_param.UserName);
  73. if(ReceiveAuthenticationRequirement()==AUTH_REQUIRED) {
  74. if(_param.AuthenticationType==AuthenticationType.Password) {
  75. SendPlainPassword();
  76. } else if(_param.AuthenticationType==AuthenticationType.PublicKey) {
  77. DoRSAChallengeResponse();
  78. }
  79. bool auth = ReceiveAuthenticationResult();
  80. if(!auth) throw new SSHException(Strings.GetString("AuthenticationFailed"));
  81. }
  82. _packetBuilder.Handler = new CallbackSSH1PacketHandler(this);
  83. return AuthenticationResult.Success;
  84. }
  85. internal void Transmit(SSH1Packet p) {
  86. lock(this) {
  87. p.WriteTo(_stream, _tCipher);
  88. }
  89. }
  90. public override void Disconnect(string msg) {
  91. if(_closed) return;
  92. SSH1DataWriter w = new SSH1DataWriter();
  93. w.Write(msg);
  94. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_DISCONNECT, w.ToByteArray());
  95. p.WriteTo(_stream, _tCipher);
  96. _stream.Flush();
  97. _closed = true;
  98. _stream.Close();
  99. }
  100. public override void Close() {
  101. if(_closed) return;
  102. _closed = true;
  103. _stream.Close();
  104. public override void SendIgnorableData(string msg) {
  105. SSH1DataWriter w = new SSH1DataWriter();
  106. w.Write(msg);
  107. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_IGNORE, w.ToByteArray());
  108. Transmit(p);
  109. }
  110. private void ReceiveServerKeys() {
  111. SSH1Packet SSH1Packet = ReceivePacket();
  112. if(SSH1Packet.Type!=PacketType.SSH_SMSG_PUBLIC_KEY) throw new SSHException("unexpected SSH SSH1Packet type " + SSH1Packet.Type, SSH1Packet.Data);
  113. SSH1DataReader reader = new SSH1DataReader(SSH1Packet.Data);
  114. _cInfo._serverinfo = new SSHServerInfo(reader); 
  115. _cInfo._hostkey = new RSAPublicKey(_cInfo._serverinfo.host_key_public_exponent, _cInfo._serverinfo.host_key_public_modulus);
  116. //read protocol support parameters
  117. int protocol_flags = reader.ReadInt32();
  118. int supported_ciphers_mask = reader.ReadInt32();
  119. _cInfo.SetSupportedCipherAlgorithms(supported_ciphers_mask);
  120. int supported_authentications_mask = reader.ReadInt32();
  121. //Debug.WriteLine(String.Format("ServerOptions {0} {1} {2}", protocol_flags, supported_ciphers_mask, supported_authentications_mask));
  122. if(reader.Rest>0) throw new SSHException("data length mismatch", SSH1Packet.Data);
  123. //Debug Info
  124. /*
  125. System.out.println("Flags="+protocol_flags);
  126. System.out.println("Cipher="+supported_ciphers_mask);
  127. System.out.println("Auth="+supported_authentications_mask);
  128. */
  129. bool found = false;
  130. foreach(CipherAlgorithm a in _param.PreferableCipherAlgorithms) {
  131. if(a!=CipherAlgorithm.Blowfish && a!=CipherAlgorithm.TripleDES)
  132. continue;
  133. else if(a==CipherAlgorithm.Blowfish && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.Blowfish))==0)
  134. continue; 
  135. else if(a==CipherAlgorithm.TripleDES && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.TripleDES))==0)
  136. continue; 
  137. _cInfo._algorithmForReception = _cInfo._algorithmForTransmittion = a;  
  138. found = true;
  139. break;
  140. }
  141. if(!found) 
  142. throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedX"), "Blowfish/TripleDES"));
  143. if(_param.AuthenticationType==AuthenticationType.Password && (supported_authentications_mask & (1 << (int)AuthenticationType.Password))==0)
  144. throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedPassword")), SSH1Packet.Data);
  145. if(_param.AuthenticationType==AuthenticationType.PublicKey && (supported_authentications_mask & (1 << (int)AuthenticationType.PublicKey))==0)
  146. throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedRSA")), SSH1Packet.Data);
  147. }
  148. private byte[] GenerateSessionKey() {
  149. //session key(256bits)
  150. byte[] session_key = new byte[32];
  151. _param.Random.NextBytes(session_key); 
  152. //for(int i=0; i<32; i++) Debug.Write(String.Format("0x{0:x}, ", session_key[i]));
  153. return session_key;
  154. }
  155. private void SendSessionKey(byte[] session_key) {
  156. try
  157. {
  158. //step1 XOR with session_id
  159. byte[] working_data = new byte[session_key.Length];
  160. byte[] session_id = CalcSessionID();
  161. Array.Copy(session_key, 0, working_data, 0, session_key.Length);
  162. for(int i=0; i<session_id.Length; i++) working_data[i] ^= session_id[i];
  163. //step2 decrypts with RSA
  164. RSAPublicKey first_encryption;
  165. RSAPublicKey second_encryption;
  166. SSHServerInfo si = _cInfo._serverinfo;
  167. int first_key_bytelen, second_key_bytelen;
  168. if(si.server_key_bits < si.host_key_bits)
  169. {
  170. first_encryption  = new RSAPublicKey(si.server_key_public_exponent, si.server_key_public_modulus);
  171. second_encryption = new RSAPublicKey(si.host_key_public_exponent, si.host_key_public_modulus);
  172. first_key_bytelen = (si.server_key_bits+7)/8;
  173. second_key_bytelen = (si.host_key_bits+7)/8;
  174. }
  175. else
  176. {
  177. first_encryption  = new RSAPublicKey(si.host_key_public_exponent, si.host_key_public_modulus);
  178. second_encryption = new RSAPublicKey(si.server_key_public_exponent, si.server_key_public_modulus);
  179. first_key_bytelen = (si.host_key_bits+7)/8;
  180. second_key_bytelen = (si.server_key_bits+7)/8;
  181. }
  182. BigInteger first_result = RSAUtil.PKCS1PadType2(new BigInteger(working_data), first_key_bytelen, _param.Random).modPow(first_encryption.Exponent, first_encryption.Modulus);
  183. BigInteger second_result = RSAUtil.PKCS1PadType2(first_result, second_key_bytelen, _param.Random).modPow(second_encryption.Exponent, second_encryption.Modulus);
  184. //output
  185. SSH1DataWriter writer = new SSH1DataWriter();
  186. writer.Write((byte)_cInfo._algorithmForTransmittion);
  187. writer.Write(si.anti_spoofing_cookie);
  188. writer.Write(second_result);
  189. writer.Write(0); //protocol flags
  190. //send
  191. SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_SESSION_KEY, writer.ToByteArray());
  192. SSH1Packet.WriteTo(_stream);
  193. _sessionID = session_id;
  194. }
  195. catch(Exception e)
  196. {
  197. if(e is IOException)
  198. throw (IOException)e;
  199. else
  200. {
  201. string t = e.StackTrace;
  202. throw new SSHException(e.Message); //IOException埲奜偼傒側SSHException偵偟偰偟傑偆
  203. }
  204. }
  205. }
  206. private void ReceiveKeyConfirmation() {
  207. SSH1Packet SSH1Packet = ReceivePacket();
  208. if(SSH1Packet.Type!=PacketType.SSH_SMSG_SUCCESS)
  209. throw new SSHException("unexpected packet type [" + SSH1Packet.Type +"] at ReceiveKeyConfirmation()", SSH1Packet.Data);
  210. }
  211. private int ReceiveAuthenticationRequirement() {
  212. SSH1Packet SSH1Packet = ReceivePacket();
  213. if(SSH1Packet.Type==PacketType.SSH_SMSG_SUCCESS)
  214. return AUTH_NOT_REQUIRED;
  215. else if(SSH1Packet.Type==PacketType.SSH_SMSG_FAILURE)
  216. return AUTH_REQUIRED;  
  217. else
  218. throw new SSHException("type " + SSH1Packet.Type, SSH1Packet.Data);
  219. }
  220. private void SendUserName(string username) {
  221. SSH1DataWriter writer = new SSH1DataWriter();
  222. writer.Write(username);
  223. SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_USER, writer.ToByteArray());
  224. SSH1Packet.WriteTo(_stream, _tCipher);
  225. }
  226. private void SendPlainPassword() {
  227. SSH1DataWriter writer = new SSH1DataWriter();
  228. writer.Write(_param.Password);
  229. SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_AUTH_PASSWORD, writer.ToByteArray());
  230. SSH1Packet.WriteTo(_stream, _tCipher);
  231. }
  232. //RSA authentication
  233. private void DoRSAChallengeResponse() {
  234. //read key
  235. SSH1UserAuthKey key = new SSH1UserAuthKey(_param.IdentityFile, _param.Password);
  236. SSH1DataWriter w = new SSH1DataWriter();
  237. w.Write(key.PublicModulus);
  238. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_AUTH_RSA, w.ToByteArray());
  239. p.WriteTo(_stream, _tCipher);
  240. p = ReceivePacket();
  241. if(p.Type==PacketType.SSH_SMSG_FAILURE)
  242. throw new SSHException(Strings.GetString("ServerRefusedRSA"));
  243. else if(p.Type!=PacketType.SSH_SMSG_AUTH_RSA_CHALLENGE)
  244. throw new SSHException(String.Format(Strings.GetString("UnexpectedResponse"), p.Type));
  245. //creating challenge
  246. SSH1DataReader r = new SSH1DataReader(p.Data);
  247. BigInteger challenge = key.decryptChallenge(r.ReadMPInt());
  248. byte[] rawchallenge = RSAUtil.StripPKCS1Pad(challenge, 2).getBytes();
  249. //building response
  250. MemoryStream bos = new MemoryStream();
  251. bos.Write(rawchallenge, 0, rawchallenge.Length); //!!mindterm偱偼摢偑侽偐偳偆偐偱曄側僴儞僪儕儞僌偑偁偭偨
  252. bos.Write(_sessionID, 0, _sessionID.Length);
  253. byte[] response = new MD5CryptoServiceProvider().ComputeHash(bos.ToArray());
  254. w = new SSH1DataWriter();
  255. w.Write(response);
  256. p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_AUTH_RSA_RESPONSE, w.ToByteArray());
  257. p.WriteTo(_stream, _tCipher);
  258. }
  259. private bool ReceiveAuthenticationResult() {
  260. SSH1Packet SSH1Packet = ReceivePacket();
  261. PacketType type = SSH1Packet.Type;
  262. if(type==PacketType.SSH_MSG_DEBUG) {
  263. SSH1DataReader r = new SSH1DataReader(SSH1Packet.Data);
  264. //Debug.WriteLine("receivedd debug message:"+Encoding.ASCII.GetString(r.ReadString()));
  265. return ReceiveAuthenticationResult();
  266. }
  267. else if(type==PacketType.SSH_SMSG_SUCCESS)
  268. return true;
  269. else if(type==PacketType.SSH_SMSG_FAILURE)
  270. return false;
  271. else
  272. throw new SSHException("type: " + type, SSH1Packet.Data);
  273. }
  274. public override SSHChannel OpenShell(ISSHChannelEventReceiver receiver) {
  275. if(_shellID!=-1)
  276. throw new SSHException("A shell is opened already");
  277. _shellID = RegisterChannelEventReceiver(null, receiver)._localID;
  278. SendRequestPTY();
  279. _executingShell = true;
  280. return new SSH1Channel(this, ChannelType.Shell, _shellID);
  281. }
  282. private void SendRequestPTY() {
  283. SSH1DataWriter writer = new SSH1DataWriter();
  284. writer.Write(_param.TerminalName);
  285. writer.Write(_param.TerminalHeight);
  286. writer.Write(_param.TerminalWidth);
  287. writer.Write(_param.TerminalPixelWidth);
  288. writer.Write(_param.TerminalPixelHeight);
  289. writer.Write(new byte[1]); //TTY_OP_END
  290. SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_REQUEST_PTY, writer.ToByteArray());
  291. SSH1Packet.WriteTo(_stream, _tCipher);
  292. }
  293. private void ExecShell() {
  294. //System.out.println("EXEC SHELL");
  295. SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_EXEC_SHELL);
  296. SSH1Packet.WriteTo(_stream, _tCipher);
  297. }
  298. public override SSHChannel ForwardPort(ISSHChannelEventReceiver receiver, string remote_host, int remote_port, string originator_host, int originator_port) {
  299. if(_shellID==-1) {
  300. ExecShell();
  301. _shellID = RegisterChannelEventReceiver(null, new SSH1DummyReceiver())._localID;
  302. }
  303.  
  304. int local_id = this.RegisterChannelEventReceiver(null, receiver)._localID;
  305. SSH1DataWriter writer = new SSH1DataWriter();
  306. writer.Write(local_id); //channel id is fixed to 0
  307. writer.Write(remote_host);
  308. writer.Write(remote_port);
  309. //originator is specified only if SSH_PROTOFLAG_HOST_IN_FWD_OPEN is specified
  310. //writer.Write(originator_host);
  311. SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_PORT_OPEN, writer.ToByteArray());
  312. SSH1Packet.WriteTo(_stream, _tCipher);
  313. return new SSH1Channel(this, ChannelType.ForwardedLocalToRemote, local_id);
  314. }
  315. public override void ListenForwardedPort(string allowed_host, int bind_port) {
  316. SSH1DataWriter writer = new SSH1DataWriter();
  317. writer.Write(bind_port);
  318. writer.Write(allowed_host);
  319. writer.Write(0);
  320. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_PORT_FORWARD_REQUEST, writer.ToByteArray());
  321. p.WriteTo(_stream, _tCipher);
  322. if(_shellID==-1) {
  323. ExecShell();
  324. _shellID = RegisterChannelEventReceiver(null, new SSH1DummyReceiver())._localID;
  325. }
  326. }
  327. public override void CancelForwardedPort(string host, int port) {
  328. throw new NotSupportedException("not implemented");
  329. }
  330. private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH1Packet packet) {
  331. SSH1DataReader reader = new SSH1DataReader(packet.Data);
  332. int server_channel = reader.ReadInt32();
  333. string host = Encoding.ASCII.GetString(reader.ReadString());
  334. int port = reader.ReadInt32();
  335. SSH1DataWriter writer = new SSH1DataWriter();
  336. PortForwardingCheckResult result = receiver.CheckPortForwardingRequest(host, port, "", 0);
  337. if(result.allowed) {
  338. int local_id = this.RegisterChannelEventReceiver(null, result.channel)._localID;
  339. _eventReceiver.EstablishPortforwarding(result.channel, new SSH1Channel(this, ChannelType.ForwardedRemoteToLocal, local_id, server_channel));
  340. writer.Write(server_channel);
  341. writer.Write(local_id);
  342. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, writer.ToByteArray());
  343. p.WriteTo(_stream, _tCipher);
  344. }
  345. else {
  346. writer.Write(server_channel);
  347. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE, writer.ToByteArray());
  348. p.WriteTo(_stream, _tCipher);
  349. }
  350. }
  351. private byte[] CalcSessionID() {
  352. MemoryStream bos = new MemoryStream();
  353. SSHServerInfo si = _cInfo._serverinfo;
  354. byte[] h = si.host_key_public_modulus.getBytes(); 
  355. byte[] s = si.server_key_public_modulus.getBytes();
  356. //System.out.println("len h="+h.Length);
  357. //System.out.println("len s="+s.Length);
  358. int off_h = (h[0]==0? 1 : 0);
  359. int off_s = (s[0]==0? 1 : 0);
  360. bos.Write(h, off_h, h.Length-off_h);
  361. bos.Write(s, off_s, s.Length-off_s);
  362. bos.Write(si.anti_spoofing_cookie, 0, si.anti_spoofing_cookie.Length);
  363. byte[] session_id = new MD5CryptoServiceProvider().ComputeHash(bos.ToArray());
  364. //System.out.println("sess-id-len=" + session_id.Length);
  365. return session_id;
  366. }
  367. //init ciphers
  368. private void InitCipher(byte[] session_key) {
  369. _tCipher = CipherFactory.CreateCipher(SSHProtocol.SSH1, _cInfo._algorithmForTransmittion, session_key);
  370. Cipher rc = CipherFactory.CreateCipher(SSHProtocol.SSH1, _cInfo._algorithmForReception, session_key);
  371. _packetBuilder.SetCipher(rc, _param.CheckMACError);
  372. }
  373. private SSH1Packet ReceivePacket() {
  374. while(true) {
  375. SSH1Packet p = null;
  376. SynchronizedSSH1PacketHandler handler = (SynchronizedSSH1PacketHandler)_packetBuilder.Handler;
  377. if(!handler.HasPacket) {
  378. handler.Wait();
  379. if(handler.State==ReceiverState.Error)
  380. throw new SSHException(handler.ErrorMessage);
  381. else if(handler.State==ReceiverState.Closed)
  382. throw new SSHException("socket closed");
  383. }
  384. p = handler.PopPacket();
  385. SSH1DataReader r = new SSH1DataReader(p.Data);
  386. PacketType pt = p.Type;
  387. if(pt==PacketType.SSH_MSG_IGNORE) {
  388. if(_eventReceiver!=null) _eventReceiver.OnIgnoreMessage(r.ReadString());
  389. }
  390. else if(pt==PacketType.SSH_MSG_DEBUG) {
  391. if(_eventReceiver!=null) _eventReceiver.OnDebugMessage(false, r.ReadString());
  392. }
  393. else
  394. return p;
  395. }
  396. }
  397. internal void AsyncReceivePacket(SSH1Packet p) {
  398. try {
  399. int len = 0, channel = 0;
  400. switch(p.Type) {
  401. case PacketType.SSH_SMSG_STDOUT_DATA:
  402. len = SSHUtil.ReadInt32(p.Data, 0);
  403. FindChannelEntry(_shellID)._receiver.OnData(p.Data, 4, len);
  404. break;
  405. case PacketType.SSH_SMSG_STDERR_DATA: {
  406. SSH1DataReader re = new SSH1DataReader(p.Data);
  407. FindChannelEntry(_shellID)._receiver.OnExtendedData((int)PacketType.SSH_SMSG_STDERR_DATA, re.ReadString());
  408. }
  409. break;
  410. case PacketType.SSH_MSG_CHANNEL_DATA:
  411. channel = SSHUtil.ReadInt32(p.Data, 0);
  412. len = SSHUtil.ReadInt32(p.Data, 4);
  413. FindChannelEntry(channel)._receiver.OnData(p.Data, 8, len);
  414. break;
  415. case PacketType.SSH_MSG_PORT_OPEN:
  416. this.ProcessPortforwardingRequest(_eventReceiver, p);
  417. break;
  418. case PacketType.SSH_MSG_CHANNEL_CLOSE: {
  419. channel = SSHUtil.ReadInt32(p.Data, 0);
  420. ISSHChannelEventReceiver r = FindChannelEntry(channel)._receiver;
  421. UnregisterChannelEventReceiver(channel);
  422. r.OnChannelClosed();
  423. }
  424. break;
  425. case PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
  426. channel = SSHUtil.ReadInt32(p.Data, 0);
  427. break;
  428. case PacketType.SSH_MSG_DISCONNECT:
  429. _eventReceiver.OnConnectionClosed();
  430. break;
  431. case PacketType.SSH_SMSG_EXITSTATUS:
  432. FindChannelEntry(_shellID)._receiver.OnChannelClosed();
  433. break;
  434. case PacketType.SSH_MSG_DEBUG: {
  435. SSH1DataReader re = new SSH1DataReader(p.Data);
  436. _eventReceiver.OnDebugMessage(false, re.ReadString());
  437. }
  438. break;
  439. case PacketType.SSH_MSG_IGNORE: {
  440. SSH1DataReader re = new SSH1DataReader(p.Data);
  441. _eventReceiver.OnIgnoreMessage(re.ReadString());
  442. }
  443. break;
  444. case PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: {
  445. int local = SSHUtil.ReadInt32(p.Data, 0);
  446. int remote = SSHUtil.ReadInt32(p.Data, 4);
  447. FindChannelEntry(local)._receiver.OnChannelReady();
  448. }
  449. break;
  450. case PacketType.SSH_SMSG_SUCCESS:
  451. if(_executingShell) {
  452. ExecShell();
  453. this.FindChannelEntry(_shellID)._receiver.OnChannelReady();
  454. _executingShell = false;
  455. }
  456. break;
  457. default:
  458. _eventReceiver.OnUnknownMessage((byte)p.Type, p.Data);
  459. break;
  460. }
  461. }
  462. catch(Exception ex) {
  463. if(!_closed)
  464. _eventReceiver.OnError(ex, ex.Message);
  465. }
  466. }
  467. }
  468. public class SSH1Channel : SSHChannel {
  469. public SSH1Channel(SSHConnection con, ChannelType type, int local_id) : base(con, type, local_id) {
  470. }
  471. public SSH1Channel(SSHConnection con, ChannelType type, int local_id, int remote_id) : base(con, type, local_id) {
  472. _remoteID = remote_id;
  473. }
  474. /**
  475.  * resizes the size of terminal
  476.  */
  477. public override void ResizeTerminal(int width, int height, int pixel_width, int pixel_height) {
  478. SSH1DataWriter writer = new SSH1DataWriter();
  479. writer.Write(height);
  480. writer.Write(width);
  481. writer.Write(pixel_width);
  482. writer.Write(pixel_height);
  483. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_WINDOW_SIZE, writer.ToByteArray());
  484. Transmit(p);
  485. }
  486. /**
  487. * transmits channel data 
  488. */
  489. public override void Transmit(byte[] data) {
  490. SSH1DataWriter wr = new SSH1DataWriter();
  491. if(_type==ChannelType.Shell) {
  492. wr.WriteAsString(data);
  493. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_STDIN_DATA, wr.ToByteArray());
  494. Transmit(p);
  495. }
  496. else {
  497. wr.Write(_remoteID);
  498. wr.WriteAsString(data);
  499. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_DATA, wr.ToByteArray());
  500. Transmit(p);
  501. }
  502. }
  503. /**
  504. * transmits channel data 
  505. */
  506. public override void Transmit(byte[] data, int offset, int length) {
  507. SSH1DataWriter wr = new SSH1DataWriter();
  508. if(_type==ChannelType.Shell) {
  509. wr.WriteAsString(data, offset, length);
  510. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_STDIN_DATA, wr.ToByteArray());
  511. Transmit(p);
  512. }
  513. else {
  514. wr.Write(_remoteID);
  515. wr.WriteAsString(data, offset, length);
  516. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_DATA, wr.ToByteArray());
  517. Transmit(p);
  518. }
  519. }
  520. public override void SendEOF() {
  521. }
  522. /**
  523.  * closes this channel
  524.  */
  525. public override void Close() {
  526. if(_connection.IsClosed) return;
  527. if(_type==ChannelType.Shell) {
  528. SSH1DataWriter wr2 = new SSH1DataWriter();
  529. wr2.Write(_remoteID);
  530. SSH1Packet p2 = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_EOF, wr2.ToByteArray());
  531. Transmit(p2);
  532. }
  533. SSH1DataWriter wr = new SSH1DataWriter();
  534. wr.Write(_remoteID);
  535. SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_CLOSE, wr.ToByteArray());
  536. Transmit(p);
  537. }
  538. private void Transmit(SSH1Packet p) {
  539. ((SSH1Connection)_connection).Transmit(p);
  540. }
  541. }
  542. //if port forwardings are performed without a shell, we use SSH1DummyChannel to receive shell data
  543. internal class SSH1DummyReceiver : ISSHChannelEventReceiver {
  544. public void OnData(byte[] data, int offset, int length) {
  545. }
  546. public void OnExtendedData(int type, byte[] data) {
  547. }
  548. public void OnChannelClosed() {
  549. }
  550. public void OnChannelEOF() {
  551. }
  552. public void OnChannelReady() {
  553. }
  554. public void OnChannelError(Exception error, string msg) {
  555. }
  556. public void OnMiscPacket(byte packet_type, byte[] data, int offset, int length) {
  557. }
  558. }
  559. }