Beispiel #1
0
        public void HandleHandshakeRequest(ClientStructure client, HandshakeRequestMsgData data)
        {
            var valid = CheckServerFull(client);

            valid &= valid && CheckUsernameLength(client, data.PlayerName);
            valid &= valid && CheckUsernameCharacters(client, data.PlayerName);
            valid &= valid && CheckPlayerIsAlreadyConnected(client, data.PlayerName);
            valid &= valid && CheckUsernameIsReserved(client, data.PlayerName);
            valid &= valid && CheckPlayerIsBanned(client, data.UniqueIdentifier);

            if (!valid)
            {
                LunaLog.Normal($"Client {data.PlayerName} ({data.UniqueIdentifier}) failed to handshake: {Reason}. Disconnecting");
                client.DisconnectClient = true;
                ClientConnectionHandler.DisconnectClient(client, Reason);
            }
            else
            {
                client.PlayerName       = data.PlayerName;
                client.UniqueIdentifier = data.UniqueIdentifier;
                client.Authenticated    = true;

                LmpPluginHandler.FireOnClientAuthenticated(client);

                LunaLog.Normal($"Client {data.PlayerName} ({data.UniqueIdentifier}) handshake successfully, Version: {data.MajorVersion}.{data.MinorVersion}.{data.BuildVersion}");

                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.HandshookSuccessfully, "success");

                var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <PlayerConnectionJoinMsgData>();
                msgData.PlayerName = client.PlayerName;
                MessageQueuer.RelayMessage <PlayerConnectionSrvMsg>(client, msgData);

                LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ClientRetriever.GetClients().Length}");
            }
        }
 private bool CheckUsernameIsReserved(ClientStructure client, string playerName)
 {
     if (playerName == "Initial" || playerName == GeneralSettings.SettingsStore.ConsoleIdentifier)
     {
         Reason = "Using reserved name";
         HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidPlayername, Reason);
         return(false);
     }
     return(true);
 }
 private bool CheckPlayerIsBanned(ClientStructure client, string uniqueId)
 {
     if (BanPlayerCommand.GetBannedPlayers().Contains(uniqueId))
     {
         Reason = "Banned";
         HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.PlayerBanned, Reason);
         return(false);
     }
     return(true);
 }
 private bool CheckServerFull(ClientStructure client)
 {
     if (ClientRetriever.GetActiveClientCount() >= GeneralSettings.SettingsStore.MaxPlayers)
     {
         Reason = "Server full";
         HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.ServerFull, Reason);
         return(false);
     }
     return(true);
 }
 private bool CheckWhitelist(ClientStructure client, string playerName)
 {
     if (GeneralSettings.SettingsStore.Whitelisted && !WhitelistCommands.Retrieve().Contains(playerName))
     {
         Reason = "Not on whitelist";
         HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.NotWhitelisted, Reason);
         return(false);
     }
     return(true);
 }
 private bool CheckUsernameLength(ClientStructure client, string username)
 {
     if (username.Length > GeneralSettings.SettingsStore.MaxUsernameLength)
     {
         Reason = $"Username too long. Max chars: {GeneralSettings.SettingsStore.MaxUsernameLength}";
         HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.ServerFull, Reason);
         return(false);
     }
     return(true);
 }
        private bool CheckUsernameCharacters(ClientStructure client, string playerName)
        {
            var regex = new Regex(@"^[-_a-zA-Z0-9]+$"); // Regex to only allow alphanumeric, dashes and underscore

            if (!regex.IsMatch(playerName))
            {
                Reason = "Invalid username characters (only A-Z, a-z, numbers, - and _)";
                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidPlayername, Reason);
                return(false);
            }
            return(true);
        }
        private bool CheckPlayerIsAlreadyConnected(ClientStructure client, string playerName)
        {
            var existingClient = ClientRetriever.GetClientByName(playerName);

            if (existingClient != null)
            {
                Reason = "Username already taken";
                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidPlayername, Reason);
                return(false);
            }
            return(true);
        }
 private bool CheckPlayerIsBanned(ClientStructure client, string playerName, string ipAddress, string publicKey)
 {
     if (BanCommands.RetrieveBannedUsernames().Contains(playerName) ||
         BanCommands.RetrieveBannedIps().Contains(ipAddress) ||
         BanCommands.RetrieveBannedKeys().Contains(publicKey))
     {
         Reason = "Banned";
         HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.PlayerBanned, Reason);
         return(false);
     }
     return(true);
 }
        private bool CheckUsernameLength(ClientStructure client, string username)
        {
            if (username.Length > GeneralSettings.SettingsStore.MaxUsernameLength)
            {
                Reason = $"Username too long. Max chars: {GeneralSettings.SettingsStore.MaxUsernameLength}";
                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidPlayername, Reason);
                return(false);
            }

            if (username.Length <= 0)
            {
                Reason = "Username too short. Min chars: 1";
                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidPlayername, Reason);
                return(false);
            }

            return(true);
        }
        private bool CheckKey(ClientStructure client, string playerName, string playerPublicKey, byte[] playerChallangeSignature)
        {
            //Check the client matches any database entry
            var storedPlayerFile = Path.Combine(ServerContext.UniverseDirectory, "Players", $"{playerName}.txt");

            if (FileHandler.FileExists(storedPlayerFile))
            {
                var storedPlayerPublicKey = FileHandler.ReadFileText(storedPlayerFile);
                if (playerPublicKey != storedPlayerPublicKey)
                {
                    Reason = "Invalid key. Username was already taken and used in the past";
                    HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidKey, Reason);
                    return(false);
                }
                using (var rsa = new RSACryptoServiceProvider(1024))
                {
                    rsa.PersistKeyInCsp = false;
                    rsa.FromXmlString(playerPublicKey);
                    var result = rsa.VerifyData(client.Challenge, CryptoConfig.CreateFromName("SHA256"), playerChallangeSignature);
                    if (!result)
                    {
                        Reason = "Public/priv key mismatch";
                        HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidKey, Reason);
                        return(false);
                    }
                }
            }
            else
            {
                try
                {
                    FileHandler.WriteToFile(storedPlayerFile, playerPublicKey);
                    LunaLog.Debug($"Client {playerName} registered!");
                }
                catch
                {
                    Reason = "Invalid username";
                    HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.InvalidPlayername, Reason);
                    return(false);
                }
            }
            return(true);
        }
        public void HandleHandshakeResponse(ClientStructure client, HandshakeResponseMsgData data)
        {
            var valid = CheckServerFull(client);

            valid &= valid && CheckUsernameLength(client, data.PlayerName);
            valid &= valid && CheckUsernameCharacters(client, data.PlayerName);
            valid &= valid && CheckWhitelist(client, data.PlayerName);
            valid &= valid && CheckPlayerIsAlreadyConnected(client, data.PlayerName);
            valid &= valid && CheckUsernameIsReserved(client, data.PlayerName);
            valid &= valid && CheckPlayerIsBanned(client, data.PlayerName, client.Endpoint.Address.ToString(), data.PublicKey);
            valid &= valid && CheckKey(client, data.PlayerName, data.PublicKey, data.ChallengeSignature);

            if (!valid)
            {
                LunaLog.Normal($"Client {data.PlayerName} failed to handshake: {Reason}. Disconnecting");
                client.DisconnectClient = true;
                ClientConnectionHandler.DisconnectClient(client, Reason);
            }
            else
            {
                client.PlayerName    = data.PlayerName;
                client.PublicKey     = data.PublicKey;
                client.Id            = Guid.NewGuid();
                client.Authenticated = true;

                LmpPluginHandler.FireOnClientAuthenticated(client);

                LunaLog.Normal($"Client {data.PlayerName} handshook successfully, Version: {data.MajorVersion}.{data.MinorVersion}.{data.BuildVersion}");

                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.HandshookSuccessfully, "success");

                var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <PlayerConnectionJoinMsgData>();
                msgData.PlayerName = client.PlayerName;

                MessageQueuer.RelayMessage <PlayerConnectionSrvMsg>(client, msgData);

                LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ClientRetriever.GetClients().Length}");
            }
        }