Exemplo n.º 1
0
        public async Task RunAsync(TcpClient client)
        {
            _client = client;
            var ipaddr = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();

            _client.ReceiveTimeout = 1000;

            var seedArr = new byte[4];

            new Random().NextBytes(seedArr);
            _mseed = seedArr;

            _clientStream = _client.GetStream();
            _reader       = new AsyncBinaryReader(_clientStream);
            _writer       = new BinaryWriter(_clientStream);
            _status       = AuthStatus.UNAUTHED;

            Debug.WriteLine("Connection from " + ipaddr);

            SendAuthChallenge();

            while (_run)
            {
                var lb1 = _ac.decrypt((await _reader.ReadBytesAsync(1)))[0];
                var lb2 = _ac.decrypt((await _reader.ReadBytesAsync(1)))[0];
                var len = (lb1 << 8) + lb2;
                Debug.WriteLine(lb1 + "|" + lb2 + " ->| " + len);
                var wp = new WorldPacket(await _reader.ReadBytesAsync(len), this);
                Debug.WriteLine("INCOMING COM:" + wp.cmd + " SIZE:" + len);
                switch (wp.cmd)
                {
                case WorldCommand.CMSG_AUTH_SESSION:
                    await HandleAuthSession(wp);

                    break;

                case WorldCommand.CMSG_PING:
                    if (_status != AuthStatus.AUTHED)    //Should not be pinging if not authed
                    {
                        Close();
                    }
                    else
                    {
                        HandlePing(wp);
                    }
                    break;

                default:
                    if (_session == null || _status == AuthStatus.UNAUTHED)    //Should not be sending anything else right now. Should also be authed by now
                    {
                        Close();
                    }
                    else
                    {
                        _session.HandlePacket(wp);
                    }
                    break;
                }
            }
        }
Exemplo n.º 2
0
        public async Task HandleLogonProofAsync()
        {
            var clientPublicKey = await _reader.ReadBytesAsync(32);

            var clientProof = await _reader.ReadBytesAsync(20);

            var crc = await _reader.ReadBytesAsync(20);

            var keyCount = await _reader.ReadUInt8Async();

            var securityFlags = await _reader.ReadUInt8Async();

            var authStatus = _authentication.Authenticate(
                clientPublicKey.Span, clientProof.Span);

            if (!authStatus)
            {
                await _writer.FailProofAsync(AuthStatus.IncorrectPassword);

                return;
            }

            // TODO: check build number and send back appropriate packet
            // (assuming WotLK right now, 3.3.5a, build 12340)
            await _writer.PassProofAsync(
                _authentication.ComputeProof(),
                0, 0);
        }
Exemplo n.º 3
0
        private async Task DrainReceivingContexts(AsyncBinaryReader binaryReader)
        {
            while (!(this.receivingContexts.IsEmpty && this.requestQueue.Count == 0))
            {
                byte[] frameHeaderBytes = await binaryReader.ReadBytesAsync(20).ConfigureAwait(false);

                if (frameHeaderBytes.Length < 20)
                {
                    throw new IOException("Socket closed during reading.");
                }

                var frameHeader = FrameHeader.Parse(frameHeaderBytes);
                if (frameHeader.ContentOffset != 20)
                {
                    this.logger.LogCritical(
                        "Invalid frame header with unexpected content offset, expected=20 actual={0}",
                        frameHeader.ContentOffset);
                    throw new InvalidDataException("Invalid frame header");
                }

                if (frameHeader.Version != 1)
                {
                    this.logger.LogWarning(
                        "Invalid frame header with unexpected version {0}",
                        frameHeader.Version);
                    throw new InvalidDataException("Invalid frame header");
                }

                byte[] framePayloadBytes = await binaryReader
                                           .ReadBytesAsync(frameHeader.ContentLength)
                                           .ConfigureAwait(false);

                if (framePayloadBytes.Length < frameHeader.ContentLength)
                {
                    throw new IOException("Socket closed during reading.");
                }

                if (this.logger.IsEnabled(LogLevel.Debug))
                {
                    var buffer = new byte[frameHeaderBytes.Length + framePayloadBytes.Length];
                    Buffer.BlockCopy(frameHeaderBytes, 0, buffer, 0, frameHeaderBytes.Length);
                    Buffer.BlockCopy(framePayloadBytes, 0, buffer, frameHeaderBytes.Length, framePayloadBytes.Length);

                    this.logger.LogDebug(
                        "Received streamId={0}:" + Environment.NewLine + "{1}",
                        frameHeader.StreamId,
                        HexUtils.Dump(buffer.AsMemory()));
                }

                if (this.receivingContexts.TryRemove((int)frameHeader.StreamId, out RequestContext requestContext))
                {
                    this.Process(requestContext, frameHeader, framePayloadBytes);
                }
                else
                {
                    this.logger.LogWarning("Dropped a frame with unexpected streamId {0}", frameHeader.StreamId);
                }
            }
        }
Exemplo n.º 4
0
        async Task <TResponse> AsyncCallAsync <TRequest, TResponse>(
            Method <TRequest, TResponse> method, TRequest request)
        {
            await pipeLock.WaitAsync();

            PipePair pipePair;

            availablePipePairs.TryTake(out pipePair);
            Debug.Assert(pipePair != null);
            try
            {
                var writer = new AsyncBinaryWriter(pipePair.OutPipe);
                var reader = new AsyncBinaryReader(pipePair.InPipe);

                // Send the RPC name.
                await writer.WriteAsync(method.FullName.Length);

                await writer.WriteAsync(Encoding.ASCII.GetBytes(method.FullName));

                // Send the request.
                using (var serializationContext = new SimpleSerializationContext())
                {
                    method.RequestMarshaller.ContextualSerializer(request, serializationContext);
                    byte[] requestBytes = serializationContext.GetPayload();
                    await writer.WriteAsync(requestBytes.Length);

                    await writer.WriteAsync(requestBytes);
                }

                // Read the response.
                int size = await reader.ReadInt32Async();

                byte[] responseBytes = await reader.ReadBytesAsync(size);

                var deserializationContext = new SimpleDeserializationContext(responseBytes);
                return(method.ResponseMarshaller.ContextualDeserializer(deserializationContext));
            }
            // Unfortunately, RpcExceptions can't be nested with InnerException.
            catch (EndOfStreamException e)
            {
                throw new RpcException(new Status(StatusCode.Unknown, e.ToString()),
                                       "Connection to server lost. Did it shut down?");
            }
            catch (Exception e) when(!(e is RpcException))
            {
                throw new RpcException(new Status(StatusCode.Unknown, e.ToString()),
                                       "Unknown failure: " + e);
            }
            finally
            {
                availablePipePairs.Add(pipePair);
                pipeLock.Release();
            }
        }
Exemplo n.º 5
0
        public async Task When_reading_bytes_from_a_stream_that_is_too_short()
        {
            var sut = new AsyncBinaryReader(new TestStream(
                0, 1, 2, 3, 4, 5
            ));

            await Assert.ThrowsAsync<EndOfStreamException>(async () =>
            {
                await sut.ReadBytesAsync(10, CancellationToken.None);
            });
        }
Exemplo n.º 6
0
        public async Task When_reading_bytes()
        {
            var sut = new AsyncBinaryReader(new TestStream(
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9
            ));

            var ba = await sut.ReadBytesAsync(10, CancellationToken.None);
            Assert.Equal(10, ba.Length);
            for (var i = 0; i < 10; i++)
                Assert.Equal(i, ba[i]);
        }
Exemplo n.º 7
0
        public async Task When_reading_negative_amounts_of_bytes()
        {
            var sut = new AsyncBinaryReader(new TestStream(
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9
            ));


            await Assert.ThrowsAsync<ArgumentOutOfRangeException>(async () =>
            {
                await sut.ReadBytesAsync(-1, CancellationToken.None);
            });
        }
Exemplo n.º 8
0
        public static async Task<ISymbolMetadata> TryOpenAsync(Stream stream, CancellationToken cancellationToken)
        {
            using (var reader = new AsyncBinaryReader(stream))
            {
                try
                {
                    var IMAGE_DOS_HEADER_e_magic = await reader.ReadBytesAsync(_mzHeader.Length, cancellationToken);
                    if (!NativeMethods.MemoryEquals(IMAGE_DOS_HEADER_e_magic, _mzHeader)) return null;

                    stream.Position = 60;
                    var IMAGE_DOS_HEADER_e_lfanew = await reader.ReadUInt32Async(cancellationToken);

                    stream.Position = IMAGE_DOS_HEADER_e_lfanew;
                    var PE_Signature = await reader.ReadBytesAsync(_peHeader.Length, cancellationToken);
                    if (!NativeMethods.MemoryEquals(PE_Signature, _peHeader)) return null;

                    stream.Position = IMAGE_DOS_HEADER_e_lfanew + 4;
                    var IMAGE_FILE_HEADER_Machine = await reader.ReadUInt16Async(cancellationToken);

                    if (IMAGE_FILE_HEADER_Machine != 0x014c &&
                        IMAGE_FILE_HEADER_Machine != 0x0200 &&
                        IMAGE_FILE_HEADER_Machine != 0x8664)
                        return null;

                    stream.Position = IMAGE_DOS_HEADER_e_lfanew + 8;
                    var IMAGE_FILE_HEADER_TimeDateStamp = await reader.ReadUInt32Async(cancellationToken);

                    stream.Position = IMAGE_DOS_HEADER_e_lfanew + 24;
                    var IMAGE_OPTIONAL_HEADER_Magic = await reader.ReadUInt16Async(cancellationToken);

                    if (IMAGE_OPTIONAL_HEADER_Magic != 0x10b &&
                        IMAGE_OPTIONAL_HEADER_Magic != 0x20b)
                        return null;

                    stream.Position = IMAGE_DOS_HEADER_e_lfanew + 80;
                    var IMAGE_OPTIONAL_HEADER_SizeOfImage = await reader.ReadUInt16Async(cancellationToken);

                    return new MZMetadata(string.Format(
                        CultureInfo.InvariantCulture,
                        "{0:X8}{1:x4}",
                        IMAGE_FILE_HEADER_TimeDateStamp,
                        IMAGE_OPTIONAL_HEADER_SizeOfImage));
                }
                catch
                {
                    return null;
                }
            }
        }
Exemplo n.º 9
0
        public async Task <UdpReceiveResult> ReceiveAsync()
        {
            // +------+----------+----------+--------+---------+----------+
            // | ATYP | DST.ADDR | DST.PORT | Length |  CRLF   | Payload  |
            // +------+----------+----------+--------+---------+----------+
            // |  1   | Variable |    2     |   2    | X'0D0A' | Variable |
            // +------+----------+----------+--------+---------+----------+

            var addressType = (AddressType)await _udpReader.ReadByteAsync();

            if (addressType == AddressType.Domain)
            {
                throw new NotSupportedException();
            }

            var address       = new IPAddress(await _udpReader.ReadBytesAsync(addressType == AddressType.IPv4 ? 4 : 16));
            var port          = IPAddress.NetworkToHostOrder(await _udpReader.ReadInt16Async());
            var payloadLength = IPAddress.NetworkToHostOrder(await _udpReader.ReadInt16Async());
            await _udpReader.ReadInt16Async(); // skip the CRLF

            var payload = await _udpReader.ReadBytesAsync(payloadLength);

            return(new UdpReceiveResult(payload, new IPEndPoint(address, port)));
        }
Exemplo n.º 10
0
        private static async Task <TcpClient> StartPlcAsync(ILogger logger, string hostname, int port)
        {
            var fakePlc = new TcpClient(hostname, port);

            logger.LogInformation("Fake PLC connected.");

            NetworkStream networkStream = fakePlc.GetStream();

            using var reader = new AsyncBinaryReader(networkStream, Encoding.ASCII, true);
            using var writer = new AsyncBinaryWriter(networkStream, Encoding.ASCII, true);

            logger.LogDebug("Receiving TestRequest frame...");
            byte[] receivedBytes = await reader.ReadBytesAsync(0x53).ConfigureAwait(false);

            logger.LogInformation("Received {0} bytes.", 0x53);

            byte[] sendingPayload = new UnifiedFrameContent
            {
                Header = new Header {
                    Status = 0
                },
                Payload = new TestResponse
                {
                    A = 42,
                    B = 3.1415926F,
                    C = "Hello World!",
                    D = Timestamp.FromDateTimeOffset(DateTimeOffset.Parse("2019-10-29T21:42:13.00000+8:00", CultureInfo.InvariantCulture)),
                }.ToByteString(),
            }.ToByteArray();
            var sendingHeader = new FrameHeader(
                version: 1,
                type: 2,
                sequenceNumber: 0,
                streamId: 1,
                contentOffset: 20,
                contentLength: (ushort)sendingPayload.Length,
                contentChecksum: Crc32C.Crc32CAlgorithm.Compute(sendingPayload));

            logger.LogDebug("Sending TestResponse frame header...");
            await sendingHeader.WriteTo(writer).ConfigureAwait(false);

            logger.LogDebug("Sending TestResponse frame body...");
            await writer.WriteAsync(sendingPayload).ConfigureAwait(false);

            logger.LogInformation("Sent TestResponse.");

            return(fakePlc);
        }
Exemplo n.º 11
0
        public async Task HandleLogonProofAsync()
        {
            var clientPublicKey = await _reader.ReadBytesAsync(32);

            var clientProof = await _reader.ReadBytesAsync(20);

            var crc = await _reader.ReadBytesAsync(20);

            var keyCount = await _reader.ReadUInt8Async();

            var securityFlags = await _reader.ReadUInt8Async();

            if (!_authentication.Authenticate(clientPublicKey, clientProof))
            {
                await SendErrorAsync(AuthStatus.IncorrectPassword);

                return;
            }

            //print sessionkey

            var proof = _authentication.ComputeProof();

            _info.sessionkey = _authentication._K.ToString("x");
            _info.s          = _authentication._s.ToString("x");
            _info.v          = _authentication._v.ToString("x");
            Program.authDatabase.Accounts.Update(_info);
            Program.authDatabase.SaveChanges();

            Debug.WriteLine(_info.sessionkey);
            // TODO: check build number and send back appropriate packet
            // (assuming WotLK right now, 3.3.5a, build 12340)

            List <byte> data = new List <byte>();

            data.Add((byte)_currentCommand);              // cmd
            data.Add(0);                                  // error
            data.AddRange(proof);                         // server proof
            data.AddRange(Enumerable.Repeat((byte)0, 4)); //accountFlags
            data.AddRange(Enumerable.Repeat((byte)0, 4)); //surveyId
            data.AddRange(Enumerable.Repeat((byte)0, 2)); //unkFlags
            await _clientStream.WriteAsync(data.ToArray(), 0, data.Count);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Asynchronously reads a bit set from the specified reader.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// A <see cref="Task{Pdb20BitSet}"/> that represents the asynchronous read operation.
        /// </returns>
        public static async Task<Pdb70BitSet> ReadAsync(AsyncBinaryReader reader, CancellationToken cancellationToken)
        {
            var result = new Pdb70BitSet(await reader.ReadInt32Async(cancellationToken));
            if (result.Words.Length != 0)
            {
                var bytes = await reader.ReadBytesAsync(result.Words.Length * sizeof(int), cancellationToken);
                Buffer.BlockCopy(bytes, 0, result.Words, 0, bytes.Length);
            }

            return result;
        }
Exemplo n.º 13
0
 private Task <byte[]> ReadChunk(AsyncBinaryReader reader)
 {
     return(reader.ReadBytesAsync(ChunkSize, cancellationToken));
 }
Exemplo n.º 14
0
        /// <summary>
        /// Securely exchanges a secret key
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="ecParams">ECDSA public / private keypair used for signing</param>
        /// <returns>A tuple containing a 256 bit hashed secret key, and the fingerprint of the remote</returns>
        /// <exception cref="CryptographicException"></exception>
        /// <exception cref="InvalidDataException">Thrown when the remote sends invalid data</exception>
        public static async Task <(byte[], ECPoint)> ExchangeKeyAsync(this WsStream stream, ECParameters ecParams)
        {
            if (ecParams.D is null)
            {
                throw new CryptographicException("Private key must be provided");
            }
            ECDsa ecDsa = ECDsa.Create(ecParams);
            // TODO: Harden security (prevent abuse, double check everything)
            // host authentication
            var pubBytes = ecDsa.ExportSubjectPublicKeyInfo();

            // key exchange
            var ecdh       = ECDiffieHellman.Create();
            var kePubBytes = ecdh.ExportSubjectPublicKeyInfo();

            // sign ecdh key to authenticate
            var signed = ecDsa.SignData(kePubBytes, HashAlgorithmName.SHA256);

            var bw = new AsyncBinaryWriter(stream);
            var br = new AsyncBinaryReader(stream);
            //1
            await bw.WriteAsync(pubBytes.Length);

            await bw.WriteAsync(pubBytes);

            //2
            await bw.WriteAsync(signed.Length);

            await bw.WriteAsync(signed);

            //3
            await bw.WriteAsync(kePubBytes.Length);

            await bw.WriteAsync(kePubBytes);

            // read remote public key and verify signature
            //1
            var remotePubKey   = ECDsa.Create();
            var remotePubBytes = await br.ReadBytesAsync(await br.ReadAssertAsync(120));

            remotePubKey.ImportSubjectPublicKeyInfo(remotePubBytes, out _);
            //2
            var remoteSignature = await br.ReadBytesAsync(await br.ReadAssertAsync(96));

            //3
            var remoteKePub = await br.ReadBytesAsync(await br.ReadAssertAsync(158));

            var remoteEcdh = ECDiffieHellman.Create();

            remoteEcdh.ImportSubjectPublicKeyInfo(remoteKePub, out _);

            // verify signed public key exchange key
            if (!remotePubKey.VerifyData(remoteKePub, remoteSignature, HashAlgorithmName.SHA256))
            {
                throw new CryptographicException("Remote public key does not match hash!");
            }
            // derive shared secret
            var sharedSecret = ecdh.DeriveKeyMaterial(remoteEcdh.PublicKey);

            // return the public key (fingerprint) of the remote, and the hashed shared secret
            return(SHA256.HashData(sharedSecret), remotePubKey.ExportParameters(false).Q);
        }