예제 #1
0
        public void OnData(byte[] data, int offset, int length) {
            _buffer.Write(data, offset, length);
            int expectedLength = SSHUtil.ReadInt32(_buffer.UnderlyingBuffer, 0);
            if(expectedLength + 4 <= _buffer.Length) {
                SSH2DataReader r = new SSH2DataReader(new DataFragment(_buffer.UnderlyingBuffer, 4, _buffer.Length-4));
                AgentForwadPacketType pt = (AgentForwadPacketType)r.ReadByte();
                //remaining len-1
                _buffer.SetOffset(0);

                switch(pt) {
                    case AgentForwadPacketType.SSH2_AGENTC_REQUEST_IDENTITIES:
                        SendKeyList();
                        break;
                    case AgentForwadPacketType.SSH2_AGENTC_SIGN_REQUEST:
                        SendSign(r);
                        break;
                    default:
                        //Debug.WriteLine("Unknown agent packet " + pt.ToString());
                        TransmitWriter(OpenWriter(AgentForwadPacketType.SSH_AGENT_FAILURE));
                        break;
                }
            }
        }
예제 #2
0
        public void OnData(byte[] data, int offset, int length)
        {
            #if DUMP_PACKET
            Dump("SFTP: OnData", data, offset, length);
            #endif
            DataFragment dataFragment;
            if (_isDataIncomplete) {
                // append to buffer
                _dataBuffer.Write(data, offset, length);

                if (_dataTotal == 0) {  // not determined yet
                    if (_dataBuffer.Length < 4)
                        return;
                    _dataTotal = SSHUtil.ReadInt32(_dataBuffer.UnderlyingBuffer, 0);
                }

                if (_dataBuffer.Length < _dataTotal)
                    return;

                _isDataIncomplete = false;
                _dataTotal = 0;
                dataFragment = new DataFragment(_dataBuffer.UnderlyingBuffer, 0, (int)_dataBuffer.Length);
            }
            else {
                if (length < 4) {
                    _dataBuffer.Reset();
                    _dataBuffer.Write(data, offset, length);
                    _isDataIncomplete = true;
                    _dataTotal = 0; // determine later...
                    return;
                }

                int total = SSHUtil.ReadInt32(data, offset);
                if (length - 4 < total) {
                    _dataBuffer.Reset();
                    _dataBuffer.Write(data, offset, length);
                    _isDataIncomplete = true;
                    _dataTotal = total;
                    return;
                }
                dataFragment = new DataFragment(data, offset, length);
            }

            SSH2DataReader reader = new SSH2DataReader(dataFragment);
            int dataLength = reader.ReadInt32();
            if (dataLength >= 1) {
                SFTPPacketType packetType = (SFTPPacketType)reader.ReadByte();
                dataLength--;
                lock (ResponseNotifier) {
                    bool processed = false;
                    if (_responseHandler != null) {
                        try {
                            processed = _responseHandler(packetType, reader);
                        }
                        catch (Exception e) {
                            _responseHandlerException = e;
                            processed = true;
                        }
                    }
                    else {
                        processed = true;
                    }

                    if (processed) {
                        Monitor.PulseAll(_responseNotifier);
                    }
                }
            }
            // FIXME: invalid packet should be alerted
        }
예제 #3
0
        private bool ProcessPacket(DataFragment packet)
        {
            SSH2DataReader r = new SSH2DataReader(packet);
            SSH2PacketType pt = (SSH2PacketType) r.ReadByte();

            if (pt == SSH2PacketType.SSH_MSG_DISCONNECT) {
                int errorcode = r.ReadInt32();
                _eventReceiver.OnConnectionClosed();
                return false;
            }
            else if (_waitingForPortForwardingResponse) {
                if (pt != SSH2PacketType.SSH_MSG_REQUEST_SUCCESS)
                    _eventReceiver.OnUnknownMessage((byte)pt, packet.GetBytes());
                _waitingForPortForwardingResponse = false;
                return true;
            }
            else if (pt == SSH2PacketType.SSH_MSG_CHANNEL_OPEN) {
                string method = r.ReadString();
                if (method == "forwarded-tcpip")
                    ProcessPortforwardingRequest(_eventReceiver, r);
                else if (method.StartsWith("auth-agent")) //in most cases, method is "*****@*****.**"
                    ProcessAgentForwardRequest(_eventReceiver, r);
                else {
                    SSH2DataWriter wr = new SSH2DataWriter();
                    wr.WriteByte((byte)SSH2PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE);
                    wr.WriteInt32(r.ReadInt32());
                    wr.WriteInt32(0);
                    wr.WriteString("unknown method");
                    wr.WriteString(""); //lang tag
                    TraceReceptionEvent("SSH_MSG_CHANNEL_OPEN rejected", "method={0}", method);
                }
                return true;
            }
            else if (pt >= SSH2PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION && pt <= SSH2PacketType.SSH_MSG_CHANNEL_FAILURE) {
                int local_channel = r.ReadInt32();
                ChannelCollection.Entry e = this.ChannelCollection.FindChannelEntry(local_channel);
                if (e != null)
                    ((SSH2Channel)e.Channel).ProcessPacket(e.Receiver, pt, r);
                else
                    Debug.WriteLine("unexpected channel pt=" + pt + " local_channel=" + local_channel.ToString());
                return true;
            }
            else if (pt == SSH2PacketType.SSH_MSG_IGNORE) {
                _eventReceiver.OnIgnoreMessage(r.ReadByteString());
                return true;
            }
            else if (_asyncKeyExchanger != null) {
                _asyncKeyExchanger.AsyncProcessPacket(packet);
                return true;
            }
            else if (pt == SSH2PacketType.SSH_MSG_KEXINIT) {
                //Debug.WriteLine("Host sent KEXINIT");
                _asyncKeyExchanger = new KeyExchanger(this, _sessionID);
                _asyncKeyExchanger.AsyncProcessPacket(packet);
                return true;
            }
            else {
                _eventReceiver.OnUnknownMessage((byte)pt, packet.GetBytes());
                return false;
            }
        }
예제 #4
0
 private AuthenticationResult ProcessAuthenticationResponse()
 {
     do {
         SSH2DataReader response = new SSH2DataReader(ReceivePacket());
         SSH2PacketType h = (SSH2PacketType) response.ReadByte();
         if (h == SSH2PacketType.SSH_MSG_USERAUTH_FAILURE) {
             string msg = response.ReadString();
             TraceReceptionEvent(h, "user authentication failed:" + msg);
             return AuthenticationResult.Failure;
         }
         else if (h == SSH2PacketType.SSH_MSG_USERAUTH_BANNER) {
             TraceReceptionEvent(h, "");
         }
         else if (h == SSH2PacketType.SSH_MSG_USERAUTH_SUCCESS) {
             TraceReceptionEvent(h, "user authentication succeeded");
             _packetizer.SetInnerHandler(new CallbackSSH2PacketHandler(this));
             return AuthenticationResult.Success; //successfully exit
         }
         else if (h == SSH2PacketType.SSH_MSG_USERAUTH_INFO_REQUEST) {
             string name = response.ReadUTF8String();
             string inst = response.ReadUTF8String();
             string lang = response.ReadString();
             int num = response.ReadInt32();
             string[] prompts = new string[num];
             for (int i = 0; i < num; i++) {
                 prompts[i] = response.ReadUTF8String();
                 bool echo = response.ReadBool();
             }
             _eventReceiver.OnAuthenticationPrompt(prompts);
             _requiredResponseCount = num;
             return AuthenticationResult.Prompt;
         }
         else
             throw new SSHException("protocol error: unexpected packet type " + h);
     } while (true);
 }
예제 #5
0
        //synchronous reception
        internal DataFragment ReceivePacket()
        {
            while (true) {
                DataFragment data = _packetReceiver.WaitResponse();

                SSH2PacketType pt = (SSH2PacketType)data[0]; //sneak

                //filter unnecessary packet
                if (pt == SSH2PacketType.SSH_MSG_IGNORE) {
                    SSH2DataReader r = new SSH2DataReader(data);
                    r.ReadByte(); //skip
                    byte[] msg = r.ReadByteString();
                    if (_eventReceiver != null)
                        _eventReceiver.OnIgnoreMessage(msg);
                    TraceReceptionEvent(pt, msg);
                }
                else if (pt == SSH2PacketType.SSH_MSG_DEBUG) {
                    SSH2DataReader r = new SSH2DataReader(data);
                    r.ReadByte(); //skip
                    bool f = r.ReadBool();
                    byte[] msg = r.ReadByteString();
                    if (_eventReceiver != null)
                        _eventReceiver.OnDebugMessage(f, msg);
                    TraceReceptionEvent(pt, msg);
                }
                else {
                    return data;
                }
            }
        }
예제 #6
0
        private bool ProcessKEXDHREPLY(DataFragment packet)
        {
            //Round2 receives response
            SSH2DataReader re = null;
            SSH2PacketType h;
            do {
                re = new SSH2DataReader(packet);
                h = (SSH2PacketType) re.ReadByte();
                if (h == SSH2PacketType.SSH_MSG_KEXDH_REPLY)
                    break; //successfully exit
                else if (h == SSH2PacketType.SSH_MSG_IGNORE || h == SSH2PacketType.SSH_MSG_DEBUG) { //continue
                    packet = _connection.ReceivePacket();
                }
                else
                    throw new SSHException(String.Format("KeyExchange response is not KEXDH_REPLY but {0}", h));
            } while (true);

            byte[] key_and_cert = re.ReadByteString();
            BigInteger f = re.ReadMPInt();
            byte[] signature = re.ReadByteString();
            Debug.Assert(re.RemainingDataLength == 0);

            //Round3 calc hash H
            SSH2DataWriter wr = new SSH2DataWriter();
            _k = f.ModPow(_x, GetDiffieHellmanPrime(_cInfo.KEXAlgorithm.Value));
            wr = new SSH2DataWriter();
            wr.WriteString(_cInfo.ClientVersionString);
            wr.WriteString(_cInfo.ServerVersionString);
            wr.WriteAsString(_clientKEXINITPayload);
            wr.WriteAsString(_serverKEXINITPayload);
            wr.WriteAsString(key_and_cert);
            wr.WriteBigInteger(_e);
            wr.WriteBigInteger(f);
            wr.WriteBigInteger(_k);
            _hash = KexComputeHash(wr.ToByteArray());

            _connection.TraceReceptionEvent(h, "verifying host key");
            if (!VerifyHostKey(key_and_cert, signature, _hash))
                return false;

            //Debug.WriteLine("hash="+DebugUtil.DumpByteArray(hash));
            if (_sessionID == null)
                _sessionID = _hash;
            return true;
        }
예제 #7
0
        private void ServiceRequest(string servicename)
        {
            Transmit(
                new SSH2Packet(SSH2PacketType.SSH_MSG_SERVICE_REQUEST)
                    .WriteString(servicename)
            );
            TraceTransmissionEvent("SSH_MSG_SERVICE_REQUEST", servicename);

            DataFragment response = ReceivePacket();
            SSH2DataReader re = new SSH2DataReader(response);
            SSH2PacketType t = (SSH2PacketType) re.ReadByte();
            if (t != SSH2PacketType.SSH_MSG_SERVICE_ACCEPT) {
                TraceReceptionEvent(t.ToString(), "service request failed");
                throw new SSHException("service establishment failed " + t);
            }

            string s = re.ReadString();
            if (servicename != s)
                throw new SSHException("protocol error");
        }
예제 #8
0
        /// <summary>
        /// Wait for response.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Caller should lock ResponseNotifier before send a request packet,
        /// and this method should be called in the lock-block.
        /// </para>
        /// </remarks>
        /// <param name="responseHandler">delegate which handles response data</param>
        /// <param name="millisecondsTimeout">timeout in milliseconds</param>
        /// <exception cref="SFTPClientTimeoutException">Timeout has occured.</exception>
        /// <exception cref="Exception">an exception which was thrown while executing responseHandler.</exception>
        public void WaitResponse(DataReceivedDelegate responseHandler, int millisecondsTimeout)
        {
            lock (_dataBufferSync) {
                bool processed = false;
                while (!processed) {
                    while (_dataBuffer.Length < 4) {
                        if (!Monitor.Wait(_dataBufferSync, millisecondsTimeout)) {
                            throw new SFTPClientTimeoutException();
                        }
                    }

                    int totalSize = SSHUtil.ReadInt32(_dataBuffer.RawBuffer, _dataBuffer.RawBufferOffset);

                    while (_dataBuffer.Length < 4 + totalSize) {
                        if (!Monitor.Wait(_dataBufferSync, millisecondsTimeout)) {
                            throw new SFTPClientTimeoutException();
                        }
                    }

                    _dataBuffer.RemoveHead(4);      // length field

                    if (totalSize >= 1) {
                        SSH2DataReader reader = new SSH2DataReader(
                                    new DataFragment(_dataBuffer.RawBuffer, _dataBuffer.RawBufferOffset, totalSize));
                        SFTPPacketType packetType = (SFTPPacketType)reader.ReadByte();
                        if (responseHandler != null) {
                            processed = responseHandler(packetType, reader);
                        }
                        else {
                            processed = true;
                        }
                    }

                    _dataBuffer.RemoveHead(totalSize);
                }
            }
        }