private void ProcessInitIvExpand2(InitIvExpand2 initIvExpand2)
        {
            packetHandler.ReceivedFinalInitAck();

            packetHandler.IncPacketCounter(PacketType.Command);

            var(publicKey, privateKey) = Ts3Crypt.GenerateTemporaryKey();

            var ekBase64 = Convert.ToBase64String(publicKey);
            var toSign   = new byte[86];

            Array.Copy(publicKey, 0, toSign, 0, 32);
            var beta = Convert.FromBase64String(initIvExpand2.Beta);

            Array.Copy(beta, 0, toSign, 32, 54);
            var sign  = Ts3Crypt.Sign(connectionDataFull.Identity.PrivateKey, toSign);
            var proof = Convert.ToBase64String(sign);

            ClientEk(ekBase64, proof);

            var result = ts3Crypt.CryptoInit2(initIvExpand2.License, initIvExpand2.Omega, initIvExpand2.Proof, initIvExpand2.Beta, privateKey);

            if (!result)
            {
                DisconnectInternal(context, Util.CustomError($@"Failed to calculate shared secret: {result.Error}"));
                return;
            }

            packetHandler.CryptoInitDone();

            DefaultClientInit();
        }
Exemple #2
0
        internal static string GetUidFromPublicKey(string publicKey)
        {
            var publicKeyBytes = Encoding.ASCII.GetBytes(publicKey);
            var hashBytes      = Ts3Crypt.Hash1It(publicKeyBytes);

            return(Convert.ToBase64String(hashBytes));
        }
Exemple #3
0
 public Ts3Server()
 {
     ts3Crypt          = new Ts3Crypt();
     ts3Crypt.Identity = Ts3Crypt.GenerateNewIdentity(0);
     packetHandler     = new PacketHandler <C2S, S2C>(ts3Crypt);
     msgProc           = new AsyncMessageProcessor(MessageHelper.GetToServerNotificationType);
     dispatcher        = EventDispatcherHelper.Create(EventDispatchType.AutoThreadPooled);
 }
Exemple #4
0
 /// <summary>Creates a new client. A client can manage one connection to a server.</summary>
 /// <param name="dispatcherType">The message processing method for incomming notifications.
 /// See <see cref="EventDispatchType"/> for further information about each type.</param>
 public Ts3FullClient(EventDispatchType dispatcherType)
 {
     status        = Ts3ClientStatus.Disconnected;
     ts3Crypt      = new Ts3Crypt();
     packetHandler = new PacketHandler(ts3Crypt);
     msgProc       = new MessageProcessor(false);
     dispatcher    = EventDispatcherHelper.Create(dispatcherType);
     wasExit       = true;
 }
        public static bool IsUidValid(string uid)
        {
            if (uid == "anonymous" || uid == "serveradmin")
            {
                return(true);
            }
            var result = Ts3Crypt.Base64Decode(uid);

            return(result.Ok && result.Value.Length == 20);
        }
Exemple #6
0
		public static R<(LicenseBlock block, int read), string> Parse(ReadOnlySpan<byte> data)
		{
			if (data.Length < MinBlockLen)
			{
				return "License too short";
			}
			if (data[0] != 0)
			{
				return $"Wrong key kind {data[0]} in license";
			}

			LicenseBlock block;
			int read;
			switch (data[33])
			{
			case 0:
				var result = ReadNullString(data.Slice(46));
				if (!result.Ok) return result.Error;
				var nullStr = result.Value;
				block = new IntermediateLicenseBlock { Issuer = nullStr.str };
				read = 5 + nullStr.read;
				break;

			case 2:
				if (!Enum.IsDefined(typeof(ServerLicenseType), data[42]))
					return $"Unknown license type {data[42]}";
				result = ReadNullString(data.Slice(47));
				if (!result.Ok) return result.Error;
				nullStr = result.Value;
				block = new ServerLicenseBlock { Issuer = result.Value.str, LicenseType = (ServerLicenseType)data[42] };
				read = 6 + nullStr.read;
				break;

			case 32:
				block = new EphemeralLicenseBlock();
				read = 0;
				break;

			default:
				return $"Invalid license block type {data[33]}";
			}

			block.NotValidBefore = Util.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(34)) + 0x50e22700uL);
			block.NotValidAfter = Util.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(38)) + 0x50e22700uL);
			if (block.NotValidAfter < block.NotValidBefore)
				return "License times are invalid";

			block.Key = data.Slice(1, 32).ToArray();

			var allLen = MinBlockLen + read;
			var hash = Ts3Crypt.Hash512It(data.Slice(1, allLen - 1).ToArray());
			block.Hash = hash.AsSpan(0, 32).ToArray();

			return (block, allLen);
		}
 /// <summary>Creates a new client. A client can manage one connection to a server.</summary>
 /// <param name="dispatcherType">The message processing method for incomming notifications.
 /// See <see cref="EventDispatchType"/> for further information about each type.</param>
 public Ts3FullClient(EventDispatchType dispatcherType)
 {
     status        = Ts3ClientStatus.Disconnected;
     ts3Crypt      = new Ts3Crypt();
     packetHandler = new PacketHandler(ts3Crypt);
     msgProc       = new AsyncMessageProcessor();
     dispatcher    = EventDispatcherHelper.Create(dispatcherType);
     context       = new ConnectionContext {
         WasExit = true
     };
 }
Exemple #8
0
        public PacketHandler(Ts3Crypt ts3Crypt)
        {
            packetAckManager  = new Dictionary <ushort, OutgoingPacket>();
            packetPingManager = new Dictionary <ushort, OutgoingPacket>();
            receiveQueue      = new RingQueue <IncomingPacket>(PacketBufferSize);
            receiveQueueLow   = new RingQueue <IncomingPacket>(PacketBufferSize);
            NetworkStats      = new NetworkStats();

            packetCounter  = new ushort[9];
            this.ts3Crypt  = ts3Crypt;
            resendThreadId = -1;
        }
        public PacketHandler(Ts3Crypt ts3Crypt)
        {
            packetAckManager = new Dictionary <ushort, C2SPacket>();
            receiveQueue     = new RingQueue <S2CPacket>(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueLow  = new RingQueue <S2CPacket>(ReceivePacketWindowSize, ushort.MaxValue + 1);
            NetworkStats     = new NetworkStats();

            packetCounter     = new ushort[9];
            generationCounter = new uint[9];
            this.ts3Crypt     = ts3Crypt;
            resendThreadId    = -1;
        }
Exemple #10
0
        public PacketHandler(Ts3Crypt ts3Crypt, Id id)
        {
            receiveQueueCommand       = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueCommandLow    = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveWindowVoice        = new GenerationWindow(ushort.MaxValue + 1);
            receiveWindowVoiceWhisper = new GenerationWindow(ushort.MaxValue + 1);

            NetworkStats = new NetworkStats();

            packetCounter     = new ushort[Ts3Crypt.PacketTypeKinds];
            generationCounter = new uint[Ts3Crypt.PacketTypeKinds];
            this.ts3Crypt     = ts3Crypt;
            this.id           = id;
        }
Exemple #11
0
        public PacketHandler(Ts3Crypt ts3Crypt)
        {
            Util.Init(out packetAckManager);
            receiveQueueCommand       = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueCommandLow    = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveWindowVoice        = new GenerationWindow(ushort.MaxValue + 1);
            receiveWindowVoiceWhisper = new GenerationWindow(ushort.MaxValue + 1);

            NetworkStats = new NetworkStats();

            packetCounter     = new ushort[Ts3Crypt.PacketTypeKinds];
            generationCounter = new uint[Ts3Crypt.PacketTypeKinds];
            this.ts3Crypt     = ts3Crypt;
            resendThreadId    = -1;
        }
        private void ProcessInitIvExpand(InitIvExpand initIvExpand)
        {
            var password = connectionDataFull.IsPasswordHashed
                                ? connectionDataFull.Password
                                : Ts3Crypt.HashPassword(connectionDataFull.Password);

            ts3Crypt.CryptoInit(initIvExpand.Alpha, initIvExpand.Beta, initIvExpand.Omega);
            packetHandler.CryptoInitDone();
            ClientInit(
                connectionDataFull.Username,
                true, true,
                string.Empty, string.Empty, password,
                string.Empty, string.Empty, string.Empty, "123,456",
                VersionSign);
        }
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When some required values are not set or invalid.</exception>
        /// <exception cref="Ts3Exception">When the connection could not be established.</exception>
        public override void Connect(ConnectionData conData)
        {
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} derivative to connect with the full client.", nameof(conData));
            }
            if (conDataFull.Identity is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }
            connectionDataFull = conDataFull;
            ConnectionData     = conData;

            Disconnect();

            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new Ts3Exception("Could not read or resolve address.");
            }

            lock (statusLock)
            {
                returnCode = 0;
                status     = Ts3ClientStatus.Connecting;

                VersionSign       = conDataFull.VersionSign;
                ts3Crypt          = new Ts3Crypt();
                ts3Crypt.Identity = conDataFull.Identity;

                var ctx = new ConnectionContext {
                    WasExit = false
                };
                context = ctx;

                packetHandler             = new PacketHandler <S2C, C2S>(ts3Crypt, conData.LogId);
                packetHandler.PacketEvent = (ref Packet <S2C> packet) => { PacketEvent(ctx, ref packet); };
                packetHandler.StopEvent   = (closeReason) => { ctx.ExitReason = closeReason; DisconnectInternal(ctx, setStatus: Ts3ClientStatus.Disconnected); };
                packetHandler.Connect(remoteAddress);
                dispatcher = new ExtraThreadEventDispatcher();
                dispatcher.Init(InvokeEvent, conData.LogId);
            }
        }
        private void ProcessInitIvExpand(InitIvExpand initIvExpand)
        {
            var password = connectionDataFull.IsPasswordHashed
                                ? connectionDataFull.Password
                                : Ts3Crypt.HashPassword(connectionDataFull.Password);

            ts3Crypt.CryptoInit(initIvExpand.Alpha, initIvExpand.Beta, initIvExpand.Omega);
            packetHandler.CryptoInitDone();
            try
            {
                ClientInit(
                    connectionDataFull.Username,
                    true, true,
                    connectionDataFull.DefaultChannel,
                    Ts3Crypt.HashPassword(connectionDataFull.DefaultChannelPassword),
                    password, string.Empty, string.Empty, string.Empty,
                    connectionDataFull.HWID, VersionSign);
            }
            catch (Ts3CommandException) { }
        }
Exemple #15
0
        private void ProcessInitIvExpand2(InitIvExpand2 initIvExpand2)
        {
            DisconnectInternal(context, Util.CustomError("Cannot connect to server 3.1 yet."));
            return;

            var password = connectionDataFull.IsPasswordHashed
                                ? connectionDataFull.Password
                                : Ts3Crypt.HashPassword(connectionDataFull.Password);

            packetHandler.IncPacketCounter(PacketType.Command);

            /*
             * ts3Crypt.GenerateTemporaryKey();
             *
             * // EK SIGN
             * var buffer = new byte[32];
             * Util.Random.NextBytes(buffer);
             * var ek = Convert.ToBase64String(Ed25519.EncodePoint(
             *      ts3Crypt.publicTmp.AffineXCoord.ToBigInteger().ToNetBi(),
             *      ts3Crypt.publicTmp.AffineYCoord.ToBigInteger().ToNetBi()));
             *
             * var toSign = new byte[86];
             * Array.Copy(buffer, 0, toSign, 0, 32);
             * var beta = Convert.FromBase64String(initIvExpand2.Beta);
             * Array.Copy(beta, 0, toSign, 32, 54);
             * var sign = Ts3Crypt.Sign(connectionDataFull.Identity.PrivateKey, toSign);
             * var proof = Convert.ToBase64String(sign);
             * ClientEk(ek, proof);
             * // END EK SIGN
             */
            ts3Crypt.CryptoInit2(initIvExpand2.License, initIvExpand2.Omega, initIvExpand2.Proof);             //  TODO ???
            packetHandler.CryptoInitDone();

            ClientInit(
                connectionDataFull.Username,
                true, true,
                connectionDataFull.DefaultChannel,
                Ts3Crypt.HashPassword(connectionDataFull.DefaultChannelPassword),
                password, string.Empty, string.Empty, string.Empty,
                "123,456", VersionSign);
        }
Exemple #16
0
        public IncomingPacket 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)
                {
                    ColorDbg.WritePkgRaw(buffer, "DROPPING");
                    continue;
                }

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

                NetworkStats.LogInPacket(packet);

                ColorDbg.WritePkgIn(packet);

                switch (packet.PacketType)
                {
                case PacketType.Voice: break;

                case PacketType.VoiceWhisper: break;

                case PacketType.Command: packet = ReceiveCommand(packet, receiveQueue, PacketType.Ack); break;

                case PacketType.CommandLow: packet = ReceiveCommand(packet, receiveQueueLow, PacketType.AckLow); break;

                case PacketType.Ping: ReceivePing(packet); break;

                case PacketType.Pong: ReceivePong(packet); break;

                case PacketType.Ack: packet = ReceiveAck(packet); break;

                case PacketType.AckLow: break;

                case PacketType.Init1: ReceiveInitAck(); break;

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

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
Exemple #17
0
        public IncomingPacket FetchPacket()
        {
            while (true)
            {
                if (Closed)
                {
                    return(null);
                }

                IncomingPacket packet = null;
                if (TryFetchPacket(receiveQueue, out 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);
                if (IsCommandPacketSet(packet))
                {
                    continue;
                }

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

                NetworkStats.LogInPacket(packet);

                switch (packet.PacketType)
                {
                case PacketType.Voice: break;

                case PacketType.VoiceWhisper: break;

                case PacketType.Command: packet = ReceiveCommand(packet); break;

                case PacketType.CommandLow: packet = ReceiveCommand(packet); break;

                case PacketType.Ping: ReceivePing(packet); break;

                case PacketType.Pong: ReceivePong(packet); break;

                case PacketType.Ack: packet = ReceiveAck(packet); break;

                case PacketType.AckLow: break;

                case PacketType.Init1: ReceiveInitAck(); break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
Exemple #18
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); }
                catch (ObjectDisposedException) { return(null); }

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

                packet = Ts3Crypt.GetS2CPacket(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.Trace("[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.Trace("[I] Ping {0}", packet.PacketId);
                    ReceivePing(packet);
                    break;

                case PacketType.Pong:
                    LoggerRaw.Trace("[I] Pong {0}", BinaryPrimitives.ReadUInt16BigEndian(packet.Data));
                    ReceivePong(packet);
                    break;

                case PacketType.Ack:
                    LoggerRaw.Debug("[I] Acking: {0}", BinaryPrimitives.ReadUInt16BigEndian(packet.Data));
                    packet = ReceiveAck(packet);
                    break;

                case PacketType.AckLow: break;

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

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

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
Exemple #19
0
 public IdentityData(BigInteger privateKey, ECPoint publicKey = null)
 {
     PrivateKey = privateKey ?? throw new ArgumentNullException(nameof(privateKey));
     PublicKey  = publicKey ?? Ts3Crypt.RestorePublicFromPrivateKey(privateKey);
 }
 public bool CheckValid() => Ts3Crypt.EdCheck(this);