Esempio n. 1
0
        private void ReceivePong(IncomingPacket packet)
        {
            ushort         answerId = NetUtil.N2Hushort(packet.Data, 0);
            OutgoingPacket sendPing;

            lock (sendLoopLock)
            {
                if (!packetPingManager.TryGetValue(answerId, out sendPing))
                {
                    return;
                }
                packetPingManager.Remove(answerId);
            }
            NetworkStats.AddPing(Util.Now - sendPing.LastSendTime);
        }
Esempio n. 2
0
        /// <summary>TS3 uses a new key and nonce for each packet sent and received. This method generates and caches these.</summary>
        /// <param name="fromServer">True if the packet is from server to client, false for client to server.</param>
        /// <param name="packetId">The id of the packet, host order.</param>
        /// <param name="generationId">Each time the packetId reaches 65535 the next packet will go on with 0 and the generationId will be increased by 1.</param>
        /// <param name="packetType">The packetType.</param>
        /// <returns>A tuple of (key, nonce)</returns>
        private Tuple <byte[], byte[]> GetKeyNonce(bool fromServer, ushort packetId, uint generationId, PacketType packetType)
        {
            if (!CryptoInitComplete)
            {
                return(DummyKeyAndNonceTuple);
            }

            // only the lower 4 bits are used for the real packetType
            byte packetTypeRaw = (byte)packetType;

            int cacheIndex = packetTypeRaw * (fromServer ? 1 : 2);

            if (cachedKeyNonces[cacheIndex] == null || cachedKeyNonces[cacheIndex].Item3 != generationId)
            {
                // this part of the key/nonce is fixed by the message direction and packetType

                byte[] tmpToHash = new byte[26];

                if (fromServer)
                {
                    tmpToHash[0] = 0x30;
                }
                else
                {
                    tmpToHash[0] = 0x31;
                }

                tmpToHash[1] = packetTypeRaw;

                Array.Copy(BitConverter.GetBytes(NetUtil.H2N(generationId)), 0, tmpToHash, 2, 4);
                Array.Copy(ivStruct, 0, tmpToHash, 6, 20);

                var result = Hash256It(tmpToHash);

                cachedKeyNonces[cacheIndex] = new Tuple <byte[], byte[], uint>(result.Slice(0, 16).ToArray(), result.Slice(16, 16).ToArray(), generationId);
            }

            byte[] key   = new byte[16];
            byte[] nonce = new byte[16];
            Array.Copy(cachedKeyNonces[cacheIndex].Item1, 0, key, 0, 16);
            Array.Copy(cachedKeyNonces[cacheIndex].Item2, 0, nonce, 0, 16);

            // finally the first two bytes get xor'd with the packet id
            key[0] ^= (byte)((packetId >> 8) & 0xFF);
            key[1] ^= (byte)((packetId) & 0xFF);

            return(new Tuple <byte[], byte[]>(key, nonce));
        }
Esempio n. 3
0
        private void ReceivePing(S2CPacket packet)
        {
            var idDiff = packet.PacketId - lastReceivedPingId;

            if (idDiff > 1 && idDiff < ReceivePacketWindowSize)
            {
                NetworkStats.LogLostPings(idDiff - 1);
            }
            if (idDiff > 0 || idDiff < -ReceivePacketWindowSize)
            {
                lastReceivedPingId = packet.PacketId;
            }
            byte[] pongData = new byte[2];
            NetUtil.H2N(packet.PacketId, pongData, 0);
            AddOutgoingPacket(pongData, PacketType.Pong);
        }
Esempio n. 4
0
        private S2CPacket ReceiveAck(S2CPacket packet)
        {
            if (packet.Data.Length < 2)
            {
                return(null);
            }
            ushort packetId = NetUtil.N2Hushort(packet.Data, 0);

            lock (sendLoopLock)
            {
                if (packetAckManager.TryGetValue(packetId, out var ackPacket))
                {
                    UpdateRto(Util.Now - ackPacket.LastSendTime);
                    packetAckManager.Remove(packetId);
                }
            }
            return(packet);
        }
Esempio n. 5
0
        public void SendAudioGroupWhisper(ReadOnlySpan <byte> data, Codec codec, GroupWhisperType type, GroupWhisperTarget target, ulong targetId = 0)
        {
            // [X,X,Y,N,M,U,U,U,U,U,U,U,U,DATA]
            // > X is a ushort in H2N order of an own audio packet counter
            //     it seems it can be the same as the packet counter so we will let the packethandler do it.
            // > Y is the codec byte (see Enum)
            // > N is a byte, specifying the GroupWhisperType
            // > M is a byte, specifying the GroupWhisperTarget
            // > U is a ulong in H2N order for the targeted channelId or groupId (0 if not applicable)
            byte[] tmpBuffer = new byte[data.Length + 13];
            tmpBuffer[2] = (byte)codec;
            tmpBuffer[3] = (byte)type;
            tmpBuffer[4] = (byte)target;
            NetUtil.H2N(targetId, tmpBuffer, 5);
            data.CopyTo(new Span <byte>(tmpBuffer, 13));

            packetHandler.AddOutgoingPacket(tmpBuffer, PacketType.VoiceWhisper, PacketFlags.Newprotocol);
        }
Esempio n. 6
0
        internal IncomingPacket Decrypt(byte[] data)
        {
            if (data.Length < InHeaderLen + MacLen)
            {
                return(null);
            }

            var packet = new IncomingPacket(data)
            {
                PacketTypeFlagged = data[MacLen + 2],
                PacketId          = NetUtil.N2Hushort(data, MacLen),
            };

            if (packet.PacketType == PacketType.Init1)
            {
                if (!FakeDecrypt(packet, TS3InitMac))
                {
                    return(null);
                }
            }
            else
            {
                if (packet.UnencryptedFlag)
                {
                    if (!FakeDecrypt(packet, fakeSignature))
                    {
                        return(null);
                    }
                }
                else
                {
                    if (!Decrypt(packet))
                    {
                        return(null);
                    }
                }
            }

            return(packet);
        }
Esempio n. 7
0
 private void ReceivePing(IncomingPacket packet)
 {
     byte[] pongData = new byte[2];
     NetUtil.H2N(packet.PacketId, pongData, 0);
     AddOutgoingPacket(pongData, PacketType.Pong);
 }
Esempio n. 8
0
 public void BuildHeader()
 {
     NetUtil.H2N(PacketId, Header, 0);
     NetUtil.H2N(ClientId, Header, 2);
     Header[4] = PacketTypeFlagged;
 }
Esempio n. 9
0
        public S2CPacket FetchPacket()
        {
            while (true)
            {
                if (Closed)
                {
                    return(null);
                }

                if (TryFetchPacket(receiveQueue, out var packet))
                {
                    return(packet);
                }
                if (TryFetchPacket(receiveQueueLow, out packet))
                {
                    return(packet);
                }

                var    dummy = new IPEndPoint(IPAddress.Any, 0);
                byte[] buffer;

                try { buffer = udpClient.Receive(ref dummy); }
                catch (IOException) { return(null); }
                catch (SocketException) { return(null); }

                if (dummy.Address.Equals(remoteAddress.Address) && dummy.Port != remoteAddress.Port)
                {
                    continue;
                }

                packet = Ts3Crypt.GetIncommingPacket(buffer);
                // Invalid packet, ignore
                if (packet == null)
                {
                    LoggerRaw.Debug("Dropping invalid packet: {0}", DebugUtil.DebugToHex(buffer));
                    continue;
                }

                GenerateGenerationId(packet);
                if (!ts3Crypt.Decrypt(packet))
                {
                    continue;
                }

                NetworkStats.LogInPacket(packet);

                switch (packet.PacketType)
                {
                case PacketType.Voice:
                case PacketType.VoiceWhisper:
                    LoggerRawVoice.ConditionalTrace("[I] {0}", packet);
                    break;

                case PacketType.Command:
                    LoggerRaw.Debug("[I] {0}", packet);
                    packet = ReceiveCommand(packet, receiveQueue, PacketType.Ack);
                    break;

                case PacketType.CommandLow:
                    LoggerRaw.Debug("[I] {0}", packet);
                    packet = ReceiveCommand(packet, receiveQueueLow, PacketType.AckLow);
                    break;

                case PacketType.Ping:
                    LoggerRaw.ConditionalTrace("[I] Ping {0}", packet.PacketId);
                    ReceivePing(packet);
                    break;

                case PacketType.Pong:
                    LoggerRaw.ConditionalTrace("[I] Pong {0}", NetUtil.N2Hushort(packet.Data, 0));
                    ReceivePong(packet);
                    break;

                case PacketType.Ack:
                    LoggerRaw.ConditionalDebug("[I] Acking: {0}", NetUtil.N2Hushort(packet.Data, 0));
                    packet = ReceiveAck(packet);
                    break;

                case PacketType.AckLow: break;

                case PacketType.Init1:
                    LoggerRaw.Debug("[I] InitID: {0}", packet.Data[0]);
                    LoggerRaw.Trace("[I] {0}", packet);
                    ReceiveInitAck(packet);
                    break;

                default: throw Util.UnhandledDefault(packet.PacketType);
                }

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
Esempio n. 10
0
        private void SendOutgoingData(ReadOnlySpan <byte> data, PacketType packetType, PacketFlags flags = PacketFlags.None)
        {
            var packet = new C2SPacket(data.ToArray(), packetType);

            lock (sendLoopLock)
            {
                var ids = GetPacketCounter(packet.PacketType);
                if (ts3Crypt.CryptoInitComplete)
                {
                    IncPacketCounter(packet.PacketType);
                }

                packet.PacketId     = ids.Id;
                packet.GenerationId = ids.Generation;
                packet.ClientId     = ClientId;
                packet.PacketFlags |= flags;

                switch (packet.PacketType)
                {
                case PacketType.Voice:
                case PacketType.VoiceWhisper:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    NetUtil.H2N(packet.PacketId, packet.Data, 0);
                    LoggerRawVoice.ConditionalTrace("[O] {0}", packet);
                    break;

                case PacketType.Command:
                case PacketType.CommandLow:
                    packet.PacketFlags |= PacketFlags.Newprotocol;
                    packetAckManager.Add(packet.PacketId, packet);
                    LoggerRaw.Debug("[O] {0}", packet);
                    break;

                case PacketType.Ping:
                    lastSentPingId      = packet.PacketId;
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    LoggerRaw.ConditionalTrace("[O] Ping {0}", packet.PacketId);
                    break;

                case PacketType.Pong:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    LoggerRaw.ConditionalTrace("[O] Pong {0}", NetUtil.N2Hushort(packet.Data, 0));
                    break;

                case PacketType.Ack:
                case PacketType.AckLow:
                    LoggerRaw.ConditionalDebug("[O] Acking {1}: {0}", NetUtil.N2Hushort(packet.Data, 0), packet.PacketType);
                    break;

                case PacketType.Init1:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    initPacketCheck     = packet;
                    LoggerRaw.Debug("[O] InitID: {0}", packet.Data[4]);
                    LoggerRaw.Trace("[O] {0}", packet);
                    break;

                default: throw Util.UnhandledDefault(packet.PacketType);
                }

                ts3Crypt.Encrypt(packet);

                packet.FirstSendTime = Util.Now;
                SendRaw(packet);
            }
        }
Esempio n. 11
0
        private void AddOutgoingPacket(OutgoingPacket packet, PacketFlags flags = PacketFlags.None)
        {
            lock (sendLoopLock)
            {
                var ids = GetPacketCounter(packet.PacketType);
                if (ts3Crypt.CryptoInitComplete)
                {
                    IncPacketCounter(packet.PacketType);
                }

                packet.PacketId     = ids.Id;
                packet.GenerationId = ids.Generation;
                packet.ClientId     = ClientId;
                packet.PacketFlags |= flags;

                switch (packet.PacketType)
                {
                case PacketType.Voice:
                case PacketType.VoiceWhisper:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    NetUtil.H2N(packet.PacketId, packet.Data, 0);
                    break;

                case PacketType.Command:
                case PacketType.CommandLow:
                    packet.PacketFlags |= PacketFlags.Newprotocol;
                    packetAckManager.Add(packet.PacketId, packet);
                    break;

                case PacketType.Ping:
                    lastSentPingId      = packet.PacketId;
                    packet.PacketFlags |= PacketFlags.Unencrypted;

                    break;

                case PacketType.Pong:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    break;

                case PacketType.Ack:
                case PacketType.AckLow:
                    break;                     // Nothing to do

                case PacketType.Init1:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    packetAckManager.Add(packet.PacketId, packet);
                    break;

                default: throw Util.UnhandledDefault(packet.PacketType);
                }

#if DIAGNOSTICS && DIAG_RAWPKG
                if (packet.PacketType != PacketType.Ping && packet.PacketType != PacketType.Pong)
                {
                    Console.WriteLine($"[OT] {packet}");
                }
#endif

                ts3Crypt.Encrypt(packet);

                packet.FirstSendTime = Util.Now;
                SendRaw(packet);
            }
        }
Esempio n. 12
0
        internal byte[] ProcessInit1(byte[] data)
        {
            const int versionLen  = 4;
            const int initTypeLen = 1;

            if (data == null)
            {
                var sendData = new byte[versionLen + initTypeLen + 4 + 4 + 8];
                Array.Copy(Initversion, 0, sendData, 0, versionLen);           // initVersion
                sendData[versionLen] = 0x00;                                   // initType
                NetUtil.H2N(Util.UnixNow, sendData, versionLen + initTypeLen); // 4byte timestamp
                for (int i = 0; i < 4; i++)
                {
                    sendData[i + versionLen + initTypeLen + 4] = (byte)Util.Random.Next(0, 256);                                         // 4byte random
                }
                return(sendData);
            }

            if (data.Length < initTypeLen)
            {
                return(null);
            }
            int type = data[0];

            if (type == 1)
            {
                var sendData = new byte[versionLen + initTypeLen + 16 + 4];
                Array.Copy(Initversion, 0, sendData, 0, versionLen); // initVersion
                sendData[versionLen] = 0x02;                         // initType
                Array.Copy(data, 1, sendData, versionLen + initTypeLen, 20);
                return(sendData);
            }
            else if (type == 3)
            {
                byte[] alphaBytes = new byte[10];
                Util.Random.NextBytes(alphaBytes);
                var    alpha   = Convert.ToBase64String(alphaBytes);
                string initAdd = Ts3Command.BuildToString("clientinitiv",
                                                          new ICommandPart[] {
                    new CommandParameter("alpha", alpha),
                    new CommandParameter("omega", Identity.PublicKeyString),
                    new CommandParameter("ip", string.Empty)
                });
                var textBytes = Util.Encoder.GetBytes(initAdd);

                // Prepare solution
                int    level = NetUtil.N2Hint(data, initTypeLen + 128);
                byte[] y     = SolveRsaChallange(data, initTypeLen, level);

                // Copy bytes for this result: [Version..., InitType..., data..., y..., text...]
                var sendData = new byte[versionLen + initTypeLen + 232 + 64 + textBytes.Length];
                // Copy this.Version
                Array.Copy(Initversion, 0, sendData, 0, versionLen);
                // Write InitType
                sendData[versionLen] = 0x04;
                // Copy data
                Array.Copy(data, initTypeLen, sendData, versionLen + initTypeLen, 232);
                // Copy y
                Array.Copy(y, 0, sendData, versionLen + initTypeLen + 232 + (64 - y.Length), y.Length);
                // Copy text
                Array.Copy(textBytes, 0, sendData, versionLen + initTypeLen + 232 + 64, textBytes.Length);

                return(sendData);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 13
0
        private void NetworkLoop(object ctxObject)
        {
            var ctx = (ConnectionContext)ctxObject;

            while (true)
            {
                lock (statusLock)
                {
                    if (ctx.WasExit)
                    {
                        break;
                    }
                }

                var packet = packetHandler.FetchPacket();
                if (packet == null)
                {
                    break;
                }

                lock (statusLock)
                {
                    if (ctx.WasExit)
                    {
                        break;
                    }

                    switch (packet.PacketType)
                    {
                    case PacketType.Command:
                    case PacketType.CommandLow:
                        string message = Util.Encoder.GetString(packet.Data, 0, packet.Data.Length);
                        LogCmd.Debug("[I] {0}", message);
                        var result = msgProc.PushMessage(message);
                        if (result.HasValue)
                        {
                            dispatcher.Invoke(result.Value);
                        }
                        break;

                    case PacketType.Voice:
                    case PacketType.VoiceWhisper:
                        OutStream?.Write(packet.Data, new Meta
                        {
                            In = new MetaIn
                            {
                                Whisper = packet.PacketType == PacketType.VoiceWhisper
                            }
                        });
                        break;

                    case PacketType.Init1:
                        // Init error
                        if (packet.Data.Length == 5 && packet.Data[0] == 1)
                        {
                            var errorNum = NetUtil.N2Huint(packet.Data, 1);
                            if (Enum.IsDefined(typeof(Ts3ErrorCode), errorNum))
                            {
                                Log.Info("Got init error: {0}", (Ts3ErrorCode)errorNum);
                            }
                            else
                            {
                                Log.Warn("Got undefined init error: {0}", errorNum);
                            }
                            DisconnectInternal(ctx, setStatus: Ts3ClientStatus.Disconnected);
                        }
                        break;
                    }
                }
            }

            lock (statusLock)
            {
                DisconnectInternal(ctx, setStatus: Ts3ClientStatus.Disconnected);
            }
        }
Esempio n. 14
0
		public override void BuildHeader()
		{
			NetUtil.H2N(PacketId, Header, 0);
			Header[2] = PacketTypeFlagged;
		}