private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH1DataReader reader) { int server_channel = reader.ReadInt32(); string host = reader.ReadString(); int port = reader.ReadInt32(); PortForwardingCheckResult result = receiver.CheckPortForwardingRequest(host, port, "", 0); if (result.allowed) { int local_id = _channel_collection.RegisterChannelEventReceiver(null, result.channel).LocalID; _eventReceiver.EstablishPortforwarding(result.channel, new SSH1Channel(this, ChannelType.ForwardedRemoteToLocal, local_id, server_channel)); Transmit( new SSH1Packet(SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) .WriteInt32(server_channel) .WriteInt32(local_id) ); } else { Transmit( new SSH1Packet(SSH1PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE) .WriteInt32(server_channel) ); } }
private void ReceiveServerKeys() { DataFragment packet = ReceivePacket(); SSH1DataReader reader = new SSH1DataReader(packet); SSH1PacketType pt = (SSH1PacketType) reader.ReadByte(); if (pt != SSH1PacketType.SSH_SMSG_PUBLIC_KEY) throw new SSHException("unexpected SSH SSH1Packet type " + pt, packet.GetBytes()); _cInfo.AntiSpoofingCookie = reader.Read(8); _cInfo.ServerKeyBits = reader.ReadInt32(); BigInteger serverKeyExponent = reader.ReadMPInt(); BigInteger serverKeyModulus = reader.ReadMPInt(); _cInfo.ServerKey = new RSAPublicKey(serverKeyExponent, serverKeyModulus); _cInfo.HostKeyBits = reader.ReadInt32(); BigInteger hostKeyExponent = reader.ReadMPInt(); BigInteger hostKeyModulus = reader.ReadMPInt(); _cInfo.HostKey = new RSAPublicKey(hostKeyExponent, hostKeyModulus); //read protocol support parameters int protocol_flags = reader.ReadInt32(); int supported_ciphers_mask = reader.ReadInt32(); _cInfo.SupportedEncryptionAlgorithmsMask = supported_ciphers_mask; int supported_authentications_mask = reader.ReadInt32(); //Debug.WriteLine(String.Format("ServerOptions {0} {1} {2}", protocol_flags, supported_ciphers_mask, supported_authentications_mask)); if (reader.RemainingDataLength > 0) throw new SSHException("data length mismatch", packet.GetBytes()); bool found = false; foreach (CipherAlgorithm a in _param.PreferableCipherAlgorithms) { if (a != CipherAlgorithm.Blowfish && a != CipherAlgorithm.TripleDES) continue; else if (a == CipherAlgorithm.Blowfish && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.Blowfish)) == 0) continue; else if (a == CipherAlgorithm.TripleDES && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.TripleDES)) == 0) continue; _cInfo.IncomingPacketCipher = _cInfo.OutgoingPacketCipher = a; found = true; break; } if (!found) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedX"), "Blowfish/TripleDES")); if (_param.AuthenticationType == AuthenticationType.Password && (supported_authentications_mask & (1 << (int)AuthenticationType.Password)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedPassword")), packet.GetBytes()); if (_param.AuthenticationType == AuthenticationType.PublicKey && (supported_authentications_mask & (1 << (int)AuthenticationType.PublicKey)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedRSA")), packet.GetBytes()); TraceReceptionEvent(pt, "received server key"); }
internal void AsyncReceivePacket(DataFragment data) { try { SSH1DataReader re = new SSH1DataReader(data); SSH1PacketType pt = (SSH1PacketType)re.ReadByte(); switch (pt) { case SSH1PacketType.SSH_SMSG_STDOUT_DATA: { int len = re.ReadInt32(); DataFragment frag = re.GetRemainingDataView(len); _channel_collection.FindChannelEntry(_shellID).Receiver.OnData(frag.Data, frag.Offset, frag.Length); } break; case SSH1PacketType.SSH_SMSG_STDERR_DATA: { _channel_collection.FindChannelEntry(_shellID).Receiver.OnExtendedData((int)SSH1PacketType.SSH_SMSG_STDERR_DATA, re.ReadByteString()); } break; case SSH1PacketType.SSH_MSG_CHANNEL_DATA: { int channel = re.ReadInt32(); int len = re.ReadInt32(); DataFragment frag = re.GetRemainingDataView(len); _channel_collection.FindChannelEntry(channel).Receiver.OnData(frag.Data, frag.Offset, frag.Length); } break; case SSH1PacketType.SSH_MSG_PORT_OPEN: ProcessPortforwardingRequest(_eventReceiver, re); break; case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE: { int channel = re.ReadInt32(); ISSHChannelEventReceiver r = _channel_collection.FindChannelEntry(channel).Receiver; _channel_collection.UnregisterChannelEventReceiver(channel); r.OnChannelClosed(); } break; case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION: { int channel = re.ReadInt32(); } break; case SSH1PacketType.SSH_MSG_DISCONNECT: _eventReceiver.OnConnectionClosed(); break; case SSH1PacketType.SSH_SMSG_EXITSTATUS: _channel_collection.FindChannelEntry(_shellID).Receiver.OnChannelClosed(); break; case SSH1PacketType.SSH_MSG_DEBUG: _eventReceiver.OnDebugMessage(false, re.ReadByteString()); break; case SSH1PacketType.SSH_MSG_IGNORE: _eventReceiver.OnIgnoreMessage(re.ReadByteString()); break; case SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: { int local = re.ReadInt32(); int remote = re.ReadInt32(); _channel_collection.FindChannelEntry(local).Receiver.OnChannelReady(); } break; case SSH1PacketType.SSH_SMSG_SUCCESS: if (_executingShell) { ExecShell(); _channel_collection.FindChannelEntry(_shellID).Receiver.OnChannelReady(); _executingShell = false; } break; default: _eventReceiver.OnUnknownMessage((byte)pt, data.GetBytes()); break; } } catch (Exception ex) { _eventReceiver.OnError(ex); } }
private void ReceiveServerKeys() { DataFragment packet = ReceivePacket(); SSH1DataReader reader = new SSH1DataReader(packet); PacketType pt = reader.ReadPacketType(); if (pt != PacketType.SSH_SMSG_PUBLIC_KEY) throw new SSHException("unexpected SSH SSH1Packet type " + pt, reader.ReadAll()); _cInfo._serverinfo = new SSHServerInfo(reader); _cInfo._hostkey = new RSAPublicKey(_cInfo._serverinfo.host_key_public_exponent, _cInfo._serverinfo.host_key_public_modulus); //read protocol support parameters int protocol_flags = reader.ReadInt32(); int supported_ciphers_mask = reader.ReadInt32(); _cInfo.SetSupportedCipherAlgorithms(supported_ciphers_mask); int supported_authentications_mask = reader.ReadInt32(); //Debug.WriteLine(String.Format("ServerOptions {0} {1} {2}", protocol_flags, supported_ciphers_mask, supported_authentications_mask)); if (reader.Rest > 0) throw new SSHException("data length mismatch", reader.ReadAll()); bool found = false; foreach (CipherAlgorithm a in _param.PreferableCipherAlgorithms) { if (a != CipherAlgorithm.Blowfish && a != CipherAlgorithm.TripleDES) continue; else if (a == CipherAlgorithm.Blowfish && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.Blowfish)) == 0) continue; else if (a == CipherAlgorithm.TripleDES && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.TripleDES)) == 0) continue; _cInfo._algorithmForReception = _cInfo._algorithmForTransmittion = a; found = true; break; } if (!found) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedX"), "Blowfish/TripleDES")); if (_param.AuthenticationType == AuthenticationType.Password && (supported_authentications_mask & (1 << (int)AuthenticationType.Password)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedPassword")), reader.ReadAll()); if (_param.AuthenticationType == AuthenticationType.PublicKey && (supported_authentications_mask & (1 << (int)AuthenticationType.PublicKey)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedRSA")), reader.ReadAll()); TraceReceptionEvent(pt, "received server key"); }
private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH1DataReader reader) { 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 = _channel_collection.RegisterChannelEventReceiver(null, result.channel).LocalID; _eventReceiver.EstablishPortforwarding(result.channel, new SSH1Channel(this, ChannelType.ForwardedRemoteToLocal, local_id, server_channel)); writer.WriteInt32(server_channel); writer.WriteInt32(local_id); SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, writer.ToByteArray()); p.WriteTo(_stream, _tCipher); } else { writer.WriteInt32(server_channel); SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE, writer.ToByteArray()); p.WriteTo(_stream, _tCipher); } }
/// <summary> /// Process packet about this channel. /// </summary> /// <param name="packetType">a packet type (message number)</param> /// <param name="packetFragment">a packet image except message number and recipient channel.</param> public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment) { if (_state == State.Closed) { return; // ignore } DataFragment dataFragmentArg; lock (_stateSync) { switch (_state) { case State.Initial: break; case State.WaitStartPTYResponse: if (packetType == SSH1PacketType.SSH_SMSG_SUCCESS) { _state = State.StartPTYSuccess; Monitor.PulseAll(_stateSync); // notifies state change _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT); } else if (packetType == SSH1PacketType.SSH_SMSG_FAILURE) { _state = State.StartPTYFailure; Monitor.PulseAll(_stateSync); // notifies state change _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT); } break; case State.Established: break; case State.Ready: switch (packetType) { case SSH1PacketType.SSH_SMSG_STDOUT_DATA: { SSH1DataReader reader = new SSH1DataReader(packetFragment); int len = reader.ReadInt32(); dataFragmentArg = reader.GetRemainingDataView(len); } goto OnData; // do it out of the lock block case SSH1PacketType.SSH_SMSG_STDERR_DATA: { SSH1DataReader reader = new SSH1DataReader(packetFragment); int len = reader.ReadInt32(); dataFragmentArg = reader.GetRemainingDataView(len); } goto OnData; // do it out of the lock block case SSH1PacketType.SSH_SMSG_EXITSTATUS: Transmit( new SSH1Packet(SSH1PacketType.SSH_CMSG_EXIT_CONFIRMATION) ); goto SetStateClosedByServer; // do it out of the lock block } goto OnUnhandledPacket; // do it out of the lock block } } return; OnData: Handler.OnData(dataFragmentArg); return; SetStateClosedByServer: Trace("CH[{0}] closed by server", LocalChannel); SetStateClosed(true); return; OnUnhandledPacket: Handler.OnUnhandledPacket((byte)packetType, packetFragment); return; }
/// <summary> /// Process packet about this channel. /// </summary> /// <param name="packetType">a packet type (message number)</param> /// <param name="packetFragment">a packet image except message number and recipient channel.</param> public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment) { if (_state == State.Closed) { return; // ignore } DataFragment dataFragmentArg; lock (_stateSync) { switch (_state) { case State.InitiatedByServer: break; case State.InitiatedByClient: if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { SSH1DataReader reader = new SSH1DataReader(packetFragment); SetRemoteChannel(reader.ReadUInt32()); _state = State.Established; Monitor.PulseAll(_stateSync); // notifies state change dataFragmentArg = new DataFragment(0); goto OnEstablished; // do it out of the lock block } if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE) { goto RequestFailed; // do it out of the lock block } break; case State.Closing: if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION) { goto SetStateClosedByClient; // do it out of the lock block } break; case State.Established: case State.Ready: if (ProcessPacketSub(packetType, packetFragment) == SubPacketProcessResult.Consumed) { return; } switch (packetType) { case SSH1PacketType.SSH_MSG_CHANNEL_DATA: { SSH1DataReader reader = new SSH1DataReader(packetFragment); int len = reader.ReadInt32(); dataFragmentArg = reader.GetRemainingDataView(len); } goto OnData; // do it out of the lock block case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE: Transmit( new SSH1Packet(SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION) .WriteUInt32(RemoteChannel) ); goto SetStateClosedByServer; // do it out of the lock block } goto OnUnhandledPacket; // do it out of the lock block } } return; OnEstablished: Trace("CH[{0}] channel opend : remoteChannel={1}", LocalChannel, RemoteChannel); Handler.OnEstablished(dataFragmentArg); OnChannelEstablished(); return; RequestFailed: Trace("CH[{0}] request failed", LocalChannel); RequestFailed(); return; SetStateClosedByClient: Trace("CH[{0}] closed by client", LocalChannel); SetStateClosed(false); return; SetStateClosedByServer: Trace("CH[{0}] closed by server", LocalChannel); SetStateClosed(true); return; OnData: Handler.OnData(dataFragmentArg); return; OnUnhandledPacket: Handler.OnUnhandledPacket((byte)packetType, packetFragment); return; }