Пример #1
0
        public ActionResult RemovePunishment(int punishmentID)
        {
            var db    = new ZkDataContext();
            var todel = db.Punishments.First(x => x.PunishmentID == punishmentID);

            db.Punishments.DeleteOnSubmit(todel);
            db.SubmitAndMergeChanges();

            if (todel.BanLobby)
            {
                Account acc = todel.AccountByAccountID;
                Global.Nightwatch.Tas.AdminUnban(acc.Name);
                if (todel.BanIP != null)
                {
                    Global.Nightwatch.Tas.AdminUnban(todel.BanIP);
                }
                var otherPenalty = Punishment.GetActivePunishment(acc.AccountID, null, null, x => x.BanLobby, db);
                if (otherPenalty != null)
                {
                    var    time = otherPenalty.BanExpires - DateTime.Now;
                    double days = time.Value.TotalDays;
                    Global.Nightwatch.Tas.AdminBan(acc.Name, days / 24, otherPenalty.Reason);
                    if (otherPenalty.BanIP != null)
                    {
                        Global.Nightwatch.Tas.AdminBanIP(otherPenalty.BanIP, days / 24, otherPenalty.Reason);
                    }
                }
            }

            return(RedirectToAction("Detail", "Users", new { id = todel.AccountID }));
        }
Пример #2
0
        public static void UpdateUserFromAccount(User user, Account acc)
        {
            user.Name           = acc.Name;
            user.DisplayName    = acc.SteamName;
            user.Avatar         = acc.Avatar;
            user.Level          = acc.Level;
            user.EffectiveMmElo = (int)Math.Round(acc.GetRating(RatingCategory.MatchMaking).Elo);
            user.EffectiveElo   = (int)Math.Round(acc.GetRating(RatingCategory.Casual).Elo);
            user.RawMmElo       = (int)Math.Round(acc.GetRating(RatingCategory.MatchMaking).RealElo);
            user.SteamID        = acc.SteamID?.ToString();
            user.IsAdmin        = acc.AdminLevel >= AdminLevel.Moderator;
            user.IsBot          = acc.IsBot;
            user.Country        = acc.Country;
            user.Faction        = acc.Faction != null ? acc.Faction.Shortcut : null;
            user.Clan           = acc.Clan != null ? acc.Clan.Shortcut : null;
            user.AccountID      = acc.AccountID;
            user.Badges         = acc.GetBadges().Select(x => x.ToString()).ToList();
            user.Icon           = acc.GetIconName();
            if (user.Badges.Count == 0)
            {
                user.Badges = null;                         // slight optimization for data transfer
            }
            Interlocked.Increment(ref user.SyncVersion);

            user.BanMute     = Punishment.GetActivePunishment(acc.AccountID, user.IpAddress, 0, x => x.BanMute) != null;
            user.BanSpecChat = Punishment.GetActivePunishment(acc.AccountID, user.IpAddress, 0, x => x.BanSpecChat) != null;
        }
Пример #3
0
        void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
        {
            if (DateTime.UtcNow.Subtract(lastPollCheck).TotalMinutes > 15)
            {
                PollController.AutoClosePolls();
                lastPollCheck = DateTime.UtcNow;
            }

            Account acc = null;

            if (Request[GlobalConst.ASmallCakeCookieName] != null)
            {
                var testAcc = Account.AccountByName(new ZkDataContext(), Request[GlobalConst.ASmallCakeLoginCookieName]);
                if (testAcc != null)
                {
                    if (AuthTools.ValidateSiteAuthToken(testAcc.Name, testAcc.Password, Request[GlobalConst.ASmallCakeCookieName]))
                    {
                        acc = testAcc;
                    }
                }
            }
            if (acc == null)
            {
                if (Request[GlobalConst.LoginCookieName] != null)
                {
                    acc = AuthServiceClient.VerifyAccountHashed(Request[GlobalConst.LoginCookieName], Request[GlobalConst.PasswordHashCookieName]);
                }
            }

            if (acc != null)
            {
                var ip = GetUserIP();
                using (var db = new ZkDataContext()) {
                    var penalty = Punishment.GetActivePunishment(acc.AccountID, ip, null, x => x.BanSite, db);
                    if (penalty != null)
                    {
                        Response.Write(string.Format("You are banned! (IP match to account {0})\n", penalty.AccountByAccountID.Name));
                        Response.Write(string.Format("Ban expires: {0} UTC\n", penalty.BanExpires));
                        Response.Write(string.Format("Reason: {0}\n", penalty.Reason));
                        Response.End();
                    }
                    else
                    {
                        HttpContext.Current.User = acc;
                        // todo replace with safer permanent cookie
                        Response.SetCookie(new HttpCookie(GlobalConst.LoginCookieName, acc.Name)
                        {
                            Expires = DateTime.Now.AddMonths(12)
                        });
                        Response.SetCookie(new HttpCookie(GlobalConst.PasswordHashCookieName, acc.Password)
                        {
                            Expires = DateTime.Now.AddMonths(12)
                        });
                    }
                }
            }
        }
Пример #4
0
        private void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
        {
            if (DateTime.UtcNow.Subtract(lastPollCheck).TotalMinutes > 60)
            {
                PollController.AutoClosePolls(); // this is silly here, should be a seaprate timer/thread
                lastPollCheck = DateTime.UtcNow;
            }

            Account acc = null;


            if (FormsAuthentication.IsEnabled && User.Identity.IsAuthenticated)
            {
                acc = Account.AccountByName(new ZkDataContext(), User.Identity.Name);
            }
            else if (Request[GlobalConst.SessionTokenVariable] != null)
            {
                int id = 0;
                if (Global.Server?.SessionTokens.TryRemove(Request[GlobalConst.SessionTokenVariable], out id) == true)
                {
                    acc = new ZkDataContext().Accounts.Find(id);
                }
            }

            if (acc != null)
            {
                var ip        = Request.UserHostAddress;
                var lastLogin = acc.AccountUserIDs.OrderByDescending(x => x.LastLogin).FirstOrDefault();
                var userID    = lastLogin?.UserID;
                var installID = lastLogin?.InstallID;
                var penalty   = Punishment.GetActivePunishment(acc.AccountID, ip, userID, installID, x => x.BanSite);
                if (penalty != null)
                {
                    Response.Write(string.Format("You are banned! (IP match to account {0})\n", penalty.AccountByAccountID.Name));
                    Response.Write(string.Format("Ban expires: {0} UTC\n", penalty.BanExpires));
                    Response.Write(string.Format("Reason: {0}\n", penalty.Reason));
                    Response.End();
                }
                else
                {
                    HttpContext.Current.User = acc;
                    FormsAuthentication.SetAuthCookie(acc.Name, true);
                }
            }

            // remove cake from URL
            var removeCake = Regex.Replace(Request.Url.ToString(), $"([?|&])({GlobalConst.SessionTokenVariable}=[^&?]+[?|&]*)", m => m.Groups[1].Value);

            if (removeCake != Request.Url.ToString())
            {
                Response.Redirect(removeCake, true);
            }
        }
        public ActionResult VotePost(int forumPostID, int delta)
        {
            var db    = new ZkDataContext();
            var myAcc = Global.Account;

            var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum);

            if (penalty != null)
            {
                return(Content(string.Format("You cannot vote while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason)));
            }

            if (myAcc.Level < GlobalConst.MinLevelForForumVote)
            {
                return(Content(string.Format("You cannot vote until you are level {0} or higher", GlobalConst.MinLevelForForumVote)));
            }
            if ((Global.Account.ForumTotalUpvotes - Global.Account.ForumTotalDownvotes) < GlobalConst.MinNetKarmaToVote)
            {
                return(Content("Your net karma is too low to vote"));
            }

            if (delta > 1)
            {
                delta = 1;
            }
            else if (delta < -1)
            {
                delta = -1;
            }

            var post   = db.ForumPosts.First(x => x.ForumPostID == forumPostID);
            var author = post.Account;

            if (author.AccountID == Global.AccountID)
            {
                return(Content("Cannot vote for your own posts"));
            }
            if (myAcc.VotesAvailable <= 0)
            {
                return(Content("Out of votes"));
            }

            var existingVote = db.AccountForumVotes.SingleOrDefault(x => x.ForumPostID == forumPostID && x.AccountID == Global.AccountID);

            if (existingVote != null) // clear existing vote
            {
                var oldDelta = existingVote.Vote;
                // reverse vote effects
                if (oldDelta > 0)
                {
                    author.ForumTotalUpvotes = author.ForumTotalUpvotes - oldDelta;
                    post.Upvotes             = post.Upvotes - oldDelta;
                }
                else if (oldDelta < 0)
                {
                    author.ForumTotalDownvotes = author.ForumTotalDownvotes + oldDelta;
                    post.Downvotes             = post.Downvotes + oldDelta;
                }
                db.AccountForumVotes.DeleteOnSubmit(existingVote);
            }
            if (delta > 0)
            {
                author.ForumTotalUpvotes = author.ForumTotalUpvotes + delta;
                post.Upvotes             = post.Upvotes + delta;
            }
            else if (delta < 0)
            {
                author.ForumTotalDownvotes = author.ForumTotalDownvotes - delta;
                post.Downvotes             = post.Downvotes - delta;
            }

            if (delta != 0)
            {
                var voteEntry = new AccountForumVote {
                    AccountID = Global.AccountID, ForumPostID = forumPostID, Vote = delta
                };
                db.AccountForumVotes.InsertOnSubmit(voteEntry);
                myAcc.VotesAvailable--;
            }

            db.SaveChanges();

            return(RedirectToAction("Thread", new { id = post.ForumThreadID, postID = forumPostID }));
        }
        public ActionResult SubmitPost(
            int?threadID,
            int?categoryID,
            int?resourceID,
            int?missionID,
            int?springBattleID,
            int?clanID,
            int?planetID,
            string text,
            string title,
            string wikiKey,
            int?forumPostID,
            bool?isMinorEdit)
        {
            if (threadID == null && missionID == null && resourceID == null && springBattleID == null && clanID == null && planetID == null &&
                forumPostID == null && string.IsNullOrWhiteSpace(title))
            {
                return(Content("Cannot post new thread with blank title"));
            }
            if (string.IsNullOrWhiteSpace(text))
            {
                return(Content("Please type some text :)"));
            }

            var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum);

            if (penalty != null)
            {
                return
                    (Content(
                         string.Format("You cannot post while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason)));
            }

            var db = new ZkDataContext();

            using (var scope = new TransactionScope())
            {
                var thread   = db.ForumThreads.SingleOrDefault(x => x.ForumThreadID == threadID);
                var category = thread?.ForumCategory;
                if (category == null && categoryID != null)
                {
                    category = db.ForumCategories.FirstOrDefault(x => x.ForumCategoryID == categoryID);
                }
                string currentTitle = null;

                // update title
                if (thread != null && !string.IsNullOrEmpty(title))
                {
                    currentTitle   = thread.Title;
                    thread.Title   = title;
                    thread.WikiKey = wikiKey;
                }
                if (thread != null && planetID != null)
                {
                    var planet = db.Planets.Single(x => x.PlanetID == planetID);
                    thread.Title = "Planet " + planet.Name;
                }
                if (thread != null && clanID != null)
                {
                    var clan = db.Clans.Single(x => x.ClanID == clanID);
                    thread.Title = "Clan " + clan.ClanName;
                }
                if (thread != null && missionID != null)
                {
                    var mission = db.Missions.Single(x => x.MissionID == missionID);
                    thread.Title = "Mission " + mission.Name;
                }
                if (thread != null && resourceID != null)
                {
                    var map = db.Resources.Single(x => x.ResourceID == resourceID);
                    thread.Title = "Map " + map.InternalName;
                }

                if (threadID == null && category != null) // new thread
                {
                    if (category.IsLocked)
                    {
                        return(Content("Thread is locked"));
                    }

                    if (category.ForumMode == ForumMode.Wiki)
                    {
                        if (string.IsNullOrEmpty(wikiKey) || !Account.IsValidLobbyName(wikiKey))
                        {
                            return(Content("You need to set a valid wiki key"));
                        }
                        if (db.ForumThreads.Any(y => y.WikiKey == wikiKey))
                        {
                            return(Content("This wiki key already exists"));
                        }
                    }

                    if (string.IsNullOrEmpty(title))
                    {
                        return(Content("Title cannot be empty"));
                    }
                    thread = new ForumThread();
                    thread.CreatedAccountID = Global.AccountID;
                    thread.Title            = title;
                    thread.WikiKey          = wikiKey;
                    thread.ForumCategoryID  = category.ForumCategoryID;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && resourceID != null) // non existing thread, we posted new post on map
                {
                    var res = db.Resources.Single(x => x.ResourceID == resourceID);
                    if (res.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread
                    {
                        Title             = "Map " + res.InternalName,
                        CreatedAccountID  = Global.AccountID,
                        LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Maps);
                    res.ForumThread      = thread;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && springBattleID != null) // non existing thread, we posted new post on battle
                {
                    var bat = db.SpringBattles.Single(x => x.SpringBattleID == springBattleID);
                    if (bat.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread {
                        Title = bat.FullTitle, CreatedAccountID = Global.AccountID, LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.SpringBattles);
                    bat.ForumThread      = thread;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && clanID != null)
                {
                    var clan = db.Clans.Single(x => x.ClanID == clanID);
                    if (clan.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread
                    {
                        Title             = "Clan " + clan.ClanName,
                        CreatedAccountID  = Global.AccountID,
                        LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Clans);
                    clan.ForumThread     = thread;
                    thread.Clan          = clan;
                    db.ForumThreads.InsertOnSubmit(thread);
                }

                if (thread == null && planetID != null)
                {
                    var planet = db.Planets.Single(x => x.PlanetID == planetID);
                    if (planet.ForumThread != null)
                    {
                        return(Content("Double post"));
                    }
                    thread = new ForumThread
                    {
                        Title             = "Planet " + planet.Name,
                        CreatedAccountID  = Global.AccountID,
                        LastPostAccountID = Global.AccountID
                    };
                    thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Planets);
                    planet.ForumThread   = thread;
                    db.ForumThreads.InsertOnSubmit(thread);
                }


                if (thread == null)
                {
                    return(Content("Thread not found"));
                }
                if (thread.IsLocked && Global.Account.AdminLevel < AdminLevel.Moderator)
                {
                    return(Content("Thread is locked"));
                }
                if (thread.RestrictedClanID != null && thread.RestrictedClanID != Global.Account.ClanID)
                {
                    return(Content("Cannot post in this clan"));
                }

                var lastPost = thread.ForumPosts.OrderByDescending(x => x.ForumPostID).FirstOrDefault();

                int?gotoPostId = null;
                //double post preventer
                if (lastPost == null || lastPost.AuthorAccountID != Global.AccountID || lastPost.Text != text ||
                    (!string.IsNullOrEmpty(title) && title != currentTitle))
                {
                    if (forumPostID != null)
                    {
                        var post = thread.ForumPosts.Single(x => x.ForumPostID == forumPostID);
                        if (!post.CanEdit(Global.Account))
                        {
                            throw new ApplicationException("Not authorized to edit the post");
                        }
                        post.ForumPostEdits.Add(
                            new ForumPostEdit
                        {
                            EditorAccountID = Global.AccountID,
                            EditTime        = DateTime.UtcNow,
                            OriginalText    = post.Text,
                            NewText         = text
                        });
                        post.Text = text;
                    }
                    else
                    {
                        var p = new ForumPost {
                            AuthorAccountID = Global.AccountID, Text = text, Created = DateTime.UtcNow
                        };
                        thread.ForumPosts.Add(p);
                        db.SaveChanges();
                        gotoPostId = p.ForumPostID;
                    }

                    if (isMinorEdit != true)
                    {
                        thread.LastPost          = DateTime.UtcNow;
                        thread.LastPostAccountID = Global.AccountID;
                    }
                    thread.PostCount = thread.ForumPosts.Count();
                    thread.UpdateLastRead(Global.AccountID, true, thread.LastPost);

                    db.SaveChanges();
                }

                scope.Complete();


                if (missionID.HasValue)
                {
                    return(RedirectToAction("Detail", "Missions", new { id = missionID }));
                }
                if (resourceID.HasValue)
                {
                    return(RedirectToAction("Detail", "Maps", new { id = resourceID }));
                }
                if (springBattleID.HasValue)
                {
                    return(RedirectToAction("Detail", "Battles", new { id = springBattleID }));
                }
                if (clanID.HasValue)
                {
                    return(RedirectToAction("Detail", "Clans", new { id = clanID }));
                }
                if (planetID.HasValue)
                {
                    return(RedirectToAction("Planet", "Planetwars", new { id = planetID }));
                }
                if (forumPostID.HasValue)
                {
                    return(RedirectToAction("Thread", "Forum", new { id = thread.ForumThreadID, postID = forumPostID }));
                }
                return(RedirectToAction("Thread", "Forum", new { id = thread.ForumThreadID, postID = gotoPostId }));
            }
        }
        public ActionResult NewPost(int?categoryID, int?threadID, int?forumPostID, string wikiKey)
        {
            var res = new NewPostResult();
            var db  = new ZkDataContext();

            var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum);

            if (penalty != null)
            {
                return
                    (Content(
                         string.Format("You cannot post while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason)));
            }

            if (threadID.HasValue && threadID > 0)
            {
                var clan = db.Clans.FirstOrDefault(x => x.ForumThreadID == threadID);
                if (clan != null && Global.ClanID != clan.ClanID)
                {
                    return(Content(string.Format("You are not a member of {0}, you cannot post in their clan thread", clan.ClanName)));
                }

                var t = db.ForumThreads.Single(x => x.ForumThreadID == threadID.Value);
                res.CurrentThread = t;
                res.LastPosts     = res.CurrentThread.ForumPosts.OrderByDescending(x => x.ForumPostID).Take(20);
                if (!categoryID.HasValue)
                {
                    categoryID = t.ForumCategoryID;
                }
            }
            if (!categoryID.HasValue)
            {
                categoryID =
                    db.ForumCategories.Where(x => !x.IsLocked && x.ForumMode == ForumMode.General).OrderBy(x => x.SortOrder).First().ForumCategoryID;
                // post in general by default
            }

            var category = db.ForumCategories.FirstOrDefault(x => x.ForumCategoryID == categoryID);

            res.Path = category?.GetPath() ?? new List <ForumCategory>();

            res.CurrentCategory = category;
            if (forumPostID != null)
            {
                var post = db.ForumPosts.Single(x => x.ForumPostID == forumPostID);
                if (!post.CanEdit(Global.Account))
                {
                    return(Content("You cannot edit this post"));
                }
                res.EditedPost = post;
            }
            if (threadID != null)
            {
                var thread = res.CurrentThread;
                res.CanSetTopic = (thread.ForumPosts.Count > 0 && thread.ForumPosts.First().ForumPostID == forumPostID &&
                                   (category.ForumMode == ForumMode.General || category.ForumMode == ForumMode.Wiki || category.ForumMode == ForumMode.Archive));
            }
            else
            {
                res.CanSetTopic = true;
            }

            res.WikiKey = wikiKey;

            return(View(res));
        }
Пример #8
0
        public async Task <LoginCheckerResponse> DoLogin(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.BannedTooManyConnectionAttempts));
                    }

                    SteamWebApi.PlayerInfo info = null;
                    if (!string.IsNullOrEmpty(login.SteamAuthToken))
                    {
                        info = await server.SteamWebApi.VerifyAndGetAccountInformation(login.SteamAuthToken);

                        if (info == null)
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.InvalidSteamToken));
                        }
                    }

                    Account accBySteamID = null;
                    Account accByLogin   = null;
                    if (info != null)
                    {
                        accBySteamID = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.SteamID == info.steamid);
                    }
                    if (!string.IsNullOrEmpty(login.Name))
                    {
                        var loginToUpper = login.Name.ToUpper();
                        accByLogin = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name) ?? db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name.ToUpper() == loginToUpper);
                    }

                    if (accBySteamID == null)
                    {
                        if (accByLogin == null)
                        {
                            LogIpFailure(ip);
                            if (!string.IsNullOrEmpty(login.Name))
                            {
                                return(new LoginCheckerResponse(LoginResponse.Code.InvalidName));
                            }
                            else
                            {
                                return(new LoginCheckerResponse(LoginResponse.Code.SteamNotLinkedAndLoginMissing));
                            }
                        }

                        if (string.IsNullOrEmpty(login.PasswordHash) || !accByLogin.VerifyPassword(login.PasswordHash))
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.InvalidPassword));
                        }
                    }
                    var acc = accBySteamID ?? accByLogin;

                    var ret = new LoginCheckerResponse(LoginResponse.Code.Ok);
                    ret.LoginResponse.Name = acc.Name;
                    var user = ret.User;

                    acc.Country = ResolveCountry(ip);
                    if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country))
                    {
                        acc.Country = "??";
                    }
                    acc.LobbyVersion = lobbyVersion;
                    acc.LastLogin    = DateTime.UtcNow;
                    if (info != null)
                    {
                        if (db.Accounts.Any(x => x.SteamID == info.steamid && x.Name != acc.Name))
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.SteamLinkedToDifferentAccount));
                        }
                        acc.SteamID   = info.steamid;
                        acc.SteamName = info.personaname;
                    }

                    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();
            }
        }
Пример #9
0
        public async Task <RegisterResponse> DoRegister(Register register, string ip)
        {
            if (!Account.IsValidLobbyName(register.Name))
            {
                return(new RegisterResponse(RegisterResponse.Code.NameHasInvalidCharacters));
            }

            if (server.ConnectedUsers.ContainsKey(register.Name))
            {
                return(new RegisterResponse(RegisterResponse.Code.AlreadyConnected));
            }

            if (string.IsNullOrEmpty(register.PasswordHash) && string.IsNullOrEmpty(register.SteamAuthToken))
            {
                return(new RegisterResponse(RegisterResponse.Code.MissingBothPasswordAndToken));
            }

            if (!VerifyIp(ip))
            {
                return(new RegisterResponse(RegisterResponse.Code.BannedTooManyAttempts));
            }

            var banPenalty = Punishment.GetActivePunishment(null, ip, register.UserID, x => x.BanLobby);

            if (banPenalty != null)
            {
                return new RegisterResponse(RegisterResponse.Code.Banned)
                       {
                           BanReason = banPenalty.Reason
                       }
            }
            ;

            SteamWebApi.PlayerInfo info = null;
            if (!string.IsNullOrEmpty(register.SteamAuthToken))
            {
                info = await server.SteamWebApi.VerifyAndGetAccountInformation(register.SteamAuthToken);

                if (info == null)
                {
                    return(new RegisterResponse(RegisterResponse.Code.InvalidSteamToken));
                }
            }

            using (var db = new ZkDataContext())
            {
                var registerName   = register.Name.ToUpper();
                var existingByName = db.Accounts.FirstOrDefault(x => x.Name.ToUpper() == registerName);
                if (existingByName != null)
                {
                    if (info != null && existingByName.SteamID == info.steamid)
                    {
                        return(new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisSteamToken));
                    }

                    if (info == null && !string.IsNullOrEmpty(register.PasswordHash) && existingByName.VerifyPassword(register.PasswordHash))
                    {
                        return(new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisPassword));
                    }

                    return(new RegisterResponse(RegisterResponse.Code.NameAlreadyTaken));
                }

                var acc = new Account()
                {
                    Name = register.Name
                };
                acc.SetPasswordHashed(register.PasswordHash);
                acc.SetName(register.Name);
                acc.SetAvatar();
                acc.Email = register.Email;
                if (info != null)
                {
                    var existingBySteam = db.Accounts.FirstOrDefault(x => x.SteamID == info.steamid);
                    if (existingBySteam != null)
                    {
                        return(new RegisterResponse(RegisterResponse.Code.SteamAlreadyRegistered));
                    }

                    acc.SteamID   = info.steamid;
                    acc.SteamName = info.personaname;
                }
                else if (string.IsNullOrEmpty(register.PasswordHash))
                {
                    return(new RegisterResponse(RegisterResponse.Code.InvalidPassword));
                }
                LogIP(db, acc, ip);
                LogUserID(db, acc, register.UserID);
                db.Accounts.Add(acc);
                db.SaveChanges();
            }
            return(new RegisterResponse(RegisterResponse.Code.Ok));
        }
Пример #10
0
        /// <summary>
        ///     Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders,
        ///     what PlanetWars structures to create, etc.
        /// </summary>
        public static LobbyHostingContext GetDedicatedServerStartSetup(LobbyHostingContext context)
        {
            var ret = context;

            try
            {
                var mode = context.Mode;

                var commProfiles = new LuaTable();
                var db           = new ZkDataContext();

                // calculate to whom to send extra comms
                var accountIDsWithExtraComms = new List <int>();
                if (mode == AutohostMode.Planetwars || mode == AutohostMode.GameFFA || mode == AutohostMode.Teams)
                {
                    var groupedByTeam = context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count());
                    var biggest       = groupedByTeam.FirstOrDefault();
                    if (biggest != null)
                    {
                        foreach (var other in groupedByTeam.Skip(1))
                        {
                            var cnt = biggest.Count() - other.Count();
                            if (cnt > 0)
                            {
                                foreach (var a in
                                         other.Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                                         .OrderByDescending(x => x.GetRating(RatingCategory.Casual).Elo)
                                         .Take(cnt))
                                {
                                    accountIDsWithExtraComms.Add(a.AccountID);
                                }
                            }
                        }
                    }
                }


                // write Planetwars details to modoptions (for widget)
                Faction attacker = null;
                Faction defender = null;
                Planet  planet   = null;
                if (mode == AutohostMode.Planetwars)
                {
                    planet   = db.Galaxies.First(x => x.IsDefault).Planets.First(x => x.Resource.InternalName == context.Map);
                    attacker =
                        context.Players.Where(x => x.AllyID == 0 && !x.IsSpectator)
                        .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                        .Where(x => x.Faction != null)
                        .Select(x => x.Faction)
                        .First();

                    defender = planet.Faction;

                    if (attacker == defender)
                    {
                        defender = null;
                    }

                    ret.ModOptions["attackingFaction"]      = attacker.Shortcut;
                    ret.ModOptions["attackingFactionName"]  = attacker.Name;
                    ret.ModOptions["attackingFactionColor"] = attacker.Color;
                    if (defender != null)
                    {
                        ret.ModOptions["defendingFaction"]      = defender.Shortcut;
                        ret.ModOptions["defendingFactionName"]  = defender.Name;
                        ret.ModOptions["defendingFactionColor"] = defender.Color;
                    }
                    else
                    {
                        ret.ModOptions["defendingFaction"]      = "Mercenary";
                        ret.ModOptions["defendingFactionName"]  = "Local militia";
                        ret.ModOptions["defendingFactionColor"] = "#CCCCCC";
                    }
                    ret.ModOptions["planet"] = planet.Name;
                }

                // write player custom keys (level, elo, is muted, etc.)
                foreach (var p in context.Players)
                {
                    var user = db.Accounts.Where(x => x.AccountID == p.LobbyID).Include(x => x.RelalationsByOwner).FirstOrDefault();
                    if (user != null)
                    {
                        var userParams = new Dictionary <string, string>();
                        ret.UserParameters[p.Name] = userParams;

                        userParams["LobbyID"]     = user.AccountID.ToString();
                        userParams["CountryCode"] = user.HideCountry ? "??" : user.Country;

                        var userBanMuted = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanMute) != null;
                        if (userBanMuted)
                        {
                            userParams["muted"] = "1";
                        }
                        userParams["faction"]  = user.Faction != null ? user.Faction.Shortcut : "";
                        userParams["clan"]     = user.Clan != null ? user.Clan.Shortcut : "";
                        userParams["clanfull"] = user.Clan != null ? user.Clan.ClanName : "";

                        userParams["level"] = user.Level.ToString();
                        //userParams["mm_elo"] = Math.Round(user.EffectiveMmElo).ToString();
                        //userParams["casual_elo"] = Math.Round(user.EffectiveElo).ToString();

                        userParams["elo"] = Math.Round(user.GetBestRating().Elo).ToString();

                        userParams["icon"]      = user.GetIconName();
                        userParams["avatar"]    = user.Avatar;
                        userParams["badges"]    = string.Join(",", user.GetBadges());
                        userParams["admin"]     = user.AdminLevel >= AdminLevel.Moderator ? "1" : "0";
                        userParams["room_boss"] = p.Name == context.FounderName ? "1" : "0";
                        if (p.PartyID.HasValue)
                        {
                            userParams["PartyID"] = p.PartyID.ToString();
                        }

                        var userSpecChatBlocked = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanSpecChat) != null;;
                        userParams["can_spec_chat"] = userSpecChatBlocked ? "0" : "1";

                        userParams["ignored"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Ignore).Select(x => x.Target.Name));
                        userParams["friends"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Friend).Select(x => x.Target.Name));

                        if (!p.IsSpectator)
                        {
                            // set valid PW structure attackers
                            if (mode == AutohostMode.Planetwars)
                            {
                                userParams["pwRank"] = (user.AccountRolesByAccountID.Where(
                                                            x =>
                                                            !x.RoleType.IsClanOnly &&
                                                            (x.RoleType.RestrictFactionID == null || x.RoleType.RestrictFactionID == user.FactionID)).OrderBy(x => x.RoleType.DisplayOrder).Select(x => (int?)x.RoleType.DisplayOrder).FirstOrDefault() ?? 999).ToString();


                                var allied = user.Faction != null && defender != null && user.Faction != defender &&
                                             defender.HasTreatyRight(user.Faction, x => x.EffectPreventIngamePwStructureDestruction == true, planet);

                                if (!allied && user.Faction != null && (user.Faction == attacker || user.Faction == defender))
                                {
                                    userParams["canAttackPwStructures"] = "1";
                                }

                                userParams["pwInstructions"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(GetPwInstructions(planet, user, db, attacker)));
                            }

                            if (accountIDsWithExtraComms.Contains(user.AccountID))
                            {
                                userParams["extracomm"] = "1";
                            }

                            var commProfileIDs       = new LuaTable();
                            var userCommandersBanned = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanCommanders) != null;
                            if (!userCommandersBanned)
                            {
                                // set up commander data
                                foreach (var c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount)
                                         )
                                {
                                    try
                                    {
                                        var commProfile = new LuaTable();

                                        if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"'))
                                        {
                                            c.Name = c.CommanderID.ToString();
                                        }
                                        commProfiles.Add("c" + c.CommanderID, commProfile);
                                        commProfileIDs.Add("c" + c.CommanderID);

                                        // process decoration icons
                                        var decorations = new LuaTable();
                                        foreach (var d in
                                                 c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(x => x.SlotID).Select(x => x.Unlock))
                                        {
                                            var iconData = db.CommanderDecorationIcons.FirstOrDefault(x => x.DecorationUnlockID == d.UnlockID);
                                            if (iconData != null)
                                            {
                                                string iconName = null, iconPosition = null;
                                                // FIXME: handle avatars and preset/custom icons
                                                if (iconData.IconType == (int)DecorationIconTypes.Faction)
                                                {
                                                    iconName = user.Faction != null ? user.Faction.Shortcut : null;
                                                }
                                                else if (iconData.IconType == (int)DecorationIconTypes.Clan)
                                                {
                                                    iconName = user.Clan != null ? user.Clan.Shortcut : null;
                                                }

                                                if (iconName != null)
                                                {
                                                    iconPosition = CommanderDecoration.GetIconPosition(d);
                                                    var entry = new LuaTable();
                                                    entry.Add("image", iconName);
                                                    decorations.Add("icon_" + iconPosition.ToLower(), entry);
                                                }
                                            }
                                            else
                                            {
                                                decorations.Add(d.Code);
                                            }
                                        }

                                        commProfile["name"]        = c.Name.Substring(0, Math.Min(25, c.Name.Length));
                                        commProfile["chassis"]     = c.Unlock.Code;
                                        commProfile["decorations"] = decorations;

                                        var modules = new LuaTable();
                                        commProfile["modules"] = modules;

                                        for (var i = 1; i <= GlobalConst.NumCommanderLevels; i++)
                                        {
                                            var modulesForLevel = new LuaTable();
                                            modules.Add(modulesForLevel);
                                            var modulesOrdered = c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i).ToList();
                                            var slots          = db.CommanderSlots.ToList().Where(x => x.MorphLevel == i && (x.ChassisID == null || (x.ChassisID == c.ChassisUnlockID))).ToList();
                                            slots.Sort(delegate(CommanderSlot x, CommanderSlot y)
                                            {
                                                UnlockTypes type1 = x.UnlockType;
                                                UnlockTypes type2 = y.UnlockType;
                                                if (type1 == UnlockTypes.WeaponManualFire || type1 == UnlockTypes.WeaponBoth)
                                                {
                                                    type1 = UnlockTypes.Weapon;
                                                }
                                                if (type2 == UnlockTypes.WeaponManualFire || type2 == UnlockTypes.WeaponBoth)
                                                {
                                                    type2 = UnlockTypes.Weapon;
                                                }
                                                int result = type1.CompareTo(type2);
                                                if (result == 0)
                                                {
                                                    return(x.CommanderSlotID.CompareTo(y.CommanderSlotID));
                                                }
                                                else
                                                {
                                                    return(result);
                                                }
                                            });
                                            foreach (var slot in slots)
                                            {
                                                String value  = String.Empty;
                                                var    module = c.CommanderModules.FirstOrDefault(x => x.SlotID == slot.CommanderSlotID);
                                                if (module != null)
                                                {
                                                    value = module.Unlock.Code;
                                                }
                                                modulesForLevel.Add(value);
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Trace.TraceError(ex.ToString());
                                        throw new ApplicationException(
                                                  $"Error processing commander: {c.CommanderID} - {c.Name} of player {user.AccountID} - {user.Name}",
                                                  ex);
                                    }
                                }
                            }
                            else
                            {
                                userParams["jokecomm"] = "1";
                            }

                            userParams["commanders"] = commProfileIDs.ToBase64String();
                        }
                    }
                }
                ret.ModOptions["commanderTypes"] = commProfiles.ToBase64String();

                // set PW structures
                if (mode == AutohostMode.Planetwars)
                {
                    var owner = planet.Faction != null ? planet.Faction.Shortcut : "";

                    var pwStructures = new LuaTable();
                    foreach (
                        var s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName)))
                    {
                        pwStructures.Add(s.StructureType.IngameUnitName,
                                         new LuaTable
                        {
                            { "unitname", s.StructureType.IngameUnitName },
                            { "owner", s.Account?.Name },
                            { "canBeEvacuated", s.StructureType.IsIngameEvacuable },
                            { "canBeDestroyed", s.StructureType.IsIngameDestructible },
                            //{ "isDestroyed", s.IsDestroyed ? true : false },
                            {
                                "name", $"{owner} {s.StructureType.Name} ({(s.Account != null ? s.Account.Name : "unowned")})"
                            },
                            { "description", s.StructureType.Description }
                        });
                    }
                    ret.ModOptions["planetwarsStructures"] = pwStructures.ToBase64String();
                }

                return(ret);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                throw;
            }
        }
Пример #11
0
        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);
                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
                           }
                };
            }
        }

        string ResolveCountry(string ip)
        {
            if (IsLanIP(ip))
            {
                return("CZ");
            }
            else
            {
                try {
                    return(geoIP.Country(ip).Country.IsoCode);
                } catch (Exception ex) {
                    Trace.TraceWarning("{0} Unable to resolve country", this);
                    return("??");
                }
            }
        }

        LoginResponse BlockLogin(string reason, Account acc, string ip, long user_id)
        {
            Talk(string.Format("Login denied for {0} IP:{1} ID:{2} reason: {3}", acc.Name, ip, user_id, reason));
            return(new LoginResponse {
                Reason = reason, ResultCode = LoginResponse.Code.Banned
            });
        }
Пример #12
0
        public async Task<RegisterResponse> DoRegister(Register register, string ip)
        {
            if (!Account.IsValidLobbyName(register.Name)) return new RegisterResponse(RegisterResponse.Code.NameHasInvalidCharacters);

            if (server.ConnectedUsers.ContainsKey(register.Name)) return new RegisterResponse(RegisterResponse.Code.AlreadyConnected);

            if (string.IsNullOrEmpty(register.PasswordHash) && string.IsNullOrEmpty(register.SteamAuthToken)) return new RegisterResponse(RegisterResponse.Code.MissingBothPasswordAndToken);

            if (!VerifyIp(ip)) return new RegisterResponse(RegisterResponse.Code.BannedTooManyAttempts);

            var banPenalty = Punishment.GetActivePunishment(null, ip, register.UserID, register.InstallID, x => x.BanLobby);
            if (banPenalty != null) return new RegisterResponse(RegisterResponse.Code.Banned) {BanReason =  banPenalty.Reason};

            SteamWebApi.PlayerInfo info = null;
            if (!string.IsNullOrEmpty(register.SteamAuthToken))
            {
                info = await server.SteamWebApi.VerifyAndGetAccountInformation(register.SteamAuthToken);
                if (info == null) return new RegisterResponse(RegisterResponse.Code.InvalidSteamToken);
            }

            using (var db = new ZkDataContext())
            {
                var registerName = register.Name.ToUpper();
                var existingByName = db.Accounts.FirstOrDefault(x => x.Name.ToUpper() == registerName);
                if (existingByName != null)
                {
                    if (info != null && existingByName.SteamID == info.steamid) return new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisSteamToken);

                    if (info == null && !string.IsNullOrEmpty(register.PasswordHash) && existingByName.VerifyPassword(register.PasswordHash)) return new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisPassword);

                    return new RegisterResponse(RegisterResponse.Code.NameAlreadyTaken);
                }

                var acc = new Account() { Name = register.Name };
                acc.SetPasswordHashed(register.PasswordHash);
                acc.SetName(register.Name);
                acc.SetAvatar();
                acc.Email = register.Email;
                if (info != null)
                {
                    var existingBySteam = db.Accounts.FirstOrDefault(x => x.SteamID == info.steamid);
                    if (existingBySteam != null)
                        return new RegisterResponse(RegisterResponse.Code.SteamAlreadyRegistered);

                    acc.SteamID = info.steamid;
                    acc.SteamName = info.personaname;
                } else if (string.IsNullOrEmpty(register.PasswordHash))
                {
                    return new RegisterResponse(RegisterResponse.Code.InvalidPassword);
                }
                LogIP(db, acc, ip);
                LogUserID(db, acc, register.UserID, register.InstallID);
                db.Accounts.Add(acc);
                db.SaveChanges();
                var smurfs = acc.GetSmurfs().Where(a => a.PunishmentsByAccountID.Any(x => x.BanExpires > DateTime.UtcNow));
                if (smurfs.Any())
                {
                    await server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("Smurf Alert! {0} might be a smurf of {1}. Check https://zero-k.info/Users/AdminUserDetail/{2}", acc.Name, smurfs.OrderByDescending(x => x.Level).First().Name, acc.AccountID));
                }
            }
            return new RegisterResponse(RegisterResponse.Code.Ok);
        }
        public async Task <ActionResult> ChatMessages(ChatModel model)
        {
            model = model ?? new ChatModel();

            var  db      = new ZkDataContext();
            bool isMuted = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanMute) != null;
            var  minTime = DateTime.UtcNow.AddDays(-30);

            if (!string.IsNullOrEmpty(model.Channel))
            {
                // only show allowed channels
                if (!Global.Server.ChannelManager.CanJoin(Global.Account, model.Channel))
                {
                    return(PartialView("LobbyChatMessages", model));
                }
                if (!String.IsNullOrEmpty(model.Message) && !isMuted)
                {
                    await Global.Server.GhostSay(new Say()
                    {
                        IsEmote = false,
                        Place   = SayPlace.Channel,
                        Ring    = false,
                        Source  = SaySource.Zk,
                        Target  = model.Channel,
                        Text    = model.Message,
                        Time    = DateTime.UtcNow,
                        User    = Global.Account.Name,
                    });
                }
                string channelName = model.Channel;
                model.Data = db.LobbyChatHistories
                             .SqlQuery("SELECT TOP 30 * FROM [dbo].[LobbyChatHistories] WHERE [Target] = {0} AND [SayPlace] = {1} AND [Time] > {2} ORDER BY [Time] DESC", channelName, SayPlace.Channel, minTime)
                             .ToList().OrderBy(x => x.Time).AsQueryable();
                //Note if using Take(), it will be slow for uncommon channels like zktourney when ordering by Time and slow for common channels like zk if ordering by ID
            }
            else if (!string.IsNullOrEmpty(model.User))
            {
                if (!String.IsNullOrEmpty(model.Message) && !isMuted)
                {
                    await Global.Server.GhostSay(new Say()
                    {
                        IsEmote = false,
                        Place   = SayPlace.User,
                        Ring    = false,
                        Source  = SaySource.Zk,
                        Target  = model.User,
                        Text    = model.Message,
                        Time    = DateTime.UtcNow,
                        User    = Global.Account.Name,
                    });
                }
                string otherName = model.User;
                string myName    = Global.Account.Name;
                //Users can abuse rename to gain access to other users PMs, it's a feature
                model.Data = db.LobbyChatHistories
                             .Where(x => (x.User == otherName && x.Target == myName || x.User == myName && x.Target == otherName) && x.SayPlace == SayPlace.User && x.Time > minTime)
                             .OrderByDescending(x => x.Time).Take(30)
                             .ToList().OrderBy(x => x.Time).AsQueryable();
            }
            else
            {
                string myName = Global.Account.Name;

                var ignoredIds   = db.AccountRelations.Where(x => (x.Relation == Relation.Ignore) && (x.OwnerAccountID == Global.AccountID)).Select(x => x.TargetAccountID).ToList();
                var ignoredNames = db.Accounts.Where(x => ignoredIds.Contains(x.AccountID)).Select(x => x.Name).ToHashSet();
                model.Data = db.LobbyChatHistories
                             .Where(x => x.Target == myName && x.SayPlace == SayPlace.User && x.Time > minTime)
                             .OrderByDescending(x => x.Time).Take(30)
                             .ToList()
                             .Where(x => !ignoredNames.Contains(x.User))
                             .OrderBy(x => x.Time)
                             .AsQueryable();
            }

            model.Message = "";

            return(PartialView("LobbyChatMessages", model));
        }
Пример #14
0
        /// <summary>
        ///     Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders,
        ///     what PlanetWars structures to create, etc.
        /// </summary>
        public static LobbyHostingContext GetDedicatedServerStartSetup(LobbyHostingContext context)
        {
            var ret = context;

            try
            {
                var mode = context.Mode;

                var commProfiles = new LuaTable();
                var db           = new ZkDataContext();

                // calculate to whom to send extra comms
                var accountIDsWithExtraComms = new Dictionary <int, int>();
                if (mode == AutohostMode.Planetwars || mode == AutohostMode.GameFFA || mode == AutohostMode.Teams)
                {
                    var groupedByTeam = context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count());
                    var biggest       = groupedByTeam.FirstOrDefault();
                    if (biggest != null)
                    {
                        foreach (var other in groupedByTeam.Skip(1))
                        {
                            var cnt = biggest.Count() - other.Count();
                            if (cnt > 0)
                            {
                                // example case: 3 players on this team, 8 players on largest team
                                // 5 bonus comms to dole out to this team
                                // per_player = 1 (integer result of 5/3)
                                // remainder: 2, so now cnt = 2
                                // iterate over all players in this team
                                //  first player: cnt == 2, >0 so we give him a second extra comm
                                //  second player: cnt == 1, >0 so same deal
                                //  from now on cnt <= 0 so the last player only gets the one extra comm
                                int per_player = cnt / other.Count();
                                cnt = cnt % other.Count();
                                foreach (var a in other
                                         .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                                         .OrderByDescending(x => x.GetRating(RatingCategory.Casual).Elo))
                                {
                                    accountIDsWithExtraComms.Add(a.AccountID, per_player + (cnt > 0 ? 1 : 0));
                                    cnt--;
                                }
                            }
                        }
                    }
                }


                // write Planetwars details to modoptions (for widget)
                Faction attacker = null;
                Faction defender = null;
                Planet  planet   = null;
                if (mode == AutohostMode.Planetwars)
                {
                    var galaxy = db.Galaxies.First(x => x.IsDefault);
                    planet   = galaxy.Planets.First(x => x.Resource.InternalName == context.Map);
                    attacker =
                        context.Players.Where(x => x.AllyID == 0 && !x.IsSpectator)
                        .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                        .Where(x => x.Faction != null)
                        .Select(x => x.Faction)
                        .First();

                    defender = planet.Faction;

                    if (attacker == defender)
                    {
                        defender = null;
                    }

                    ret.ModOptions["attackingFaction"]      = attacker.Shortcut;
                    ret.ModOptions["attackingFactionName"]  = attacker.Name;
                    ret.ModOptions["attackingFactionColor"] = attacker.Color;
                    if (defender != null)
                    {
                        ret.ModOptions["defendingFaction"]      = defender.Shortcut;
                        ret.ModOptions["defendingFactionName"]  = defender.Name;
                        ret.ModOptions["defendingFactionColor"] = defender.Color;
                    }
                    else
                    {
                        ret.ModOptions["defendingFaction"]      = "Mercenary";
                        ret.ModOptions["defendingFactionName"]  = "Local militia";
                        ret.ModOptions["defendingFactionColor"] = "#CCCCCC";
                    }
                    ret.ModOptions["planet"]        = planet.Name;
                    ret.ModOptions["pw_galaxyTurn"] = galaxy.Turn.ToString();

                    ret.ModOptions["pw_baseIP"]            = GlobalConst.BaseInfluencePerBattle.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_dropshipIP"]        = planet.GetEffectiveShipIpBonus(attacker).ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_defenseIP"]         = planet.GetEffectiveIpDefense().ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_attackerIP"]        = (planet.PlanetFactions.FirstOrDefault(x => x.FactionID == attacker.FactionID)?.Influence ?? 0).ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_maxIP"]             = GlobalConst.PlanetWarsMaximumIP.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_neededIP"]          = GlobalConst.InfluenceToCapturePlanet.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_attackerWinLoseCC"] = GlobalConst.PlanetWarsAttackerWinLoseCcMultiplier.ToString(CultureInfo.InvariantCulture);
                    ret.ModOptions["pw_defenderWinKillCC"] = GlobalConst.PlanetWarsDefenderWinKillCcMultiplier.ToString(CultureInfo.InvariantCulture);
                }

                // write player custom keys (level, elo, is muted, etc.)
                foreach (var p in context.Players)
                {
                    var user = db.Accounts.Where(x => x.AccountID == p.LobbyID).Include(x => x.RelalationsByOwner).FirstOrDefault();
                    if (user != null)
                    {
                        var userParams = new Dictionary <string, string>();
                        ret.UserParameters[p.Name] = userParams;

                        userParams["LobbyID"]     = user.AccountID.ToString();
                        userParams["CountryCode"] = user.HideCountry ? "??" : user.Country;

                        var userBanMuted = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanMute) != null;
                        if (userBanMuted)
                        {
                            userParams["muted"] = "1";
                        }
                        userParams["faction"]  = user.Faction != null ? user.Faction.Shortcut : "";
                        userParams["clan"]     = user.Clan != null ? user.Clan.Shortcut : "";
                        userParams["clanfull"] = user.Clan != null ? user.Clan.ClanName : "";

                        userParams["level"] = user.Level.ToString();
                        //userParams["mm_elo"] = Math.Round(user.EffectiveMmElo).ToString();
                        //userParams["casual_elo"] = Math.Round(user.EffectiveElo).ToString();

                        userParams["elo"]       = Math.Round(user.GetRating(context.ApplicableRating).Elo).ToString();
                        userParams["elo_order"] = context.Players.Where(x => !x.IsSpectator)
                                                  .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID))
                                                  .Where(x => x.GetRating(context.ApplicableRating).Elo > user.GetRating(context.ApplicableRating).Elo)
                                                  .Count()
                                                  .ToString();

                        userParams["icon"]      = user.GetIconName();
                        userParams["avatar"]    = user.Avatar;
                        userParams["badges"]    = string.Join(",", user.GetBadges());
                        userParams["admin"]     = user.AdminLevel >= AdminLevel.Moderator ? "1" : "0";
                        userParams["room_boss"] = p.Name == context.FounderName ? "1" : "0";
                        if (p.PartyID.HasValue)
                        {
                            userParams["PartyID"] = p.PartyID.ToString();
                        }

                        var userSpecChatBlocked = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanSpecChat) != null;;
                        userParams["can_spec_chat"] = userSpecChatBlocked ? "0" : "1";

                        userParams["ignored"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Ignore).Select(x => x.Target.Name));
                        userParams["friends"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Friend).Select(x => x.Target.Name));

                        if (!p.IsSpectator)
                        {
                            // set valid PW structure attackers
                            if (mode == AutohostMode.Planetwars)
                            {
                                userParams["pwRank"] = (user.AccountRolesByAccountID.Where(
                                                            x =>
                                                            !x.RoleType.IsClanOnly &&
                                                            (x.RoleType.RestrictFactionID == null || x.RoleType.RestrictFactionID == user.FactionID)).OrderBy(x => x.RoleType.DisplayOrder).Select(x => (int?)x.RoleType.DisplayOrder).FirstOrDefault() ?? 999).ToString();


                                var allied = user.Faction != null && defender != null && user.Faction != defender &&
                                             defender.HasTreatyRight(user.Faction, x => x.EffectPreventIngamePwStructureDestruction == true, planet);

                                if (!allied && user.Faction != null && (user.Faction == attacker || user.Faction == defender))
                                {
                                    userParams["canAttackPwStructures"] = "1";
                                }

                                userParams["pwInstructions"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(GetPwInstructions(planet, user, db, attacker)));
                            }

                            if (accountIDsWithExtraComms.ContainsKey(user.AccountID))
                            {
                                userParams["extracomm"] = accountIDsWithExtraComms[user.AccountID].ToString();
                            }

                            var commProfileIDs       = new LuaTable();
                            var userCommandersBanned = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanCommanders) != null;
                            if (!userCommandersBanned)
                            {
                                // set up commander data
                                foreach (var c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount)
                                         )
                                {
                                    try
                                    {
                                        var commProfile = new LuaTable();

                                        if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"'))
                                        {
                                            c.Name = c.CommanderID.ToString();
                                        }
                                        commProfiles.Add("c" + c.CommanderID, commProfile);
                                        commProfileIDs.Add("c" + c.CommanderID);

                                        // process decoration icons
                                        var decorations = new LuaTable();
                                        foreach (var d in
                                                 c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(x => x.SlotID).Select(x => x.Unlock))
                                        {
                                            var iconData = db.CommanderDecorationIcons.FirstOrDefault(x => x.DecorationUnlockID == d.UnlockID);
                                            if (iconData != null)
                                            {
                                                string iconName = null, iconPosition = null;
                                                // FIXME: handle avatars and preset/custom icons
                                                if (iconData.IconType == (int)DecorationIconTypes.Faction)
                                                {
                                                    iconName = user.Faction != null ? user.Faction.Shortcut : null;
                                                }
                                                else if (iconData.IconType == (int)DecorationIconTypes.Clan)
                                                {
                                                    iconName = user.Clan != null ? user.Clan.Shortcut : null;
                                                }

                                                if (iconName != null)
                                                {
                                                    iconPosition = CommanderDecoration.GetIconPosition(d);
                                                    var entry = new LuaTable();
                                                    entry.Add("image", iconName);
                                                    decorations.Add("icon_" + iconPosition.ToLower(), entry);
                                                }
                                            }
                                            else
                                            {
                                                decorations.Add(d.Code);
                                            }
                                        }

                                        commProfile["name"]        = LuaTable.SanitizeString(c.Name.Substring(0, Math.Min(25, c.Name.Length))) ?? "dummy";
                                        commProfile["chassis"]     = c.Unlock.Code;
                                        commProfile["decorations"] = decorations;

                                        var modules = new LuaTable();
                                        commProfile["modules"] = modules;

                                        for (var i = 1; i <= GlobalConst.NumCommanderLevels; i++)
                                        {
                                            var modulesForLevel = new LuaTable();
                                            modules.Add(modulesForLevel);
                                            //var modulesOrdered = c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i).ToList();
                                            var slots = db.CommanderSlots.ToList().Where(x => x.MorphLevel == i && (x.ChassisID == null || (x.ChassisID == c.ChassisUnlockID))).ToList();
                                            slots.Sort(delegate(CommanderSlot x, CommanderSlot y)
                                            {
                                                UnlockTypes type1 = x.UnlockType;
                                                UnlockTypes type2 = y.UnlockType;
                                                if (type1 == UnlockTypes.WeaponManualFire || type1 == UnlockTypes.WeaponBoth)
                                                {
                                                    type1 = UnlockTypes.Weapon;
                                                }
                                                if (type2 == UnlockTypes.WeaponManualFire || type2 == UnlockTypes.WeaponBoth)
                                                {
                                                    type2 = UnlockTypes.Weapon;
                                                }
                                                int result = type1.CompareTo(type2);
                                                if (result == 0)
                                                {
                                                    return(x.CommanderSlotID.CompareTo(y.CommanderSlotID));
                                                }
                                                else
                                                {
                                                    return(result);
                                                }
                                            });
                                            foreach (var slot in slots)
                                            {
                                                String value  = String.Empty;
                                                var    module = c.CommanderModules.FirstOrDefault(x => x.SlotID == slot.CommanderSlotID);
                                                if (module != null)
                                                {
                                                    value = module.Unlock.Code;
                                                }
                                                modulesForLevel.Add(value);
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Trace.TraceError(ex.ToString());
                                        throw new ApplicationException(
                                                  $"Error processing commander: {c.CommanderID} - {c.Name} of player {user.AccountID} - {user.Name}",
                                                  ex);
                                    }
                                }
                            }
                            else
                            {
                                userParams["jokecomm"] = "1";
                            }

                            userParams["commanders"] = commProfileIDs.ToBase64String();
                        }
                    }
                }
                ret.ModOptions["commanderTypes"] = commProfiles.ToBase64String();

                /* General-purpose identifier.
                 * Prefer the more specific ones below when possible */
                ret.ModOptions["serverType"] = "ZKLS";

                /* Access to commands normally accessible only by the host.
                 * Lua calls prepend the / on their own, but not the autohost,
                 * so /say doesn't need it, but the cheat command does */
                ret.ModOptions["cheatCommandPrefix"] = "say !hostsay /";

                /* The server is listening for SPRINGIE strings (the game can skip those otherwise).
                 * See https://github.com/ZeroK-RTS/Zero-K-Infrastructure/blob/master/Shared/LobbyClient/DedicatedServer.cs#L317 */
                ret.ModOptions["sendSpringieData"] = "1";

                // set PW structures
                if (mode == AutohostMode.Planetwars)
                {
                    var owner = planet.Faction != null ? planet.Faction.Shortcut : "";

                    var pwStructures = new LuaTable();
                    foreach (
                        var s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName)))
                    {
                        pwStructures.Add(s.StructureType.IngameUnitName,
                                         new LuaTable
                        {
                            { "unitname", s.StructureType.IngameUnitName },
                            { "owner", s.Account?.Name },
                            { "canBeEvacuated", s.StructureType.IsIngameEvacuable },
                            { "canBeDestroyed", s.StructureType.IsIngameDestructible },
                            { "isInactive", !s.IsActive },
                            {
                                "name", $"{owner} {s.StructureType.Name} ({(s.Account != null ? s.Account.Name : "unowned")})"
                            },
                            { "description", s.StructureType.Description }
                        });
                    }
                    ret.ModOptions["planetwarsStructures"] = pwStructures.ToBase64String();
                }

                return(ret);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                throw;
            }
        }
Пример #15
0
        public async Task <LoginCheckerResponse> DoLogin(Login login, string ip, List <ulong> dlc)
        {
            var limit = MiscVar.ZklsMaxUsers;

            if (limit > 0 && server.ConnectedUsers.Count >= limit)
            {
                return(new LoginCheckerResponse(LoginResponse.Code.ServerFull));
            }
            await semaphore.WaitAsync();

            try
            {
                var userID       = login.UserID;
                var installID    = login.InstallID;
                var lobbyVersion = login.LobbyVersion;

                using (var db = new ZkDataContext())
                {
                    if (!VerifyIp(ip))
                    {
                        return(new LoginCheckerResponse(LoginResponse.Code.BannedTooManyConnectionAttempts));
                    }

                    SteamWebApi.PlayerInfo info = null;
                    if (!string.IsNullOrEmpty(login.SteamAuthToken))
                    {
                        info = await server.SteamWebApi.VerifyAndGetAccountInformation(login.SteamAuthToken);

                        if (info == null)
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.InvalidSteamToken));
                        }
                    }

                    Account accBySteamID = null;
                    Account accByLogin   = null;
                    if (info != null)
                    {
                        accBySteamID = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.SteamID == info.steamid);
                    }
                    if (!string.IsNullOrEmpty(login.Name))
                    {
                        accByLogin = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name) ?? db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name.Equals(login.Name, StringComparison.CurrentCultureIgnoreCase));
                    }

                    if (accBySteamID == null)
                    {
                        if (accByLogin == null)
                        {
                            LogIpFailure(ip);
                            if (!string.IsNullOrEmpty(login.Name))
                            {
                                return(new LoginCheckerResponse(LoginResponse.Code.InvalidName));
                            }
                            else
                            {
                                return(new LoginCheckerResponse(LoginResponse.Code.SteamNotLinkedAndLoginMissing));
                            }
                        }

                        if (string.IsNullOrEmpty(login.PasswordHash) || !accByLogin.VerifyPassword(login.PasswordHash))
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.InvalidPassword));
                        }
                    }
                    var acc = accBySteamID ?? accByLogin;

                    var ret = new LoginCheckerResponse(LoginResponse.Code.Ok);
                    ret.LoginResponse.Name = acc.Name;
                    var user = ret.User;

                    acc.Country = ResolveCountry(ip);
                    if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country))
                    {
                        acc.Country = "??";
                    }
                    acc.LobbyVersion = lobbyVersion;
                    acc.LastLogin    = DateTime.UtcNow;
                    if (info != null)
                    {
                        if (db.Accounts.Any(x => x.SteamID == info.steamid && x.Name != acc.Name))
                        {
                            LogIpFailure(ip);
                            return(new LoginCheckerResponse(LoginResponse.Code.SteamLinkedToDifferentAccount));
                        }
                        acc.SteamID   = info.steamid;
                        acc.SteamName = info.personaname;
                    }

                    user.LobbyVersion = login.LobbyVersion;
                    user.IpAddress    = ip;

                    acc.VerifyAndAddDlc(dlc);

                    UpdateUserFromAccount(user, acc);
                    LogIP(db, acc, ip);
                    LogUserID(db, acc, userID, installID);

                    if (String.IsNullOrEmpty(installID) && !acc.HasVpnException)
                    {
                        await server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("{0} just logged in with an unsupported lobby https://zero-k.info/Users/AdminUserDetail/{1}", acc.Name, acc.AccountID));
                    }

                    db.SaveChanges();

                    ret.LoginResponse.SessionToken = Guid.NewGuid().ToString(); // create session token

                    var banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, installID, x => x.BanLobby);

                    if (banPenalty != null)
                    {
                        return
                            (BlockLogin(
                                 $"Banned until {banPenalty.BanExpires} (match to {banPenalty.AccountByAccountID.Name}), reason: {banPenalty.Reason}",
                                 acc,
                                 ip,
                                 userID,
                                 installID));
                    }

                    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, installID));
                        }
                    }

                    return(ret);
                }
            }
            finally
            {
                semaphore.Release();
            }
        }
Пример #16
0
        public AuthService(TasClient client)
        {
            this.client = client;

            /*
             * this.client.Input += (s, e) =>
             * {
             * Console.WriteLine(e.Command +" "+ Utils.Glue(e.Args));
             * };
             * this.client.Output += (s, e) =>
             * {
             * Console.WriteLine(e.Data.Key + " " +Utils.Glue(e.Data.Value.Select(x=>x.ToString()).ToArray()));
             * };*/

            this.client.LoginAccepted += (s, e) =>
            {
                requests.Clear();
                client.JoinChannel(ModeratorChannel);
                client.JoinChannel(Top20Channel);
                using (var db = new ZkDataContext()) foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
                    {
                        client.JoinChannel(fac.Shortcut);
                    }
            };

            this.client.TestLoginAccepted += (s, e) =>
            {
                RequestInfo entry;
                if (requests.TryGetValue(client.MessageID, out entry))
                {
                    entry.CorrectName = e.ServerParams[0];
                    entry.LobbyID     = Convert.ToInt32(e.ServerParams[1]);
                    if (client.ExistingUsers.ContainsKey(entry.CorrectName))
                    {
                        entry.User = client.ExistingUsers[entry.CorrectName];
                    }
                    entry.WaitHandle.Set();
                }

                requests.TryRemove(client.MessageID, out entry);
            };

            this.client.UserAdded += (s, e) =>
            {
                using (var db = new ZkDataContext())
                {
                    var acc = Account.AccountByLobbyID(db, e.Data.LobbyID);
                    if (acc != null)
                    {
                        this.client.Extensions.PublishAccountData(acc);
                        if (acc.SpringieLevel > 2 || acc.IsZeroKAdmin)
                        {
                            client.ForceJoinChannel(e.Data.Name, ModeratorChannel);
                        }
                        if (topPlayers.IsTop20(e.Data.LobbyID))
                        {
                            client.ForceJoinChannel(e.Data.Name, Top20Channel);
                        }
                        if (acc.Clan != null)
                        {
                            client.ForceJoinChannel(e.Data.Name, acc.Clan.GetClanChannel(), acc.Clan.Password);
                        }
                        if (acc.Faction != null && acc.Level >= GlobalConst.FactionChannelMinLevel && acc.CanPlayerPlanetWars())
                        {
                            client.ForceJoinChannel(e.Data.Name, acc.Faction.Shortcut);
                        }
                    }
                    client.RequestUserIP(e.Data.Name);
                    client.RequestUserID(e.Data.Name);
                }
            };

            this.client.UserIDRecieved += (sender, args) =>
            {
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        using (var db = new ZkDataContext())
                        {
                            var acc     = Account.AccountByName(db, args.Name);
                            var penalty = Punishment.GetActivePunishment(acc != null ? acc.AccountID : 0, null, args.ID, x => x.BanLobby, db);

                            if (penalty != null)
                            {
                                client.AdminKickFromLobby(args.Name,
                                                          string.Format("Banned until {0} (ID match to {1}), reason: {2}", penalty.BanExpires, penalty.AccountByAccountID.Name, penalty.Reason));
                            }
                            ;

                            if (acc != null && args.ID != 0)
                            {
                                var entry = acc.AccountUserIDS.FirstOrDefault(x => x.UserID == args.ID);
                                if (entry == null)
                                {
                                    entry = new AccountUserID {
                                        AccountID = acc.AccountID, UserID = args.ID, FirstLogin = DateTime.UtcNow
                                    };
                                    db.AccountUserIDS.InsertOnSubmit(entry);
                                }
                                entry.LoginCount++;
                                entry.LastLogin = DateTime.UtcNow;
                            }

                            Account accAnteep  = db.Accounts.FirstOrDefault(x => x.AccountID == 4490);
                            bool isAnteepSmurf = accAnteep.AccountUserIDS.Any(x => x.UserID == args.ID);
                            if (isAnteepSmurf)
                            {
                                client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", args.Name, args.ID,
                                                                                                       acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false);
                            }

                            if (args.ID != 0 && args.ID < 1000)
                            {
                                client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", args.Name, args.ID,
                                                                                                       acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false);
                            }

                            db.SubmitChanges();
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError("Error getting user ID: {0}", ex);
                    }
                });
            };

            this.client.UserIPRecieved += (sender, args) =>
            {
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        Account acc = null;
                        using (var db = new ZkDataContext())
                        {
                            acc = Account.AccountByName(db, args.Name);

                            var penalty = Punishment.GetActivePunishment(acc != null ? acc.AccountID : 0, args.IP, null, x => x.BanLobby, db);
                            if (penalty != null)
                            {
                                client.AdminKickFromLobby(args.Name,
                                                          string.Format("Banned until {0} (IP match to {1}), reason: {2}", penalty.BanExpires, penalty.AccountByAccountID.Name, penalty.Reason));
                            }
                            if (acc != null)
                            {
                                var entry = acc.AccountIPS.FirstOrDefault(x => x.IP == args.IP);
                                if (entry == null)
                                {
                                    entry = new AccountIP {
                                        AccountID = acc.AccountID, IP = args.IP, FirstLogin = DateTime.UtcNow
                                    };
                                    db.AccountIPS.InsertOnSubmit(entry);
                                }
                                entry.LoginCount++;
                                entry.LastLogin = DateTime.UtcNow;
                            }
                            db.SubmitChanges();
                        }

                        try
                        {
                            if (acc == null || !acc.HasVpnException)
                            {
                                if (GlobalConst.VpnCheckEnabled)
                                {
                                    // check user IP against http://dnsbl.tornevall.org
                                    // does not catch all smurfs
                                    // mostly false positives, do not use
                                    var reversedIP = string.Join(".", args.IP.Split('.').Reverse().ToArray());
                                    try
                                    {
                                        var resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList;
                                        if (resolved.Length > 0)
                                        {
                                            client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)",
                                                                                                                   args.Name, args.IP, resolved.Length, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false);
                                            //client.AdminKickFromLobby(args.Name,
                                            //                      "Connection using proxy or VPN is not allowed! (You can ask for exception). See http://dnsbl.tornevall.org/removal.php to get your IP removed from the blacklist.");
                                        }
                                    }
                                    catch (System.Net.Sockets.SocketException sockEx)
                                    {
                                        // not in database, do nothing
                                    }
                                }
                                using (var db = new ZkDataContext())
                                {
                                    Account accAnteep  = db.Accounts.FirstOrDefault(x => x.AccountID == 4490);
                                    bool isAnteepSmurf = accAnteep.AccountIPS.Any(x => x.IP == args.IP);
                                    if (isAnteepSmurf)
                                    {
                                        client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", args.Name, args.IP,
                                                                                                               acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false);
                                    }
                                }

                                using (ZkDataContext db = new ZkDataContext())
                                {
                                    for (int i = 0; i <= 1; i++)
                                    {
                                        var whois = new Whois();
                                        var data  = whois.QueryByIp(args.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";
                                        }

                                        var blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList();
                                        var blockedHosts     = db.BlockedHosts.Select(x => x.HostName).ToList();

                                        /*if (acc.Country == "MY")
                                         * {
                                         *  client.Say(TasClient.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);
                                         * }*/
                                        if (blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) || (blockedHosts.Any(x => data["notify"].Contains(x))))
                                        {
                                            client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)");
                                        }
                                        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))
                                            {
                                                client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)");
                                                break;
                                            }
                                        }

                                        var hostname = Dns.GetHostEntry(args.IP).HostName;
                                        if (blockedHosts.Any(hostname.Contains))
                                        {
                                            client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)");
                                        }
                                    }
                                }
                            }
                        }
                        catch (System.Net.Sockets.SocketException sockEx)
                        {
                            // do nothing
                        }
                        catch (Exception ex)
                        {
                            Trace.TraceError("VPN check error: {0}", ex);
                            client.Say(TasClient.SayPlace.Channel, ModeratorChannel, ex.ToString(), false);
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError("Error getting user IP: {0}", ex);
                        //client.Say(TasClient.SayPlace.User, "KingRaptor", ex.ToString(), false);
                    }
                });
            };

            this.client.UserStatusChanged += (s, e) =>
            {
                var user = client.ExistingUsers[e.ServerParams[0]];
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        using (var db = new ZkDataContext()) UpdateUser(user.LobbyID, user.Name, user, null, db);
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError(ex.ToString());
                    }
                },
                                      TaskCreationOptions.LongRunning);
            };

            this.client.BattleUserJoined += (s, e) =>
            {
                var battle  = client.ExistingBattles[e.BattleID];
                var founder = battle.Founder;
                if (founder.IsSpringieManaged)
                {
                    try
                    {
                        var user = client.ExistingUsers[e.UserName];

                        /*  obsolete; all major lobbies have multiengine support
                         * if (!user.IsZkLobbyUser && !user.IsNotaLobby && battle.EngineVersion != client.ServerSpringVersion &&
                         *  battle.EngineVersion != client.ServerSpringVersion + ".0") {
                         *  client.Say(TasClient.SayPlace.User,
                         *             user.Name,
                         *             string.Format(
                         *                 "ALERT! YOU WILL DESYNC!! You NEED SPRING ENGINE {0} to play here. Simply join the game with Zero-K lobby ( http://zero-k.info/Wiki/Download ) OR get the engine from http://springrts.com/dl/buildbot/default/ OR build it on your Linux: http://springrts.com/wiki/Building_Spring_on_Linux ",
                         *                 battle.EngineVersion),
                         *             false);
                         * }
                         */
                        using (var db = new ZkDataContext())
                        {
                            var acc   = Account.AccountByLobbyID(db, user.LobbyID);
                            var name  = founder.Name.TrimNumbers();
                            var aconf = db.AutohostConfigs.FirstOrDefault(x => x.Login == name);
                            if (acc != null && user != null && aconf != null &&
                                (acc.LastLobbyVersionCheck == null || DateTime.UtcNow.Subtract(acc.LastLobbyVersionCheck.Value).TotalDays > 3) &&
                                aconf.AutohostMode != 0)
                            {
                                client.RequestLobbyVersion(user.Name);
                            }

                            /*
                             * if (acc != null)
                             * {
                             *  int numIDs = acc.AccountUserIDS != null ? acc.AccountUserIDS.Count : 0;
                             *  if (numIDs == 0) client.Say(TasClient.SayPlace.User, "KingRaptor", string.Format("USER {0} joined battle {1}; has {2} userIDs; lobby version {3}", acc.Name, founder.Name, numIDs, acc.LobbyVersion), false);
                             * }
                             * else
                             *  client.Say(TasClient.SayPlace.User, "KingRaptor", string.Format("USER {0} joined battle {1}", e.UserName + " (NO ACCOUNT)", founder.Name), false);
                             *
                             * if (acc != null)
                             * {
                             *  if (!acc.AccountUserIDS.Any())
                             *  {
                             *      string reason = string.Format("Sorry you are using unsupported lobby ({0}), please upgrade or use Zero-K Lobby, Weblobby or SpringLobby", acc.LobbyVersion);
                             *      client.Say(TasClient.SayPlace.User, user.Name, reason, false);
                             *      client.Say(TasClient.SayPlace.User, founder.Name, string.Format("!kick {0} {1}", acc.LobbyVersion, reason), false);
                             *  }
                             * }*/
                        }
                    }
                    catch (Exception ex)
                    {
                        //client.Say(TasClient.SayPlace.User, "KingRaptor", ex.ToString(), false);
                        Trace.TraceError("Error procesisng battle user joined: {0}", ex);
                    }
                }
            };

            this.client.TestLoginDenied += (s, e) =>
            {
                RequestInfo entry;
                if (requests.TryGetValue(client.MessageID, out entry))
                {
                    entry.WaitHandle.Set();
                }
                requests.TryRemove(client.MessageID, out entry);
            };

            this.client.UserLobbyVersionRecieved += (s, e) =>
            {
                using (var db = new ZkDataContext())
                {
                    var acc = Account.AccountByName(db, e.Name);
                    if (acc != null)
                    {
                        acc.LobbyVersion          = e.LobbyVersion;
                        acc.LastLobbyVersionCheck = DateTime.UtcNow;
                        db.SubmitAndMergeChanges();
                        if (!acc.LobbyVersion.StartsWith("ZK"))
                        {
                            // FIXME abma broke this (LobbyVersion is now some huge-ass integer instead)
                            //client.Say(TasClient.SayPlace.User,
                            //           e.Name,
                            //           string.Format(
                            //               "WARNING: You are connected using {0} which is not fully compatible with this host. Please use Zero-K lobby. Download it from http://zero-k.info   NOTE: to play all Spring games with Zero-K lobby, untick \"Official games\" on its multiplayer tab. Thank you!",
                            //               e.LobbyVersion),
                            //           false);
                        }
                    }
                }
            };

            this.client.BattleFound +=
                (s, e) => { if (e.Data.Founder.IsZkLobbyUser && !e.Data.Founder.IsBot)
                            {
                                client.SetBotMode(e.Data.Founder.Name, true);
                            }
            };

            this.client.ChannelUserAdded += (sender, args) =>
            {
                try
                {
                    var channel = args.ServerParams[0];
                    var user    = args.ServerParams[1];
                    if (channel == ModeratorChannel)
                    {
                        var u = client.ExistingUsers[user];
                        if (u.SpringieLevel <= 2 && !u.IsZeroKAdmin)
                        {
                            client.ForceLeaveChannel(user, ModeratorChannel);
                        }
                    }
                    else if (channel == Top20Channel)
                    {
                        var u = client.ExistingUsers[user];
                        if (!topPlayers.IsTop20(u.LobbyID) && u.Name != client.UserName)
                        {
                            client.ForceLeaveChannel(user, Top20Channel);
                        }
                    }
                    else
                    {
                        using (var db = new ZkDataContext())
                        {
                            var fac = db.Factions.FirstOrDefault(x => x.Shortcut == channel);
                            if (fac != null)
                            {
                                // faction channel
                                var u   = client.ExistingUsers[user];
                                var acc = Account.AccountByLobbyID(db, u.LobbyID);
                                if (acc == null || acc.FactionID != fac.FactionID || acc.Level < GlobalConst.FactionChannelMinLevel)
                                {
                                    client.ForceLeaveChannel(user, channel);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error procesisng channel user added: {0}", ex);
                }
            };
            this.client.ChannelUserRemoved += (sender, args) =>
            {
                try
                {
                    var channel = args.ServerParams[0];
                    var user    = args.ServerParams[1];
                    if (channel == ModeratorChannel)
                    {
                        var u = client.ExistingUsers[user];
                        if (u.SpringieLevel > 2 || u.IsZeroKAdmin)
                        {
                            client.ForceJoinChannel(user, ModeratorChannel);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error procesisng channel user added: {0}", ex);
                }
            };
        }