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(); }
internal static string GetUidFromPublicKey(string publicKey) { var publicKeyBytes = Encoding.ASCII.GetBytes(publicKey); var hashBytes = Ts3Crypt.Hash1It(publicKeyBytes); return(Convert.ToBase64String(hashBytes)); }
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); }
/// <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); }
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 }; }
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; }
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; }
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) { } }
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); }
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); } } }
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); } } }
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); } } }
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);