示例#1
0
        private void InternalWritePacket(IPacket p)
        {
            if (!socket.Connected)
            {
                return;
            }

            byte paddingLength;
            var  payload = p.ToSshMessage();

            switch (SocketModeTx)
            {
            case Mode.Ascii:
            {
                var data = payload.Concat(new byte[] { (byte)'\r', (byte)'\n' }).ToArray();
                st.Write(data, 0, data.Length);
                SocketModeTx = Mode.PlainText;
                break;
            }

            case Mode.PlainText:
            {
                ClientSequence++;
                int packetLength = GetPacketLength(payload.Length, out paddingLength);
                pw.WriteInt32(packetLength);
                pw.Write(paddingLength);
                pw.Write(payload);
                pw.Write(new byte[paddingLength]);
                break;
            }

            case Mode.CipherText:
            {
                if (txCompressionEnabled || (txCompressionEnabled = IsTxCompressionEnabled()))
                {
                    if (TxZlibTransform == null)
                    {
                        TxZlibTransform = new ZlibTransform(CompressionMode.Compress);
                    }

                    var compressedLength = TxZlibTransform.TransformBlock(payload, 0, payload.Length, zlibTxBuffer, 0);
                    Debug.WriteLine(string.Format("Compression Out: In: {0}; Out: {1}; TotalIn: {2}; TotalOut: {3}; TotalRatio: {4}",
                                                  payload.Length, compressedLength, TxZlibTransform.TotalIn, TxZlibTransform.TotalOut, TxZlibTransform.Ratio));
                    payload = new byte[compressedLength];
                    Buffer.BlockCopy(zlibTxBuffer, 0, payload, 0, compressedLength);
                }

                var    hmac         = EncryptorMac;
                int    packetLength = GetPacketLength(payload.Length, out paddingLength);
                byte[] padding      = new byte[paddingLength];
                Extensions.Random.GetBytes(padding);

                hmac.WriteUInt32(ClientSequence++);
                hmac.WriteInt32(packetLength);
                hmac.Write(paddingLength);
                hmac.Write(payload);
                hmac.Write(padding);

                pw.WriteInt32(packetLength);
                pw.Write(paddingLength);
                pw.Write(payload);
                pw.Write(padding);
                // mac isn't encrypted, write directly to network stream
                st.Write(hmac.Hash, 0, hmac.BlockSize);
                hmac.Reset();
                break;
            }
            }

            if (p.Code == MessageCode.SSH_MSG_NEWKEYS)
            {
                SocketModeTx = Mode.CipherText;
                pw           = new PacketWriter(new CryptoStream(st, Encryptor, CryptoStreamMode.Write));
            }
        }
示例#2
0
        private IPacket PrivateReadPacket()
        {
            IPacket p = null;

            switch (SocketModeRx)
            {
            case Mode.Ascii:
            {
                p = new SshIdentification(pr.ReadLine().ToByteArray());
                break;
            }

            case Mode.PlainText:
            {
                ServerSequence++;
                int  packetLength  = pr.ReadInt32();
                byte paddingLength = pr.ReadByte();
                var  payload       = pr.ReadBytes(packetLength - paddingLength - 1);
                pr.ReadBytes(paddingLength);
                p = PacketFactory.Create(session, payload);
                break;
            }

            case Mode.CipherText:
            {
                if (Decryptor == null)
                {
                    session.KexProcessor.Wait();
                }

                int  packetLength  = pr.ReadInt32();
                byte paddingLength = pr.ReadByte();
                var  payload       = pr.ReadBytes(packetLength - paddingLength - 1);
                var  padding       = pr.ReadBytes(paddingLength);

                var hmac = DecryptorMac;
                hmac.WriteUInt32(ServerSequence++);
                hmac.WriteInt32(packetLength);
                hmac.Write(paddingLength);
                hmac.Write(payload);
                hmac.Write(padding);

                if (rxCompressionEnabled || (rxCompressionEnabled = IsRxCompressionEnabled()))
                {
                    if (RxZlibTransform == null)
                    {
                        RxZlibTransform = new ZlibTransform(CompressionMode.Decompress);
                    }

                    var length = RxZlibTransform.TransformBlock(payload, 0, payload.Length, zlibRxBuffer, 0);
                    Debug.WriteLine(string.Format("Compression In: In: {0}; Out: {1}; TotalIn: {2}; TotalOut: {3}; TotalRatio: {4}",
                                                  payload.Length, length, RxZlibTransform.TotalIn, RxZlibTransform.TotalOut, RxZlibTransform.Ratio));
                    payload = new byte[length];
                    Buffer.BlockCopy(zlibRxBuffer, 0, payload, 0, length);
                }

                // mac isn't encrypted, read directly from network stream
                byte[] mac = new byte[hmac.BlockSize];
                st.Read(mac, 0, hmac.BlockSize);

                if (!hmac.IsMatch(mac))
                {
                    throw new CryptographicException("MAC couldn't be verified!");
                }
                hmac.Reset();

                p = PacketFactory.Create(session, payload);
                break;
            }
            }

            if (p.Code == MessageCode.SSH_MSG_IDENTIFICATION)
            {
                SocketModeRx = Mode.PlainText;
            }
            if (p.Code == MessageCode.SSH_MSG_NEWKEYS)
            {
                SocketModeRx = Mode.CipherText;
            }
            return(p);
        }