2
0

Session.cs 61 KB

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