Example #1
0
        //public IAsyncAction OnData(byte[] data, int offset, int length) {
        public void OnData(byte[] data, int offset, int length)
        {
            //return Task.Run(async () =>
            //{
            try
            {
                while (_buffer.Length - _writeOffset < length)
                {
                    ExpandBuffer();
                }
                Array.Copy(data, offset, _buffer, _writeOffset, length);
                _writeOffset += length;

                SSH2Packet p = ConstructPacket();
                while (p != null)
                {
                    //await _handler.OnPacket(p);
                    _handler.OnPacket(p);
                    p = ConstructPacket();
                }
                ReduceBuffer();
            }
            catch (Exception ex)
            {
                OnError(ex, ex.Message);
            }
            //}).AsAsyncAction();
        }
Example #2
0
        //returns true if a new packet could be obtained
        private SSH2Packet ConstructPacket()
        {
            SSH2Packet packet = null;

            if (_event != null && !_event.WaitOne(3000))
            {
                throw new Exception("waithandle timed out");
            }

            if (_cipher == null)
            {
                if (_writeOffset - _readOffset < 4)
                {
                    return(null);
                }
                int len = SSHUtil.ReadInt32(_buffer, _readOffset);
                if (_writeOffset - _readOffset < 4 + len)
                {
                    return(null);
                }

                packet       = SSH2Packet.FromPlainStream(_buffer, _readOffset);
                _readOffset += 4 + len;
                _sequence++;
            }
            else
            {
                if (_head == null)
                {
                    if (_writeOffset - _readOffset < _cipher.BlockSize)
                    {
                        return(null);
                    }
                    _head = new byte[_cipher.BlockSize];
                    byte[] eh = new byte[_cipher.BlockSize];
                    Array.Copy(_buffer, _readOffset, eh, 0, eh.Length);
                    _readOffset += eh.Length;
                    _cipher.Decrypt(eh, 0, eh.Length, _head, 0);
                }

                int len = SSHUtil.ReadInt32(_head, 0);
                if (_writeOffset - _readOffset < len + 4 - _head.Length + _mac.Size)
                {
                    return(null);
                }

                packet       = SSH2Packet.FromDecryptedHead(_head, _buffer, _readOffset, _cipher, _sequence++, _mac);
                _readOffset += 4 + len - _head.Length + _mac.Size;
                _head        = null;
            }

            return(packet);
        }
Example #3
0
 public void OnPacket(SSH2Packet packet)
 {
     //return Task.Run(() =>
     //{
     lock (this)
     {
         _packets.Add(packet);
         if (_packets.Count > 0)
         {
             SetReady();
         }
     }
     //});
 }
Example #4
0
        public static SSH2Packet FromPlainPayload(byte[] payload, int blocksize, Random rnd)
        {
            SSH2Packet p = new SSH2Packet();
            int        r = 11 - payload.Length % blocksize;

            while (r < 4)
            {
                r += blocksize;
            }
            p._padding = new byte[r];             //block size is 8, and padding length is at least 4 bytes
            rnd.NextBytes(p._padding);
            p._payload      = payload;
            p._packetLength = 1 + payload.Length + p._padding.Length;
            return(p);
        }
Example #5
0
        public static SSH2Packet FromDecryptedHead(byte[] head, byte[] buffer, int offset, Cipher cipher, int sequence, MAC mac)
        {
            SSH2Packet p = new SSH2Packet();

            p._packetLength = SSHUtil.ReadInt32(head, 0);
            if (p._packetLength <= 0 || p._packetLength >= MAX_PACKET_LENGTH)
            {
                throw new Exception(String.Format("packet size {0} is invalid", p._packetLength));
            }
            SSH2DataWriter buf = new SSH2DataWriter();

            buf.Write(sequence);
            buf.Write(head);
            if (p._packetLength > (cipher.BlockSize - 4))
            {
                byte[] tmp = new byte[p._packetLength - (cipher.BlockSize - 4)];
                cipher.Decrypt(buffer, offset, tmp.Length, tmp, 0);
                offset += tmp.Length;
                buf.Write(tmp);
            }
            byte[] result      = buf.ToByteArray();
            int    padding_len = (int)result[8];

            if (padding_len < 4)
            {
                throw new Exception("padding length is invalid");
            }

            byte[] payload = new byte[result.Length - 9 - padding_len];
            Array.Copy(result, 9, payload, 0, payload.Length);
            p._payload = payload;

            if (mac != null)
            {
                p._mac = mac.Calc(result);
                if (SSHUtil.memcmp(p._mac, 0, buffer, offset, mac.Size) != 0)
                {
                    throw new Exception("MAC Error");
                }
            }
            return(p);
        }
Example #6
0
 public SSH2Packet PopPacket()
 {
     lock (this) {
         if (_packets.Count == 0)
         {
             return(null);
         }
         else
         {
             SSH2Packet p = null;
             p = (SSH2Packet)_packets[0];
             _packets.RemoveAt(0);
             if (_packets.Count == 0)
             {
                 _event.Reset();
             }
             return(p);
         }
     }
 }
Example #7
0
        //no decryption, no mac
        public static SSH2Packet FromPlainStream(byte[] buffer, int offset)
        {
            SSH2Packet p = new SSH2Packet();

            p._packetLength = SSHUtil.ReadInt32(buffer, offset);
            if (p._packetLength <= 0 || p._packetLength >= MAX_PACKET_LENGTH)
            {
                throw new Exception(String.Format("packet size {0} is invalid", p._packetLength));
            }
            offset += 4;

            byte pl = buffer[offset++];

            if (pl < 4)
            {
                throw new Exception(String.Format("padding length {0} is invalid", pl));
            }
            p._payload = new byte[p._packetLength - 1 - pl];
            Array.Copy(buffer, offset, p._payload, 0, p._payload.Length);
            return(p);
        }
Example #8
0
        //no decryption, no mac
        public static SSH2Packet FromPlainStream(byte[] buffer, int offset)
        {
            SSH2Packet p = new SSH2Packet();
            p._packetLength = SSHUtil.ReadInt32(buffer, offset);
            if(p._packetLength<=0 || p._packetLength>=MAX_PACKET_LENGTH) throw new Exception(String.Format("packet size {0} is invalid", p._packetLength));
            offset += 4;

            byte pl = buffer[offset++];
            if(pl < 4) throw new Exception(String.Format("padding length {0} is invalid", pl));
            p._payload = new byte[p._packetLength - 1 - pl];
            Array.Copy(buffer, offset, p._payload, 0, p._payload.Length);
            return p;
        }
Example #9
0
 public static SSH2Packet FromPlainPayload(byte[] payload, int blocksize, Random rnd)
 {
     SSH2Packet p = new SSH2Packet();
     int r = 11 - payload.Length % blocksize;
     while(r < 4) r += blocksize;
     p._padding = new byte[r]; //block size is 8, and padding length is at least 4 bytes
     rnd.NextBytes(p._padding);
     p._payload = payload;
     p._packetLength = 1+payload.Length+p._padding.Length;
     return p;
 }
Example #10
0
        public static SSH2Packet FromDecryptedHead(byte[] head, byte[] buffer, int offset, Cipher cipher, int sequence, MAC mac)
        {
            SSH2Packet p = new SSH2Packet();
            p._packetLength = SSHUtil.ReadInt32(head, 0);
            if(p._packetLength<=0 || p._packetLength>=MAX_PACKET_LENGTH) throw new Exception(String.Format("packet size {0} is invalid", p._packetLength));
            SSH2DataWriter buf = new SSH2DataWriter();
            buf.Write(sequence);
            buf.Write(head);
            if(p._packetLength > (cipher.BlockSize - 4)) {
                byte[] tmp = new byte[p._packetLength-(cipher.BlockSize - 4)];
                cipher.Decrypt(buffer, offset, tmp.Length, tmp, 0);
                offset += tmp.Length;
                buf.Write(tmp);
            }
            byte[] result = buf.ToByteArray();
            int padding_len = (int)result[8];
            if(padding_len<4) throw new Exception("padding length is invalid");

            byte[] payload = new byte[result.Length-9-padding_len];
            Array.Copy(result, 9, payload, 0, payload.Length);
            p._payload = payload;

            if(mac!=null) {
                p._mac = mac.Calc(result);
                if(SSHUtil.memcmp(p._mac, 0, buffer, offset, mac.Size)!=0)
                    throw new Exception("MAC Error");
            }
            return p;
        }
Example #11
0
        private bool ProcessPacket(SSH2Packet packet)
        {
            //Debug.WriteLine("ProcessPacket pt="+pt);
            SSH2DataReader r = new SSH2DataReader(packet.Data);
            PacketType pt = r.ReadPacketType();

            if(pt==PacketType.SSH_MSG_DISCONNECT) {
                int errorcode = r.ReadInt32();
                byte[] tmpdata = r.ReadString();
                string description = Encoding.UTF8.GetString(tmpdata, 0 ,tmpdata.Length);
                _eventReceiver.OnConnectionClosed();
                return false;
            }
            else if(_waitingForPortForwardingResponse) {
                if(pt!=PacketType.SSH_MSG_REQUEST_SUCCESS)
                    _eventReceiver.OnUnknownMessage((byte)pt, r.Image);
                _waitingForPortForwardingResponse = false;
                return true;
            }
            else if(pt==PacketType.SSH_MSG_CHANNEL_OPEN) {
                ProcessPortforwardingRequest(_eventReceiver, r);
                return true;
            }
            else if(pt>=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION && pt<=PacketType.SSH_MSG_CHANNEL_FAILURE) {
                int local_channel = r.ReadInt32();
                ChannelEntry e = FindChannelEntry(local_channel);
                if(e!=null) //throw new Exception("Unknown channel "+local_channel);
                    ((SSH2Channel)e._channel).ProcessPacket(e._receiver, pt, 5+r.Rest, r);
                else
                    Debug.WriteLine("unexpected channel pt="+pt+" local_channel="+local_channel.ToString());
                return true;
            }
            else if(pt==PacketType.SSH_MSG_IGNORE) {
                _eventReceiver.OnIgnoreMessage(r.ReadString());
                return true;
            }
            else if(_asyncKeyExchanger!=null) {
                _asyncKeyExchanger.AsyncProcessPacket(packet);
                return true;
            }
            else if(pt==PacketType.SSH_MSG_KEXINIT) {
                //Debug.WriteLine("Host sent KEXINIT");
                _asyncKeyExchanger = new KeyExchanger(this, _sessionID);
                _asyncKeyExchanger.AsyncProcessPacket(packet);
                return true;
            }
            else {
                _eventReceiver.OnUnknownMessage((byte)pt, r.Image);
                return false;
            }
        }
Example #12
0
 public void AsyncProcessPacket(SSH2Packet packet)
 {
     switch(_status) {
         case Status.INITIAL:
             _startedByHost = true;
             ProcessKEXINIT(packet);
             SendKEXINIT();
             SendKEXDHINIT();
             break;
         case Status.WAIT_KEXINIT:
             ProcessKEXINIT(packet);
             SendKEXDHINIT();
             break;
         case Status.WAIT_KEXDH_REPLY:
             ProcessKEXDHREPLY(packet);
             SendNEWKEYS();
             break;
         case Status.WAIT_NEWKEYS:
             ProcessNEWKEYS(packet);
             Debug.Assert(_status==Status.FINISHED);
             break;
     }
 }
Example #13
0
        private bool ProcessKEXDHREPLY(SSH2Packet packet)
        {
            //Round2 receives response
            SSH2DataReader re = new SSH2DataReader(packet.Data);
            PacketType h = re.ReadPacketType();
            if(h!=PacketType.SSH_MSG_KEXDH_REPLY) throw new Exception(String.Format("KeyExchange response is not KEXDH_REPLY but {0}", h));
            byte[] key_and_cert = re.ReadString();
            BigInteger f = re.ReadMPInt();
            byte[] signature = re.ReadString();
            Debug.Assert(re.Rest==0);

            //Round3 calc hash H
            SSH2DataWriter wr = new SSH2DataWriter();
            _k = f.modPow(_x, DH_PRIME);
            wr = new SSH2DataWriter();
            wr.Write(_cInfo._clientVersionString);
            wr.Write(_cInfo._serverVersionString);
            wr.WriteAsString(_clientKEXINITPayload);
            wr.WriteAsString(_serverKEXINITPayload);
            wr.WriteAsString(key_and_cert);
            wr.Write(_e);
            wr.Write(f);
            wr.Write(_k);
            _hash = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1).HashData(wr.ToByteArray().AsBuffer()).ToArray();

            if(!VerifyHostKey(key_and_cert, signature, _hash)) return false;

            //Debug.WriteLine("hash="+DebugUtil.DumpByteArray(hash));
            if(_sessionID==null) _sessionID = _hash;
            return true;
        }
Example #14
0
 public void OnPacket(SSH2Packet packet)
 {
     _connection.AsyncReceivePacket(packet);
 }
Example #15
0
 internal void AsyncReceivePacket(SSH2Packet packet)
 {
     try {
         ProcessPacket(packet);
     }
     catch(Exception ex) {
         //Debug.WriteLine(ex.StackTrace);
         if(!_closed)
             _eventReceiver.OnError(ex, ex.Message);
     }
 }
Example #16
0
 public void OnPacket(SSH2Packet packet)
 {
     //return Task.Run(() =>
     //{
         lock (this)
         {
             _packets.Add(packet);
             if (_packets.Count > 0)
                 SetReady();
         }
     //});
 }
Example #17
0
        private void ProcessKEXINIT(SSH2Packet packet)
        {
            _serverKEXINITPayload = packet.Data;
            SSH2DataReader re = new SSH2DataReader(_serverKEXINITPayload);
            byte[] head = re.Read(17); //Type and cookie
            if(head[0]!=(byte)PacketType.SSH_MSG_KEXINIT) throw new Exception(String.Format("Server response is not SSH_MSG_KEXINIT but {0}", head[0]));
            Encoding enc = Encoding.UTF8;
            byte[] tmpdata;

            tmpdata = re.ReadString();
            string kex = enc.GetString(tmpdata,0,tmpdata.Length);
            _cInfo._supportedKEXAlgorithms = kex;
            CheckAlgorithmSupport("keyexchange", kex, "diffie-hellman-group1-sha1");

            tmpdata = re.ReadString();
            string host_key = enc.GetString(tmpdata, 0, tmpdata.Length);
            _cInfo._supportedHostKeyAlgorithms = host_key;
            _cInfo._algorithmForHostKeyVerification = DecideHostKeyAlgorithm(host_key);

            tmpdata = re.ReadString();
            string enc_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            _cInfo._supportedCipherAlgorithms = enc_cs;
            _cInfo._algorithmForTransmittion = DecideCipherAlgorithm(enc_cs);

            tmpdata = re.ReadString();
            string enc_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            _cInfo._algorithmForReception = DecideCipherAlgorithm(enc_sc);

            tmpdata = re.ReadString();
            string mac_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("mac", mac_cs, "hmac-sha1");

            tmpdata = re.ReadString();
            string mac_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("mac", mac_sc, "hmac-sha1");

            tmpdata = re.ReadString();
            string comp_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("compression", comp_cs, "none");
            tmpdata = re.ReadString();
            string comp_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("compression", comp_sc, "none");

            tmpdata = re.ReadString();
            string lang_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            tmpdata = re.ReadString();
            string lang_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            bool flag = re.ReadBool();
            int reserved = re.ReadInt32();
            Debug.Assert(re.Rest==0);
            if(flag) throw new Exception(resLoader.GetString("AlgNegotiationFailed"));
        }
Example #18
0
 public void OnPacket(SSH2Packet packet)
 {
     _connection.AsyncReceivePacket(packet);
 }
Example #19
0
        private void ProcessNEWKEYS(SSH2Packet packet)
        {
            //confirms new key
            try {
                byte[] response = packet.Data;
                if(response.Length!=1 || response[0]!=(byte)PacketType.SSH_MSG_NEWKEYS) throw new Exception("SSH_MSG_NEWKEYS failed");

                _newKeyEvent.WaitOne();
                _newKeyEvent.Dispose();
                _con.LockCommunication();
                _con.RefreshKeys(_sessionID, _tc, _rc, _tm, _rm);
                _status = Status.FINISHED;
            }
            finally {
                _con.UnlockCommunication();
            }
        }