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

Telnet服务器

开发平台:

C#

  1. /*
  2.  Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3.  This file is a part of the Granados SSH Client Library that is subject to
  4.  the license included in the distributed package.
  5.  You may not use this file except in compliance with the license.
  6.  $Id: ConnectionRoot.cs,v 1.2 2005/04/20 08:58:56 okajima Exp $
  7. */
  8. using System;
  9. using System.Collections;
  10. using System.IO;
  11. using System.Net.Sockets;
  12. using System.Text;
  13. using Granados.Crypto;
  14. using Granados.PKI;
  15. using Granados.SSHCV1;
  16. using Granados.SSHCV2;
  17. namespace Granados.SSHC
  18. {
  19. public abstract class SSHConnection {
  20. internal AbstractSocket _stream;
  21. internal ISSHConnectionEventReceiver _eventReceiver;
  22. protected byte[] _sessionID;
  23. internal Cipher _tCipher; //transmission
  24. //internal Cipher _rCipher; //reception
  25. protected SSHConnectionParameter _param;
  26. protected object _tLockObject = new Object();
  27. protected bool _closed;
  28. protected bool _autoDisconnect;
  29. protected AuthenticationResult _authenticationResult;
  30. protected SSHConnection(SSHConnectionParameter param, ISSHConnectionEventReceiver receiver) {
  31. _param = (SSHConnectionParameter)param.Clone();
  32. _eventReceiver = receiver;
  33. _channel_entries = new ArrayList(16);
  34. _autoDisconnect = true;
  35. }
  36. public abstract SSHConnectionInfo ConnectionInfo { get; }
  37. /**
  38. * returns true if any data from server is available
  39. */
  40. public bool Available {
  41. get {
  42. if(_closed)
  43. return false;
  44. else
  45. return _stream.DataAvailable;
  46. }
  47. }
  48. public SSHConnectionParameter Param {
  49. get {
  50. return _param;
  51. }
  52. }
  53. public AuthenticationResult AuthenticationResult {
  54. get {
  55. return _authenticationResult;
  56. }
  57. }
  58. internal abstract IByteArrayHandler PacketBuilder {
  59. get ;
  60. }
  61. public ISSHConnectionEventReceiver EventReceiver {
  62. get {
  63. return _eventReceiver;
  64. }
  65. }
  66. public bool IsClosed {
  67. get {
  68. return _closed;
  69. }
  70. }
  71. public bool AutoDisconnect {
  72. get {
  73. return _autoDisconnect;
  74. }
  75. set {
  76. _autoDisconnect = value;
  77. }
  78. }
  79. internal abstract AuthenticationResult Connect(AbstractSocket target);
  80. /**
  81. * terminates this connection
  82. */
  83. public abstract void Disconnect(string msg);
  84. /**
  85. * opens a pseudo terminal
  86. */
  87. public abstract SSHChannel OpenShell(ISSHChannelEventReceiver receiver);
  88. /**
  89.  * forwards the remote end to another host
  90.  */ 
  91. public abstract SSHChannel ForwardPort(ISSHChannelEventReceiver receiver, string remote_host, int remote_port, string originator_host, int originator_port);
  92. /**
  93.  * listens a connection on the remote end
  94.  */ 
  95. public abstract void ListenForwardedPort(string allowed_host, int bind_port);
  96. /**
  97.  * cancels binded port
  98.  */ 
  99. public abstract void CancelForwardedPort(string host, int port);
  100. /**
  101. * closes socket directly.
  102. */
  103. public abstract void Close();
  104. public abstract void SendIgnorableData(string msg);
  105. /**
  106.  * opens another SSH connection via port-forwarded connection
  107.  */ 
  108. public SSHConnection OpenPortForwardedAnotherConnection(SSHConnectionParameter param, ISSHConnectionEventReceiver receiver, string host, int port) {
  109. ProtocolNegotiationHandler pnh = new ProtocolNegotiationHandler(param);
  110. ChannelSocket s = new ChannelSocket(pnh);
  111. SSHChannel ch = ForwardPort(s, host, port, "localhost", 0);
  112. s.SSHChennal = ch;
  113. return SSHConnection.Connect(param, receiver, pnh, s);
  114. }
  115. //channel id support
  116. protected class ChannelEntry {
  117. public int _localID;
  118. public ISSHChannelEventReceiver _receiver;
  119. public SSHChannel _channel;
  120. }
  121. protected ArrayList _channel_entries;
  122. protected int _channel_sequence;
  123. protected ChannelEntry FindChannelEntry(int id) {
  124. for(int i=0; i<_channel_entries.Count; i++) {
  125. ChannelEntry e = (ChannelEntry)_channel_entries[i];
  126. if(e._localID==id) return e;
  127. }
  128. return null;
  129. }
  130. protected ChannelEntry RegisterChannelEventReceiver(SSHChannel ch, ISSHChannelEventReceiver r) {
  131. lock(this) {
  132. ChannelEntry e = new ChannelEntry();
  133. e._channel = ch;
  134. e._receiver = r;
  135. e._localID = _channel_sequence++;
  136. for(int i=0; i<_channel_entries.Count; i++) {
  137. if(_channel_entries[i]==null) {
  138. _channel_entries[i] = e;
  139. return e;
  140. }
  141. }
  142. _channel_entries.Add(e);
  143. return e;
  144. }
  145. }
  146. internal void RegisterChannel(int local_id, SSHChannel ch) {
  147. FindChannelEntry(local_id)._channel = ch;
  148. }
  149. internal void UnregisterChannelEventReceiver(int id) {
  150. lock(this) {
  151. foreach(ChannelEntry e in _channel_entries) {
  152. if(e._localID==id) {
  153. _channel_entries.Remove(e);
  154. break;
  155. }
  156. }
  157. if(this.ChannelCount==0 && _autoDisconnect) Disconnect(""); //auto close
  158. }
  159. }
  160. public virtual int ChannelCount {
  161. get {
  162. int r = 0;
  163. for(int i=0; i<_channel_entries.Count; i++) {
  164. if(_channel_entries[i]!=null) r++;
  165. }
  166. return r;
  167. }
  168. }
  169. //establishes a SSH connection in subject to ConnectionParameter
  170. public static SSHConnection Connect(SSHConnectionParameter param, ISSHConnectionEventReceiver receiver, Socket underlying_socket) {
  171. if(param.UserName==null) throw new InvalidOperationException("UserName property is not set");
  172. if(param.Password==null) throw new InvalidOperationException("Password property is not set");
  173. ProtocolNegotiationHandler pnh = new ProtocolNegotiationHandler(param);
  174. PlainSocket s = new PlainSocket(underlying_socket, pnh);
  175. s.RepeatAsyncRead();
  176. return ConnectMain(param, receiver, pnh, s);
  177. }
  178. internal static SSHConnection Connect(SSHConnectionParameter param, ISSHConnectionEventReceiver receiver, ProtocolNegotiationHandler pnh, AbstractSocket s) {
  179. if(param.UserName==null) throw new InvalidOperationException("UserName property is not set");
  180. if(param.Password==null) throw new InvalidOperationException("Password property is not set");
  181. return ConnectMain(param, receiver, pnh, s);
  182. }
  183. private static SSHConnection ConnectMain(SSHConnectionParameter param, ISSHConnectionEventReceiver receiver, ProtocolNegotiationHandler pnh, AbstractSocket s) {
  184. pnh.Wait();
  185. if(pnh.State!=ReceiverState.Ready) throw new SSHException(pnh.ErrorMessage);
  186. string sv = pnh.ServerVersion;
  187. SSHConnection con = null;
  188. if(param.Protocol==SSHProtocol.SSH1)
  189. con = new SSH1Connection(param, receiver, sv, SSHUtil.ClientVersionString(param.Protocol));
  190. else
  191. con = new SSH2Connection(param, receiver, sv, SSHUtil.ClientVersionString(param.Protocol));
  192. s.SetHandler(con.PacketBuilder);
  193. SendMyVersion(s, param);
  194. if(con.Connect(s)!=AuthenticationResult.Failure)
  195. return con;
  196. else {
  197. s.Close();
  198. return null;
  199. }
  200. }
  201. private static void SendMyVersion(AbstractSocket stream, SSHConnectionParameter param) {
  202. string cv = SSHUtil.ClientVersionString(param.Protocol);
  203. if(param.Protocol==SSHProtocol.SSH1)
  204. cv += param.SSH1VersionEOL;
  205. else
  206. cv += "rn";
  207. byte[] data = Encoding.ASCII.GetBytes(cv);
  208. stream.Write(data, 0, data.Length);
  209. }
  210. }
  211. public enum ChannelType {
  212. Session,
  213. Shell,
  214. ForwardedLocalToRemote,
  215. ForwardedRemoteToLocal
  216. }
  217. public abstract class SSHChannel {
  218. protected ChannelType _type;
  219. protected int _localID;
  220. protected int _remoteID;
  221. protected SSHConnection _connection;
  222. protected SSHChannel(SSHConnection con, ChannelType type, int local_id) {
  223. con.RegisterChannel(local_id, this);
  224. _connection = con;
  225. _type = type;
  226. _localID = local_id;
  227. }
  228. public int LocalChannelID {
  229. get {
  230. return _localID;
  231. }
  232. }
  233. public int RemoteChannelID {
  234. get {
  235. return _remoteID;
  236. }
  237. }
  238. public SSHConnection Connection {
  239. get {
  240. return _connection;
  241. }
  242. }
  243. public ChannelType Type {
  244. get {
  245. return _type;
  246. }
  247. }
  248. /**
  249.  * resizes the size of terminal
  250.  */
  251. public abstract void ResizeTerminal(int width, int height, int pixel_width, int pixel_height);
  252. /**
  253. * transmits channel data 
  254. */
  255. public abstract void Transmit(byte[] data);
  256. /**
  257. * transmits channel data 
  258. */
  259. public abstract void Transmit(byte[] data, int offset, int length);
  260. /**
  261.  * sends EOF(SSH2 only)
  262.  */
  263. public abstract void SendEOF();
  264. /**
  265.  * closes this channel
  266.  */
  267. public abstract void Close();
  268. }
  269. }