/// <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; }
/// <summary> /// Process forwarded message. /// </summary> /// <param name="message">a forwarded message</param> private void ProcessMessage(DataFragment message) { if (_authKeyProvider == null || !_authKeyProvider.IsAuthKeyProviderEnabled) { SendFailure(); return; } SSH1DataReader reader = new SSH1DataReader(message); OpenSSHAgentForwardingMessageType messageType = (OpenSSHAgentForwardingMessageType)reader.ReadByte(); switch (messageType) { // for SSH1 keys case OpenSSHAgentForwardingMessageType.SSH_AGENTC_REQUEST_RSA_IDENTITIES: SSH1Identities(); break; case OpenSSHAgentForwardingMessageType.SSH_AGENTC_RSA_CHALLENGE: { reader.ReadUInt32(); // ignored BigInteger e = reader.ReadMPInt(); BigInteger n = reader.ReadMPInt(); BigInteger encryptedChallenge = reader.ReadMPInt(); byte[] sessionId = reader.Read(16); uint responseType = reader.ReadUInt32(); SSH1IRSAChallenge(e, n, encryptedChallenge, sessionId, responseType); } break; // for SSH2 keys case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_REQUEST_IDENTITIES: SSH2Identities(); break; case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_SIGN_REQUEST: { byte[] blob = reader.ReadByteString(); byte[] data = reader.ReadByteString(); uint flags = reader.ReadUInt32(); SSH2Sign(blob, data, flags); } break; default: SendFailure(); break; } }