예제 #1
0
        protected void HandleConnectAccept(IPEndPoint address, BitStream stream)
        {
            var nonce       = new Nonce();
            var serverNonce = new Nonce();

            nonce.Read(stream);
            serverNonce.Read(stream);

            var decryptPos = stream.GetBytePosition();

            stream.SetBytePosition(decryptPos);

            var conn = FindPendingConnection(address);

            if (conn == null || conn.ConnectionState != NetConnectionState.AwaitingConnectResponse)
            {
                return;
            }

            var cParams = conn.GetConnectionParameters();

            if (cParams.Nonce != nonce || cParams.ServerNonce != serverNonce)
            {
                return;
            }

            if (cParams.UsingCrypto)
            {
                var theCipher = new SymmetricCipher(cParams.SharedSecret);

                if (!stream.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, decryptPos, theCipher))
                {
                    return;
                }
            }

            stream.Read(out uint recvSequence);
            conn.SetInitialRecvSequence(recvSequence);

            string errorString = null;

            if (!conn.ReadConnectAccept(stream, ref errorString))
            {
                RemovePendingConnection(conn);
                return;
            }

            if (cParams.UsingCrypto)
            {
                stream.Read(SymmetricCipher.KeySize, cParams.InitVector);

                conn.SetSymmetricCipher(new SymmetricCipher(cParams.SymmetricKey, cParams.InitVector));
            }

            AddConnection(conn);
            RemovePendingConnection(conn);

            conn.ConnectionState = NetConnectionState.Connected;
            conn.OnConnectionEstablished();
        }
예제 #2
0
        protected void HandleConnectChallengeRequest(IPEndPoint addr, BitStream stream)
        {
            if (!AllowConnections)
            {
                return;
            }

            var clientNonce = new Nonce();

            clientNonce.Read(stream);

            var wantsKeyExchange = stream.ReadFlag();
            var wantsCertificate = stream.ReadFlag();

            SendConnectChallengeResponse(addr, clientNonce, wantsKeyExchange, wantsCertificate);
        }
예제 #3
0
        protected void HandleDisconnect(IPEndPoint client, BitStream reader)
        {
            var conn = FindConnection(client);

            if (conn == null)
            {
                return;
            }

            var cParams = conn.GetConnectionParameters();

            var nonce = new Nonce();

            nonce.Read(reader);

            var serverNonce = new Nonce();

            serverNonce.Read(reader);

            if (nonce != cParams.Nonce || serverNonce != cParams.ServerNonce)
            {
                return;
            }

            var decryptPos = reader.GetBytePosition();

            reader.SetBytePosition(decryptPos);

            if (cParams.UsingCrypto)
            {
                var theCipher = new SymmetricCipher(cParams.SharedSecret);

                if (!reader.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, decryptPos, theCipher))
                {
                    return;
                }
            }

            reader.ReadString(out string reason);

            conn.ConnectionState = NetConnectionState.Disconnected;
            conn.OnConnectionTerminated(TerminationReason.ReasonRemoteDisconnectPacket, reason);

            RemoveConnection(conn);
        }
예제 #4
0
        protected void HandleConnectReject(IPEndPoint address, BitStream stream)
        {
            var nonce       = new Nonce();
            var serverNonce = new Nonce();

            nonce.Read(stream);
            serverNonce.Read(stream);

            var conn = FindPendingConnection(address);

            if (conn == null || (conn.ConnectionState != NetConnectionState.AwaitingChallengeResponse && conn.ConnectionState != NetConnectionState.AwaitingConnectResponse))
            {
                return;
            }

            var cParams = conn.GetConnectionParameters();

            if (cParams.Nonce != nonce || cParams.ServerNonce != serverNonce)
            {
                return;
            }

            stream.ReadString(out string reason);

            if (reason == "Puzzle")
            {
                cParams.PuzzleRetried = true;

                conn.ConnectionState  = NetConnectionState.AwaitingChallengeResponse;
                conn.ConnectSendCount = 0;

                cParams.Nonce.GetRandom();

                SendConnectChallengeRequest(conn);

                return;
            }

            conn.ConnectionState = NetConnectionState.ConnectRejected;
            conn.OnConnectTerminated(TerminationReason.ReasonRemoteHostRejectedConnection, reason);

            RemovePendingConnection(conn);
        }
예제 #5
0
        protected void HandlePunch(IPEndPoint address, BitStream stream)
        {
            var firstNonce = new Nonce();

            firstNonce.Read(stream);

            Console.WriteLine("Received punch packet from {0} - {1}", address, Convert.ToBase64String(firstNonce.Data));

            var           found = false;
            NetConnection conn  = null;

            foreach (var pair in PendingConnections)
            {
                conn = pair.Value;
                var cParams = conn.GetConnectionParameters();

                if (conn.ConnectionState != NetConnectionState.SendingPunchPackets)
                {
                    continue;
                }

                if ((cParams.IsInitiator && firstNonce != cParams.ServerNonce) || (!cParams.IsInitiator && firstNonce != cParams.Nonce))
                {
                    continue;
                }

                if (cParams.PossibleAddresses.Contains(address))
                {
                    if (cParams.IsInitiator)
                    {
                        found = true;
                        break;
                    }

                    continue;
                }

                var cont = cParams.PossibleAddresses.Any(ep => ep.Address.Equals(address.Address) && ep.AddressFamily == address.AddressFamily);

                if (!cont)
                {
                    continue;
                }

                if (cParams.PossibleAddresses.Count < 5)
                {
                    cParams.PossibleAddresses.Add(address);
                }

                if (cParams.IsInitiator)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                return;
            }

            var cParam    = conn.GetConnectionParameters();
            var theCipher = new SymmetricCipher(cParam.ArrangedSecret);

            if (stream.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, stream.GetBytePosition(), theCipher))
            {
                return;
            }

            var nextNonce = new Nonce();

            nextNonce.Read(stream);

            if (nextNonce != cParam.Nonce)
            {
                return;
            }

            if (stream.ReadFlag())
            {
                if (stream.ReadFlag())
                {
                    cParam.Certificate = new Certificate(stream);
                    if (!cParam.Certificate.IsValid() || !conn.ValidateCertificate(cParam.Certificate, true))
                    {
                        return;
                    }

                    cParam.PublicKey = cParam.Certificate.GetPublicKey();
                }
                else
                {
                    cParam.PublicKey = new AsymmetricKey(stream);
                    if (!cParam.PublicKey.IsValid() || !conn.ValidatePublicKey(cParam.PublicKey, true))
                    {
                        return;
                    }
                }

                if (PrivateKey == null || PrivateKey.GetKeySize() != cParam.PublicKey.GetKeySize())
                {
                    cParam.PrivateKey = new AsymmetricKey(cParam.PublicKey.GetKeySize());
                }
                else
                {
                    cParam.PrivateKey = PrivateKey;
                }

                cParam.SharedSecret = cParam.PrivateKey.ComputeSharedSecretKey(cParam.PublicKey);

                RandomUtil.Read(cParam.SymmetricKey, SymmetricCipher.KeySize);

                cParam.UsingCrypto = true;
            }
        }
예제 #6
0
        protected void HandleConnectChallengeResponse(IPEndPoint address, BitStream stream)
        {
            var conn = FindPendingConnection(address);

            if (conn == null || conn.ConnectionState != NetConnectionState.AwaitingChallengeResponse)
            {
                return;
            }

            var theNonce = new Nonce();

            theNonce.Read(stream);

            var cParams = conn.GetConnectionParameters();

            if (theNonce != cParams.Nonce)
            {
                return;
            }

            stream.Read(out cParams.ClientIdentity);
            cParams.ServerNonce.Read(stream);
            stream.Read(out cParams.PuzzleDifficulty);

            if (cParams.PuzzleDifficulty > ClientPuzzleManager.MaxPuzzleDifficulty)
            {
                return;
            }

            if (stream.ReadFlag())
            {
                if (stream.ReadFlag())
                {
                    cParams.Certificate = new Certificate(stream);
                    if (!cParams.Certificate.IsValid() || !conn.ValidateCertificate(cParams.Certificate, true))
                    {
                        return;
                    }

                    cParams.PublicKey = cParams.Certificate.GetPublicKey();
                }
                else
                {
                    cParams.PublicKey = new AsymmetricKey(stream);
                    if (!cParams.PublicKey.IsValid() || !conn.ValidatePublicKey(cParams.PublicKey, true))
                    {
                        return;
                    }
                }

                if (PrivateKey == null || PrivateKey.GetKeySize() != cParams.PublicKey.GetKeySize())
                {
                    cParams.PrivateKey = new AsymmetricKey(cParams.PublicKey.GetKeySize());
                }
                else
                {
                    cParams.PrivateKey = PrivateKey;
                }

                cParams.SharedSecret = cParams.PrivateKey.ComputeSharedSecretKey(cParams.PublicKey);
                RandomUtil.Read(cParams.SymmetricKey, SymmetricCipher.KeySize);

                cParams.UsingCrypto = true;
            }

            conn.ConnectionState  = NetConnectionState.ComputingPuzzleSolution;
            conn.ConnectSendCount = 0;

            cParams.PuzzleSolution = 0;

            conn.ConnectLastSendTime = CurrentTime;

            ContinuePuzzleSolution(conn);
        }
예제 #7
0
        protected void HandleArrangedConnectRequest(IPEndPoint client, BitStream reader)
        {
            var nonce = new Nonce();

            nonce.Read(reader);

            var oldConnection = FindConnection(client);

            if (oldConnection != null)
            {
                var cp = oldConnection.GetConnectionParameters();
                if (cp.Nonce == nonce)
                {
                    SendConnectAccept(oldConnection);
                    return;
                }
            }

            NetConnection conn  = null;
            var           found = false;

            foreach (var pair in PendingConnections)
            {
                conn = pair.Value;
                var cp = conn.GetConnectionParameters();

                if (conn.ConnectionState != NetConnectionState.SendingPunchPackets || cp.IsInitiator)
                {
                    continue;
                }

                if (nonce != cp.Nonce)
                {
                    continue;
                }

                if (cp.PossibleAddresses.Any(ep => ep.Address.Equals(client.Address) && ep.AddressFamily == client.AddressFamily))
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                return;
            }

            var cParams   = conn.GetConnectionParameters();
            var theCipher = new SymmetricCipher(cParams.ArrangedSecret);

            if (!reader.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, reader.GetBytePosition(), theCipher))
            {
                return;
            }

            reader.SetBytePosition(reader.GetBytePosition());

            var serverNonce = new Nonce();

            serverNonce.Read(reader);
            if (serverNonce != cParams.ServerNonce)
            {
                return;
            }

            if (reader.ReadFlag())
            {
                if (PrivateKey == null)
                {
                    return;
                }

                cParams.UsingCrypto = true;
                cParams.PublicKey   = new AsymmetricKey(reader);
                cParams.PrivateKey  = PrivateKey;

                var decryptPos = reader.GetBytePosition();
                reader.SetBytePosition(decryptPos);

                cParams.SharedSecret = cParams.PrivateKey.ComputeSharedSecretKey(cParams.PublicKey);

                var theCipher2 = new SymmetricCipher(cParams.SharedSecret);

                if (!reader.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, decryptPos, theCipher2))
                {
                    return;
                }

                reader.Read(NetConnection.MessageSignatureBytes, cParams.SymmetricKey);
                RandomUtil.Read(cParams.InitVector, SymmetricCipher.KeySize);
            }

            cParams.DebugObjectSizes = reader.ReadFlag();
            reader.Read(out uint connectSequence);

            if (oldConnection != null)
            {
                Disconnect(oldConnection, TerminationReason.ReasonSelfDisconnect, "");
            }

            conn.SetNetAddress(client);
            conn.SetInitialRecvSequence(connectSequence);

            if (cParams.UsingCrypto)
            {
                conn.SetSymmetricCipher(new SymmetricCipher(cParams.SymmetricKey, cParams.InitVector));
            }

            string errorString = null;

            if (!conn.ReadConnectRequest(reader, ref errorString))
            {
                SendConnectReject(cParams, client, errorString);
                RemovePendingConnection(conn);
                return;
            }

            AddConnection(conn);

            RemovePendingConnection(conn);

            conn.ConnectionState = NetConnectionState.Connected;
            conn.OnConnectionEstablished();

            SendConnectAccept(conn);
        }