public async Task<LoginCheckerResponse> Login(Login login, string ip) { await semaphore.WaitAsync(); try { var userID = login.UserID; var lobbyVersion = login.LobbyVersion; using (var db = new ZkDataContext()) { if (!VerifyIp(ip)) return new LoginCheckerResponse(LoginResponse.Code.Banned, "Too many conneciton attempts"); var acc = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name); if (acc == null) { LogIpFailure(ip); return new LoginCheckerResponse(LoginResponse.Code.InvalidName, "Invalid user name"); } if (!acc.VerifyPassword(login.PasswordHash)) { LogIpFailure(ip); return new LoginCheckerResponse(LoginResponse.Code.InvalidPassword, "Invalid password"); } var ret = new LoginCheckerResponse(LoginResponse.Code.Ok, null); var user = ret.User; acc.Country = ResolveCountry(ip); if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country)) acc.Country = "unknown"; acc.LobbyVersion = lobbyVersion; acc.LastLogin = DateTime.UtcNow; user.LobbyVersion = login.LobbyVersion; user.IpAddress = ip; UpdateUserFromAccount(user, acc); LogIP(db, acc, ip); LogUserID(db, acc, userID); db.SaveChanges(); ret.LoginResponse.SessionToken = Guid.NewGuid().ToString(); // create session token var banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby); if (banPenalty != null) return BlockLogin( $"Banned until {banPenalty.BanExpires} (match to {banPenalty.AccountByAccountID.Name}), reason: {banPenalty.Reason}", acc, ip, userID); if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled) if (HasVpn(ip, acc, db)) return BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID); return ret; } } finally { semaphore.Release(); } }
public LoginResponse Login(User user, Login login, Client client) { string ip = client.RemoteEndpointIP; long userID = login.UserID; string lobbyVersion = login.LobbyVersion; using (var db = new ZkDataContext()) { Account acc = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name); if (acc == null) return new LoginResponse { ResultCode = LoginResponse.Code.InvalidName }; if (!acc.VerifyPassword(login.PasswordHash)) return new LoginResponse { ResultCode = LoginResponse.Code.InvalidPassword }; if (state.Clients.ContainsKey(login.Name)) return new LoginResponse { ResultCode = LoginResponse.Code.AlreadyConnected }; acc.Country = ResolveCountry(ip); if (acc.Country == null || String.IsNullOrEmpty(acc.Country)) acc.Country = "unknown"; acc.LobbyVersion = lobbyVersion; acc.LastLogin = DateTime.UtcNow; user.ClientType = login.ClientType; user.LobbyVersion = login.LobbyVersion; UpdateUserFromAccount(user, acc); LogIP(db, acc, ip); LogUserID(db, acc, userID); db.SaveChanges(); var banMute = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanMute, db); if (banMute != null) user.BanMute = true; Punishment banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby, db); if (banPenalty != null) { return BlockLogin( string.Format("Banned until {0} (match to {1}), reason: {2}", banPenalty.BanExpires, banPenalty.AccountByAccountID.Name, banPenalty.Reason), acc, ip, userID); } Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490); if (accAnteep != null) { if (accAnteep.AccountUserIDs.Any(y => y.UserID == userID)) { Talk(String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", acc.Name, userID, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } if (userID > 0 && userID < 1000) { Talk(String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", acc.Name, userID, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } if (accAnteep.AccountIPs.Any(y => y.IP == ip)) { Talk(String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", acc.Name, ip, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } } if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled) { // check user IP against http://dnsbl.tornevall.org // does not catch all smurfs // mostly false positives, do not use string reversedIP = string.Join(".", ip.Split('.').Reverse().ToArray()); try { IPAddress[] resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList; if (resolved.Length > 0) { Talk(String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", acc.Name, ip, resolved.Length, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } } catch (SocketException sockEx) { // not in database, do nothing } } try { if (!acc.HasVpnException) { for (int i = 0; i <= 1; i++) { var whois = new Whois(); Dictionary<string, string> data = whois.QueryByIp(ip, i == 1); if (!data.ContainsKey("netname")) data["netname"] = "UNKNOWN NETNAME"; if (!data.ContainsKey("org-name")) data["org-name"] = "UNKNOWN ORG"; if (!data.ContainsKey("abuse-mailbox")) data["abuse-mailbox"] = "no mailbox"; if (!data.ContainsKey("notify")) data["notify"] = "no notify address"; if (!data.ContainsKey("role")) data["role"] = "UNKNOWN ROLE"; if (!data.ContainsKey("descr")) data["descr"] = "no description"; if (!data.ContainsKey("remarks")) data["remarks"] = "no remarks"; List<string> blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList(); List<string> blockedHosts = db.BlockedHosts.Select(x => x.HostName).ToList(); /*if (acc.Country == "MY") { client.Say(SayPlace.User, "KingRaptor", String.Format("USER {0}\nnetname: {1}\norgname: {2}\ndescr: {3}\nabuse-mailbox: {4}", acc.Name, data["netname"], data["org-name"], data["descr"], data["abuse-mailbox"]), false); }*/ bool blockedHost = blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) || (blockedHosts.Any(x => data["notify"].Contains(x))); foreach (string company in blockedCompanies) { if (data["netname"].ToLower().Contains(company) || data["org-name"].ToLower().Contains(company) || data["descr"].ToLower().Contains(company) || data["role"].ToLower().Contains(company) || data["remarks"].ToLower().Contains(company)) { blockedHost = true; break; } } string hostname = Dns.GetHostEntry(ip).HostName; if (blockedHosts.Any(hostname.Contains)) blockedHost = true; if (blockedHost) return BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID); } } } catch (SocketException sockEx) {} catch (Exception ex) { Trace.TraceError("VPN check error: {0}", ex); } if (state.Clients.TryAdd(login.Name, client)) return new LoginResponse { ResultCode = LoginResponse.Code.Ok }; else return new LoginResponse() {ResultCode = LoginResponse.Code.AlreadyConnected}; } }