private void ClientInitRequest(NetIncomingMessage inc) { DebugConsole.Log("Received client init request"); if (ConnectedClients.Find(c => c.Connection == inc.SenderConnection) != null) { //this client was already authenticated //another init request means they didn't get any update packets yet DebugConsole.Log("Client already connected, ignoring..."); return; } UnauthenticatedClient unauthClient = unauthenticatedClients.Find(uc => uc.Connection == inc.SenderConnection); if (unauthClient == null) { //client did not ask for nonce first, can't authorize inc.SenderConnection.Disconnect(DisconnectReason.AuthenticationRequired.ToString()); if (unauthClient.SteamID > 0) { Steam.SteamManager.StopAuthSession(unauthClient.SteamID); } return; } if (serverSettings.HasPassword && inc.SenderConnection != OwnerConnection) { //decrypt message and compare password string clPw = inc.ReadString(); if (!serverSettings.IsPasswordCorrect(clPw, unauthClient.Nonce)) { unauthClient.FailedAttempts++; if (unauthClient.FailedAttempts > 3) { //disconnect and ban after too many failed attempts serverSettings.BanList.BanPlayer("Unnamed", unauthClient.Connection.RemoteEndPoint.Address, "DisconnectMessage.TooManyFailedLogins", duration: null); DisconnectUnauthClient(inc, unauthClient, DisconnectReason.TooManyFailedLogins, ""); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", Color.Red); return; } else { //not disconnecting the player here, because they'll still use the same connection and nonce if they try logging in again NetOutgoingMessage reject = server.CreateMessage(); reject.Write((byte)ServerPacketHeader.AUTH_FAILURE); reject.Write("Wrong password! You have " + Convert.ToString(4 - unauthClient.FailedAttempts) + " more attempts before you're banned from the server."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", Color.Red); CompressOutgoingMessage(reject); server.SendMessage(reject, unauthClient.Connection, NetDeliveryMethod.Unreliable); unauthClient.AuthTimer = 10.0f; return; } } } string clVersion = inc.ReadString(); UInt16 contentPackageCount = inc.ReadUInt16(); List <string> contentPackageNames = new List <string>(); List <string> contentPackageHashes = new List <string>(); for (int i = 0; i < contentPackageCount; i++) { string packageName = inc.ReadString(); string packageHash = inc.ReadString(); contentPackageNames.Add(packageName); contentPackageHashes.Add(packageHash); if (contentPackageCount == 0) { DebugConsole.Log("Client is using content package " + (packageName ?? "null") + " (" + (packageHash ?? "null" + ")")); } } if (contentPackageCount == 0) { DebugConsole.Log("Client did not list any content packages."); } string clName = Client.SanitizeName(inc.ReadString()); if (string.IsNullOrWhiteSpace(clName)) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NoName, ""); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", Color.Red); return; } if (clVersion != GameMain.Version.ToString()) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidVersion, $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={clVersion}"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", Color.Red); return; } //check if the client is missing any of the content packages the server requires List <ContentPackage> missingPackages = new List <ContentPackage>(); foreach (ContentPackage contentPackage in GameMain.SelectedPackages) { if (!contentPackage.HasMultiplayerIncompatibleContent) { continue; } bool packageFound = false; for (int i = 0; i < contentPackageCount; i++) { if (contentPackageNames[i] == contentPackage.Name && contentPackageHashes[i] == contentPackage.MD5hash.Hash) { packageFound = true; break; } } if (!packageFound) { missingPackages.Add(contentPackage); } } if (missingPackages.Count == 1) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error); return; } else if (missingPackages.Count > 1) { List <string> packageStrs = new List <string>(); missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp))); DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error); return; } string GetPackageStr(ContentPackage contentPackage) { return("\"" + contentPackage.Name + "\" (hash " + contentPackage.MD5hash.ShortHash + ")"); } //check if the client is using any contentpackages that are not compatible with the server List <Pair <string, string> > incompatiblePackages = new List <Pair <string, string> >(); for (int i = 0; i < contentPackageNames.Count; i++) { if (!GameMain.Config.SelectedContentPackages.Any(cp => cp.Name == contentPackageNames[i] && cp.MD5hash.Hash == contentPackageHashes[i])) { incompatiblePackages.Add(new Pair <string, string>(contentPackageNames[i], contentPackageHashes[i])); } } if (incompatiblePackages.Count == 1) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage, $"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr2(incompatiblePackages[0])}"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content package " + GetPackageStr2(incompatiblePackages[0]) + ")", ServerLog.MessageType.Error); return; } else if (incompatiblePackages.Count > 1) { List <string> packageStrs = new List <string>(); incompatiblePackages.ForEach(cp => packageStrs.Add(GetPackageStr2(cp))); DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage, $"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error); return; } string GetPackageStr2(Pair <string, string> nameAndHash) { return("\"" + nameAndHash.First + "\" (hash " + Md5Hash.GetShortHash(nameAndHash.Second) + ")"); } if (!serverSettings.Whitelist.IsWhiteListed(clName, inc.SenderConnection.RemoteEndPoint.Address)) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NotOnWhitelist, ""); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", Color.Red); return; } if (!Client.IsValidName(clName, this)) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidName, ""); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", Color.Red); return; } if (inc.SenderConnection != OwnerConnection && Homoglyphs.Compare(clName.ToLower(), Name.ToLower())) { DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NameTaken, ""); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", Color.Red); return; } Client nameTaken = ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), clName.ToLower())); if (nameTaken != null) { if (nameTaken.Connection.RemoteEndPoint.Address.ToString() == inc.SenderEndPoint.Address.ToString()) { //both name and IP address match, replace this player's connection nameTaken.Connection.Disconnect(DisconnectReason.SessionTaken.ToString()); nameTaken.Connection = unauthClient.Connection; nameTaken.InitClientSync(); //reinitialize sync ids because this is a new connection unauthenticatedClients.Remove(unauthClient); unauthClient = null; return; } else { //can't authorize this client DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NameTaken, ""); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", Color.Red); return; } } //new client Client newClient = new Client(clName, GetNewClientID()); newClient.InitClientSync(); newClient.Connection = unauthClient.Connection; newClient.SteamID = unauthClient.SteamID; unauthenticatedClients.Remove(unauthClient); unauthClient = null; ConnectedClients.Add(newClient); LastClientListUpdateID++; if (newClient.Connection == OwnerConnection) { newClient.GivePermission(ClientPermissions.All); newClient.PermittedConsoleCommands.AddRange(DebugConsole.Commands); GameMain.Server.UpdateClientPermissions(newClient); GameMain.Server.SendConsoleMessage("Granted all permissions to " + newClient.Name + ".", newClient); } GameMain.Server.SendChatMessage($"ServerMessage.JoinedServer~[client]={clName}", ChatMessageType.Server, null); var savedPermissions = serverSettings.ClientPermissions.Find(cp => cp.SteamID > 0 ? cp.SteamID == newClient.SteamID : newClient.IPMatches(cp.IP)); if (savedPermissions != null) { newClient.SetPermissions(savedPermissions.Permissions, savedPermissions.PermittedCommands); } else { newClient.SetPermissions(ClientPermissions.None, new List <DebugConsole.Command>()); } }
private void ClientInitRequest(NetIncomingMessage inc) { Boolean isNilModClient = false; if (ConnectedClients.Find(c => c.Connection == inc.SenderConnection) != null) { //this client was already authenticated //another init request means they didn't get any update packets yet return; } UnauthenticatedClient unauthClient = unauthenticatedClients.Find(uc => uc.Connection == inc.SenderConnection); if (unauthClient == null) { //client did not ask for nonce first, can't authorize inc.SenderConnection.Disconnect("Client (" + unauthClient.Connection.RemoteEndPoint.Address.ToString() + ") did not properly request authentication."); return; } if (!string.IsNullOrEmpty(password)) { //decrypt message and compare password string saltedPw = password; saltedPw = saltedPw + Convert.ToString(unauthClient.Nonce); saltedPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(saltedPw))); string clPw = inc.ReadString(); if (clPw != saltedPw) { unauthClient.failedAttempts++; if (unauthClient.failedAttempts > 3) { //disconnect and ban after too many failed attempts banList.BanPlayer("PASSWORDBAN", unauthClient.Connection.RemoteEndPoint.Address.ToString(), "Too many failed login attempts.", null); DisconnectUnauthClient(inc, unauthClient, "Too many failed login attempts. You have been automatically banned from the server."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", Color.Red); GameServer.LogToClientconsole(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)"); return; } else { //not disconnecting the player here, because they'll still use the same connection and nonce if they try logging in again NetOutgoingMessage reject = server.CreateMessage(); reject.Write((byte)ServerPacketHeader.AUTH_FAILURE); reject.Write("Wrong password! You have " + Convert.ToString(4 - unauthClient.failedAttempts) + " more attempts before you're banned from the server."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", Color.Red); GameServer.LogToClientconsole(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)"); server.SendMessage(reject, unauthClient.Connection, NetDeliveryMethod.Unreliable); unauthClient.AuthTimer = 10.0f; return; } } } string clVersion = inc.ReadString(); string clPackageName = inc.ReadString(); string clPackageHash = inc.ReadString(); string clName = Client.SanitizeName(inc.ReadString()); if (string.IsNullOrWhiteSpace(clName)) { DisconnectUnauthClient(inc, unauthClient, "You need a name."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", Color.Red); GameServer.LogToClientconsole(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)"); return; } if (clVersion != GameMain.Version.ToString()) { DisconnectUnauthClient(inc, unauthClient, "Version " + GameMain.Version + " required to connect to the server (Your version: " + clVersion + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version) - CLVersion: " + clVersion + " vs servers " + GameMain.Version, ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version) - CLVersion: " + clVersion + " vs servers " + GameMain.Version, Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version) - CLVersion: " + clVersion + " vs servers " + GameMain.Version); return; } if (clPackageName != GameMain.SelectedPackage.Name) { DisconnectUnauthClient(inc, unauthClient, "Your content package (" + clPackageName + ") doesn't match the server's version (" + GameMain.SelectedPackage.Name + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server with Incorrect Content Package: (" + clPackageName + ") vs servers (" + GameMain.SelectedPackage.Name + ")", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server with Incorrect Content Package: (" + clPackageName + ") vs servers (" + GameMain.SelectedPackage.Name + ")", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server with Incorrect Content Package: (" + clPackageName + ") vs servers (" + GameMain.SelectedPackage.Name + ")"); return; } if (clPackageHash.Substring(0, 7).Contains("NILMOD_")) { if (!GameMain.NilMod.AllowNilModClients) { DisconnectUnauthClient(inc, unauthClient, "This server does not permit Nilmod clients (Please rejoin using Vanilla)."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Nilmod clients are not permitted to connect).", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Nilmod clients are not permitted to connect).", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Nilmod clients are not permitted to connect)."); return; } else { isNilModClient = true; clPackageHash = clPackageHash.Substring(7); } } else { if (!GameMain.NilMod.AllowVanillaClients) { DisconnectUnauthClient(inc, unauthClient, "This server does not permit Vanilla clients (Please rejoin using Nilmod)."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Vanilla clients are not permitted to connect).", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Vanilla clients are not permitted to connect).", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Vanilla clients are not permitted to connect)."); return; } } if (GameMain.NilMod.BypassMD5 == true) { if (clPackageHash != GameMain.NilMod.ServerMD5A && clPackageHash != GameMain.NilMod.ServerMD5B) { DisconnectUnauthClient(inc, unauthClient, "Your content package (MD5: " + clPackageHash + ") doesn't match the server's version (MD5: " + GameMain.NilMod.ServerMD5A + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash) MD5: (" + clPackageHash + ") vs servers MD5A: (" + GameMain.NilMod.ServerMD5A + "), MD5B: (" + GameMain.NilMod.ServerMD5B + ")", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash):" + clPackageHash + " vs servers " + GameMain.NilMod.ServerMD5A + ", (" + GameMain.NilMod.ServerMD5B + ")", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash):" + clPackageHash + " vs servers " + GameMain.NilMod.ServerMD5A + ", (" + GameMain.NilMod.ServerMD5B + ")"); return; } } else { if (clPackageHash != GameMain.SelectedPackage.MD5hash.Hash) { DisconnectUnauthClient(inc, unauthClient, "Your content package (MD5: " + clPackageHash + ") doesn't match the server's version (MD5: " + GameMain.SelectedPackage.MD5hash.Hash + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash)"); return; } } if (!whitelist.IsWhiteListed(clName, inc.SenderConnection.RemoteEndPoint.Address.ToString())) { DisconnectUnauthClient(inc, unauthClient, "You're not in this server's whitelist."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)"); return; } if (GameMain.NilMod.MinimumNameLength > clName.Length) { DisconnectUnauthClient(inc, unauthClient, "Your name is too short, Minimum length on this server is " + GameMain.NilMod.MinimumNameLength + " characters."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name too short)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name too short, minimum length is " + GameMain.NilMod.MinimumNameLength + " characters)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name too short, minimum length is " + GameMain.NilMod.MinimumNameLength + " characters)"); return; } if (!Client.IsValidName(clName)) { DisconnectUnauthClient(inc, unauthClient, "Your name contains illegal symbols."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)"); return; } if (!GameMain.NilMod.AllowCyrillicText && Regex.IsMatch(clName, @"\p{IsCyrillic}")) { DisconnectUnauthClient(inc, unauthClient, "This server does not allow Cyrillic alphabets."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Name contains cyrillic characters)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Name contains cyrillic characters)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Name contains cyrillic characters)"); return; } if (!GameMain.NilMod.AllowEnglishText && Regex.IsMatch(clName, "^[a-zA-Z]*$")) { DisconnectUnauthClient(inc, unauthClient, "This server does not allow English alphabets."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Name contains english characters)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Name contains english characters)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Name contains english characters)"); return; } //Nilmod prevent players rejoining as server hosts current name OR server name. if (Homoglyphs.Compare(clName.ToLower(), Name.ToLower()) || Homoglyphs.Compare(clName.ToLower(), GameMain.NilMod.PlayYourselfName.ToLower()) || Homoglyphs.Compare(clName.ToLower(), NilMod.NilModGriefWatcher.GriefWatchName)) { DisconnectUnauthClient(inc, unauthClient, "That name is taken by the server."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)"); return; } Client nameTaken = ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), clName.ToLower())); if (nameTaken != null) { if (nameTaken.Connection.RemoteEndPoint.Address.ToString() == inc.SenderEndPoint.Address.ToString()) { //both name and IP address match, replace this player's connection nameTaken.Connection.Disconnect("Your session was taken by a new connection on the same IP address."); nameTaken.Connection = unauthClient.Connection; nameTaken.InitClientSync(); //reinitialize sync ids because this is a new connection unauthenticatedClients.Remove(unauthClient); unauthClient = null; return; } else { //can't authorize this client DisconnectUnauthClient(inc, unauthClient, "That name is taken."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)"); return; } } //MaxIdenticalIPConnections List <Client> SimilarIP = ConnectedClients.FindAll(c => c.Connection.RemoteEndPoint.Address.ToString() == inc.SenderConnection.RemoteEndPoint.Address.ToString()); if (SimilarIP.Count >= GameMain.NilMod.MaxIdenticalIPConnections) { //can't authorize this client DisconnectUnauthClient(inc, unauthClient, "Too many similar IPs are on the server, max is " + GameMain.NilMod.MaxIdenticalIPConnections); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Max Identical IP Connections exceeded)", ServerLog.MessageType.Connection); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Max Identical IP Connections exceeded, max is " + GameMain.NilMod.MaxIdenticalIPConnections + ")", Color.Red); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (Max Identical IP Connections exceeded, max is " + GameMain.NilMod.MaxIdenticalIPConnections + ")"); return; } KickedClient kickedclient = null; if (GameMain.NilMod.KickedClients.Count > 0) { for (int i = GameMain.NilMod.KickedClients.Count - 1; i >= 0; i--) { if (GameMain.NilMod.KickedClients[i].IPAddress == unauthClient.Connection.RemoteEndPoint.Address.ToString()) { if (GameMain.NilMod.KickedClients[i].RejoinTimer > 0f) { DisconnectUnauthClient(inc, unauthClient, "You have been kicked for " + ToolBox.SecondsToReadableTime(GameMain.NilMod.KickedClients[i].RejoinTimer) + ".\n" + GameMain.NilMod.KickedClients[i].KickReason.Replace("You have been kicked from the server.", "")); return; } else { kickedclient = GameMain.NilMod.KickedClients[i]; } } } } if (banList.IsBanned(inc.SenderEndPoint.Address.ToString())) { if (GameMain.NilMod.EnablePlayerLogSystem) { DebugConsole.NewMessage("Banned Player tried to join the server (" + inc.SenderEndPoint.Address.ToString() + " - " + clName.ToString() + ")" + NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, false, true, false), Color.Red); ServerLog.WriteLine("Banned Player tried to join the server (" + inc.SenderEndPoint.Address.ToString() + " - " + clName.ToString() + ")" + NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, false, true, false), ServerLog.MessageType.Connection); GameServer.LogToClientconsole("Banned Player tried to join the server (" + inc.SenderEndPoint.Address.ToString() + " - " + clName.ToString() + ")" + NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, false, true, false)); } else { DebugConsole.NewMessage("Banned Player tried to join the server (" + inc.SenderEndPoint.Address.ToString() + " - " + clName.ToString() + ")", Color.Red); ServerLog.WriteLine("Banned Player tried to join the server (" + inc.SenderEndPoint.Address.ToString() + " - " + clName.ToString() + ")", ServerLog.MessageType.Connection); GameServer.LogToClientconsole("Banned Player tried to join the server (" + inc.SenderEndPoint.Address.ToString() + " - " + clName.ToString() + ")"); } string banText = ""; if (GameMain.NilMod.BansInfoAddBanName) { banText = "You've been banned as '" + banList.GetBanName(inc.SenderEndPoint.Address.ToString()) + "'."; } else { banText = "You've been banned from the server."; } //Add Ban duration text if (banList.GetBanExpiry(inc.SenderEndPoint.Address.ToString()) != null && GameMain.NilMod.BansInfoAddBanDuration) { if (GameMain.NilMod.BansInfoUseRemainingTime) { TimeSpan banRemaining = Convert.ToDateTime(banList.GetBanExpiry(inc.SenderEndPoint.Address.ToString())).Subtract(DateTime.Now); banText += "\n" + "Expires in: "; if (banRemaining.Days > 0) { banText += banRemaining.Days + " Days, "; } if (banRemaining.Hours > 0) { banText += banRemaining.Hours + " Hours, "; } if (banRemaining.Minutes > 0) { banText += banRemaining.Minutes + " Minutes, "; } banText = banText.Substring(0, banText.Length - 2); } else { banText += "\n" + "Expire on: " + banList.GetBanExpiry(inc.SenderEndPoint.Address.ToString()) + "\n" + "Currently: " + DateTime.Now.ToString(); } } //Permanent ban text else if (banList.GetBanExpiry(inc.SenderEndPoint.Address.ToString()) == null && GameMain.NilMod.BansInfoAddBanDuration) { if (GameMain.NilMod.BansInfoAddBanName) { banText = "You've been permanently banned as '" + banList.GetBanName(inc.SenderEndPoint.Address.ToString()) + "'"; } else { banText = "You've been permanently banned from the server."; } } if (GameMain.NilMod.BansInfoAddCustomString) { banText += "\n" + GameMain.NilMod.BansInfoCustomtext; } if (GameMain.NilMod.BansInfoAddBanReason) { banText += "\n" + "for:" + banList.GetBanReason(inc.SenderEndPoint.Address.ToString()); } DisconnectUnauthClient(inc, unauthClient, banText); /* * if (banList.GetBanExpiry(inc.SenderEndPoint.Address.ToString()) != null) * { * //None Permament Ban * DisconnectUnauthClient(inc, unauthClient, "You have been banned As '" + banList.GetBanName(inc.SenderEndPoint.Address.ToString()) + "' with reason: " + banList.GetBanReason(inc.SenderEndPoint.Address.ToString()) + " \n Expires On: " + banList.GetBanExpiry(inc.SenderEndPoint.Address.ToString()) + " (Currently: " + DateTime.Now.ToString() + "). \n" + "Appeal at www.barotraumaserver.com"); + } + else + { + //Permanent ban + DisconnectUnauthClient(inc, unauthClient, "You have been banned As '" + banList.GetBanName(inc.SenderEndPoint.Address.ToString()) + "' with reason: " + banList.GetBanReason(inc.SenderEndPoint.Address.ToString()) + "\n" + " \n This ban is permanent. \n" + "Appeal at Blabla (Custom text here)! \n \n \n \n \n \n."); + } */ return; } //new client Client newClient = new Client(clName, GetNewClientID()); newClient.IsNilModClient = isNilModClient; newClient.RequiresNilModSync = isNilModClient; newClient.NilModSyncResendTimer = 4f; newClient.InitClientSync(); newClient.Connection = unauthClient.Connection; unauthenticatedClients.Remove(unauthClient); unauthClient = null; SavedClientPermission savedPermissions = clientPermissions.Find(cp => cp.IP == newClient.Connection.RemoteEndPoint.Address.ToString()); if (savedPermissions == null) { savedPermissions = defaultpermission; } newClient.OwnerSlot = savedPermissions.OwnerSlot; newClient.AdministratorSlot = savedPermissions.AdministratorSlot; newClient.TrustedSlot = savedPermissions.TrustedSlot; newClient.AllowInGamePM = savedPermissions.AllowInGamePM; newClient.GlobalChatSend = savedPermissions.GlobalChatSend; newClient.GlobalChatReceive = savedPermissions.GlobalChatReceive; newClient.KarmaImmunity = savedPermissions.KarmaImmunity; newClient.BypassSkillRequirements = savedPermissions.BypassSkillRequirements; newClient.PrioritizeJob = savedPermissions.PrioritizeJob; newClient.IgnoreJobMinimum = savedPermissions.IgnoreJobMinimum; newClient.KickImmunity = savedPermissions.KickImmunity; newClient.BanImmunity = savedPermissions.BanImmunity; newClient.HideJoin = savedPermissions.HideJoin; newClient.AccessDeathChatAlive = savedPermissions.AccessDeathChatAlive; newClient.AdminPrivateMessage = savedPermissions.AdminPrivateMessage; newClient.AdminChannelSend = savedPermissions.AdminChannelSend; newClient.AdminChannelReceive = savedPermissions.AdminChannelReceive; newClient.SendServerConsoleInfo = savedPermissions.SendServerConsoleInfo; newClient.CanBroadcast = savedPermissions.CanBroadcast; newClient.SetPermissions(savedPermissions.Permissions, savedPermissions.PermittedCommands); ConnectedClients.Add(newClient); #if CLIENT GameSession.inGameInfo.AddClient(newClient); GameMain.NetLobbyScreen.AddPlayer(newClient.Name); #endif if (GameMain.NilMod.EnableVPNBanlist) { CoroutineManager.StartCoroutine(NilMod.NilModVPNBanlist.CheckVPNBan(newClient, clName.ToString()), "NilModVPNBanlist"); } if (!GameMain.NilMod.EnableVPNBanlist) { if (GameMain.NilMod.EnablePlayerLogSystem) { if (!newClient.HideJoin) { GameMain.Server.SendChatMessage(NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, false, false, true), ChatMessageType.Server, null); } DebugConsole.NewMessage(NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, true, true, true), Color.White); Log(NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, true, true, true), ServerLog.MessageType.Connection); GameServer.LogToClientconsole(NilMod.NilModPlayerLog.ListPrevious(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName, true, true, true)); NilMod.NilModPlayerLog.LogPlayer(inc.SenderConnection.RemoteEndPoint.Address.ToString(), clName); } else { DisconnectedCharacter ReconnectedClient = null; if (GameMain.NilMod.DisconnectedCharacters.Count > 0) { ReconnectedClient = GameMain.NilMod.DisconnectedCharacters.Find(dc => dc.IPAddress == inc.SenderConnection.RemoteEndPoint.Address.ToString() && dc.clientname == clName); } if (kickedclient != null) { GameMain.Server.SendChatMessage("Recently Kicked Player " + clName + " (" + kickedclient.clientname + ") has rejoined the server.", ChatMessageType.Server, null); DebugConsole.NewMessage("Recently Kicked Player " + clName + " (" + kickedclient.clientname + ") (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has joined the server.", Color.White); Log("Recently Kicked Player " + clName + " (" + kickedclient.clientname + ") (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has joined the server.", ServerLog.MessageType.Connection); GameServer.LogToClientconsole("Recently Kicked Player " + clName + " (" + kickedclient.clientname + ") (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has joined the server."); if (GameMain.NilMod.ClearKickStateNameOnRejoin) { GameMain.NilMod.KickedClients.Remove(kickedclient); } else { kickedclient.ExpireTimer += GameMain.NilMod.KickStateNameTimerIncreaseOnRejoin; if (kickedclient.ExpireTimer > GameMain.NilMod.KickMaxStateNameTimer) { kickedclient.ExpireTimer = GameMain.NilMod.KickMaxStateNameTimer; } } } else if (ReconnectedClient == null) { if (!newClient.HideJoin) { GameMain.Server.SendChatMessage(clName + " has joined the server.", ChatMessageType.Server, null); } DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has joined the server.", Color.White); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has joined the server.", ServerLog.MessageType.Connection); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has joined the server."); } else { if (!newClient.HideJoin) { GameMain.Server.SendChatMessage(clName + " has reconnected to the server.", ChatMessageType.Server, null); } DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has reconnected to the server.", Color.White); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has reconnected to the server.", ServerLog.MessageType.Connection); GameServer.LogToClientconsole(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") has reconnected to the server."); } } } }
private void ClientInitRequest(NetIncomingMessage inc) { if (ConnectedClients.Find(c => c.Connection == inc.SenderConnection) != null) { //this client was already authenticated //another init request means they didn't get any update packets yet return; } UnauthenticatedClient unauthClient = unauthenticatedClients.Find(uc => uc.Connection == inc.SenderConnection); if (unauthClient == null) { //client did not ask for nonce first, can't authorize inc.SenderConnection.Disconnect("Client did not properly request authentication."); return; } if (!string.IsNullOrEmpty(password)) { //decrypt message and compare password string saltedPw = password; saltedPw = saltedPw + Convert.ToString(unauthClient.Nonce); saltedPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(saltedPw))); string clPw = inc.ReadString(); if (clPw != saltedPw) { unauthClient.failedAttempts++; if (unauthClient.failedAttempts > 3) { //disconnect and ban after too many failed attempts banList.BanPlayer("Unnamed", unauthClient.Connection.RemoteEndPoint.Address.ToString()); DisconnectUnauthClient(inc, unauthClient, "Too many failed login attempts. You have been automatically banned from the server."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", Color.Red); return; } else { //not disconnecting the player here, because they'll still use the same connection and nonce if they try logging in again NetOutgoingMessage reject = server.CreateMessage(); reject.Write((byte)ServerPacketHeader.AUTH_FAILURE); reject.Write("Wrong password! You have " + Convert.ToString(4 - unauthClient.failedAttempts) + " more attempts before you're banned from the server."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", Color.Red); server.SendMessage(reject, unauthClient.Connection, NetDeliveryMethod.Unreliable); unauthClient.AuthTimer = 10.0f; return; } } } string clVersion = inc.ReadString(); string clPackageName = inc.ReadString(); string clPackageHash = inc.ReadString(); string clName = Client.SanitizeName(inc.ReadString()); if (string.IsNullOrWhiteSpace(clName)) { DisconnectUnauthClient(inc, unauthClient, "You need a name."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", ServerLog.MessageType.Error); DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", Color.Red); return; } if (clVersion != GameMain.Version.ToString()) { DisconnectUnauthClient(inc, unauthClient, "Version " + GameMain.Version + " required to connect to the server (Your version: " + clVersion + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", Color.Red); return; } if (clPackageName != GameMain.SelectedPackage.Name) { DisconnectUnauthClient(inc, unauthClient, "Your content package (" + clPackageName + ") doesn't match the server's version (" + GameMain.SelectedPackage.Name + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package name)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package name)", Color.Red); return; } if (clPackageHash != GameMain.SelectedPackage.MD5hash.Hash) { DisconnectUnauthClient(inc, unauthClient, "Your content package (MD5: " + clPackageHash + ") doesn't match the server's version (MD5: " + GameMain.SelectedPackage.MD5hash.Hash + ")"); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong content package hash)", Color.Red); return; } if (!whitelist.IsWhiteListed(clName, inc.SenderConnection.RemoteEndPoint.Address.ToString())) { DisconnectUnauthClient(inc, unauthClient, "You're not in this server's whitelist."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", Color.Red); return; } if (!Client.IsValidName(clName)) { DisconnectUnauthClient(inc, unauthClient, "Your name contains illegal symbols."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", Color.Red); return; } if (clName.ToLower() == Name.ToLower()) { DisconnectUnauthClient(inc, unauthClient, "That name is taken."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", Color.Red); return; } Client nameTaken = ConnectedClients.Find(c => c.name.ToLower() == clName.ToLower()); if (nameTaken != null) { if (nameTaken.Connection.RemoteEndPoint.Address.ToString() == inc.SenderEndPoint.Address.ToString()) { //both name and IP address match, replace this player's connection nameTaken.Connection.Disconnect("Your session was taken by a new connection on the same IP address."); nameTaken.Connection = unauthClient.Connection; nameTaken.InitClientSync(); //reinitialize sync ids because this is a new connection unauthenticatedClients.Remove(unauthClient); unauthClient = null; return; } else { //can't authorize this client DisconnectUnauthClient(inc, unauthClient, "That name is taken."); Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", ServerLog.MessageType.Error); DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", Color.Red); return; } } //new client Client newClient = new Client(clName, GetNewClientID()); newClient.InitClientSync(); newClient.Connection = unauthClient.Connection; unauthenticatedClients.Remove(unauthClient); unauthClient = null; ConnectedClients.Add(newClient); GameMain.NetLobbyScreen.AddPlayer(newClient.name); GameMain.Server.SendChatMessage(clName + " has joined the server.", ChatMessageType.Server, null); var savedPermissions = clientPermissions.Find(cp => cp.IP == newClient.Connection.RemoteEndPoint.Address.ToString()); if (savedPermissions != null) { newClient.SetPermissions(savedPermissions.Permissions); } else { newClient.SetPermissions(ClientPermissions.None); } }