Session.cs 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732
  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. var ep = new IPEndPoint(Dns.GetHostAddresses(this.ConnectionInfo.Host)[0], this.ConnectionInfo.Port);
  347. this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  348. var socketBufferSize = 2 * MAXIMUM_PACKET_SIZE;
  349. this._socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  350. this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, socketBufferSize);
  351. this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, socketBufferSize);
  352. // Connect socket with 5 seconds timeout
  353. var connectResult = this._socket.BeginConnect(ep, null, null);
  354. connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout);
  355. // Build list of available messages while connecting
  356. this._messagesMetadata = (from type in this.GetType().Assembly.GetTypes()
  357. from messageAttribute in type.GetCustomAttributes(false).OfType<MessageAttribute>()
  358. select new MessageMetadata
  359. {
  360. Name = messageAttribute.Name,
  361. Number = messageAttribute.Number,
  362. Enabled = false,
  363. Activated = false,
  364. Type = type,
  365. }).ToList();
  366. this._socket.EndConnect(connectResult);
  367. Match versionMatch = null;
  368. // Get server version from the server,
  369. // ignore text lines which are sent before if any
  370. using (var ns = new NetworkStream(this._socket))
  371. {
  372. using (var sr = new StreamReader(ns))
  373. {
  374. while (true)
  375. {
  376. this.ServerVersion = sr.ReadLine();
  377. if (string.IsNullOrEmpty(this.ServerVersion))
  378. {
  379. throw new InvalidOperationException("Server string is null or empty.");
  380. }
  381. versionMatch = _serverVersionRe.Match(this.ServerVersion);
  382. if (versionMatch.Success)
  383. {
  384. break;
  385. }
  386. }
  387. }
  388. }
  389. // Get server SSH version
  390. var version = versionMatch.Result("${protoversion}");
  391. if (!(version.Equals("2.0") || version.Equals("1.99")))
  392. {
  393. throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReason.ProtocolVersionNotSupported);
  394. }
  395. this.Write(Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
  396. // Register Transport response messages
  397. this.RegisterMessage("SSH_MSG_DISCONNECT");
  398. this.RegisterMessage("SSH_MSG_IGNORE");
  399. this.RegisterMessage("SSH_MSG_UNIMPLEMENTED");
  400. this.RegisterMessage("SSH_MSG_DEBUG");
  401. this.RegisterMessage("SSH_MSG_SERVICE_ACCEPT");
  402. this.RegisterMessage("SSH_MSG_KEXINIT");
  403. this.RegisterMessage("SSH_MSG_NEWKEYS");
  404. // Some server implementations might sent this message first, prior establishing encryption algorithm
  405. this.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
  406. // Start incoming request listener
  407. this._messageListenerCompleted = new ManualResetEvent(false);
  408. this.ExecuteThread(() =>
  409. {
  410. try
  411. {
  412. this.MessageListener();
  413. }
  414. finally
  415. {
  416. this._messageListenerCompleted.Set();
  417. }
  418. });
  419. // Wait for key exchange to be completed
  420. this.WaitHandle(this._keyExchangeCompletedWaitHandle);
  421. // If sessionId is not set then its not connected
  422. if (this.SessionId == null)
  423. {
  424. this.Disconnect();
  425. return;
  426. }
  427. // Request user authorization service
  428. this.SendMessage(new ServiceRequestMessage(ServiceName.UserAuthentication));
  429. // Wait for service to be accepted
  430. this.WaitHandle(this._serviceAccepted);
  431. if (string.IsNullOrEmpty(this.ConnectionInfo.Username))
  432. {
  433. throw new SshException("Username is not specified.");
  434. }
  435. // Try authenticate using none method
  436. using (var noneConnectionInfo = new NoneConnectionInfo(this.ConnectionInfo.Host, this.ConnectionInfo.Port, this.ConnectionInfo.Username))
  437. {
  438. noneConnectionInfo.Authenticate(this);
  439. this._isAuthenticated = noneConnectionInfo.IsAuthenticated;
  440. if (!this._isAuthenticated)
  441. {
  442. // Ensure that authentication method is allowed
  443. if (!noneConnectionInfo.AllowedAuthentications.Contains(this.ConnectionInfo.Name))
  444. {
  445. throw new SshAuthenticationException("User authentication method is not supported.");
  446. }
  447. // In future, if more then one authentication methods are supported perform the check here.
  448. // Authenticate using provided connection info object
  449. this.ConnectionInfo.Authenticate(this);
  450. this._isAuthenticated = this.ConnectionInfo.IsAuthenticated;
  451. }
  452. }
  453. if (!this._isAuthenticated)
  454. {
  455. throw new SshAuthenticationException("User cannot be authenticated.");
  456. }
  457. // Register Connection messages
  458. this.RegisterMessage("SSH_MSG_GLOBAL_REQUEST");
  459. this.RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
  460. this.RegisterMessage("SSH_MSG_REQUEST_FAILURE");
  461. this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
  462. this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_FAILURE");
  463. this.RegisterMessage("SSH_MSG_CHANNEL_WINDOW_ADJUST");
  464. this.RegisterMessage("SSH_MSG_CHANNEL_EXTENDED_DATA");
  465. this.RegisterMessage("SSH_MSG_CHANNEL_REQUEST");
  466. this.RegisterMessage("SSH_MSG_CHANNEL_SUCCESS");
  467. this.RegisterMessage("SSH_MSG_CHANNEL_FAILURE");
  468. this.RegisterMessage("SSH_MSG_CHANNEL_DATA");
  469. this.RegisterMessage("SSH_MSG_CHANNEL_EOF");
  470. this.RegisterMessage("SSH_MSG_CHANNEL_CLOSE");
  471. Monitor.Pulse(this);
  472. }
  473. }
  474. finally
  475. {
  476. _authenticationConnection.Release();
  477. }
  478. }
  479. /// <summary>
  480. /// Disconnects from the server
  481. /// </summary>
  482. public void Disconnect()
  483. {
  484. this.Dispose();
  485. }
  486. internal T CreateChannel<T>() where T : Channel, new()
  487. {
  488. return CreateChannel<T>(0, 0x100000, 0x8000);
  489. }
  490. internal T CreateChannel<T>(uint serverChannelNumber, uint windowSize, uint packetSize) where T : Channel, new()
  491. {
  492. T channel = new T();
  493. lock (this)
  494. {
  495. channel.Initialize(this, serverChannelNumber, windowSize, packetSize);
  496. }
  497. return channel;
  498. }
  499. /// <summary>
  500. /// Sends "keep alive" message to keep connection alive.
  501. /// </summary>
  502. internal void SendKeepAlive()
  503. {
  504. this.SendMessage(new IgnoreMessage());
  505. }
  506. /// <summary>
  507. /// Waits for handle to signal while checking other handles as well including timeout check to prevent waiting for ever
  508. /// </summary>
  509. /// <param name="waitHandle">The wait handle.</param>
  510. internal void WaitHandle(WaitHandle waitHandle)
  511. {
  512. var waitHandles = new WaitHandle[]
  513. {
  514. this._exceptionWaitHandle,
  515. waitHandle,
  516. };
  517. var index = EventWaitHandle.WaitAny(waitHandles, this.ConnectionInfo.Timeout);
  518. if (index < 1)
  519. {
  520. throw this._exception;
  521. }
  522. else if (index > 1)
  523. {
  524. this.SendDisconnect(DisconnectReason.ByApplication, "Operation timeout");
  525. throw new SshOperationTimeoutException("Session operation has timed out");
  526. }
  527. }
  528. /// <summary>
  529. /// Sends packet message to the server.
  530. /// </summary>
  531. /// <param name="message">The message.</param>
  532. internal void SendMessage(Message message)
  533. {
  534. if (this._socket == null || !this._socket.Connected)
  535. return;
  536. // Messages can be sent by different thread so we need to synchronize it
  537. var paddingMultiplier = this._clientCipher == null ? (byte)8 : (byte)this._clientCipher.BlockSize; // Should be recalculate base on cipher min length if cipher specified
  538. var messageData = message.GetBytes();
  539. if (messageData.Length > Session.MAXIMUM_PAYLOAD_SIZE)
  540. {
  541. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Payload cannot be more then {0} bytes.", Session.MAXIMUM_PAYLOAD_SIZE));
  542. }
  543. if (this._clientCompression != null)
  544. {
  545. messageData = this._clientCompression.Compress(messageData);
  546. }
  547. var packetLength = messageData.Length + 4 + 1; // add length bytes and padding byte
  548. byte paddingLength = (byte)((-packetLength) & (paddingMultiplier - 1));
  549. if (paddingLength < paddingMultiplier)
  550. {
  551. paddingLength += paddingMultiplier;
  552. }
  553. // Build Packet data
  554. var packetData = new byte[4 + 1 + messageData.Length + paddingLength];
  555. // Add packet length
  556. ((uint)packetData.Length - 4).GetBytes().CopyTo(packetData, 0);
  557. // Add packet padding length
  558. packetData[4] = paddingLength;
  559. // Add packet payload
  560. messageData.CopyTo(packetData, 4 + 1);
  561. // Add random padding
  562. var paddingBytes = new byte[paddingLength];
  563. _randomizer.GetBytes(paddingBytes);
  564. paddingBytes.CopyTo(packetData, 4 + 1 + messageData.Length);
  565. // Lock handling of _outboundPacketSequence since it must be sent sequently to server
  566. lock (this._socket)
  567. {
  568. // Calculate packet hash
  569. var hashData = new byte[4 + packetData.Length];
  570. this._outboundPacketSequence.GetBytes().CopyTo(hashData, 0);
  571. packetData.CopyTo(hashData, 4);
  572. // Encrypt packet data
  573. if (this._clientCipher != null)
  574. {
  575. packetData = this._clientCipher.Encrypt(packetData);
  576. }
  577. if (packetData.Length > Session.MAXIMUM_PACKET_SIZE)
  578. {
  579. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Packet is too big. Maximum packet size is {0} bytes.", Session.MAXIMUM_PACKET_SIZE));
  580. }
  581. if (this._clientMac == null)
  582. {
  583. this.Write(packetData);
  584. }
  585. else
  586. {
  587. var hash = this._clientMac.ComputeHash(hashData.ToArray());
  588. var data = new byte[packetData.Length + this._clientMac.HashSize / 8];
  589. packetData.CopyTo(data, 0);
  590. hash.CopyTo(data, packetData.Length);
  591. this.Write(data);
  592. }
  593. this._outboundPacketSequence++;
  594. Monitor.Pulse(this._socket);
  595. }
  596. }
  597. /// <summary>
  598. /// Receives the message from the server.
  599. /// </summary>
  600. /// <returns></returns>
  601. private Message ReceiveMessage()
  602. {
  603. if (!this._socket.Connected)
  604. return null;
  605. // No lock needed since all messages read by only one thread
  606. var blockSize = this._serverCipher == null ? (byte)8 : (byte)this._serverCipher.BlockSize;
  607. // Read packet length first
  608. var firstBlock = this.Read(blockSize);
  609. if (this._serverCipher != null)
  610. {
  611. firstBlock = this._serverCipher.Decrypt(firstBlock);
  612. }
  613. var packetLength = (uint)(firstBlock[0] << 24 | firstBlock[1] << 16 | firstBlock[2] << 8 | firstBlock[3]);
  614. // Test packet minimum and maximum boundaries
  615. if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > Session.MAXIMUM_PACKET_SIZE - 4)
  616. throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Bad packet length {0}", packetLength), DisconnectReason.ProtocolError);
  617. // Read rest of the packet data
  618. int bytesToRead = (int)(packetLength - (blockSize - 4));
  619. var data = new byte[bytesToRead + blockSize];
  620. firstBlock.CopyTo(data, 0);
  621. byte[] serverHash = null;
  622. if (this._serverMac != null)
  623. {
  624. serverHash = new byte[this._serverMac.HashSize / 8];
  625. bytesToRead += serverHash.Length;
  626. }
  627. if (bytesToRead > 0)
  628. {
  629. var nextBlocks = this.Read(bytesToRead);
  630. if (serverHash != null)
  631. {
  632. Array.Copy(nextBlocks, nextBlocks.Length - serverHash.Length, serverHash, 0, serverHash.Length);
  633. nextBlocks = nextBlocks.Take(nextBlocks.Length - serverHash.Length).ToArray();
  634. }
  635. if (nextBlocks.Length > 0)
  636. {
  637. if (this._serverCipher != null)
  638. {
  639. nextBlocks = this._serverCipher.Decrypt(nextBlocks);
  640. }
  641. nextBlocks.CopyTo(data, blockSize);
  642. }
  643. }
  644. var paddingLength = data[4];
  645. var messagePayload = new byte[packetLength - paddingLength - 1];
  646. Array.Copy(data, 5, messagePayload, 0, messagePayload.Length);
  647. if (this._serverDecompression != null)
  648. {
  649. messagePayload = this._serverDecompression.Decompress(messagePayload);
  650. }
  651. // Validate message against MAC
  652. if (this._serverMac != null)
  653. {
  654. var clientHashData = new byte[4 + data.Length];
  655. var lengthBytes = this._inboundPacketSequence.GetBytes();
  656. lengthBytes.CopyTo(clientHashData, 0);
  657. data.CopyTo(clientHashData, 4);
  658. // Calculate packet hash
  659. var clientHash = this._serverMac.ComputeHash(clientHashData);
  660. if (!serverHash.SequenceEqual(clientHash))
  661. {
  662. throw new SshConnectionException("MAC error", DisconnectReason.MacError);
  663. }
  664. }
  665. this._inboundPacketSequence++;
  666. return this.LoadMessage(messagePayload);
  667. }
  668. private void SendDisconnect(DisconnectReason reasonCode, string message)
  669. {
  670. // If disconnect message was sent already dont send it again
  671. if (this._isDisconnectMessageSent)
  672. return;
  673. var disconnectMessage = new DisconnectMessage(reasonCode, message);
  674. this.SendMessage(disconnectMessage);
  675. this._isDisconnectMessageSent = true;
  676. }
  677. /// <summary>
  678. /// Handles the message.
  679. /// </summary>
  680. /// <typeparam name="T"></typeparam>
  681. /// <param name="message">The message.</param>
  682. private void HandleMessage<T>(T message) where T : Message
  683. {
  684. this.OnMessageReceived(message);
  685. }
  686. #region Handle transport messages
  687. private void HandleMessage(DisconnectMessage message)
  688. {
  689. this.OnDisconnectReceived(message);
  690. // Shutdown and disconnect from the socket
  691. if (this._socket != null)
  692. {
  693. lock (this._socket)
  694. {
  695. if (this._socket != null)
  696. {
  697. this._socket.Disconnect(true);
  698. // When socket is disconnected wait for listener to finish
  699. if (this._messageListenerCompleted != null)
  700. {
  701. // Wait for listener task to finish
  702. this._messageListenerCompleted.WaitOne();
  703. this._messageListenerCompleted.Dispose();
  704. this._messageListenerCompleted = null;
  705. }
  706. this._socket.Dispose();
  707. this._socket = null;
  708. }
  709. }
  710. }
  711. }
  712. private void HandleMessage(IgnoreMessage message)
  713. {
  714. this.OnIgnoreReceived(message);
  715. }
  716. private void HandleMessage(UnimplementedMessage message)
  717. {
  718. this.OnUnimplementedReceived(message);
  719. }
  720. private void HandleMessage(DebugMessage message)
  721. {
  722. this.OnDebugReceived(message);
  723. }
  724. private void HandleMessage(ServiceRequestMessage message)
  725. {
  726. this.OnServiceRequestReceived(message);
  727. }
  728. private void HandleMessage(ServiceAcceptMessage message)
  729. {
  730. // TODO: Refactor to avoid this method here
  731. this.OnServiceAcceptReceived(message);
  732. this._serviceAccepted.Set();
  733. }
  734. private void HandleMessage(KeyExchangeInitMessage message)
  735. {
  736. this.OnKeyExchangeInitReceived(message);
  737. }
  738. private void HandleMessage(NewKeysMessage message)
  739. {
  740. this.OnNewKeysReceived(message);
  741. }
  742. #endregion
  743. #region Handle User Authentication messages
  744. private void HandleMessage(RequestMessage message)
  745. {
  746. this.OnUserAuthenticationRequestReceived(message);
  747. }
  748. private void HandleMessage(FailureMessage message)
  749. {
  750. this.OnUserAuthenticationFailureReceived(message);
  751. }
  752. private void HandleMessage(SuccessMessage message)
  753. {
  754. this.OnUserAuthenticationSuccessReceived(message);
  755. }
  756. private void HandleMessage(BannerMessage message)
  757. {
  758. this.OnUserAuthenticationBannerReceived(message);
  759. }
  760. #endregion
  761. #region Handle connection messages
  762. private void HandleMessage(GlobalRequestMessage message)
  763. {
  764. this.OnGlobalRequestReceived(message);
  765. }
  766. private void HandleMessage(RequestSuccessMessage message)
  767. {
  768. this.OnRequestSuccessReceived(message);
  769. }
  770. private void HandleMessage(RequestFailureMessage message)
  771. {
  772. this.OnRequestFailureReceived(message);
  773. }
  774. private void HandleMessage(ChannelOpenMessage message)
  775. {
  776. this.OnChannelOpenReceived(message);
  777. }
  778. private void HandleMessage(ChannelOpenConfirmationMessage message)
  779. {
  780. this.OnChannelOpenConfirmationReceived(message);
  781. }
  782. private void HandleMessage(ChannelOpenFailureMessage message)
  783. {
  784. this.OnChannelOpenFailureReceived(message);
  785. }
  786. private void HandleMessage(ChannelWindowAdjustMessage message)
  787. {
  788. this.OnChannelWindowAdjustReceived(message);
  789. }
  790. private void HandleMessage(ChannelDataMessage message)
  791. {
  792. this.OnChannelDataReceived(message);
  793. }
  794. private void HandleMessage(ChannelExtendedDataMessage message)
  795. {
  796. this.OnChannelExtendedDataReceived(message);
  797. }
  798. private void HandleMessage(ChannelEofMessage message)
  799. {
  800. this.OnChannelEofReceived(message);
  801. }
  802. private void HandleMessage(ChannelCloseMessage message)
  803. {
  804. this.OnChannelCloseReceived(message);
  805. }
  806. private void HandleMessage(ChannelRequestMessage message)
  807. {
  808. this.OnChannelRequestReceived(message);
  809. }
  810. private void HandleMessage(ChannelSuccessMessage message)
  811. {
  812. this.OnChannelSuccessReceived(message);
  813. }
  814. private void HandleMessage(ChannelFailureMessage message)
  815. {
  816. this.OnChannelFailureReceived(message);
  817. }
  818. #endregion
  819. #region Handle received message events
  820. /// <summary>
  821. /// Called when <see cref="DisconnectMessage"/> received.
  822. /// </summary>
  823. /// <param name="message"><see cref="DisconnectMessage"/> message.</param>
  824. protected virtual void OnDisconnectReceived(DisconnectMessage message)
  825. {
  826. if (this.DisconnectReceived != null)
  827. {
  828. this.DisconnectReceived(this, new MessageEventArgs<DisconnectMessage>(message));
  829. }
  830. if (this.Disconnected != null)
  831. {
  832. this.Disconnected(this, new EventArgs());
  833. }
  834. }
  835. /// <summary>
  836. /// Called when <see cref="IgnoreMessage"/> received.
  837. /// </summary>
  838. /// <param name="message"><see cref="IgnoreMessage"/> message.</param>
  839. protected virtual void OnIgnoreReceived(IgnoreMessage message)
  840. {
  841. if (this.IgnoreReceived != null)
  842. {
  843. this.IgnoreReceived(this, new MessageEventArgs<IgnoreMessage>(message));
  844. }
  845. }
  846. /// <summary>
  847. /// Called when <see cref="UnimplementedMessage"/> message received.
  848. /// </summary>
  849. /// <param name="message"><see cref="UnimplementedMessage"/> message.</param>
  850. protected virtual void OnUnimplementedReceived(UnimplementedMessage message)
  851. {
  852. if (this.UnimplementedReceived != null)
  853. {
  854. this.UnimplementedReceived(this, new MessageEventArgs<UnimplementedMessage>(message));
  855. }
  856. }
  857. /// <summary>
  858. /// Called when <see cref="DebugMessage"/> message received.
  859. /// </summary>
  860. /// <param name="message"><see cref="DebugMessage"/> message.</param>
  861. protected virtual void OnDebugReceived(DebugMessage message)
  862. {
  863. if (this.DebugReceived != null)
  864. {
  865. this.DebugReceived(this, new MessageEventArgs<DebugMessage>(message));
  866. }
  867. }
  868. /// <summary>
  869. /// Called when <see cref="ServiceRequestMessage"/> message received.
  870. /// </summary>
  871. /// <param name="message"><see cref="ServiceRequestMessage"/> message.</param>
  872. protected virtual void OnServiceRequestReceived(ServiceRequestMessage message)
  873. {
  874. if (this.ServiceRequestReceived != null)
  875. {
  876. this.ServiceRequestReceived(this, new MessageEventArgs<ServiceRequestMessage>(message));
  877. }
  878. }
  879. /// <summary>
  880. /// Called when <see cref="ServiceAcceptMessage"/> message received.
  881. /// </summary>
  882. /// <param name="message"><see cref="ServiceAcceptMessage"/> message.</param>
  883. protected virtual void OnServiceAcceptReceived(ServiceAcceptMessage message)
  884. {
  885. if (this.ServiceAcceptReceived != null)
  886. {
  887. this.ServiceAcceptReceived(this, new MessageEventArgs<ServiceAcceptMessage>(message));
  888. }
  889. }
  890. /// <summary>
  891. /// Called when <see cref="KeyExchangeInitMessage"/> message received.
  892. /// </summary>
  893. /// <param name="message"><see cref="KeyExchangeInitMessage"/> message.</param>
  894. protected virtual void OnKeyExchangeInitReceived(KeyExchangeInitMessage message)
  895. {
  896. this._keyExchangeCompletedWaitHandle.Reset();
  897. // Disable all registered messages except key exchange related
  898. foreach (var messageMetadata in this._messagesMetadata)
  899. {
  900. if (messageMetadata.Activated == true && messageMetadata.Number > 2 && (messageMetadata.Number < 20 || messageMetadata.Number > 30))
  901. messageMetadata.Enabled = false;
  902. }
  903. var keyExchangeAlgorithmName = (from c in this.ConnectionInfo.KeyExchangeAlgorithms.Keys
  904. from s in message.KeyExchangeAlgorithms
  905. where s == c
  906. select c).FirstOrDefault();
  907. if (keyExchangeAlgorithmName == null)
  908. {
  909. throw new SshConnectionException("Failed to negotiate key exchange algorithm.", DisconnectReason.KeyExchangeFailed);
  910. }
  911. // Create instance of key exchange algorithm that will be used
  912. this._keyExchange = this.ConnectionInfo.KeyExchangeAlgorithms[keyExchangeAlgorithmName].CreateInstance<KeyExchange>();
  913. // Start the algorithm implementation
  914. this._keyExchange.Start(this, message);
  915. if (this.KeyExchangeInitReceived != null)
  916. {
  917. this.KeyExchangeInitReceived(this, new MessageEventArgs<KeyExchangeInitMessage>(message));
  918. }
  919. }
  920. /// <summary>
  921. /// Called when <see cref="NewKeysMessage"/> message received.
  922. /// </summary>
  923. /// <param name="message"><see cref="NewKeysMessage"/> message.</param>
  924. protected virtual void OnNewKeysReceived(NewKeysMessage message)
  925. {
  926. // Update sessionId
  927. if (this.SessionId == null)
  928. {
  929. this.SessionId = this._keyExchange.ExchangeHash;
  930. }
  931. // Dispose of old ciphers and hash algorithms
  932. if (this._serverCipher != null)
  933. {
  934. this._serverCipher.Dispose();
  935. this._serverCipher = null;
  936. }
  937. if (this._clientCipher != null)
  938. {
  939. this._clientCipher.Dispose();
  940. this._clientCipher = null;
  941. }
  942. if (this._serverMac != null)
  943. {
  944. this._serverMac.Dispose();
  945. this._serverMac = null;
  946. }
  947. if (this._clientMac != null)
  948. {
  949. this._clientMac.Dispose();
  950. this._clientMac = null;
  951. }
  952. // Update negotiated algorithms
  953. this._serverCipher = this._keyExchange.CreateServerCipher();
  954. this._clientCipher = this._keyExchange.CreateClientCipher();
  955. this._serverMac = this._keyExchange.CreateServerHash();
  956. this._clientMac = this._keyExchange.CreateClientHash();
  957. this._clientCompression = this._keyExchange.CreateCompressor();
  958. this._serverDecompression = this._keyExchange.CreateDecompressor();
  959. // Dispose of old KeyExchange object as it is no longer needed.
  960. if (this._keyExchange != null)
  961. {
  962. this._keyExchange.Dispose();
  963. this._keyExchange = null;
  964. }
  965. // Enable all active registered messages
  966. foreach (var messageMetadata in this._messagesMetadata)
  967. {
  968. if (messageMetadata.Activated == true)
  969. messageMetadata.Enabled = true;
  970. }
  971. if (this.NewKeysReceived != null)
  972. {
  973. this.NewKeysReceived(this, new MessageEventArgs<NewKeysMessage>(message));
  974. }
  975. // Signal that key exchange completed
  976. this._keyExchangeCompletedWaitHandle.Set();
  977. }
  978. /// <summary>
  979. /// Called when <see cref="RequestMessage"/> message received.
  980. /// </summary>
  981. /// <param name="message"><see cref="RequestMessage"/> message.</param>
  982. protected virtual void OnUserAuthenticationRequestReceived(RequestMessage message)
  983. {
  984. if (this.UserAuthenticationRequestReceived != null)
  985. {
  986. this.UserAuthenticationRequestReceived(this, new MessageEventArgs<RequestMessage>(message));
  987. }
  988. }
  989. /// <summary>
  990. /// Called when <see cref="FailureMessage"/> message received.
  991. /// </summary>
  992. /// <param name="message"><see cref="FailureMessage"/> message.</param>
  993. protected virtual void OnUserAuthenticationFailureReceived(FailureMessage message)
  994. {
  995. if (this.UserAuthenticationFailureReceived != null)
  996. {
  997. this.UserAuthenticationFailureReceived(this, new MessageEventArgs<FailureMessage>(message));
  998. }
  999. }
  1000. /// <summary>
  1001. /// Called when <see cref="SuccessMessage"/> message received.
  1002. /// </summary>
  1003. /// <param name="message"><see cref="SuccessMessage"/> message.</param>
  1004. protected virtual void OnUserAuthenticationSuccessReceived(SuccessMessage message)
  1005. {
  1006. if (this.UserAuthenticationSuccessReceived != null)
  1007. {
  1008. this.UserAuthenticationSuccessReceived(this, new MessageEventArgs<SuccessMessage>(message));
  1009. }
  1010. }
  1011. /// <summary>
  1012. /// Called when <see cref="BannerMessage"/> message received.
  1013. /// </summary>
  1014. /// <param name="message"><see cref="BannerMessage"/> message.</param>
  1015. protected virtual void OnUserAuthenticationBannerReceived(BannerMessage message)
  1016. {
  1017. if (this.UserAuthenticationBannerReceived != null)
  1018. {
  1019. this.UserAuthenticationBannerReceived(this, new MessageEventArgs<BannerMessage>(message));
  1020. }
  1021. }
  1022. /// <summary>
  1023. /// Called when <see cref="GlobalRequestMessage"/> message received.
  1024. /// </summary>
  1025. /// <param name="message"><see cref="GlobalRequestMessage"/> message.</param>
  1026. protected virtual void OnGlobalRequestReceived(GlobalRequestMessage message)
  1027. {
  1028. if (this.GlobalRequestReceived != null)
  1029. {
  1030. this.GlobalRequestReceived(this, new MessageEventArgs<GlobalRequestMessage>(message));
  1031. }
  1032. }
  1033. /// <summary>
  1034. /// Called when <see cref="RequestSuccessMessage"/> message received.
  1035. /// </summary>
  1036. /// <param name="message"><see cref="RequestSuccessMessage"/> message.</param>
  1037. protected virtual void OnRequestSuccessReceived(RequestSuccessMessage message)
  1038. {
  1039. if (this.RequestSuccessReceived != null)
  1040. {
  1041. this.RequestSuccessReceived(this, new MessageEventArgs<RequestSuccessMessage>(message));
  1042. }
  1043. }
  1044. /// <summary>
  1045. /// Called when <see cref="RequestFailureMessage"/> message received.
  1046. /// </summary>
  1047. /// <param name="message"><see cref="RequestFailureMessage"/> message.</param>
  1048. protected virtual void OnRequestFailureReceived(RequestFailureMessage message)
  1049. {
  1050. if (this.RequestFailureReceived != null)
  1051. {
  1052. this.RequestFailureReceived(this, new MessageEventArgs<RequestFailureMessage>(message));
  1053. }
  1054. }
  1055. /// <summary>
  1056. /// Called when <see cref="ChannelOpenMessage"/> message received.
  1057. /// </summary>
  1058. /// <param name="message"><see cref="ChannelOpenMessage"/> message.</param>
  1059. protected virtual void OnChannelOpenReceived(ChannelOpenMessage message)
  1060. {
  1061. if (this.ChannelOpenReceived != null)
  1062. {
  1063. this.ChannelOpenReceived(this, new MessageEventArgs<ChannelOpenMessage>(message));
  1064. }
  1065. }
  1066. /// <summary>
  1067. /// Called when <see cref="ChannelOpenConfirmationMessage"/> message received.
  1068. /// </summary>
  1069. /// <param name="message"><see cref="ChannelOpenConfirmationMessage"/> message.</param>
  1070. protected virtual void OnChannelOpenConfirmationReceived(ChannelOpenConfirmationMessage message)
  1071. {
  1072. if (this.ChannelOpenConfirmationReceived != null)
  1073. {
  1074. this.ChannelOpenConfirmationReceived(this, new MessageEventArgs<ChannelOpenConfirmationMessage>(message));
  1075. }
  1076. }
  1077. /// <summary>
  1078. /// Called when <see cref="ChannelOpenFailureMessage"/> message received.
  1079. /// </summary>
  1080. /// <param name="message"><see cref="ChannelOpenFailureMessage"/> message.</param>
  1081. protected virtual void OnChannelOpenFailureReceived(ChannelOpenFailureMessage message)
  1082. {
  1083. if (this.ChannelOpenFailureReceived != null)
  1084. {
  1085. this.ChannelOpenFailureReceived(this, new MessageEventArgs<ChannelOpenFailureMessage>(message));
  1086. }
  1087. }
  1088. /// <summary>
  1089. /// Called when <see cref="ChannelWindowAdjustMessage"/> message received.
  1090. /// </summary>
  1091. /// <param name="message"><see cref="ChannelWindowAdjustMessage"/> message.</param>
  1092. protected virtual void OnChannelWindowAdjustReceived(ChannelWindowAdjustMessage message)
  1093. {
  1094. if (this.ChannelWindowAdjustReceived != null)
  1095. {
  1096. this.ChannelWindowAdjustReceived(this, new MessageEventArgs<ChannelWindowAdjustMessage>(message));
  1097. }
  1098. }
  1099. /// <summary>
  1100. /// Called when <see cref="ChannelDataMessage"/> message received.
  1101. /// </summary>
  1102. /// <param name="message"><see cref="ChannelDataMessage"/> message.</param>
  1103. protected virtual void OnChannelDataReceived(ChannelDataMessage message)
  1104. {
  1105. if (this.ChannelDataReceived != null)
  1106. {
  1107. this.ChannelDataReceived(this, new MessageEventArgs<ChannelDataMessage>(message));
  1108. }
  1109. }
  1110. /// <summary>
  1111. /// Called when <see cref="ChannelExtendedDataMessage"/> message received.
  1112. /// </summary>
  1113. /// <param name="message"><see cref="ChannelExtendedDataMessage"/> message.</param>
  1114. protected virtual void OnChannelExtendedDataReceived(ChannelExtendedDataMessage message)
  1115. {
  1116. if (this.ChannelExtendedDataReceived != null)
  1117. {
  1118. this.ChannelExtendedDataReceived(this, new MessageEventArgs<ChannelExtendedDataMessage>(message));
  1119. }
  1120. }
  1121. /// <summary>
  1122. /// Called when <see cref="ChannelCloseMessage"/> message received.
  1123. /// </summary>
  1124. /// <param name="message"><see cref="ChannelCloseMessage"/> message.</param>
  1125. protected virtual void OnChannelEofReceived(ChannelEofMessage message)
  1126. {
  1127. if (this.ChannelEofReceived != null)
  1128. {
  1129. this.ChannelEofReceived(this, new MessageEventArgs<ChannelEofMessage>(message));
  1130. }
  1131. }
  1132. /// <summary>
  1133. /// Called when <see cref="ChannelCloseMessage"/> message received.
  1134. /// </summary>
  1135. /// <param name="message"><see cref="ChannelCloseMessage"/> message.</param>
  1136. protected virtual void OnChannelCloseReceived(ChannelCloseMessage message)
  1137. {
  1138. if (this.ChannelCloseReceived != null)
  1139. {
  1140. this.ChannelCloseReceived(this, new MessageEventArgs<ChannelCloseMessage>(message));
  1141. }
  1142. }
  1143. /// <summary>
  1144. /// Called when <see cref="ChannelRequestMessage"/> message received.
  1145. /// </summary>
  1146. /// <param name="message"><see cref="ChannelRequestMessage"/> message.</param>
  1147. protected virtual void OnChannelRequestReceived(ChannelRequestMessage message)
  1148. {
  1149. if (this.ChannelRequestReceived != null)
  1150. {
  1151. this.ChannelRequestReceived(this, new MessageEventArgs<ChannelRequestMessage>(message));
  1152. }
  1153. }
  1154. /// <summary>
  1155. /// Called when <see cref="ChannelSuccessMessage"/> message received.
  1156. /// </summary>
  1157. /// <param name="message"><see cref="ChannelSuccessMessage"/> message.</param>
  1158. protected virtual void OnChannelSuccessReceived(ChannelSuccessMessage message)
  1159. {
  1160. if (this.ChannelSuccessReceived != null)
  1161. {
  1162. this.ChannelSuccessReceived(this, new MessageEventArgs<ChannelSuccessMessage>(message));
  1163. }
  1164. }
  1165. /// <summary>
  1166. /// Called when <see cref="ChannelFailureMessage"/> message received.
  1167. /// </summary>
  1168. /// <param name="message"><see cref="ChannelFailureMessage"/> message.</param>
  1169. protected virtual void OnChannelFailureReceived(ChannelFailureMessage message)
  1170. {
  1171. if (this.ChannelFailureReceived != null)
  1172. {
  1173. this.ChannelFailureReceived(this, new MessageEventArgs<ChannelFailureMessage>(message));
  1174. }
  1175. }
  1176. /// <summary>
  1177. /// Called when <see cref="Message"/> message received.
  1178. /// </summary>
  1179. /// <param name="message"><see cref="Message"/> message.</param>
  1180. protected virtual void OnMessageReceived(Message message)
  1181. {
  1182. if (this.MessageReceived != null)
  1183. {
  1184. this.MessageReceived(this, new MessageEventArgs<Message>(message));
  1185. }
  1186. }
  1187. #endregion
  1188. #region Read & Write operations
  1189. /// <summary>
  1190. /// Reads the specified length of bytes from the server
  1191. /// </summary>
  1192. /// <param name="length">The length.</param>
  1193. /// <returns></returns>
  1194. private byte[] Read(int length)
  1195. {
  1196. var buffer = new byte[length];
  1197. var offset = 0;
  1198. int receivedTotal = 0; // how many bytes is already received
  1199. do
  1200. {
  1201. try
  1202. {
  1203. var receivedBytes = this._socket.Receive(buffer, offset + receivedTotal, length - receivedTotal, SocketFlags.None);
  1204. if (receivedBytes > 0)
  1205. {
  1206. receivedTotal += receivedBytes;
  1207. continue;
  1208. }
  1209. else
  1210. {
  1211. throw new SshConnectionException("An established connection was aborted by the software in your host machine.", DisconnectReason.ConnectionLost);
  1212. }
  1213. }
  1214. catch (SocketException exp)
  1215. {
  1216. if (exp.SocketErrorCode == SocketError.WouldBlock ||
  1217. exp.SocketErrorCode == SocketError.IOPending ||
  1218. exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
  1219. {
  1220. // socket buffer is probably empty, wait and try again
  1221. Thread.Sleep(30);
  1222. }
  1223. else
  1224. throw; // any serious error occurred
  1225. }
  1226. } while (receivedTotal < length);
  1227. return buffer;
  1228. }
  1229. /// <summary>
  1230. /// Writes the specified data to the server.
  1231. /// </summary>
  1232. /// <param name="data">The data.</param>
  1233. private void Write(byte[] data)
  1234. {
  1235. int sent = 0; // how many bytes is already sent
  1236. int length = data.Length;
  1237. do
  1238. {
  1239. try
  1240. {
  1241. sent += this._socket.Send(data, sent, length - sent, SocketFlags.None);
  1242. }
  1243. catch (SocketException ex)
  1244. {
  1245. if (ex.SocketErrorCode == SocketError.WouldBlock ||
  1246. ex.SocketErrorCode == SocketError.IOPending ||
  1247. ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
  1248. {
  1249. // socket buffer is probably full, wait and try again
  1250. Thread.Sleep(30);
  1251. }
  1252. else
  1253. throw; // any serious error occurr
  1254. }
  1255. } while (sent < length);
  1256. }
  1257. #endregion
  1258. #region Message loading functions
  1259. /// <summary>
  1260. /// Registers SSH Message with the session.
  1261. /// </summary>
  1262. /// <param name="messageName">Name of the message.</param>
  1263. public void RegisterMessage(string messageName)
  1264. {
  1265. this.InternalRegisterMessage(messageName);
  1266. }
  1267. /// <summary>
  1268. /// Removes SSH message from the session
  1269. /// </summary>
  1270. /// <param name="messageName">Name of the message.</param>
  1271. public void UnRegisterMessage(string messageName)
  1272. {
  1273. this.InternalUnRegisterMessage(messageName);
  1274. }
  1275. /// <summary>
  1276. /// Loads the message.
  1277. /// </summary>
  1278. /// <param name="data">Message data.</param>
  1279. /// <returns>New message</returns>
  1280. private Message LoadMessage(byte[] data)
  1281. {
  1282. var messageType = data[0];
  1283. var messageMetadata = (from m in this._messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).SingleOrDefault();
  1284. if (messageMetadata == null)
  1285. throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
  1286. var message = messageMetadata.Type.CreateInstance<Message>();
  1287. message.Load(data);
  1288. return message;
  1289. }
  1290. partial void InternalRegisterMessage(string messageName);
  1291. partial void InternalUnRegisterMessage(string messageName);
  1292. #endregion
  1293. partial void ExecuteThread(Action action);
  1294. /// <summary>
  1295. /// Listens for incoming message from the server and handles them. This method run as a task on separate thread.
  1296. /// </summary>
  1297. private void MessageListener()
  1298. {
  1299. try
  1300. {
  1301. while (this._socket.Connected)
  1302. {
  1303. var message = this.ReceiveMessage();
  1304. if (message == null)
  1305. {
  1306. throw new NullReferenceException("The 'message' variable cannot be null");
  1307. }
  1308. else
  1309. {
  1310. this.HandleMessage((dynamic)message);
  1311. }
  1312. }
  1313. }
  1314. catch (Exception exp)
  1315. {
  1316. this.RaiseError(exp);
  1317. }
  1318. }
  1319. /// <summary>
  1320. /// Raises the <see cref="ErrorOccured"/> event.
  1321. /// </summary>
  1322. /// <param name="exp">The exp.</param>
  1323. private void RaiseError(Exception exp)
  1324. {
  1325. var connectionException = exp as SshConnectionException;
  1326. // If connection exception was raised while isDisconnecting is true then this is expected
  1327. // case and should be ignore
  1328. if (connectionException != null && this._isDisconnecting)
  1329. return;
  1330. this._exception = exp;
  1331. this._exceptionWaitHandle.Set();
  1332. if (this.ErrorOccured != null)
  1333. {
  1334. this.ErrorOccured(this, new ExceptionEventArgs(exp));
  1335. }
  1336. if (connectionException != null && connectionException.DisconnectReason != DisconnectReason.ConnectionLost)
  1337. {
  1338. this.SendDisconnect(connectionException.DisconnectReason, exp.ToString());
  1339. }
  1340. }
  1341. #region IDisposable Members
  1342. private bool _disposed = false;
  1343. /// <summary>
  1344. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
  1345. /// </summary>
  1346. public void Dispose()
  1347. {
  1348. Dispose(true);
  1349. GC.SuppressFinalize(this);
  1350. }
  1351. /// <summary>
  1352. /// Releases unmanaged and - optionally - managed resources
  1353. /// </summary>
  1354. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param>
  1355. protected virtual void Dispose(bool disposing)
  1356. {
  1357. // Check to see if Dispose has already been called.
  1358. if (!this._disposed)
  1359. {
  1360. // If disposing equals true, dispose all managed
  1361. // and unmanaged ResourceMessages.
  1362. if (disposing)
  1363. {
  1364. this._isDisconnecting = true;
  1365. if (this._socket != null)
  1366. {
  1367. // If socket still open try to send disconnect message to the server
  1368. this.SendDisconnect(DisconnectReason.ByApplication, "Connection terminated by the client.");
  1369. this._socket.Dispose();
  1370. this._socket = null;
  1371. }
  1372. if (this._messageListenerCompleted != null)
  1373. {
  1374. // Wait for socket to be closed and for task to complete before disposing a task
  1375. this._messageListenerCompleted.WaitOne();
  1376. this._messageListenerCompleted.Dispose();
  1377. this._messageListenerCompleted = null;
  1378. }
  1379. if (this._serviceAccepted != null)
  1380. {
  1381. this._serviceAccepted.Dispose();
  1382. this._serviceAccepted = null;
  1383. }
  1384. if (this._exceptionWaitHandle != null)
  1385. {
  1386. this._exceptionWaitHandle.Dispose();
  1387. this._exceptionWaitHandle = null;
  1388. }
  1389. if (this._keyExchangeCompletedWaitHandle != null)
  1390. {
  1391. this._keyExchangeCompletedWaitHandle.Dispose();
  1392. this._keyExchangeCompletedWaitHandle = null;
  1393. }
  1394. if (this._serverCipher != null)
  1395. {
  1396. this._serverCipher.Dispose();
  1397. this._serverCipher = null;
  1398. }
  1399. if (this._clientCipher != null)
  1400. {
  1401. this._clientCipher.Dispose();
  1402. this._clientCipher = null;
  1403. }
  1404. if (this._serverMac != null)
  1405. {
  1406. this._serverMac.Dispose();
  1407. this._serverMac = null;
  1408. }
  1409. if (this._clientMac != null)
  1410. {
  1411. this._clientMac.Dispose();
  1412. this._clientMac = null;
  1413. }
  1414. if (this._keyExchange != null)
  1415. {
  1416. this._keyExchange.Dispose();
  1417. this._keyExchange = null;
  1418. }
  1419. }
  1420. // Note disposing has been done.
  1421. this._disposed = true;
  1422. }
  1423. }
  1424. /// <summary>
  1425. /// Releases unmanaged resources and performs other cleanup operations before the
  1426. /// <see cref="Session"/> is reclaimed by garbage collection.
  1427. /// </summary>
  1428. ~Session()
  1429. {
  1430. // Do not re-create Dispose clean-up code here.
  1431. // Calling Dispose(false) is optimal in terms of
  1432. // readability and maintainability.
  1433. Dispose(false);
  1434. }
  1435. #endregion
  1436. private class MessageMetadata
  1437. {
  1438. public string Name { get; set; }
  1439. public byte Number { get; set; }
  1440. public bool Enabled { get; set; }
  1441. public bool Activated { get; set; }
  1442. public Type Type { get; set; }
  1443. }
  1444. }
  1445. }