📄 ssh1connection.cs
字号:
}
public override SSHChannel OpenShell(ISSHChannelEventReceiver receiver) {
if(_shellID!=-1)
throw new SSHException("A shell is opened already");
_shellID = RegisterChannelEventReceiver(null, receiver)._localID;
SendRequestPTY();
_executingShell = true;
return new SSH1Channel(this, ChannelType.Shell, _shellID);
}
private void SendRequestPTY() {
SSH1DataWriter writer = new SSH1DataWriter();
writer.Write(_param.TerminalName);
writer.Write(_param.TerminalHeight);
writer.Write(_param.TerminalWidth);
writer.Write(_param.TerminalPixelWidth);
writer.Write(_param.TerminalPixelHeight);
writer.Write(new byte[1]); //TTY_OP_END
SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_REQUEST_PTY, writer.ToByteArray());
SSH1Packet.WriteTo(_stream, _tCipher);
}
private void ExecShell() {
//System.out.println("EXEC SHELL");
SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_EXEC_SHELL);
SSH1Packet.WriteTo(_stream, _tCipher);
}
public override SSHChannel ForwardPort(ISSHChannelEventReceiver receiver, string remote_host, int remote_port, string originator_host, int originator_port) {
if(_shellID==-1) {
ExecShell();
_shellID = RegisterChannelEventReceiver(null, new SSH1DummyReceiver())._localID;
}
int local_id = this.RegisterChannelEventReceiver(null, receiver)._localID;
SSH1DataWriter writer = new SSH1DataWriter();
writer.Write(local_id); //channel id is fixed to 0
writer.Write(remote_host);
writer.Write(remote_port);
//originator is specified only if SSH_PROTOFLAG_HOST_IN_FWD_OPEN is specified
//writer.Write(originator_host);
SSH1Packet SSH1Packet = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_PORT_OPEN, writer.ToByteArray());
SSH1Packet.WriteTo(_stream, _tCipher);
return new SSH1Channel(this, ChannelType.ForwardedLocalToRemote, local_id);
}
public override void ListenForwardedPort(string allowed_host, int bind_port) {
SSH1DataWriter writer = new SSH1DataWriter();
writer.Write(bind_port);
writer.Write(allowed_host);
writer.Write(0);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_PORT_FORWARD_REQUEST, writer.ToByteArray());
p.WriteTo(_stream, _tCipher);
if(_shellID==-1) {
ExecShell();
_shellID = RegisterChannelEventReceiver(null, new SSH1DummyReceiver())._localID;
}
}
public override void CancelForwardedPort(string host, int port) {
throw new NotSupportedException("not implemented");
}
private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH1Packet packet) {
SSH1DataReader reader = new SSH1DataReader(packet.Data);
int server_channel = reader.ReadInt32();
string host = Encoding.ASCII.GetString(reader.ReadString());
int port = reader.ReadInt32();
SSH1DataWriter writer = new SSH1DataWriter();
PortForwardingCheckResult result = receiver.CheckPortForwardingRequest(host, port, "", 0);
if(result.allowed) {
int local_id = this.RegisterChannelEventReceiver(null, result.channel)._localID;
_eventReceiver.EstablishPortforwarding(result.channel, new SSH1Channel(this, ChannelType.ForwardedRemoteToLocal, local_id, server_channel));
writer.Write(server_channel);
writer.Write(local_id);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, writer.ToByteArray());
p.WriteTo(_stream, _tCipher);
}
else {
writer.Write(server_channel);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE, writer.ToByteArray());
p.WriteTo(_stream, _tCipher);
}
}
private byte[] CalcSessionID() {
MemoryStream bos = new MemoryStream();
SSHServerInfo si = _cInfo._serverinfo;
byte[] h = si.host_key_public_modulus.getBytes();
byte[] s = si.server_key_public_modulus.getBytes();
//System.out.println("len h="+h.Length);
//System.out.println("len s="+s.Length);
int off_h = (h[0]==0? 1 : 0);
int off_s = (s[0]==0? 1 : 0);
bos.Write(h, off_h, h.Length-off_h);
bos.Write(s, off_s, s.Length-off_s);
bos.Write(si.anti_spoofing_cookie, 0, si.anti_spoofing_cookie.Length);
byte[] session_id = new MD5CryptoServiceProvider().ComputeHash(bos.ToArray());
//System.out.println("sess-id-len=" + session_id.Length);
return session_id;
}
//init ciphers
private void InitCipher(byte[] session_key) {
_tCipher = CipherFactory.CreateCipher(SSHProtocol.SSH1, _cInfo._algorithmForTransmittion, session_key);
Cipher rc = CipherFactory.CreateCipher(SSHProtocol.SSH1, _cInfo._algorithmForReception, session_key);
_packetBuilder.SetCipher(rc, _param.CheckMACError);
}
private SSH1Packet ReceivePacket() {
while(true) {
SSH1Packet p = null;
SynchronizedSSH1PacketHandler handler = (SynchronizedSSH1PacketHandler)_packetBuilder.Handler;
if(!handler.HasPacket) {
handler.Wait();
if(handler.State==ReceiverState.Error)
throw new SSHException(handler.ErrorMessage);
else if(handler.State==ReceiverState.Closed)
throw new SSHException("socket closed");
}
p = handler.PopPacket();
SSH1DataReader r = new SSH1DataReader(p.Data);
PacketType pt = p.Type;
if(pt==PacketType.SSH_MSG_IGNORE) {
if(_eventReceiver!=null) _eventReceiver.OnIgnoreMessage(r.ReadString());
}
else if(pt==PacketType.SSH_MSG_DEBUG) {
if(_eventReceiver!=null) _eventReceiver.OnDebugMessage(false, r.ReadString());
}
else
return p;
}
}
internal void AsyncReceivePacket(SSH1Packet p) {
try {
int len = 0, channel = 0;
switch(p.Type) {
case PacketType.SSH_SMSG_STDOUT_DATA:
len = SSHUtil.ReadInt32(p.Data, 0);
FindChannelEntry(_shellID)._receiver.OnData(p.Data, 4, len);
break;
case PacketType.SSH_SMSG_STDERR_DATA: {
SSH1DataReader re = new SSH1DataReader(p.Data);
FindChannelEntry(_shellID)._receiver.OnExtendedData((int)PacketType.SSH_SMSG_STDERR_DATA, re.ReadString());
}
break;
case PacketType.SSH_MSG_CHANNEL_DATA:
channel = SSHUtil.ReadInt32(p.Data, 0);
len = SSHUtil.ReadInt32(p.Data, 4);
FindChannelEntry(channel)._receiver.OnData(p.Data, 8, len);
break;
case PacketType.SSH_MSG_PORT_OPEN:
this.ProcessPortforwardingRequest(_eventReceiver, p);
break;
case PacketType.SSH_MSG_CHANNEL_CLOSE: {
channel = SSHUtil.ReadInt32(p.Data, 0);
ISSHChannelEventReceiver r = FindChannelEntry(channel)._receiver;
UnregisterChannelEventReceiver(channel);
r.OnChannelClosed();
}
break;
case PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
channel = SSHUtil.ReadInt32(p.Data, 0);
break;
case PacketType.SSH_MSG_DISCONNECT:
_eventReceiver.OnConnectionClosed();
break;
case PacketType.SSH_SMSG_EXITSTATUS:
FindChannelEntry(_shellID)._receiver.OnChannelClosed();
break;
case PacketType.SSH_MSG_DEBUG: {
SSH1DataReader re = new SSH1DataReader(p.Data);
_eventReceiver.OnDebugMessage(false, re.ReadString());
}
break;
case PacketType.SSH_MSG_IGNORE: {
SSH1DataReader re = new SSH1DataReader(p.Data);
_eventReceiver.OnIgnoreMessage(re.ReadString());
}
break;
case PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: {
int local = SSHUtil.ReadInt32(p.Data, 0);
int remote = SSHUtil.ReadInt32(p.Data, 4);
FindChannelEntry(local)._receiver.OnChannelReady();
}
break;
case PacketType.SSH_SMSG_SUCCESS:
if(_executingShell) {
ExecShell();
this.FindChannelEntry(_shellID)._receiver.OnChannelReady();
_executingShell = false;
}
break;
default:
_eventReceiver.OnUnknownMessage((byte)p.Type, p.Data);
break;
}
}
catch(Exception ex) {
if(!_closed)
_eventReceiver.OnError(ex, ex.Message);
}
}
}
public class SSH1Channel : SSHChannel {
public SSH1Channel(SSHConnection con, ChannelType type, int local_id) : base(con, type, local_id) {
}
public SSH1Channel(SSHConnection con, ChannelType type, int local_id, int remote_id) : base(con, type, local_id) {
_remoteID = remote_id;
}
/**
* resizes the size of terminal
*/
public override void ResizeTerminal(int width, int height, int pixel_width, int pixel_height) {
SSH1DataWriter writer = new SSH1DataWriter();
writer.Write(height);
writer.Write(width);
writer.Write(pixel_width);
writer.Write(pixel_height);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_WINDOW_SIZE, writer.ToByteArray());
Transmit(p);
}
/**
* transmits channel data
*/
public override void Transmit(byte[] data) {
SSH1DataWriter wr = new SSH1DataWriter();
if(_type==ChannelType.Shell) {
wr.WriteAsString(data);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_STDIN_DATA, wr.ToByteArray());
Transmit(p);
}
else {
wr.Write(_remoteID);
wr.WriteAsString(data);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_DATA, wr.ToByteArray());
Transmit(p);
}
}
/**
* transmits channel data
*/
public override void Transmit(byte[] data, int offset, int length) {
SSH1DataWriter wr = new SSH1DataWriter();
if(_type==ChannelType.Shell) {
wr.WriteAsString(data, offset, length);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_STDIN_DATA, wr.ToByteArray());
Transmit(p);
}
else {
wr.Write(_remoteID);
wr.WriteAsString(data, offset, length);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_DATA, wr.ToByteArray());
Transmit(p);
}
}
public override void SendEOF() {
}
/**
* closes this channel
*/
public override void Close() {
if(_connection.IsClosed) return;
if(_type==ChannelType.Shell) {
SSH1DataWriter wr2 = new SSH1DataWriter();
wr2.Write(_remoteID);
SSH1Packet p2 = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_EOF, wr2.ToByteArray());
Transmit(p2);
}
SSH1DataWriter wr = new SSH1DataWriter();
wr.Write(_remoteID);
SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_CLOSE, wr.ToByteArray());
Transmit(p);
}
private void Transmit(SSH1Packet p) {
((SSH1Connection)_connection).Transmit(p);
}
}
//if port forwardings are performed without a shell, we use SSH1DummyChannel to receive shell data
internal class SSH1DummyReceiver : ISSHChannelEventReceiver {
public void OnData(byte[] data, int offset, int length) {
}
public void OnExtendedData(int type, byte[] data) {
}
public void OnChannelClosed() {
}
public void OnChannelEOF() {
}
public void OnChannelReady() {
}
public void OnChannelError(Exception error, string msg) {
}
public void OnMiscPacket(byte packet_type, byte[] data, int offset, int length) {
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -