Example #1
0
        /// <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;
            }
        }