Session.cs 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Security.Cryptography;
  8. using System.Text;
  9. using System.Text.RegularExpressions;
  10. using System.Threading;
  11. using Renci.SshNet.Channels;
  12. using Renci.SshNet.Common;
  13. using Renci.SshNet.Compression;
  14. using Renci.SshNet.Messages;
  15. using Renci.SshNet.Messages.Authentication;
  16. using Renci.SshNet.Messages.Connection;
  17. using Renci.SshNet.Messages.Transport;
  18. using Renci.SshNet.Security;
  19. using System.Globalization;
  20. namespace Renci.SshNet
  21. {
  22. /// <summary>
  23. /// Provides functionality to connect and interact with SSH server.
  24. /// </summary>
  25. public partial class Session : IDisposable
  26. {
  27. /// <summary>
  28. /// Specifies maximum packet size defined by the protocol.
  29. /// </summary>
  30. protected const int MAXIMUM_PACKET_SIZE = 35000;
  31. /// <summary>
  32. /// Specifies maximum payload size defined by the protocol.
  33. /// </summary>
  34. protected const int MAXIMUM_PAYLOAD_SIZE = 1024 * 32;
  35. private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
  36. private static Regex _serverVersionRe = new Regex("^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.+)( SP.+)?$", RegexOptions.Compiled);
  37. /// <summary>
  38. /// Controls how many authentication attempts can take place at the same time.
  39. /// </summary>
  40. /// <remarks>
  41. /// Some server may restrict number to prevent authentication attacks
  42. /// </remarks>
  43. private static SemaphoreLight _authenticationConnection = new SemaphoreLight(3);
  44. /// <summary>
  45. /// Holds metada about session messages
  46. /// </summary>
  47. private IEnumerable<MessageMetadata> _messagesMetadata;
  48. /// <summary>
  49. /// Holds connection socket.
  50. /// </summary>
  51. private Socket _socket;
  52. /// <summary>
  53. /// Holds reference to task that listens for incoming messages
  54. /// </summary>
  55. private EventWaitHandle _messageListenerCompleted;
  56. /// <summary>
  57. /// Specifies outbound packet number
  58. /// </summary>
  59. private volatile UInt32 _outboundPacketSequence = 0;
  60. /// <summary>
  61. /// Specifies incoming packet number
  62. /// </summary>
  63. private UInt32 _inboundPacketSequence = 0;
  64. /// <summary>
  65. /// WaitHandle to signal that last service request was accepted
  66. /// </summary>
  67. private EventWaitHandle _serviceAccepted = new AutoResetEvent(false);
  68. /// <summary>
  69. /// WaitHandle to signal that exception was thrown by another thread.
  70. /// </summary>
  71. private EventWaitHandle _exceptionWaitHandle = new AutoResetEvent(false);
  72. /// <summary>
  73. /// WaitHandle to signal that key exchange was completed.
  74. /// </summary>
  75. private EventWaitHandle _keyExchangeCompletedWaitHandle = new ManualResetEvent(false);
  76. /// <summary>
  77. /// Exception that need to be thrown by waiting thread
  78. /// </summary>
  79. private Exception _exception;
  80. /// <summary>
  81. /// Specifies whether connection is authenticated
  82. /// </summary>
  83. private bool _isAuthenticated;
  84. /// <summary>
  85. /// Specifies whether user issued Disconnect command or not
  86. /// </summary>
  87. private bool _isDisconnecting;
  88. private KeyExchange _keyExchange;
  89. private HMac _serverMac;
  90. private HMac _clientMac;
  91. private Cipher _clientCipher;
  92. private Cipher _serverCipher;
  93. private Compressor _serverDecompression;
  94. private Compressor _clientCompression;
  95. private SemaphoreLight _sessionSemaphore;
  96. /// <summary>
  97. /// Gets the session semaphore that controls session channels.
  98. /// </summary>
  99. /// <value>The session semaphore.</value>
  100. public SemaphoreLight SessionSemaphore
  101. {
  102. get
  103. {
  104. if (this._sessionSemaphore == null)
  105. {
  106. lock (this)
  107. {
  108. if (this._sessionSemaphore == null)
  109. {
  110. this._sessionSemaphore = new SemaphoreLight(this.ConnectionInfo.MaxSessions);
  111. }
  112. }
  113. }
  114. return this._sessionSemaphore;
  115. }
  116. }
  117. private bool _isDisconnectMessageSent;
  118. private uint _nextChannelNumber;
  119. /// <summary>
  120. /// Gets the next channel number.
  121. /// </summary>
  122. /// <value>The next channel number.</value>
  123. internal uint NextChannelNumber
  124. {
  125. get
  126. {
  127. uint result;
  128. lock (this)
  129. {
  130. result = this._nextChannelNumber++;
  131. }
  132. return result;
  133. }
  134. }
  135. /// <summary>
  136. /// Gets a value indicating whether socket connected.
  137. /// </summary>
  138. /// <value>
  139. /// <c>true</c> if socket connected; otherwise, <c>false</c>.
  140. /// </value>
  141. public bool IsConnected
  142. {
  143. get
  144. {
  145. return this._socket != null && this._socket.Connected && this._isAuthenticated && this._messageListenerCompleted != null;
  146. }
  147. }
  148. /// <summary>
  149. /// Gets or sets the session id.
  150. /// </summary>
  151. /// <value>The session id.</value>
  152. public byte[] SessionId { get; private set; }
  153. private Message _clientInitMessage;
  154. /// <summary>
  155. /// Gets the client init message.
  156. /// </summary>
  157. /// <value>The client init message.</value>
  158. public Message ClientInitMessage
  159. {
  160. get
  161. {
  162. if (this._clientInitMessage == null)
  163. {
  164. this._clientInitMessage = new KeyExchangeInitMessage()
  165. {
  166. KeyExchangeAlgorithms = this.ConnectionInfo.KeyExchangeAlgorithms.Keys,
  167. ServerHostKeyAlgorithms = this.ConnectionInfo.HostKeyAlgorithms.Keys,
  168. EncryptionAlgorithmsClientToServer = this.ConnectionInfo.Encryptions.Keys,
  169. EncryptionAlgorithmsServerToClient = this.ConnectionInfo.Encryptions.Keys,
  170. MacAlgorithmsClientToServer = this.ConnectionInfo.HmacAlgorithms.Keys,
  171. MacAlgorithmsServerToClient = this.ConnectionInfo.HmacAlgorithms.Keys,
  172. CompressionAlgorithmsClientToServer = this.ConnectionInfo.CompressionAlgorithms.Keys,
  173. CompressionAlgorithmsServerToClient = this.ConnectionInfo.CompressionAlgorithms.Keys,
  174. LanguagesClientToServer = new string[] { string.Empty },
  175. LanguagesServerToClient = new string[] { string.Empty },
  176. FirstKexPacketFollows = false,
  177. Reserved = 0,
  178. };
  179. }
  180. return this._clientInitMessage;
  181. }
  182. }
  183. /// <summary>
  184. /// Gets or sets the server version string.
  185. /// </summary>
  186. /// <value>The server version.</value>
  187. public string ServerVersion { get; private set; }
  188. /// <summary>
  189. /// Gets or sets the client version string.
  190. /// </summary>
  191. /// <value>The client version.</value>
  192. public string ClientVersion { get; private set; }
  193. /// <summary>
  194. /// Gets or sets the connection info.
  195. /// </summary>
  196. /// <value>The connection info.</value>
  197. public ConnectionInfo ConnectionInfo { get; private set; }
  198. /// <summary>
  199. /// Occurs when an error occurred.
  200. /// </summary>
  201. public event EventHandler<ExceptionEventArgs> ErrorOccured;
  202. /// <summary>
  203. /// Occurs when session has been disconnected form the server.
  204. /// </summary>
  205. public event EventHandler<EventArgs> Disconnected;
  206. #region Message events
  207. /// <summary>
  208. /// Occurs when <see cref="DisconnectMessage"/> message received
  209. /// </summary>
  210. internal event EventHandler<MessageEventArgs<DisconnectMessage>> DisconnectReceived;
  211. /// <summary>
  212. /// Occurs when <see cref="IgnoreMessage"/> message received
  213. /// </summary>
  214. internal event EventHandler<MessageEventArgs<IgnoreMessage>> IgnoreReceived;
  215. /// <summary>
  216. /// Occurs when <see cref="UnimplementedMessage"/> message received
  217. /// </summary>
  218. internal event EventHandler<MessageEventArgs<UnimplementedMessage>> UnimplementedReceived;
  219. /// <summary>
  220. /// Occurs when <see cref="DebugMessage"/> message received
  221. /// </summary>
  222. internal event EventHandler<MessageEventArgs<DebugMessage>> DebugReceived;
  223. /// <summary>
  224. /// Occurs when <see cref="ServiceRequestMessage"/> message received
  225. /// </summary>
  226. internal event EventHandler<MessageEventArgs<ServiceRequestMessage>> ServiceRequestReceived;
  227. /// <summary>
  228. /// Occurs when <see cref="ServiceAcceptMessage"/> message received
  229. /// </summary>
  230. internal event EventHandler<MessageEventArgs<ServiceAcceptMessage>> ServiceAcceptReceived;
  231. /// <summary>
  232. /// Occurs when <see cref="KeyExchangeInitMessage"/> message received
  233. /// </summary>
  234. internal event EventHandler<MessageEventArgs<KeyExchangeInitMessage>> KeyExchangeInitReceived;
  235. /// <summary>
  236. /// Occurs when <see cref="NewKeysMessage"/> message received
  237. /// </summary>
  238. internal event EventHandler<MessageEventArgs<NewKeysMessage>> NewKeysReceived;
  239. /// <summary>
  240. /// Occurs when <see cref="RequestMessage"/> message received
  241. /// </summary>
  242. internal event EventHandler<MessageEventArgs<RequestMessage>> UserAuthenticationRequestReceived;
  243. /// <summary>
  244. /// Occurs when <see cref="FailureMessage"/> message received
  245. /// </summary>
  246. internal event EventHandler<MessageEventArgs<FailureMessage>> UserAuthenticationFailureReceived;
  247. /// <summary>
  248. /// Occurs when <see cref="SuccessMessage"/> message received
  249. /// </summary>
  250. internal event EventHandler<MessageEventArgs<SuccessMessage>> UserAuthenticationSuccessReceived;
  251. /// <summary>
  252. /// Occurs when <see cref="BannerMessage"/> message received
  253. /// </summary>
  254. internal event EventHandler<MessageEventArgs<BannerMessage>> UserAuthenticationBannerReceived;
  255. /// <summary>
  256. /// Occurs when <see cref="GlobalRequestMessage"/> message received
  257. /// </summary>
  258. internal event EventHandler<MessageEventArgs<GlobalRequestMessage>> GlobalRequestReceived;
  259. /// <summary>
  260. /// Occurs when <see cref="RequestSuccessMessage"/> message received
  261. /// </summary>
  262. internal event EventHandler<MessageEventArgs<RequestSuccessMessage>> RequestSuccessReceived;
  263. /// <summary>
  264. /// Occurs when <see cref="RequestFailureMessage"/> message received
  265. /// </summary>
  266. internal event EventHandler<MessageEventArgs<RequestFailureMessage>> RequestFailureReceived;
  267. /// <summary>
  268. /// Occurs when <see cref="ChannelOpenMessage"/> message received
  269. /// </summary>
  270. internal event EventHandler<MessageEventArgs<ChannelOpenMessage>> ChannelOpenReceived;
  271. /// <summary>
  272. /// Occurs when <see cref="ChannelOpenConfirmationMessage"/> message received
  273. /// </summary>
  274. internal event EventHandler<MessageEventArgs<ChannelOpenConfirmationMessage>> ChannelOpenConfirmationReceived;
  275. /// <summary>
  276. /// Occurs when <see cref="ChannelOpenFailureMessage"/> message received
  277. /// </summary>
  278. internal event EventHandler<MessageEventArgs<ChannelOpenFailureMessage>> ChannelOpenFailureReceived;
  279. /// <summary>
  280. /// Occurs when <see cref="ChannelWindowAdjustMessage"/> message received
  281. /// </summary>
  282. internal event EventHandler<MessageEventArgs<ChannelWindowAdjustMessage>> ChannelWindowAdjustReceived;
  283. /// <summary>
  284. /// Occurs when <see cref="ChannelDataMessage"/> message received
  285. /// </summary>
  286. internal event EventHandler<MessageEventArgs<ChannelDataMessage>> ChannelDataReceived;
  287. /// <summary>
  288. /// Occurs when <see cref="ChannelExtendedDataMessage"/> message received
  289. /// </summary>
  290. internal event EventHandler<MessageEventArgs<ChannelExtendedDataMessage>> ChannelExtendedDataReceived;
  291. /// <summary>
  292. /// Occurs when <see cref="ChannelEofMessage"/> message received
  293. /// </summary>
  294. internal event EventHandler<MessageEventArgs<ChannelEofMessage>> ChannelEofReceived;
  295. /// <summary>
  296. /// Occurs when <see cref="ChannelCloseMessage"/> message received
  297. /// </summary>
  298. internal event EventHandler<MessageEventArgs<ChannelCloseMessage>> ChannelCloseReceived;
  299. /// <summary>
  300. /// Occurs when <see cref="ChannelRequestMessage"/> message received
  301. /// </summary>
  302. internal event EventHandler<MessageEventArgs<ChannelRequestMessage>> ChannelRequestReceived;
  303. /// <summary>
  304. /// Occurs when <see cref="ChannelSuccessMessage"/> message received
  305. /// </summary>
  306. internal event EventHandler<MessageEventArgs<ChannelSuccessMessage>> ChannelSuccessReceived;
  307. /// <summary>
  308. /// Occurs when <see cref="ChannelFailureMessage"/> message received
  309. /// </summary>
  310. internal event EventHandler<MessageEventArgs<ChannelFailureMessage>> ChannelFailureReceived;
  311. /// <summary>
  312. /// Occurs when message received and is not handled by any of the event handlers
  313. /// </summary>
  314. internal event EventHandler<MessageEventArgs<Message>> MessageReceived;
  315. #endregion
  316. /// <summary>
  317. /// Initializes a new instance of the <see cref="Session"/> class.
  318. /// </summary>
  319. /// <param name="connectionInfo">The connection info.</param>
  320. internal Session(ConnectionInfo connectionInfo)
  321. {
  322. this.ConnectionInfo = connectionInfo;
  323. this.ClientVersion = string.Format(CultureInfo.CurrentCulture, "SSH-2.0-Renci.SshNet.SshClient.{0}", this.GetType().Assembly.GetName().Version);
  324. }
  325. /// <summary>
  326. /// Connects to the server.
  327. /// </summary>
  328. public void Connect()
  329. {
  330. if (this.ConnectionInfo == null)
  331. {
  332. throw new ArgumentNullException("connectionInfo");
  333. }
  334. if (this.IsConnected)
  335. return;
  336. try
  337. {
  338. _authenticationConnection.Wait();
  339. if (this.IsConnected)
  340. return;
  341. lock (this)
  342. {
  343. // If connected don't connect again
  344. if (this.IsConnected)
  345. return;
  346. this.OpenSocket();
  347. Match versionMatch = null;
  348. // Get server version from the server,
  349. // ignore text lines which are sent before if any
  350. using (var ns = new NetworkStream(this._socket))
  351. {
  352. using (var sr = new StreamReader(ns))
  353. {
  354. while (true)
  355. {
  356. this.ServerVersion = sr.ReadLine();
  357. if (string.IsNullOrEmpty(this.ServerVersion))
  358. {
  359. throw new InvalidOperationException("Server string is null or empty.");
  360. }
  361. versionMatch = _serverVersionRe.Match(this.ServerVersion);
  362. if (versionMatch.Success)
  363. {
  364. break;
  365. }
  366. }
  367. }
  368. }
  369. // Get server SSH version
  370. var version = versionMatch.Result("${protoversion}");
  371. if (!(version.Equals("2.0") || version.Equals("1.99")))
  372. {
  373. throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReason.ProtocolVersionNotSupported);
  374. }
  375. this.Write(Renci.SshNet.Common.ASCIIEncoding.Current.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
  376. // Register Transport response messages
  377. this.RegisterMessage("SSH_MSG_DISCONNECT");
  378. this.RegisterMessage("SSH_MSG_IGNORE");
  379. this.RegisterMessage("SSH_MSG_UNIMPLEMENTED");
  380. this.RegisterMessage("SSH_MSG_DEBUG");
  381. this.RegisterMessage("SSH_MSG_SERVICE_ACCEPT");
  382. this.RegisterMessage("SSH_MSG_KEXINIT");
  383. this.RegisterMessage("SSH_MSG_NEWKEYS");
  384. // Some server implementations might sent this message first, prior establishing encryption algorithm
  385. this.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
  386. // Start incoming request listener
  387. this._messageListenerCompleted = new ManualResetEvent(false);
  388. this.ExecuteThread(() =>
  389. {
  390. try
  391. {
  392. this.MessageListener();
  393. }
  394. finally
  395. {
  396. this._messageListenerCompleted.Set();
  397. }
  398. });
  399. // Wait for key exchange to be completed
  400. this.WaitHandle(this._keyExchangeCompletedWaitHandle);
  401. // If sessionId is not set then its not connected
  402. if (this.SessionId == null)
  403. {
  404. this.Disconnect();
  405. return;
  406. }
  407. // Request user authorization service
  408. this.SendMessage(new ServiceRequestMessage(ServiceName.UserAuthentication));
  409. // Wait for service to be accepted
  410. this.WaitHandle(this._serviceAccepted);
  411. if (string.IsNullOrEmpty(this.ConnectionInfo.Username))
  412. {
  413. throw new SshException("Username is not specified.");
  414. }
  415. // Try authenticate using none method
  416. using (var noneConnectionInfo = new NoneConnectionInfo(this.ConnectionInfo.Host, this.ConnectionInfo.Port, this.ConnectionInfo.Username))
  417. {
  418. noneConnectionInfo.Authenticate(this);
  419. this._isAuthenticated = noneConnectionInfo.IsAuthenticated;
  420. if (!this._isAuthenticated)
  421. {
  422. // Ensure that authentication method is allowed
  423. if (!noneConnectionInfo.AllowedAuthentications.Contains(this.ConnectionInfo.Name))
  424. {
  425. throw new SshAuthenticationException("User authentication method is not supported.");
  426. }
  427. // In future, if more then one authentication methods are supported perform the check here.
  428. // Authenticate using provided connection info object
  429. this.ConnectionInfo.Authenticate(this);
  430. this._isAuthenticated = this.ConnectionInfo.IsAuthenticated;
  431. }
  432. }
  433. if (!this._isAuthenticated)
  434. {
  435. throw new SshAuthenticationException("User cannot be authenticated.");
  436. }
  437. // Register Connection messages
  438. this.RegisterMessage("SSH_MSG_GLOBAL_REQUEST");
  439. this.RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
  440. this.RegisterMessage("SSH_MSG_REQUEST_FAILURE");
  441. this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
  442. this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_FAILURE");
  443. this.RegisterMessage("SSH_MSG_CHANNEL_WINDOW_ADJUST");
  444. this.RegisterMessage("SSH_MSG_CHANNEL_EXTENDED_DATA");
  445. this.RegisterMessage("SSH_MSG_CHANNEL_REQUEST");
  446. this.RegisterMessage("SSH_MSG_CHANNEL_SUCCESS");
  447. this.RegisterMessage("SSH_MSG_CHANNEL_FAILURE");
  448. this.RegisterMessage("SSH_MSG_CHANNEL_DATA");
  449. this.RegisterMessage("SSH_MSG_CHANNEL_EOF");
  450. this.RegisterMessage("SSH_MSG_CHANNEL_CLOSE");
  451. Monitor.Pulse(this);
  452. }
  453. }
  454. finally
  455. {
  456. _authenticationConnection.Release();
  457. }
  458. }
  459. /// <summary>
  460. /// Disconnects from the server
  461. /// </summary>
  462. public void Disconnect()
  463. {
  464. this.Dispose();
  465. }
  466. internal T CreateChannel<T>() where T : Channel, new()
  467. {
  468. return CreateChannel<T>(0, 0x100000, 0x8000);
  469. }
  470. internal T CreateChannel<T>(uint serverChannelNumber, uint windowSize, uint packetSize) where T : Channel, new()
  471. {
  472. T channel = new T();
  473. lock (this)
  474. {
  475. channel.Initialize(this, serverChannelNumber, windowSize, packetSize);
  476. }
  477. return channel;
  478. }
  479. /// <summary>
  480. /// Sends "keep alive" message to keep connection alive.
  481. /// </summary>
  482. internal void SendKeepAlive()
  483. {
  484. this.SendMessage(new IgnoreMessage());
  485. }
  486. /// <summary>
  487. /// Waits for handle to signal while checking other handles as well including timeout check to prevent waiting for ever
  488. /// </summary>
  489. /// <param name="waitHandle">The wait handle.</param>
  490. internal void WaitHandle(WaitHandle waitHandle)
  491. {
  492. var waitHandles = new WaitHandle[]
  493. {
  494. this._exceptionWaitHandle,
  495. waitHandle,
  496. };
  497. var index = EventWaitHandle.WaitAny(waitHandles, this.ConnectionInfo.Timeout);
  498. if (index < 1)
  499. {
  500. throw this._exception;
  501. }
  502. else if (index > 1)
  503. {
  504. this.SendDisconnect(DisconnectReason.ByApplication, "Operation timeout");
  505. throw new SshOperationTimeoutException("Session operation has timed out");
  506. }
  507. }
  508. /// <summary>
  509. /// Sends packet message to the server.
  510. /// </summary>
  511. /// <param name="message">The message.</param>
  512. internal void SendMessage(Message message)
  513. {
  514. if (this._socket == null || !this._socket.Connected)
  515. return;
  516. // Messages can be sent by different thread so we need to synchronize it
  517. var paddingMultiplier = this._clientCipher == null ? (byte)8 : (byte)this._clientCipher.BlockSize; // Should be recalculate base on cipher min length if cipher specified
  518. var messageData = message.GetBytes();
  519. if (messageData.Length > Session.MAXIMUM_PAYLOAD_SIZE)
  520. {
  521. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Payload cannot be more then {0} bytes.", Session.MAXIMUM_PAYLOAD_SIZE));
  522. }
  523. if (this._clientCompression != null)
  524. {
  525. messageData = this._clientCompression.Compress(messageData);
  526. }
  527. var packetLength = messageData.Length + 4 + 1; // add length bytes and padding byte
  528. byte paddingLength = (byte)((-packetLength) & (paddingMultiplier - 1));
  529. if (paddingLength < paddingMultiplier)
  530. {
  531. paddingLength += paddingMultiplier;
  532. }
  533. // Build Packet data
  534. var packetData = new byte[4 + 1 + messageData.Length + paddingLength];
  535. // Add packet length
  536. ((uint)packetData.Length - 4).GetBytes().CopyTo(packetData, 0);
  537. // Add packet padding length
  538. packetData[4] = paddingLength;
  539. // Add packet payload
  540. messageData.CopyTo(packetData, 4 + 1);
  541. // Add random padding
  542. var paddingBytes = new byte[paddingLength];
  543. _randomizer.GetBytes(paddingBytes);
  544. paddingBytes.CopyTo(packetData, 4 + 1 + messageData.Length);
  545. // Lock handling of _outboundPacketSequence since it must be sent sequently to server
  546. lock (this._socket)
  547. {
  548. // Calculate packet hash
  549. var hashData = new byte[4 + packetData.Length];
  550. this._outboundPacketSequence.GetBytes().CopyTo(hashData, 0);
  551. packetData.CopyTo(hashData, 4);
  552. // Encrypt packet data
  553. if (this._clientCipher != null)
  554. {
  555. packetData = this._clientCipher.Encrypt(packetData);
  556. }
  557. if (packetData.Length > Session.MAXIMUM_PACKET_SIZE)
  558. {
  559. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Packet is too big. Maximum packet size is {0} bytes.", Session.MAXIMUM_PACKET_SIZE));
  560. }
  561. if (this._clientMac == null)
  562. {
  563. this.Write(packetData);
  564. }
  565. else
  566. {
  567. var hash = this._clientMac.ComputeHash(hashData.ToArray());
  568. var data = new byte[packetData.Length + this._clientMac.HashSize / 8];
  569. packetData.CopyTo(data, 0);
  570. hash.CopyTo(data, packetData.Length);
  571. this.Write(data);
  572. }
  573. this._outboundPacketSequence++;
  574. Monitor.Pulse(this._socket);
  575. }
  576. }
  577. /// <summary>
  578. /// Receives the message from the server.
  579. /// </summary>
  580. /// <returns></returns>
  581. private Message ReceiveMessage()
  582. {
  583. if (!this._socket.Connected)
  584. return null;
  585. // No lock needed since all messages read by only one thread
  586. var blockSize = this._serverCipher == null ? (byte)8 : (byte)this._serverCipher.BlockSize;
  587. // Read packet length first
  588. var firstBlock = this.Read(blockSize);
  589. if (this._serverCipher != null)
  590. {
  591. firstBlock = this._serverCipher.Decrypt(firstBlock);
  592. }
  593. var packetLength = (uint)(firstBlock[0] << 24 | firstBlock[1] << 16 | firstBlock[2] << 8 | firstBlock[3]);
  594. // Test packet minimum and maximum boundaries
  595. if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > Session.MAXIMUM_PACKET_SIZE - 4)
  596. throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Bad packet length {0}", packetLength), DisconnectReason.ProtocolError);
  597. // Read rest of the packet data
  598. int bytesToRead = (int)(packetLength - (blockSize - 4));
  599. var data = new byte[bytesToRead + blockSize];
  600. firstBlock.CopyTo(data, 0);
  601. byte[] serverHash = null;
  602. if (this._serverMac != null)
  603. {
  604. serverHash = new byte[this._serverMac.HashSize / 8];
  605. bytesToRead += serverHash.Length;
  606. }
  607. if (bytesToRead > 0)
  608. {
  609. var nextBlocks = this.Read(bytesToRead);
  610. if (serverHash != null)
  611. {
  612. Array.Copy(nextBlocks, nextBlocks.Length - serverHash.Length, serverHash, 0, serverHash.Length);
  613. nextBlocks = nextBlocks.Take(nextBlocks.Length - serverHash.Length).ToArray();
  614. }
  615. if (nextBlocks.Length > 0)
  616. {
  617. if (this._serverCipher != null)
  618. {
  619. nextBlocks = this._serverCipher.Decrypt(nextBlocks);
  620. }
  621. nextBlocks.CopyTo(data, blockSize);
  622. }
  623. }
  624. var paddingLength = data[4];
  625. var messagePayload = new byte[packetLength - paddingLength - 1];
  626. Array.Copy(data, 5, messagePayload, 0, messagePayload.Length);
  627. if (this._serverDecompression != null)
  628. {
  629. messagePayload = this._serverDecompression.Decompress(messagePayload);
  630. }
  631. // Validate message against MAC
  632. if (this._serverMac != null)
  633. {
  634. var clientHashData = new byte[4 + data.Length];
  635. var lengthBytes = this._inboundPacketSequence.GetBytes();
  636. lengthBytes.CopyTo(clientHashData, 0);
  637. data.CopyTo(clientHashData, 4);
  638. // Calculate packet hash
  639. var clientHash = this._serverMac.ComputeHash(clientHashData);
  640. if (!serverHash.SequenceEqual(clientHash))
  641. {
  642. throw new SshConnectionException("MAC error", DisconnectReason.MacError);
  643. }
  644. }
  645. this._inboundPacketSequence++;
  646. return this.LoadMessage(messagePayload);
  647. }
  648. private void SendDisconnect(DisconnectReason reasonCode, string message)
  649. {
  650. // If disconnect message was sent already dont send it again
  651. if (this._isDisconnectMessageSent)
  652. return;
  653. var disconnectMessage = new DisconnectMessage(reasonCode, message);
  654. this.SendMessage(disconnectMessage);
  655. this._isDisconnectMessageSent = true;
  656. }
  657. /// <summary>
  658. /// Handles the message.
  659. /// </summary>
  660. /// <typeparam name="T"></typeparam>
  661. /// <param name="message">The message.</param>
  662. private void HandleMessage<T>(T message) where T : Message
  663. {
  664. this.OnMessageReceived(message);
  665. }
  666. #region Handle transport messages
  667. private void HandleMessage(DisconnectMessage message)
  668. {
  669. this.OnDisconnectReceived(message);
  670. // Shutdown and disconnect from the socket
  671. if (this._socket != null)
  672. {
  673. lock (this._socket)
  674. {
  675. if (this._socket != null)
  676. {
  677. this._socket.Disconnect(true);
  678. // When socket is disconnected wait for listener to finish
  679. if (this._messageListenerCompleted != null)
  680. {
  681. // Wait for listener task to finish
  682. this._messageListenerCompleted.WaitOne();
  683. this._messageListenerCompleted.Dispose();
  684. this._messageListenerCompleted = null;
  685. }
  686. this._socket.Dispose();
  687. this._socket = null;
  688. }
  689. }
  690. }
  691. }
  692. private void HandleMessage(IgnoreMessage message)
  693. {
  694. this.OnIgnoreReceived(message);
  695. }
  696. private void HandleMessage(UnimplementedMessage message)
  697. {
  698. this.OnUnimplementedReceived(message);
  699. }
  700. private void HandleMessage(DebugMessage message)
  701. {
  702. this.OnDebugReceived(message);
  703. }
  704. private void HandleMessage(ServiceRequestMessage message)
  705. {
  706. this.OnServiceRequestReceived(message);
  707. }
  708. private void HandleMessage(ServiceAcceptMessage message)
  709. {
  710. // TODO: Refactor to avoid this method here
  711. this.OnServiceAcceptReceived(message);
  712. this._serviceAccepted.Set();
  713. }
  714. private void HandleMessage(KeyExchangeInitMessage message)
  715. {
  716. this.OnKeyExchangeInitReceived(message);
  717. }
  718. private void HandleMessage(NewKeysMessage message)
  719. {
  720. this.OnNewKeysReceived(message);
  721. }
  722. #endregion
  723. #region Handle User Authentication messages
  724. private void HandleMessage(RequestMessage message)
  725. {
  726. this.OnUserAuthenticationRequestReceived(message);
  727. }
  728. private void HandleMessage(FailureMessage message)
  729. {
  730. this.OnUserAuthenticationFailureReceived(message);
  731. }
  732. private void HandleMessage(SuccessMessage message)
  733. {
  734. this.OnUserAuthenticationSuccessReceived(message);
  735. }
  736. private void HandleMessage(BannerMessage message)
  737. {
  738. this.OnUserAuthenticationBannerReceived(message);
  739. }
  740. #endregion
  741. #region Handle connection messages
  742. private void HandleMessage(GlobalRequestMessage message)
  743. {
  744. this.OnGlobalRequestReceived(message);
  745. }
  746. private void HandleMessage(RequestSuccessMessage message)
  747. {
  748. this.OnRequestSuccessReceived(message);
  749. }
  750. private void HandleMessage(RequestFailureMessage message)
  751. {
  752. this.OnRequestFailureReceived(message);
  753. }
  754. private void HandleMessage(ChannelOpenMessage message)
  755. {
  756. this.OnChannelOpenReceived(message);
  757. }
  758. private void HandleMessage(ChannelOpenConfirmationMessage message)
  759. {
  760. this.OnChannelOpenConfirmationReceived(message);
  761. }
  762. private void HandleMessage(ChannelOpenFailureMessage message)
  763. {
  764. this.OnChannelOpenFailureReceived(message);
  765. }
  766. private void HandleMessage(ChannelWindowAdjustMessage message)
  767. {
  768. this.OnChannelWindowAdjustReceived(message);
  769. }
  770. private void HandleMessage(ChannelDataMessage message)
  771. {
  772. this.OnChannelDataReceived(message);
  773. }
  774. private void HandleMessage(ChannelExtendedDataMessage message)
  775. {
  776. this.OnChannelExtendedDataReceived(message);
  777. }
  778. private void HandleMessage(ChannelEofMessage message)
  779. {
  780. this.OnChannelEofReceived(message);
  781. }
  782. private void HandleMessage(ChannelCloseMessage message)
  783. {
  784. this.OnChannelCloseReceived(message);
  785. }
  786. private void HandleMessage(ChannelRequestMessage message)
  787. {
  788. this.OnChannelRequestReceived(message);
  789. }
  790. private void HandleMessage(ChannelSuccessMessage message)
  791. {
  792. this.OnChannelSuccessReceived(message);
  793. }
  794. private void HandleMessage(ChannelFailureMessage message)
  795. {
  796. this.OnChannelFailureReceived(message);
  797. }
  798. #endregion
  799. #region Handle received message events
  800. /// <summary>
  801. /// Called when <see cref="DisconnectMessage"/> received.
  802. /// </summary>
  803. /// <param name="message"><see cref="DisconnectMessage"/> message.</param>
  804. protected virtual void OnDisconnectReceived(DisconnectMessage message)
  805. {
  806. if (this.DisconnectReceived != null)
  807. {
  808. this.DisconnectReceived(this, new MessageEventArgs<DisconnectMessage>(message));
  809. }
  810. if (this.Disconnected != null)
  811. {
  812. this.Disconnected(this, new EventArgs());
  813. }
  814. }
  815. /// <summary>
  816. /// Called when <see cref="IgnoreMessage"/> received.
  817. /// </summary>
  818. /// <param name="message"><see cref="IgnoreMessage"/> message.</param>
  819. protected virtual void OnIgnoreReceived(IgnoreMessage message)
  820. {
  821. if (this.IgnoreReceived != null)
  822. {
  823. this.IgnoreReceived(this, new MessageEventArgs<IgnoreMessage>(message));
  824. }
  825. }
  826. /// <summary>
  827. /// Called when <see cref="UnimplementedMessage"/> message received.
  828. /// </summary>
  829. /// <param name="message"><see cref="UnimplementedMessage"/> message.</param>
  830. protected virtual void OnUnimplementedReceived(UnimplementedMessage message)
  831. {
  832. if (this.UnimplementedReceived != null)
  833. {
  834. this.UnimplementedReceived(this, new MessageEventArgs<UnimplementedMessage>(message));
  835. }
  836. }
  837. /// <summary>
  838. /// Called when <see cref="DebugMessage"/> message received.
  839. /// </summary>
  840. /// <param name="message"><see cref="DebugMessage"/> message.</param>
  841. protected virtual void OnDebugReceived(DebugMessage message)
  842. {
  843. if (this.DebugReceived != null)
  844. {
  845. this.DebugReceived(this, new MessageEventArgs<DebugMessage>(message));
  846. }
  847. }
  848. /// <summary>
  849. /// Called when <see cref="ServiceRequestMessage"/> message received.
  850. /// </summary>
  851. /// <param name="message"><see cref="ServiceRequestMessage"/> message.</param>
  852. protected virtual void OnServiceRequestReceived(ServiceRequestMessage message)
  853. {
  854. if (this.ServiceRequestReceived != null)
  855. {
  856. this.ServiceRequestReceived(this, new MessageEventArgs<ServiceRequestMessage>(message));
  857. }
  858. }
  859. /// <summary>
  860. /// Called when <see cref="ServiceAcceptMessage"/> message received.
  861. /// </summary>
  862. /// <param name="message"><see cref="ServiceAcceptMessage"/> message.</param>
  863. protected virtual void OnServiceAcceptReceived(ServiceAcceptMessage message)
  864. {
  865. if (this.ServiceAcceptReceived != null)
  866. {
  867. this.ServiceAcceptReceived(this, new MessageEventArgs<ServiceAcceptMessage>(message));
  868. }
  869. }
  870. /// <summary>
  871. /// Called when <see cref="KeyExchangeInitMessage"/> message received.
  872. /// </summary>
  873. /// <param name="message"><see cref="KeyExchangeInitMessage"/> message.</param>
  874. protected virtual void OnKeyExchangeInitReceived(KeyExchangeInitMessage message)
  875. {
  876. this._keyExchangeCompletedWaitHandle.Reset();
  877. // Disable all registered messages except key exchange related
  878. foreach (var messageMetadata in this._messagesMetadata)
  879. {
  880. if (messageMetadata.Activated == true && messageMetadata.Number > 2 && (messageMetadata.Number < 20 || messageMetadata.Number > 30))
  881. messageMetadata.Enabled = false;
  882. }
  883. var keyExchangeAlgorithmName = (from c in this.ConnectionInfo.KeyExchangeAlgorithms.Keys
  884. from s in message.KeyExchangeAlgorithms
  885. where s == c
  886. select c).FirstOrDefault();
  887. if (keyExchangeAlgorithmName == null)
  888. {
  889. throw new SshConnectionException("Failed to negotiate key exchange algorithm.", DisconnectReason.KeyExchangeFailed);
  890. }
  891. // Create instance of key exchange algorithm that will be used
  892. this._keyExchange = this.ConnectionInfo.KeyExchangeAlgorithms[keyExchangeAlgorithmName].CreateInstance<KeyExchange>();
  893. // Start the algorithm implementation
  894. this._keyExchange.Start(this, message);
  895. if (this.KeyExchangeInitReceived != null)
  896. {
  897. this.KeyExchangeInitReceived(this, new MessageEventArgs<KeyExchangeInitMessage>(message));
  898. }
  899. }
  900. /// <summary>
  901. /// Called when <see cref="NewKeysMessage"/> message received.
  902. /// </summary>
  903. /// <param name="message"><see cref="NewKeysMessage"/> message.</param>
  904. protected virtual void OnNewKeysReceived(NewKeysMessage message)
  905. {
  906. // Update sessionId
  907. if (this.SessionId == null)
  908. {
  909. this.SessionId = this._keyExchange.ExchangeHash;
  910. }
  911. // Dispose of old ciphers and hash algorithms
  912. if (this._serverMac != null)
  913. {
  914. this._serverMac.Dispose();
  915. this._serverMac = null;
  916. }
  917. if (this._clientMac != null)
  918. {
  919. this._clientMac.Dispose();
  920. this._clientMac = null;
  921. }
  922. // Update negotiated algorithms
  923. this._serverCipher = this._keyExchange.CreateServerCipher();
  924. this._clientCipher = this._keyExchange.CreateClientCipher();
  925. this._serverMac = this._keyExchange.CreateServerHash();
  926. this._clientMac = this._keyExchange.CreateClientHash();
  927. this._clientCompression = this._keyExchange.CreateCompressor();
  928. this._serverDecompression = this._keyExchange.CreateDecompressor();
  929. // Dispose of old KeyExchange object as it is no longer needed.
  930. if (this._keyExchange != null)
  931. {
  932. this._keyExchange.Dispose();
  933. this._keyExchange = null;
  934. }
  935. // Enable all active registered messages
  936. foreach (var messageMetadata in this._messagesMetadata)
  937. {
  938. if (messageMetadata.Activated == true)
  939. messageMetadata.Enabled = true;
  940. }
  941. if (this.NewKeysReceived != null)
  942. {
  943. this.NewKeysReceived(this, new MessageEventArgs<NewKeysMessage>(message));
  944. }
  945. // Signal that key exchange completed
  946. this._keyExchangeCompletedWaitHandle.Set();
  947. }
  948. /// <summary>
  949. /// Called when <see cref="RequestMessage"/> message received.
  950. /// </summary>
  951. /// <param name="message"><see cref="RequestMessage"/> message.</param>
  952. protected virtual void OnUserAuthenticationRequestReceived(RequestMessage message)
  953. {
  954. if (this.UserAuthenticationRequestReceived != null)
  955. {
  956. this.UserAuthenticationRequestReceived(this, new MessageEventArgs<RequestMessage>(message));
  957. }
  958. }
  959. /// <summary>
  960. /// Called when <see cref="FailureMessage"/> message received.
  961. /// </summary>
  962. /// <param name="message"><see cref="FailureMessage"/> message.</param>
  963. protected virtual void OnUserAuthenticationFailureReceived(FailureMessage message)
  964. {
  965. if (this.UserAuthenticationFailureReceived != null)
  966. {
  967. this.UserAuthenticationFailureReceived(this, new MessageEventArgs<FailureMessage>(message));
  968. }
  969. }
  970. /// <summary>
  971. /// Called when <see cref="SuccessMessage"/> message received.
  972. /// </summary>
  973. /// <param name="message"><see cref="SuccessMessage"/> message.</param>
  974. protected virtual void OnUserAuthenticationSuccessReceived(SuccessMessage message)
  975. {
  976. if (this.UserAuthenticationSuccessReceived != null)
  977. {
  978. this.UserAuthenticationSuccessReceived(this, new MessageEventArgs<SuccessMessage>(message));
  979. }
  980. }
  981. /// <summary>
  982. /// Called when <see cref="BannerMessage"/> message received.
  983. /// </summary>
  984. /// <param name="message"><see cref="BannerMessage"/> message.</param>
  985. protected virtual void OnUserAuthenticationBannerReceived(BannerMessage message)
  986. {
  987. if (this.UserAuthenticationBannerReceived != null)
  988. {
  989. this.UserAuthenticationBannerReceived(this, new MessageEventArgs<BannerMessage>(message));
  990. }
  991. }
  992. /// <summary>
  993. /// Called when <see cref="GlobalRequestMessage"/> message received.
  994. /// </summary>
  995. /// <param name="message"><see cref="GlobalRequestMessage"/> message.</param>
  996. protected virtual void OnGlobalRequestReceived(GlobalRequestMessage message)
  997. {
  998. if (this.GlobalRequestReceived != null)
  999. {
  1000. this.GlobalRequestReceived(this, new MessageEventArgs<GlobalRequestMessage>(message));
  1001. }
  1002. }
  1003. /// <summary>
  1004. /// Called when <see cref="RequestSuccessMessage"/> message received.
  1005. /// </summary>
  1006. /// <param name="message"><see cref="RequestSuccessMessage"/> message.</param>
  1007. protected virtual void OnRequestSuccessReceived(RequestSuccessMessage message)
  1008. {
  1009. if (this.RequestSuccessReceived != null)
  1010. {
  1011. this.RequestSuccessReceived(this, new MessageEventArgs<RequestSuccessMessage>(message));
  1012. }
  1013. }
  1014. /// <summary>
  1015. /// Called when <see cref="RequestFailureMessage"/> message received.
  1016. /// </summary>
  1017. /// <param name="message"><see cref="RequestFailureMessage"/> message.</param>
  1018. protected virtual void OnRequestFailureReceived(RequestFailureMessage message)
  1019. {
  1020. if (this.RequestFailureReceived != null)
  1021. {
  1022. this.RequestFailureReceived(this, new MessageEventArgs<RequestFailureMessage>(message));
  1023. }
  1024. }
  1025. /// <summary>
  1026. /// Called when <see cref="ChannelOpenMessage"/> message received.
  1027. /// </summary>
  1028. /// <param name="message"><see cref="ChannelOpenMessage"/> message.</param>
  1029. protected virtual void OnChannelOpenReceived(ChannelOpenMessage message)
  1030. {
  1031. if (this.ChannelOpenReceived != null)
  1032. {
  1033. this.ChannelOpenReceived(this, new MessageEventArgs<ChannelOpenMessage>(message));
  1034. }
  1035. }
  1036. /// <summary>
  1037. /// Called when <see cref="ChannelOpenConfirmationMessage"/> message received.
  1038. /// </summary>
  1039. /// <param name="message"><see cref="ChannelOpenConfirmationMessage"/> message.</param>
  1040. protected virtual void OnChannelOpenConfirmationReceived(ChannelOpenConfirmationMessage message)
  1041. {
  1042. if (this.ChannelOpenConfirmationReceived != null)
  1043. {
  1044. this.ChannelOpenConfirmationReceived(this, new MessageEventArgs<ChannelOpenConfirmationMessage>(message));
  1045. }
  1046. }
  1047. /// <summary>
  1048. /// Called when <see cref="ChannelOpenFailureMessage"/> message received.
  1049. /// </summary>
  1050. /// <param name="message"><see cref="ChannelOpenFailureMessage"/> message.</param>
  1051. protected virtual void OnChannelOpenFailureReceived(ChannelOpenFailureMessage message)
  1052. {
  1053. if (this.ChannelOpenFailureReceived != null)
  1054. {
  1055. this.ChannelOpenFailureReceived(this, new MessageEventArgs<ChannelOpenFailureMessage>(message));
  1056. }
  1057. }
  1058. /// <summary>
  1059. /// Called when <see cref="ChannelWindowAdjustMessage"/> message received.
  1060. /// </summary>
  1061. /// <param name="message"><see cref="ChannelWindowAdjustMessage"/> message.</param>
  1062. protected virtual void OnChannelWindowAdjustReceived(ChannelWindowAdjustMessage message)
  1063. {
  1064. if (this.ChannelWindowAdjustReceived != null)
  1065. {
  1066. this.ChannelWindowAdjustReceived(this, new MessageEventArgs<ChannelWindowAdjustMessage>(message));
  1067. }
  1068. }
  1069. /// <summary>
  1070. /// Called when <see cref="ChannelDataMessage"/> message received.
  1071. /// </summary>
  1072. /// <param name="message"><see cref="ChannelDataMessage"/> message.</param>
  1073. protected virtual void OnChannelDataReceived(ChannelDataMessage message)
  1074. {
  1075. if (this.ChannelDataReceived != null)
  1076. {
  1077. this.ChannelDataReceived(this, new MessageEventArgs<ChannelDataMessage>(message));
  1078. }
  1079. }
  1080. /// <summary>
  1081. /// Called when <see cref="ChannelExtendedDataMessage"/> message received.
  1082. /// </summary>
  1083. /// <param name="message"><see cref="ChannelExtendedDataMessage"/> message.</param>
  1084. protected virtual void OnChannelExtendedDataReceived(ChannelExtendedDataMessage message)
  1085. {
  1086. if (this.ChannelExtendedDataReceived != null)
  1087. {
  1088. this.ChannelExtendedDataReceived(this, new MessageEventArgs<ChannelExtendedDataMessage>(message));
  1089. }
  1090. }
  1091. /// <summary>
  1092. /// Called when <see cref="ChannelCloseMessage"/> message received.
  1093. /// </summary>
  1094. /// <param name="message"><see cref="ChannelCloseMessage"/> message.</param>
  1095. protected virtual void OnChannelEofReceived(ChannelEofMessage message)
  1096. {
  1097. if (this.ChannelEofReceived != null)
  1098. {
  1099. this.ChannelEofReceived(this, new MessageEventArgs<ChannelEofMessage>(message));
  1100. }
  1101. }
  1102. /// <summary>
  1103. /// Called when <see cref="ChannelCloseMessage"/> message received.
  1104. /// </summary>
  1105. /// <param name="message"><see cref="ChannelCloseMessage"/> message.</param>
  1106. protected virtual void OnChannelCloseReceived(ChannelCloseMessage message)
  1107. {
  1108. if (this.ChannelCloseReceived != null)
  1109. {
  1110. this.ChannelCloseReceived(this, new MessageEventArgs<ChannelCloseMessage>(message));
  1111. }
  1112. }
  1113. /// <summary>
  1114. /// Called when <see cref="ChannelRequestMessage"/> message received.
  1115. /// </summary>
  1116. /// <param name="message"><see cref="ChannelRequestMessage"/> message.</param>
  1117. protected virtual void OnChannelRequestReceived(ChannelRequestMessage message)
  1118. {
  1119. if (this.ChannelRequestReceived != null)
  1120. {
  1121. this.ChannelRequestReceived(this, new MessageEventArgs<ChannelRequestMessage>(message));
  1122. }
  1123. }
  1124. /// <summary>
  1125. /// Called when <see cref="ChannelSuccessMessage"/> message received.
  1126. /// </summary>
  1127. /// <param name="message"><see cref="ChannelSuccessMessage"/> message.</param>
  1128. protected virtual void OnChannelSuccessReceived(ChannelSuccessMessage message)
  1129. {
  1130. if (this.ChannelSuccessReceived != null)
  1131. {
  1132. this.ChannelSuccessReceived(this, new MessageEventArgs<ChannelSuccessMessage>(message));
  1133. }
  1134. }
  1135. /// <summary>
  1136. /// Called when <see cref="ChannelFailureMessage"/> message received.
  1137. /// </summary>
  1138. /// <param name="message"><see cref="ChannelFailureMessage"/> message.</param>
  1139. protected virtual void OnChannelFailureReceived(ChannelFailureMessage message)
  1140. {
  1141. if (this.ChannelFailureReceived != null)
  1142. {
  1143. this.ChannelFailureReceived(this, new MessageEventArgs<ChannelFailureMessage>(message));
  1144. }
  1145. }
  1146. /// <summary>
  1147. /// Called when <see cref="Message"/> message received.
  1148. /// </summary>
  1149. /// <param name="message"><see cref="Message"/> message.</param>
  1150. protected virtual void OnMessageReceived(Message message)
  1151. {
  1152. if (this.MessageReceived != null)
  1153. {
  1154. this.MessageReceived(this, new MessageEventArgs<Message>(message));
  1155. }
  1156. }
  1157. #endregion
  1158. #region Read & Write operations
  1159. /// <summary>
  1160. /// Reads the specified length of bytes from the server
  1161. /// </summary>
  1162. /// <param name="length">The length.</param>
  1163. /// <returns></returns>
  1164. private byte[] Read(int length)
  1165. {
  1166. byte[] buffer = new byte[length];
  1167. this.InternalRead(length, ref buffer);
  1168. return buffer;
  1169. }
  1170. /// <summary>
  1171. /// Writes the specified data to the server.
  1172. /// </summary>
  1173. /// <param name="data">The data.</param>
  1174. partial void Write(byte[] data);
  1175. #endregion
  1176. #region Message loading functions
  1177. /// <summary>
  1178. /// Registers SSH Message with the session.
  1179. /// </summary>
  1180. /// <param name="messageName">Name of the message.</param>
  1181. public void RegisterMessage(string messageName)
  1182. {
  1183. this.InternalRegisterMessage(messageName);
  1184. }
  1185. /// <summary>
  1186. /// Removes SSH message from the session
  1187. /// </summary>
  1188. /// <param name="messageName">Name of the message.</param>
  1189. public void UnRegisterMessage(string messageName)
  1190. {
  1191. this.InternalUnRegisterMessage(messageName);
  1192. }
  1193. /// <summary>
  1194. /// Loads the message.
  1195. /// </summary>
  1196. /// <param name="data">Message data.</param>
  1197. /// <returns>New message</returns>
  1198. private Message LoadMessage(byte[] data)
  1199. {
  1200. var messageType = data[0];
  1201. var messageMetadata = (from m in this._messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).SingleOrDefault();
  1202. if (messageMetadata == null)
  1203. throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
  1204. var message = messageMetadata.Type.CreateInstance<Message>();
  1205. message.Load(data);
  1206. return message;
  1207. }
  1208. partial void InternalRegisterMessage(string messageName);
  1209. partial void InternalUnRegisterMessage(string messageName);
  1210. #endregion
  1211. partial void ExecuteThread(Action action);
  1212. partial void OpenSocket();
  1213. partial void InternalRead(int length, ref byte[] buffer);
  1214. /// <summary>
  1215. /// Listens for incoming message from the server and handles them. This method run as a task on separate thread.
  1216. /// </summary>
  1217. private void MessageListener()
  1218. {
  1219. try
  1220. {
  1221. while (this._socket.Connected)
  1222. {
  1223. var message = this.ReceiveMessage();
  1224. if (message == null)
  1225. {
  1226. throw new NullReferenceException("The 'message' variable cannot be null");
  1227. }
  1228. else
  1229. {
  1230. this.HandleMessage((dynamic)message);
  1231. }
  1232. }
  1233. }
  1234. catch (Exception exp)
  1235. {
  1236. this.RaiseError(exp);
  1237. }
  1238. }
  1239. /// <summary>
  1240. /// Raises the <see cref="ErrorOccured"/> event.
  1241. /// </summary>
  1242. /// <param name="exp">The exp.</param>
  1243. private void RaiseError(Exception exp)
  1244. {
  1245. var connectionException = exp as SshConnectionException;
  1246. // If connection exception was raised while isDisconnecting is true then this is expected
  1247. // case and should be ignore
  1248. if (connectionException != null && this._isDisconnecting)
  1249. return;
  1250. this._exception = exp;
  1251. this._exceptionWaitHandle.Set();
  1252. if (this.ErrorOccured != null)
  1253. {
  1254. this.ErrorOccured(this, new ExceptionEventArgs(exp));
  1255. }
  1256. if (connectionException != null && connectionException.DisconnectReason != DisconnectReason.ConnectionLost)
  1257. {
  1258. this.SendDisconnect(connectionException.DisconnectReason, exp.ToString());
  1259. }
  1260. }
  1261. #region IDisposable Members
  1262. private bool _disposed = false;
  1263. /// <summary>
  1264. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
  1265. /// </summary>
  1266. public void Dispose()
  1267. {
  1268. Dispose(true);
  1269. GC.SuppressFinalize(this);
  1270. }
  1271. /// <summary>
  1272. /// Releases unmanaged and - optionally - managed resources
  1273. /// </summary>
  1274. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param>
  1275. protected virtual void Dispose(bool disposing)
  1276. {
  1277. // Check to see if Dispose has already been called.
  1278. if (!this._disposed)
  1279. {
  1280. // If disposing equals true, dispose all managed
  1281. // and unmanaged ResourceMessages.
  1282. if (disposing)
  1283. {
  1284. this._isDisconnecting = true;
  1285. if (this._socket != null)
  1286. {
  1287. // If socket still open try to send disconnect message to the server
  1288. this.SendDisconnect(DisconnectReason.ByApplication, "Connection terminated by the client.");
  1289. this._socket.Dispose();
  1290. this._socket = null;
  1291. }
  1292. if (this._messageListenerCompleted != null)
  1293. {
  1294. // Wait for socket to be closed and for task to complete before disposing a task
  1295. this._messageListenerCompleted.WaitOne();
  1296. this._messageListenerCompleted.Dispose();
  1297. this._messageListenerCompleted = null;
  1298. }
  1299. if (this._serviceAccepted != null)
  1300. {
  1301. this._serviceAccepted.Dispose();
  1302. this._serviceAccepted = null;
  1303. }
  1304. if (this._exceptionWaitHandle != null)
  1305. {
  1306. this._exceptionWaitHandle.Dispose();
  1307. this._exceptionWaitHandle = null;
  1308. }
  1309. if (this._keyExchangeCompletedWaitHandle != null)
  1310. {
  1311. this._keyExchangeCompletedWaitHandle.Dispose();
  1312. this._keyExchangeCompletedWaitHandle = null;
  1313. }
  1314. if (this._serverMac != null)
  1315. {
  1316. this._serverMac.Dispose();
  1317. this._serverMac = null;
  1318. }
  1319. if (this._clientMac != null)
  1320. {
  1321. this._clientMac.Dispose();
  1322. this._clientMac = null;
  1323. }
  1324. if (this._keyExchange != null)
  1325. {
  1326. this._keyExchange.Dispose();
  1327. this._keyExchange = null;
  1328. }
  1329. }
  1330. // Note disposing has been done.
  1331. this._disposed = true;
  1332. }
  1333. }
  1334. /// <summary>
  1335. /// Releases unmanaged resources and performs other cleanup operations before the
  1336. /// <see cref="Session"/> is reclaimed by garbage collection.
  1337. /// </summary>
  1338. ~Session()
  1339. {
  1340. // Do not re-create Dispose clean-up code here.
  1341. // Calling Dispose(false) is optimal in terms of
  1342. // readability and maintainability.
  1343. Dispose(false);
  1344. }
  1345. #endregion
  1346. private class MessageMetadata
  1347. {
  1348. public string Name { get; set; }
  1349. public byte Number { get; set; }
  1350. public bool Enabled { get; set; }
  1351. public bool Activated { get; set; }
  1352. public Type Type { get; set; }
  1353. }
  1354. }
  1355. }