Esempio n. 1
0
        public void FriendActionRequest(ChatSession session, FriendActionReqMessage message)
        {
            var plr = session.Player;

            if (message.AccountId == plr.Account.Id)
            {
                return;
            }

            using (var authdb = AuthDatabase.Open())
                using (var db = GameDatabase.Open())
                {
                    var target = DbUtil.Find <AccountDto>(authdb, statement => statement
                                                          .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                          .WithParameters(new { Id = message.AccountId })).FirstOrDefault();

                    var targetPlayerAccount = DbUtil.Find <PlayerDto>(db, statement => statement
                                                                      .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                                      .WithParameters(new { Id = message.AccountId })).FirstOrDefault();

                    if (target == null || targetPlayerAccount == null)
                    {
                        plr.SendAsync(new FriendActionAckMessage
                        {
                            Friend = new FriendDto(),
                            Result = FriendResult.UserNotExist,
                            Unk    = 0
                        });
                        return;
                    }

                    var targetPlayer = GameServer.Instance.PlayerManager.Get(message.AccountId);
                    session.Player.FriendManager.GetValue(message.AccountId, out var friend);

                    switch (message.Action)
                    {
                    case FriendAction.Add:
                        if (friend != null)
                        {
                            plr.SendAsync(new ServerResultAckMessage(ServerResult.DBError));
                            return;
                        }

                        var settingMananger = new PlayerSettingManager(null, targetPlayerAccount);
                        switch (settingMananger.GetSetting("AllowFriendRequest"))
                        {
                        case CommunitySetting.Allow:
                            friend = plr.FriendManager.AddOrUpdate(message.AccountId, targetPlayer,
                                                                   FriendState.Requesting, FriendState.RequestDialog);

                            session.SendAsync(new FriendActionAckMessage
                            {
                                Friend = friend.GetFriend(),
                                Result = FriendResult.Ok,
                                Unk    = 0
                            });

                            if (targetPlayer != null)
                            {
                                targetPlayer.ChatSession?.SendAsync(new FriendActionAckMessage
                                {
                                    Friend = friend.GetPlayer(),
                                    Result = FriendResult.Ok,
                                    Unk    = 0
                                });
                            }

                            break;

                        case CommunitySetting.Deny:
                            session.SendAsync(new FriendActionAckMessage
                            {
                                Friend = new FriendDto(),
                                Result = FriendResult.UserNotExist,
                                Unk    = 0
                            });
                            break;
                        }

                        break;

                    case FriendAction.Decline:
                    case FriendAction.Remove:
                        if (friend == null)
                        {
                            plr.SendAsync(new ServerResultAckMessage(ServerResult.DBError));
                            return;
                        }

                        friend.PlayerState = FriendState.NotInList;
                        friend.FriendState = FriendState.NotInList;
                        plr.FriendManager.Remove(message.AccountId, targetPlayer);

                        session.SendAsync(new FriendActionAckMessage
                        {
                            Friend = friend.GetFriend(),
                            Result = FriendResult.Ok,
                            Unk    = 0
                        });
                        session.SendAsync(
                            new FriendListAckMessage(plr.FriendManager.Select(d => d.GetFriend())
                                                     .Where(x => x.State != 0).ToArray()));

                        if (targetPlayer != null)
                        {
                            targetPlayer.ChatSession?.SendAsync(new FriendActionAckMessage
                            {
                                Friend = friend.GetPlayer(),
                                Result = FriendResult.Ok,
                                Unk    = 0
                            });
                            targetPlayer.ChatSession?.SendAsync(
                                new FriendListAckMessage(targetPlayer.FriendManager.Select(d => d.GetFriend())
                                                         .Where(x => x.State != 0).ToArray()));
                        }

                        break;

                    case FriendAction.Update:
                        if (friend == null)
                        {
                            plr.SendAsync(new ServerResultAckMessage(ServerResult.DBError));
                            return;
                        }

                        friend = plr.FriendManager.AddOrUpdate(message.AccountId, targetPlayer,
                                                               FriendState.InList, FriendState.InList);

                        session.SendAsync(new FriendActionAckMessage
                        {
                            Friend = friend.GetFriend(),
                            Result = FriendResult.Ok,
                            Unk    = 0
                        });

                        if (targetPlayer != null)
                        {
                            targetPlayer.ChatSession?.SendAsync(new FriendActionAckMessage
                            {
                                Friend = friend.GetPlayer(),
                                Result = FriendResult.Ok,
                                Unk    = 0
                            });
                        }

                        break;

                    default:
                        Console.WriteLine("UNKNOWN FriendAction:" + message.Action);
                        break;
                    }

                    targetPlayer?.SendAsync(new ChatPlayerInfoAckMessage(plr.Map <Player, PlayerInfoDto>()));
                    plr.SendAsync(new ChatPlayerInfoAckMessage(targetPlayerAccount.Map <PlayerDto, PlayerInfoDto>()));
                }
        }
Esempio n. 2
0
            public bool Execute(GameServer server, Player plr, string[] args)
            {
                if (args.Length < 1)
                {
                    plr.SendConsoleMessage(S4Color.Red + "Wrong Usage, possible usages:");
                    plr.SendConsoleMessage(S4Color.Red + "> level <username> <level>");
                    return(true);
                }

                if (args.Length >= 2)
                {
                    AccountDto account;
                    PlayerDto  playerdto;
                    using (var db = AuthDatabase.Open())
                    {
                        account = (db.Find <AccountDto>(statement => statement
                                                        .Include <BanDto>(join => join.LeftOuterJoin())
                                                        .Where($"{nameof(AccountDto.Nickname):C} = @Nickname")
                                                        .WithParameters(new { Nickname = args[0] })))
                                  .FirstOrDefault();

                        if (account == null)
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Unknown player!");
                            return(true);
                        }

                        playerdto = (db.Find <PlayerDto>(statement => statement
                                                         .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                         .WithParameters(new { account.Id })))
                                    .FirstOrDefault();

                        if (playerdto == null)
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Unknown player!");
                            return(true);
                        }
                        else
                        {
                            if (byte.TryParse(args[1], out var level))
                            {
                                plr.SendConsoleMessage(S4Color.Green + $"Changed {account.Nickname}'s level to {args[1]}");
                                plr.Level       = level;
                                playerdto.Level = level;
                                db.Update(playerdto);

                                var player = GameServer.Instance.PlayerManager.Get((ulong)account.Id);
                                if (player != null)
                                {
                                    player.Level = level;
                                    player.Session?.SendAsync(new PlayerAccountInfoAckMessage(player.Map <Player, PlayerAccountInfoDto>()));
                                    player.NeedsToSave = true;
                                }
                            }
                            else
                            {
                                plr.SendConsoleMessage(S4Color.Red + "Wrong Usage, possible usages:");
                                plr.SendConsoleMessage(S4Color.Red + "> level <username> <level>");
                            }
                        }
                    }
                }

                return(true);
            }
        private static async Task LoginAsync(IChannelHandlerContext context, string username, string password,
                                             string hwid, string secretkey)
        {
            // This var is used for sending the unban date to the launcher
            var unbandate = DateTimeOffset.Now;

            try
            {
                var endpoint = new IPEndPoint(((IPEndPoint)context.Channel.RemoteAddress).Address.MapToIPv4(),
                                              ((IPEndPoint)context.Channel.RemoteAddress).Port);
                if (username.Length >= 20)
                {
                    Logger.Error("Login & Password to long for {0}", endpoint);
                    var check = new CCMessage();
                    check.Write(false);
                    check.Write("Username is more than 20 chars");
                    RmiSend(context, 16, check);
                    return;
                }

                if (hwid == string.Empty)
                {
                    Logger.Error("No HWID found on endpoint {0}", endpoint);
                    var check = new CCMessage();
                    check.Write(false);
                    check.Write("Cannot Generate HWID");
                    RmiSend(context, 16, check);
                    return;
                }


                if (Config.Instance.AuthAPI.BlockedHWIDS.Contains(hwid))
                {
                    Logger.Error("Hwid ban(conf): {0}, Address: {1}", hwid, endpoint);
                    goto hwidban;
                }

                if (Config.Instance.LauncherCheck)
                {
                    // Launcher Check
                    if (secretkey != Config.Instance.LauncherCheckKey)
                    {
                        Logger.Error("Wrong Launcher => User: "******" hwid: " + hwid + " from " + endpoint);
                        var keycheck = new CCMessage();
                        keycheck.Write(false);
                        keycheck.Write("Invalid Launcher");
                        RmiSend(context, 16, keycheck);
                        return;
                    }
                }

                using (var db = AuthDatabase.Open())
                {
                    Logger.Information("AuthAPI login from {0}, HWID: {1}", endpoint, hwid);


                    if (username.Length < 4 || password.Length < 4)
                    {
                        Logger.Error("Too short credentials for {username} / {endpoint}", username, endpoint);
                        var lengtherr = new CCMessage();
                        lengtherr.Write(false);
                        lengtherr.Write("Invalid length of username/password");
                        RmiSend(context, 16, lengtherr);
                        return;
                    }

                    if (!Namecheck.IsNameValid(username))
                    {
                        Logger.Error("Invalid username for {username} / {endpoint}", username, endpoint);
                        var nickerr = new CCMessage();
                        nickerr.Write(false);
                        nickerr.Write("Username contains invalid characters");
                        RmiSend(context, 16, nickerr);
                        return;
                    }

                    var result = await db.FindAsync <AccountDto>(statement => statement
                                                                 .Where($"{nameof(AccountDto.Username):C} = @{nameof(username)}")
                                                                 .Include <BanDto>(join => join.LeftOuterJoin())
                                                                 .WithParameters(new { Username = username }));

                    var account = result.FirstOrDefault();

                    var hwidResult = await db.FindAsync <HwidBanDto>(statement => statement
                                                                     .Where($"{nameof(HwidBanDto.Hwid):C} = @{nameof(hwid)}")
                                                                     .WithParameters(new { Hwid = hwid }));

                    if (hwidResult?.Any() ?? false)
                    {
                        Logger.Error("Hwid ban(db): {0}, Address: {1}", hwid, endpoint);
                        goto hwidban;
                    }

                    if (account == null &&
                        (Config.Instance.NoobMode || Config.Instance.AutoRegister))
                    {
                        account = new AccountDto {
                            Username = username
                        };

                        var newSalt = new byte[24];
                        using (var csprng = new RNGCryptoServiceProvider())
                        {
                            csprng.GetBytes(newSalt);
                        }

                        var hash = new byte[24];
                        using (var pbkdf2 = new Rfc2898DeriveBytes(password, newSalt, 24000))
                        {
                            hash = pbkdf2.GetBytes(24);
                        }

                        account.Password = Convert.ToBase64String(hash);
                        account.Salt     = Convert.ToBase64String(newSalt);

                        await db.InsertAsync(account);
                    }

                    var salt = Convert.FromBase64String(account?.Salt ?? "");

                    var passwordGuess =
                        new Rfc2898DeriveBytes(password, salt, 24000).GetBytes(24);
                    var actualPassword =
                        Convert.FromBase64String(account?.Password ?? "");

                    var difference =
                        (uint)passwordGuess.Length ^ (uint)actualPassword.Length;

                    for (var i = 0;
                         i < passwordGuess.Length && i < actualPassword.Length;
                         i++)
                    {
                        difference |= (uint)(passwordGuess[i] ^ actualPassword[i]);
                    }

                    if ((difference != 0 ||
                         string.IsNullOrWhiteSpace(account?.Password ?? "")) &&
                        !Config.Instance.NoobMode)
                    {
                        Logger.Error("Wrong credentials for {username} / {endpoint}", username, endpoint);
                        goto wrong;
                    }

                    if (account != null)
                    {
                        var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                        var ban = account.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
                        if (ban != null)
                        {
                            var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                            unbandate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                            Logger.Error("{user} is banned until {until}", account.Username, unbanDate);
                            goto ban;
                        }

                        account.LoginToken = AuthHash
                                             .GetHash256(
                            $"{context.Channel.RemoteAddress}-{account.Username}-{account.Password}-{endpoint.Address.MapToIPv4()}")
                                             .ToLower();
                        account.LastLogin = $"{DateTimeOffset.UtcNow:yyyyMMddHHmmss}";
                        account.AuthToken = string.Empty;
                        account.newToken  = string.Empty;
                        await db.UpdateAsync(account);

                        var history = new AuthHistoryDto
                        {
                            Account   = account,
                            AccountId = account.Id,
                            Date      = DateTimeOffset.Now.ToUnixTimeSeconds(),
                            HWID      = hwid
                        };

                        await db.InsertAsync(history);

                        var ack = new CCMessage();
                        ack.Write(true);
                        ack.Write(account.LoginToken);
                        RmiSend(context, 16, ack);
                    }

                    Logger.Information("AuthAPI login success for {username}", username);
                    return;
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());
                goto error;
            }

wrong:
            {
                var error = new CCMessage();
                error.Write(false);
                error.Write("Invalid username or password");
                RmiSend(context, 16, error);
            }

error:
            {
                var error = new CCMessage();
                error.Write(false);
                error.Write("Login error");
                RmiSend(context, 16, error);
            }

ban:
            {
                var error = new CCMessage();
                error.Write(false);
                error.Write("Account is banned until " + unbandate);
                RmiSend(context, 16, error);
            }

hwidban:
            {
                var error = new CCMessage();
                error.Write(false);
                error.Write("You have been blocked");
                RmiSend(context, 16, error);
            }
        }
        public async void CharacterFirstCreateHandler(GameSession session, CharacterFirstCreateReqMessage message)
        {
            var plr  = session.Player;
            var cmng = plr.CharacterManager;

            if (!await AuthService.IsNickAvailableAsync(message.Nickname))
            {
                await session.SendAsync(new ServerResultAckMessage(ServerResult.NicknameUnavailable));

                return;
            }

            using (var db = AuthDatabase.Open())
            {
                var result = (await db.FindAsync <AccountDto>(smtp => smtp
                                                              .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                              .WithParameters(new { session.Player.Account.Id })
                                                              )).FirstOrDefault();

                if (result == null)
                {
                    await session.SendAsync(new ServerResultAckMessage(ServerResult.CreateCharacterFailed));

                    return;
                }

                result.Nickname = message.Nickname;
                await db.UpdateAsync(result);

                plr.Account.Nickname = message.Nickname;
            }

            try
            {
                cmng.Create(0, (CharacterGender)message.Gender, 0, 0, 0, 0);
                cmng.Select(0);
            }
            catch (CharacterException ex)
            {
                Logger.ForAccount(session)
                .Error(ex.Message);
                await session.SendAsync(new ServerResultAckMessage(ServerResult.CreateCharacterFailed));

                return;
            }

            await AuthService.LoginAsync(session);

            IEnumerable <StartItemDto> startItems;

            using (var db = GameDatabase.Open())
            {
                startItems = await db.FindAsync <StartItemDto>(statement => statement
                                                               .Where(
                                                                   $"{nameof(StartItemDto.RequiredSecurityLevel):C} <= @{nameof(plr.Account.SecurityLevel)}")
                                                               .WithParameters(new { plr.Account.SecurityLevel }));
            }

            foreach (var startItem in startItems)
            {
                var shop     = GameServer.Instance.ResourceCache.GetShop();
                var item     = shop.Items.Values.First(group => group.GetItemInfo(startItem.ShopItemInfoId) != null);
                var itemInfo = item.GetItemInfo(startItem.ShopItemInfoId);
                var effect   = itemInfo.EffectGroup.GetEffect(startItem.ShopEffectId);

                var price = itemInfo.PriceGroup.GetPrice(startItem.ShopPriceId);
                if (price == null)
                {
                    Logger.Warning("Cant find ShopPrice for Start item {startItemId} - Forgot to reload the cache?",
                                   startItem.Id);
                    continue;
                }

                var color = startItem.Color;
                if (color > item.ColorGroup)
                {
                    Logger.Warning("Start item {startItemId} has an invalid color {color}", startItem.Id, color);
                    color = 0;
                }

                var count = startItem.Count;
                if (count > 0 && item.ItemNumber.Category <= ItemCategory.Skill)
                {
                    Logger.Warning("Start item {startItemId} cant have stacks(quantity={count})", startItem.Id,
                                   count);
                    count = 0;
                }

                if (count < 0)
                {
                    count = 0;
                }
                var reteff = new List <uint>
                {
                    effect.Effect
                };
                plr.Inventory.Create(itemInfo, price, color, reteff.ToArray(), (uint)count);
            }

            try
            {
                foreach (var itemNumber in message.FirstItems)
                {
                    if (itemNumber != 0)
                    {
                        var pi = plr.Inventory.Create(itemNumber, ItemPriceType.PEN, ItemPeriodType.None, 0, 0, new uint[] { 0 }, 1);
                        cmng.CurrentCharacter.Costumes.Equip(pi, (CostumeSlot)pi.ItemNumber.SubCategory);
                    }
                }
            }
            catch (ArgumentException e)
            {
                Logger.Debug(e, "Problem creating new items");
            }
        }
        public override void ChannelRead(IChannelHandlerContext context, object messageData)
        {
            var buffer = messageData as IByteBuffer;
            var data   = new byte[0];

            if (buffer != null)
            {
                data = buffer.ToArray();
            }

            var   msg     = new CCMessage(data, data.Length);
            short magic   = 0;
            var   message = new ByteArray();

            if (msg.Read(ref magic) &&
                magic == Magic &&
                msg.Read(ref message))
            {
                var receivedMessage          = new CCMessage(message);
                CCMessage.MessageType coreId = 0;
                if (!receivedMessage.Read(ref coreId))
                {
                    return;
                }

                switch (coreId)
                {
                case CCMessage.MessageType.Rmi:
                    short rmiId = 0;
                    if (receivedMessage.Read(ref rmiId))
                    {
                        switch (rmiId)
                        {
                        case 15:
                        {
                            var username   = "";
                            var password   = "";
                            var register   = false;
                            var korealogin = false;

                            if (receivedMessage.Read(ref username) &&
                                receivedMessage.Read(ref password) &&
                                receivedMessage.Read(ref register))
                            {
                                //receivedMessage.Read(ref korealogin);

                                using (var db = AuthDatabase.Open())
                                {
                                    Logger.Information("Authentication login from {endpoint}",
                                                       context.Channel.RemoteAddress.ToString());

                                    if (username.Length > 5 && password.Length > 5)
                                    {
                                        var result = db.Find <AccountDto>(statement => statement
                                                                          .Where($"{nameof(AccountDto.Username):C} = @{nameof(username)}")
                                                                          .Include <BanDto>(join => @join.LeftOuterJoin())
                                                                          .WithParameters(new { Username = username }));

                                        var account = result.FirstOrDefault();

                                        if (account == null &&
                                            (Config.Instance.NoobMode || Config.Instance.AutoRegister))
                                        {
                                            account = new AccountDto {
                                                Username = username
                                            };

                                            var newSalt = new byte[24];
                                            using (var csprng = new RNGCryptoServiceProvider())
                                            {
                                                csprng.GetBytes(newSalt);
                                            }

                                            var hash = new Rfc2898DeriveBytes(password, newSalt, 24000).GetBytes(24);

                                            account.Password = Convert.ToBase64String(hash);
                                            account.Salt     = Convert.ToBase64String(newSalt);
                                            db.InsertAsync(account);
                                        }

                                        var salt = Convert.FromBase64String(account?.Salt ?? "");

                                        var passwordGuess  = new Rfc2898DeriveBytes(password, salt, 24000).GetBytes(24);
                                        var actualPassword = Convert.FromBase64String(account?.Password ?? "");

                                        var difference =
                                            (uint)passwordGuess.Length ^ (uint)actualPassword.Length;

                                        for (var i = 0;
                                             i < passwordGuess.Length && i < actualPassword.Length;
                                             i++)
                                        {
                                            difference |= (uint)(passwordGuess[i] ^ actualPassword[i]);
                                        }

                                        if ((difference != 0 ||
                                             string.IsNullOrWhiteSpace(account?.Password ?? "")) &&
                                            !Config.Instance.NoobMode)
                                        {
                                            Logger.Error(
                                                "Wrong authentication credentials for {username} / {endpoint}",
                                                username, context.Channel.RemoteAddress.ToString());
                                            var ack = new CCMessage();
                                            ack.Write(false);
                                            ack.Write("Login failed");
                                            RmiSend(context, 16, ack);
                                        }
                                        else
                                        {
                                            if (account != null)
                                            {
                                                account.LoginToken = AuthHash
                                                                     .GetHash256(
                                                    $"{context.Channel.RemoteAddress}-{account.Username}-{account.Password}")
                                                                     .ToLower();
                                                account.LastLogin = $"{DateTimeOffset.Now}";
                                                account.AuthToken = "";
                                                account.newToken  = "";
                                                db.UpdateAsync(account);

                                                var ack = new CCMessage();
                                                ack.Write(true);
                                                ack.Write(account.LoginToken);
                                                //ack.Write(korealogin);
                                                RmiSend(context, 16, ack);
                                            }
                                            Logger.Information("Authentication success for {username}",
                                                               username);
                                        }
                                    }
                                    else
                                    {
                                        Logger.Error(
                                            "Wrong authentication credentials for {username} / {endpoint}",
                                            username, context.Channel.RemoteAddress.ToString());
                                        var ack = new CCMessage();
                                        ack.Write(false);
                                        ack.Write("Invalid length of username/password");
                                        RmiSend(context, 16, ack);
                                    }
                                }
                            }
                            else
                            {
                                Logger.Error("Wrong login for {endpoint}",
                                             context.Channel.RemoteAddress.ToString());
                                var ack = new CCMessage();
                                ack.Write(false);
                                ack.Write("Invalid loginpacket");
                                RmiSend(context, 16, ack);
                            }
                            break;
                        }

                        case 17:
                            context.CloseAsync();
                            break;

                        default:
                            Logger.Error("Received unknown rmiId{rmi} from {endpoint}", rmiId,
                                         context.Channel.RemoteAddress.ToString());
                            break;
                        }
                    }
                    break;

                case CCMessage.MessageType.Notify:
                    context.CloseAsync();
                    //var info = "";
                    //receivedMessage.Read(ref info);
                    //Logger.Information("Received info! -> {received}", info);
                    break;

                default:
                    Logger.Error("Received unknown coreID{coreid} from {endpoint}", coreId,
                                 context.Channel.RemoteAddress.ToString());
                    break;
                }
            }
            else
            {
                Logger.Error("Received invalid packetstruct from {endpoint}", context.Channel.RemoteAddress.ToString());
                context.CloseAsync();
            }
        }
Esempio n. 6
0
        public static async Task LoginAsync(GameSession session)
        {
            var plr = session.Player;

            plr.LoggedIn = true;

            try
            {
                using (var db = AuthDatabase.Open())
                {
                    var account = db.Find <AccountDto>(statement => statement
                                                       .Where($"{nameof(AccountDto.Id):C} = @{nameof(session.Player.Account.Id)}")
                                                       .WithParameters(new { session.Player.Account.Id })).FirstOrDefault();

                    if (account != null && account.IsServer)
                    {
                        account.IsServer = false;
                        DbUtil.Update(db, account);
                    }
                }

                plr?.SendAsync(new MoneyRefreshCashInfoAckMessage(plr.PEN, plr.AP));
                plr?.SendAsync(new CharacterCurrentSlotInfoAckMessage
                {
                    ActiveCharacter = plr.CharacterManager.CurrentSlot,
                    CharacterCount  = (byte)plr.CharacterManager.Count,
                    MaxSlots        = 3
                });

                plr?.SendAsync(new MoenyRefreshCoinInfoAckMessage(plr.Coins1, plr.Coins2));
                plr?.SendAsync(new ShoppingBasketListInfoAckMessage());

                foreach (var data in ArraySplitter.Split(
                             plr.Inventory.Select(i => i.Map <PlayerItem, ItemDto>()).ToArray(),
                             300))
                {
                    plr?.SendAsync(new ItemInventoryInfoAckMessage(data));
                }

                plr?.SendAsync(new PlayeArcadeMapInfoAckMessage());
                plr?.SendAsync(new PlayerArcadeStageInfoAckMessage());
                plr?.SendAsync(new ClubMyInfoAckMessage(plr.Map <Player, ClubMyInfoDto>()));

                foreach (var @char in plr.CharacterManager)
                {
                    plr?.SendAsync(new CharacterCurrentInfoAckMessage
                    {
                        Slot  = @char.Slot,
                        Style = new CharacterStyle(@char.Gender, @char.Slot)
                    });

                    plr?.SendAsync(new CharacterCurrentItemInfoAckMessage
                    {
                        Slot    = @char.Slot,
                        Weapons = @char.Weapons.GetItems().Select(i => i?.Id ?? 0).ToArray(),
                        Skills  = new[] { @char.Skills.GetItem(SkillSlot.Skill)?.Id ?? 0 },
                        Clothes = @char.Costumes.GetItems().Select(i => i?.Id ?? 0).ToArray()
                    });
                }
            }
            finally
            {
                plr?.SendAsync(new ItemEquipBoostItemInfoAckMessage());
                plr?.SendAsync(new EspherChipLv5Message());
                plr?.SendAsync(new ItemClearInvalidEquipItemAckMessage());
                plr?.SendAsync(new ItemClearEsperChipAckMessage());
                plr?.SendAsync(new MapOpenInfosMessage());
                await plr.SendAsync(new PlayerAccountInfoAckMessage(plr.Map <Player, PlayerAccountInfoDto>()));

                await plr.SendAsync(new ServerResultAckMessage(ServerResult.WelcomeToS4World));
            }
        }
Esempio n. 7
0
        public async Task KRLoginHandler(ProudSession session, LoginKRReqMessage message)
        {
            var ip = session.RemoteEndPoint.Address.ToString();

            var account = new AccountDto();

            using (var db = AuthDatabase.Open())
            {
                if (message.AccountHashCode != "")
                {
                    Logger.Information($"Login from {ip}");

                    var result = await db.FindAsync <AccountDto>(statement => statement
                                                                 .Where($"{nameof(AccountDto.LoginToken):C} = @{nameof(message.AccountHashCode)}")
                                                                 .Include <BanDto>(join => join.LeftOuterJoin())
                                                                 .WithParameters(new { message.AccountHashCode }));

                    account = result.FirstOrDefault();

                    if (account != null)
                    {
                        if ((DateTimeOffset.Now - DateTimeOffset.Parse(account.LastLogin)).Minutes >= 5)
                        {
                            await session.SendAsync(new LoginKRAckMessage(AuthLoginResult.Failed2));

                            Logger.Error("Wrong login for {ip}", ip);
                            return;
                        }
                    }
                    else
                    {
                        await session.SendAsync(new LoginKRAckMessage(AuthLoginResult.Failed2));

                        Logger.Error("Wrong login for {ip}", ip);
                        return;
                    }
                }
                else if (message.AuthToken != "" && message.NewToken != "")
                {
                    Logger.Information("Session login from {ip}", ip);

                    var result = await db.FindAsync <AccountDto>(statement => statement
                                                                 .Where($"{nameof(AccountDto.AuthToken):C} = @{nameof(message.AuthToken)}")
                                                                 .Include <BanDto>(join => join.LeftOuterJoin())
                                                                 .WithParameters(new { message.AuthToken }));

                    account = result.FirstOrDefault();

                    if (account != null)
                    {
                        if (account.AuthToken != message.AuthToken && account.newToken != message.NewToken)
                        {
                            await session.SendAsync(new LoginKRAckMessage(AuthLoginResult.Failed2));

                            Logger.Error("Wrong session login for {ip} ({AuthToken}, {newToken})", ip,
                                         account.AuthToken, account.newToken);
                            return;
                        }
                    }
                    else
                    {
                        await session.SendAsync(new LoginKRAckMessage(AuthLoginResult.Failed2));

                        Logger.Error("Wrong session login for {ip}", ip);
                        return;
                    }
                }

                var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                var ban = account.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
                if (ban != null)
                {
                    var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                    Logger.Error("{user} is banned until {until}", account.Username, unbanDate);
                    await session.SendAsync(new LoginKRAckMessage(unbanDate));

                    return;
                }

                Logger.Information("Login success for {user}", account.Username);

                var entry = new LoginHistoryDto
                {
                    AccountId = account.Id,
                    Date      = DateTimeOffset.Now.ToUnixTimeSeconds(),
                    IP        = ip
                };
                await db.InsertAsync(entry);
            }


            var datetime      = $"{DateTimeOffset.Now.DateTime}";
            var sessionId     = Hash.GetUInt32 <CRC32>($"<{account.Username}+{account.Password}>");
            var authsessionId = Hash.GetString <CRC32>($"<{account.Username}+{sessionId}+{datetime}>");
            var newsessionId  = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>");

            using (var db = AuthDatabase.Open())
            {
                account.LoginToken = "";
                account.AuthToken  = authsessionId;
                account.newToken   = newsessionId;
                await db.UpdateAsync(account);
            }
            await session.SendAsync(new LoginKRAckMessage(AuthLoginResult.OK, (ulong)account.Id, sessionId, authsessionId,
                                                          newsessionId, datetime));
        }
Esempio n. 8
0
        public async Task <bool> Execute(GameServer server, Player plr, string[] args)
        {
            if (args.Length < 1)
            {
                plr.SendConsoleMessage(S4Color.Red + "Wrong Usage, possible usages:");
                plr.SendConsoleMessage(S4Color.Red + "> /ban <username> roomkick - roomkick");
                plr.SendConsoleMessage(S4Color.Red + "> /ban <username> - permanent ban");
                plr.SendConsoleMessage(S4Color.Red + "> /ban <username> pardon - unban");
                plr.SendConsoleMessage(S4Color.Red + "> /ban <username> days <duration(days)> - ban for x days");
                plr.SendConsoleMessage(S4Color.Red + "> /ban <username> mins <duration(minutes)> - ban for x minutes");
                plr.SendConsoleMessage(S4Color.Red + "> /ban <username> secs <duration(seconds)> - ban for x seconds");
                plr.SendConsoleMessage(S4Color.Red +
                                       "> /ban <username> <currentdate(ex:20180130)> <unk> <duration(seconds)>");
                return(true);
            }

            if (args.Length < 2)
            {
                Array.Resize(ref args, args.Length + 1);
                args[1] = "none";
            }

            var unban             = false;
            var nickname          = args[0];
            var durationInSeconds = 0;

            try
            {
                AccountDto account;
                switch (args[1])
                {
                case "pardon":
                    unban = true;
                    break;

                case "roomkick":
                    using (var db = AuthDatabase.Open())
                    {
                        account = (await DbUtil.FindAsync <AccountDto>(db, statement => statement
                                                                       .Include <BanDto>(join => join.LeftOuterJoin())
                                                                       .Where($"{nameof(AccountDto.Nickname):C} = @Nickname")
                                                                       .WithParameters(new { Nickname = nickname }))
                                   ).FirstOrDefault();

                        if (account == null)
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Unknown player");
                            return(true);
                        }

                        var player = GameServer.Instance.PlayerManager.Get((ulong)account.Id);
                        if (player == null)
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Player is not online");
                            return(true);
                        }

                        player.Room?.Leave(player, RoomLeaveReason.ModeratorKick);
                        plr.SendConsoleMessage(S4Color.Green + $"Kicked {account.Nickname} out of room");
                    }

                    return(true);

                case "secs":
                    int.TryParse(args[2], out durationInSeconds);
                    break;

                case "mins":
                    int.TryParse(args[2], out var durationInMinutes);
                    durationInSeconds = durationInMinutes * 60;
                    break;

                case "days":
                    int.TryParse(args[2], out var durationInDays);
                    durationInSeconds = durationInDays * 24 * 60 * 60; //days->hours->minutes->seconds
                    break;

                default:
                    if (DateTimeOffset.TryParseExact(args[1], "yyyyMMdd", CultureInfo.InvariantCulture,
                                                     DateTimeStyles.None, out _))
                    {
                        if (args.Length >= 4)
                        {
                            int.TryParse(args[2], out var unk);
                            int.TryParse(args[3], out var durationInMs);
                            durationInSeconds = durationInMs / 60;
                        }
                    }
                    else
                    {
                        durationInSeconds = (int)TimeSpan.FromDays(10 * 365).TotalSeconds;
                    }

                    break;
                }

                using (var db = AuthDatabase.Open())
                {
                    account = (await DbUtil.FindAsync <AccountDto>(db, statement => statement
                                                                   .Include <BanDto>(join => join.LeftOuterJoin())
                                                                   .Where($"{nameof(AccountDto.Nickname):C} = @Nickname")
                                                                   .WithParameters(new { Nickname = nickname }))
                               ).FirstOrDefault();

                    if (account == null)
                    {
                        plr.SendConsoleMessage(S4Color.Red + "Unknown player");
                        return(true);
                    }

                    if (unban)
                    {
                        foreach (var accountBan in account.Bans)
                        {
                            accountBan.Duration = 0;
                            await DbUtil.UpdateAsync(db, accountBan);
                        }

                        await DbUtil.UpdateAsync(db, account);

                        CommandManager.Logger.Information(
                            $"{plr?.Account?.Nickname ?? "Unknown player"} has unbanned {account.Nickname}");
                        plr?.SendConsoleMessage(S4Color.Green + $"Unbanned {account.Nickname}");
                    }
                    else
                    {
                        if (plr.Account.SecurityLevel <= (SecurityLevel)account.SecurityLevel)
                        {
                            plr.SendConsoleMessage($"You cannot ban this player");
                            return(true);
                        }

                        var duration = TimeSpan.FromSeconds(durationInSeconds);

                        var ban = new BanDto
                        {
                            AccountId = account.Id,
                            Account   = account,
                            Date      = 0,
                            Duration  = DateTimeOffset.Now.Add(duration).ToUnixTimeSeconds(),
                            Reason    = $"GMConsole - {plr?.Account?.Nickname ?? "n/A"}"
                        };

                        var player = GameServer.Instance.PlayerManager.Get((ulong)account.Id);
                        player?.Session?.CloseAsync();

                        await DbUtil.InsertAsync(db, ban);

                        await DbUtil.UpdateAsync(db, account);

                        var uptime = new StringBuilder();
                        if (duration.Days > 0)
                        {
                            uptime.AppendFormat("{0} days ", duration.Days);
                        }
                        if (duration.Hours > 0)
                        {
                            uptime.AppendFormat("{0} hours ", duration.Hours);
                        }
                        if (duration.Minutes > 0)
                        {
                            uptime.AppendFormat("{0} minutes ", duration.Minutes);
                        }
                        if (duration.Seconds > 0)
                        {
                            uptime.AppendFormat("{0} seconds ", duration.Seconds);
                        }

                        CommandManager.Logger.Information(
                            $"{plr?.Account?.Nickname ?? "Unknown player"} has banned {account.Nickname} for {uptime}");
                        plr?.SendConsoleMessage(S4Color.Green + $"Banned {account.Nickname} for {uptime}");
                    }
                }
            }
            catch (Exception)
            {
                plr.SendConsoleMessage(S4Color.Red + "Unknown player");
            }

            return(true);
        }
Esempio n. 9
0
        private static async void LoginAsync(IChannelHandlerContext context, string username, string password, string hwid, string test)
        {
            lock (_loginSync)
            {
                try
                {
                    using (var db = AuthDatabase.Open())
                    {
                        Logger.Information("Authentication login from {endpoint}",
                            context.Channel.RemoteAddress.ToString());

                        if (test != "test")
                            goto loginerror;

                        var hwidban = db.Find<HwidBanDto>(statement => statement
                        .Where(
                            $"{nameof(HwidBanDto.Hwid):C} = @{nameof(hwid)}")
                        .WithParameters(new { hwid }));

                        if (hwidban.Any())
                        {
                            Logger.Error("Hwid ban {0} for {1}", hwid, context.Channel.RemoteAddress);
                            goto HwidBan;
                        }

                        if (username.Length > 5 && password.Length > 5 &&
                            Namecheck.IsNameValid(username))
                        {
                            var result = db.Find<AccountDto>(statement => statement
                                .Where(
                                    $"{nameof(AccountDto.Username):C} = @{nameof(username)}")
                                .WithParameters(new { Username = username }));

                            var account = result.FirstOrDefault();

                            if (account == null &&
                                (Config.Instance.NoobMode || Config.Instance.AutoRegister))
                            {
                                account = new AccountDto { Username = username };

                                var newSalt = new byte[24];
                                using (var csprng = new RNGCryptoServiceProvider())
                                {
                                    csprng.GetBytes(newSalt);
                                }

                                var hash = new byte[24];
                                using (var pbkdf2 = new Rfc2898DeriveBytes(password, newSalt, 24000))
                                {
                                    hash = pbkdf2.GetBytes(24);
                                }

                                account.Password = Convert.ToBase64String(hash);
                                account.Salt = Convert.ToBase64String(newSalt);

                                db.InsertAsync(account);
                            }

                             var ban = db.Find<BanDto>(statement => statement
                                .Where($"{nameof(BanDto.AccountId):C} = @{nameof(account.Id)}")
                                .WithParameters(new { account.Id })).FirstOrDefault();

                            if (ban != null)
                            {
                                var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                                Logger.Error("{user} is banned until {until}", account.Username, unbanDate);

                                CCMessage error = new CCMessage();
                                error.Write(false);
                                error.Write("You ban until " + unbanDate);
                                RmiSend(context, 16, error);
                            }

                            var salt = Convert.FromBase64String(account?.Salt ?? "");

                            var passwordGuess =
                                new Rfc2898DeriveBytes(password, salt, 24000).GetBytes(24);
                            var actualPassword =
                                Convert.FromBase64String(account?.Password ?? "");

                            var difference =
                                (uint)passwordGuess.Length ^ (uint)actualPassword.Length;

                            for (var i = 0;
                                i < passwordGuess.Length && i < actualPassword.Length;
                                i++)
                                difference |= (uint)(passwordGuess[i] ^ actualPassword[i]);

                            if ((difference != 0 ||
                                 string.IsNullOrWhiteSpace(account?.Password ?? "")) &&
                                !Config.Instance.NoobMode)
                            {
                                Logger.Error(
                                    "Wrong authentication credentials for {username} / {endpoint}",
                                    username, context.Channel.RemoteAddress.ToString());
                                var ack = new CCMessage();
                                ack.Write(false);
                                ack.Write("Login failed");
                                RmiSend(context, 16, ack);
                            }
                            else
                            {
                                if (account != null)
                                {
                                    account.LoginToken = AuthHash
                                        .GetHash256(
                                            $"{context.Channel.RemoteAddress}-{account.Username}-{account.Password}")
                                        .ToLower();
                                    account.LastLogin =
                                        $"{DateTimeOffset.UtcNow:yyyyMMddHHmmss}";
                                    account.AuthToken = "";
                                    account.newToken = "";
                                    db.UpdateAsync(account);

                                    var ack = new CCMessage();
                                    ack.Write(true);
                                    ack.Write(account.LoginToken);
                                    RmiSend(context, 16, ack);
                                }

                                var authhistory = new AuthHistoryDto()
                                {
                                    AccountId = account.Id,
                                    Date = DateTime.UtcNow.ToString(),
                                    HWID = hwid
                                };
                                db.Insert(authhistory);

                                Logger.Information("Authentication success for {username}",
                                    username);

                                if (account.LoginToken != "" && account.LoginToken.Length == 64)
                                {
                                    account.IsConnect = true;
                                    db.Update(account);
                                }
                            }
                        }
                        else
                        {
                            Logger.Error(
                                "Wrong authentication credentials for {username} / {endpoint}",
                                username, context.Channel.RemoteAddress.ToString());
                            var ack = new CCMessage();
                            ack.Write(false);
                            ack.Write("Invalid length of username/password");
                            RmiSend(context, 16, ack);
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e.ToString());
                    var ack = new CCMessage();
                    ack.Write(false);
                    ack.Write("Login Error");
                    RmiSend(context, 16, ack);
                }

                HwidBan:
                {
                    var error = new CCMessage();
                    error.Write(false);
                    error.Write("You Banned.");
                    RmiSend(context, 16, error);
                    return;
                }
                loginerror:
                {
                    var error = new CCMessage();
                    error.Write(false);
                    error.Write("Failed to login.");
                    RmiSend(context, 16, error);
                    return;
                }
            }
        }
Esempio n. 10
0
        public async Task EULoginHandler(ProudSession session, LoginEUReqMessage message)
        {
            var ip = session.RemoteEndPoint.Address.ToString();

            var account = new AccountDto();

            using (var db = AuthDatabase.Open())
            {
                if (message.Username != "" && message.Password != "")
                {
                    Logger.Information($"Login from {ip}");

                    if (message.Username.Length > 5 && message.Password.Length > 5)
                    {
                        var result = db.Find <AccountDto>(statement => statement
                                                          .Where($"{nameof(AccountDto.Username):C} = @{nameof(message.Username)}")
                                                          .Include <BanDto>(join => join.LeftOuterJoin())
                                                          .WithParameters(new { message.Username }));

                        account = result.FirstOrDefault();

                        if (account == null && (Config.Instance.NoobMode || Config.Instance.AutoRegister))
                        {
                            account = new AccountDto {
                                Username = message.Username
                            };

                            var newSalt = new byte[24];
                            using (var csprng = new RNGCryptoServiceProvider())
                            {
                                csprng.GetBytes(newSalt);
                            }

                            var hash = new Rfc2898DeriveBytes(message.Password, newSalt, 24000).GetBytes(24);

                            account.Password = Convert.ToBase64String(hash);
                            account.Salt     = Convert.ToBase64String(newSalt);
                            await db.InsertAsync(account);
                        }

                        var salt = Convert.FromBase64String(account?.Salt ?? "");

                        var passwordGuess  = new Rfc2898DeriveBytes(message.Password, salt, 24000).GetBytes(24);
                        var actualPassword = Convert.FromBase64String(account?.Password ?? "");

                        var difference = (uint)passwordGuess.Length ^ (uint)actualPassword.Length;

                        for (var i = 0;
                             i < passwordGuess.Length && i < actualPassword.Length;
                             i++)
                        {
                            difference |= (uint)(passwordGuess[i] ^ actualPassword[i]);
                        }

                        if ((difference != 0 ||
                             string.IsNullOrWhiteSpace(account?.Password ?? "")) &&
                            !Config.Instance.NoobMode)
                        {
                            await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.WrongIdorPw));

                            Logger.Error("Wrong login for {ip}", ip);
                            return;
                        }

                        if (account != null)
                        {
                            account.LastLogin = $"{DateTimeOffset.Now}";
                            account.AuthToken = "";
                            account.newToken  = "";
                            await db.UpdateAsync(account);
                        }
                    }
                    else
                    {
                        await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.WrongIdorPw));

                        Logger.Error("Wrong login for {ip}", ip);
                        return;
                    }
                }
                else if (message.token != "")
                {
                    Logger.Information($"Login from {ip}");

                    var result = await db.FindAsync <AccountDto>(statement => statement
                                                                 .Where($"{nameof(AccountDto.LoginToken):C} = @{nameof(message.token)}")
                                                                 .Include <BanDto>(join => join.LeftOuterJoin())
                                                                 .WithParameters(new { message.token }));

                    account = result.FirstOrDefault();

                    if (account != null)
                    {
                        if ((DateTimeOffset.Now - DateTimeOffset.Parse(account.LastLogin)).Minutes >= 5)
                        {
                            await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.Failed2));

                            Logger.Error("Wrong login for {ip}", ip);
                            return;
                        }
                    }
                    else
                    {
                        await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.Failed2));

                        Logger.Error("Wrong login for {ip}", ip);
                        return;
                    }
                }
                else if (message.AuthToken != "" && message.NewToken != "")
                {
                    Logger.Information("Session login from {ip}", ip);

                    var result = await db.FindAsync <AccountDto>(statement => statement
                                                                 .Where($"{nameof(AccountDto.AuthToken):C} = @{nameof(message.AuthToken)}")
                                                                 .Include <BanDto>(join => join.LeftOuterJoin())
                                                                 .WithParameters(new { message.AuthToken }));

                    account = result.FirstOrDefault();

                    if (account != null)
                    {
                        if (account.AuthToken != message.AuthToken && account.newToken != message.NewToken)
                        {
                            await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.Failed2));

                            Logger.Error("Wrong session login for {ip} ({AuthToken}, {newToken})", ip,
                                         account.AuthToken, account.newToken);
                            return;
                        }
                    }
                    else
                    {
                        await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.Failed2));

                        Logger.Error("Wrong session login for {ip}", ip);
                        return;
                    }
                }

                var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                var ban = account.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
                if (ban != null)
                {
                    var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                    Logger.Error("{user} is banned until {until}", account.Username, unbanDate);
                    await session.SendAsync(new LoginEUAckMessage(unbanDate));

                    return;
                }

                Logger.Information("Login success for {user}", account.Username);

                var entry = new LoginHistoryDto
                {
                    AccountId = account.Id,
                    Date      = DateTimeOffset.Now.ToUnixTimeSeconds(),
                    IP        = ip
                };
                await db.InsertAsync(entry);
            }


            var datetime      = $"{DateTimeOffset.Now.DateTime}";
            var sessionId     = Hash.GetUInt32 <CRC32>($"<{account.Username}+{account.Password}>");
            var authsessionId = Hash.GetString <CRC32>($"<{account.Username}+{sessionId}+{datetime}>");
            var newsessionId  = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>");

            using (var db = AuthDatabase.Open())
            {
                account.LoginToken = "";
                account.AuthToken  = authsessionId;
                account.newToken   = newsessionId;
                await db.UpdateAsync(account);
            }
            await session.SendAsync(new LoginEUAckMessage(AuthLoginResult.OK, (ulong)account.Id, sessionId, authsessionId,
                                                          newsessionId, datetime));
        }
Esempio n. 11
0
            public async Task<bool> Execute(GameServer server, Player plr, string[] args)
            {
                if (args.Length < 1)
                {
                    plr.SendConsoleMessage(S4Color.Red + "Wrong Usage, possible usages:");
                    plr.SendConsoleMessage(S4Color.Red + "> level <nickname> <level>");
                    return true;
                }

                if (args.Length >= 2)
                {
                    AccountDto account;
                    using (var db = AuthDatabase.Open())
                    {
                        account = (await DbUtil.FindAsync<AccountDto>(db, statement => statement
                            .Include<BanDto>(join => join.LeftOuterJoin())
                            .Where($"{nameof(AccountDto.Nickname):C} = @Nickname")
                            .WithParameters(new { Nickname = args[0] }))).FirstOrDefault();

                        if (account == null)
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Unknown player");
                            return true;
                        }

                        var playerdto = (await DbUtil.FindAsync<PlayerDto>(db, statement => statement
                                .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                .WithParameters(new { account.Id }))
                            ).FirstOrDefault();

                        if (playerdto == null)
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Unknown player");
                            return true;
                        }

                        if (byte.TryParse(args[1], out var level))
                        {
                            var expTable = GameServer.Instance.ResourceCache.GetExperience();

                            if (expTable.TryGetValue(level, out var exp))
                            {
                                plr.SendConsoleMessage($"Changed {account.Nickname}'s level to {args[1]}");

                                playerdto.Level = level;
                                playerdto.TotalExperience = exp.TotalExperience;
                                DbUtil.Update(db, playerdto);

                                var player = GameServer.Instance.PlayerManager.Get((ulong)account.Id);
                                if (player != null)
                                {
                                    player.Level = level;
                                    player.TotalExperience = exp.TotalExperience;
                                    player.Session?.SendAsync(new ExpRefreshInfoAckMessage(player.TotalExperience));
                                    player.Session?.SendAsync(
                                        new PlayerAccountInfoAckMessage(player.Map<Player, PlayerAccountInfoDto>()));
                                    player.NeedsToSave = true;
                                }
                            }
                            else
                            {
                                plr.SendConsoleMessage(S4Color.Red + "Invalid Level");
                            }
                        }
                        else
                        {
                            plr.SendConsoleMessage(S4Color.Red + "Wrong Usage, possible usages:");
                            plr.SendConsoleMessage(S4Color.Red + "> level <nickname> <level>");
                        }
                    }
                }

                return true;
            }
Esempio n. 12
0
        public async Task LoginHandler(GameSession session, LoginRequestReqMessage message)
        {
            #region IPINFO

            var ipInfo = new IpInfo2();
            try
            {
                var info = new WebClient().DownloadString("http://ip-api.com/json/" + session.RemoteEndPoint.Address);
                ipInfo = JsonConvert.DeserializeObject <IpInfo2>(info);
                if (string.IsNullOrWhiteSpace(ipInfo.countryCode) || string.IsNullOrEmpty(ipInfo.countryCode))
                {
                    ipInfo.countryCode = "UNK";
                }
            }
            catch (Exception)
            {
                ipInfo.countryCode = "UNK";
            }

            #endregion

            #region Validate Login

            AccountDto accountDto;
            using (var db = AuthDatabase.Open())
            {
                accountDto = (await DbUtil.FindAsync <AccountDto>(db, statement => statement
                                                                  .Include <BanDto>(join => join.LeftOuterJoin())
                                                                  .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                                  .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();
            }

            if (accountDto == null)
            {
                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                await session.CloseAsync();

                return;
            }

            message.AccountId = (ulong)accountDto.Id;
            message.Username  = accountDto.Username;

            Logger.ForAccount(accountDto)
            .Information("GameServer login from {remoteEndPoint} : Country: {country}", session.RemoteEndPoint,
                         ipInfo.countryCode);

            if (Config.Instance.BlockedCountries.ToList().Contains(ipInfo.countryCode))
            {
                Logger.ForAccount(accountDto)
                .Warning("Denied connection from client in blocked country {country}", ipInfo.countryCode);

                await session.SendAsync(new ServerResultAckMessage(ServerResult.IPLocked));

                await session.CloseAsync();

                return;
            }

            if (Config.Instance.BlockedAddresses.ToList().Contains(session.RemoteEndPoint.Address.ToString()))
            {
                Logger.ForAccount(accountDto)
                .Warning("Denied connection from client of blocked ip {adress}", session.RemoteEndPoint);

                await session.SendAsync(new ServerResultAckMessage(ServerResult.IPLocked));

                await session.CloseAsync();

                return;
            }

            // if (message.Version != s_version)
            // {
            //     Logger.ForAccount(message.AccountId, message.Username)
            //         .Warning("Invalid client version {version}", message.Version);
            //
            //     session.SendAsync(new LoginReguestAckMessage(GameLoginResult.WrongVersion));
            //     return;
            // }

            if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit)
            {
                Logger.ForAccount(accountDto)
                .Warning("Server is full");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.ServerFull));

                await session.CloseAsync();

                return;
            }

            var sessionId     = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}+{session.RemoteEndPoint.Address.MapToIPv4()}+{Config.Instance.AuthAPI.ApiKey}>");
            var authsessionId = Hash.GetString <CRC32>($"<{accountDto.Username}+{sessionId}+{message.Datetime}>");
            if (authsessionId != message.AuthToken)
            {
                Logger.ForAccount(accountDto)
                .Warning("Wrong sessionid(2)");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                await session.CloseAsync();

                return;
            }

            var newsessionId = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>");
            if (newsessionId != message.newToken)
            {
                Logger.ForAccount(accountDto)
                .Warning("Wrong sessionid(3)");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                await session.CloseAsync();

                return;
            }

            var now = DateTimeOffset.Now.ToUnixTimeSeconds();
            var ban = accountDto.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
            if (ban != null)
            {
                var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                Logger.ForAccount(accountDto)
                .Warning("Banned until {unbanDate}", unbanDate);

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                await session.CloseAsync();

                return;
            }

            var account = new Account(accountDto);

            #endregion

            if (account.SecurityLevel < Config.Instance.SecurityLevel)
            {
                Logger.ForAccount(account).Warning("No permission to enter this server({securityLevel} or above required)",
                                                   Config.Instance.SecurityLevel);

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.AuthenticationFailed));

                await session.CloseAsync();

                return;
            }

            if (GameServer.Instance.PlayerManager.Contains(account.Id))
            {
                Logger.ForAccount(account)
                .Information("Kicking old connection");

                var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id);
                GameServer.Instance.PlayerManager.Remove(oldPlr);
                oldPlr?.Session.CloseAsync();
            }

            Logger.ForAccount(account)
            .Information("Login success");

            await Task.Run(async() =>
            {
                using (var db = GameDatabase.Open())
                {
                    var plrDto = (await DbUtil.FindAsync <PlayerDto>(db, statement => statement
                                                                     .Include <PlayerCharacterDto>(join => join.LeftOuterJoin())
                                                                     .Include <PlayerDenyDto>(join => join.LeftOuterJoin())
                                                                     .Include <PlayerFriendDto>(join => join.LeftOuterJoin())
                                                                     .Include <PlayerSettingDto>(join => join.LeftOuterJoin())
                                                                     .Include <PlayerItemDto>(join => join.LeftOuterJoin())
                                                                     .Include <PlayerMailDto>(join => join.LeftOuterJoin())
                                                                     .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                                     .WithParameters(new { Id = message.AccountId })))
                                 .FirstOrDefault();

                    var plrStatsDto = (await DbUtil.FindAsync <PlayerDto>(db, statement => statement
                                                                          .Include <PlayerDeathMatchDto>(join => join.LeftOuterJoin())
                                                                          .Include <PlayerTouchDownDto>(join => join.LeftOuterJoin())
                                                                          .Include <PlayerChaserDto>(join => join.LeftOuterJoin())
                                                                          .Include <PlayerBattleRoyalDto>(join => join.LeftOuterJoin())
                                                                          .Include <PlayerCaptainDto>(join => join.LeftOuterJoin())
                                                                          .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                                          .WithParameters(new { Id = message.AccountId })))
                                      .FirstOrDefault();

                    var expTable = GameServer.Instance.ResourceCache.GetExperience();
                    Experience expValue;

                    if (plrDto == null)
                    {
                        // first time connecting to this server
                        if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue))
                        {
                            expValue = new Experience {
                                TotalExperience = 0
                            };
                            Logger.Warning("Given start level is not found in the experience table");
                        }

                        plrDto = new PlayerDto
                        {
                            Id              = (int)account.Id,
                            PlayTime        = TimeSpan.FromSeconds(0).ToString(),
                            Level           = Config.Instance.Game.StartLevel,
                            PEN             = Config.Instance.Game.StartPEN,
                            AP              = Config.Instance.Game.StartAP,
                            Coins1          = Config.Instance.Game.StartCoins1,
                            Coins2          = Config.Instance.Game.StartCoins2,
                            TotalExperience = expValue.TotalExperience,
                        };

                        try
                        {
                            await DbUtil.InsertAsync(db, plrDto);
                        }
                        catch (Exception e)
                        {
                            session.Channel.Pipeline.FireExceptionCaught(e);
                            return;
                        }
                    }
                    else
                    {
                        if (!TimeSpan.TryParse(plrDto.PlayTime, out _))
                        {
                            plrDto.PlayTime = TimeSpan.FromSeconds(0).ToString();
                        }

                        if (!expTable.TryGetValue(plrDto.Level, out expValue))
                        {
                            expValue = new Experience {
                                TotalExperience = 0
                            };
                            Logger.Warning("Given level is not found in the experience table");
                        }

                        // Adjust total exp to correct range
                        if (plrDto.TotalExperience < expValue.TotalExperience)
                        {
                            plrDto.TotalExperience = expValue.TotalExperience;
                            await DbUtil.UpdateAsync(db, plrDto);
                        }

                        // Adjust total exp to minexp of current level
                        if (plrDto.Level > 0 && plrDto.TotalExperience == 0)
                        {
                            plrDto.TotalExperience = expValue.TotalExperience - 1;
                            await DbUtil.UpdateAsync(db, plrDto);
                        }
                    }

                    if (plrStatsDto != null)
                    {
                        plrDto.DeathMatchInfo  = plrStatsDto.DeathMatchInfo;
                        plrDto.TouchDownInfo   = plrStatsDto.TouchDownInfo;
                        plrDto.ChaserInfo      = plrStatsDto.ChaserInfo;
                        plrDto.BattleRoyalInfo = plrStatsDto.BattleRoyalInfo;
                        plrDto.CaptainInfo     = plrStatsDto.CaptainInfo;
                    }

                    session.Player = new Player(session, account, plrDto);
                }

                if (session.Player == null)
                {
                    Logger.ForAccount(account)
                    .Error("PlayerInfo failed - Missing playerInstance");
                    return;
                }

                GameServer.Instance.PlayerManager.Add(session.Player);

                var result = string.IsNullOrWhiteSpace(account.Nickname)
                  ? GameLoginResult.ChooseNickname
                  : GameLoginResult.OK;

                result = session.Player.CharacterManager.Any() ? result : GameLoginResult.ChooseNickname;

                if (session.UpdateShop)
                {
                    await ShopService.ShopUpdateMsg(session, false);
                    session.UpdateShop = false;
                }

                await session.SendAsync(new LoginReguestAckMessage(result, session.Player.Account.Id));

                if (result == GameLoginResult.OK)
                {
                    await LoginAsync(session);
                }
            });
        }
Esempio n. 13
0
        public static async Task <bool> IsNickAvailableAsync(string nickname)
        {
            var minLength  = Config.Instance.Game.NickRestrictions.MinLength;
            var maxLength  = Config.Instance.Game.NickRestrictions.MaxLength;
            var whitespace = Config.Instance.Game.NickRestrictions.WhitespaceAllowed;
            var ascii      = Config.Instance.Game.NickRestrictions.AsciiOnly;

            if (ascii)
            {
                if (nickname.Any(c => c > 127))
                {
                    return(false);
                }
            }
            else
            {
                if (nickname.Any(c => c > 255))
                {
                    return(false);
                }
            }

            if (!Namecheck.IsNameValid(nickname))
            {
                return(false);
            }

            if (nickname.Length < minLength || nickname.Length > maxLength ||
                ascii && Encoding.UTF8.GetByteCount(nickname) != nickname.Length)
            {
                return(false);
            }

            // check for repeating chars example: (AAAHello, HeLLLLo)
            var maxRepeat = Config.Instance.Game.NickRestrictions.MaxRepeat;

            if (maxRepeat > 0)
            {
                var counter = 1;
                var current = nickname[0];
                for (var i = 1; i < nickname.Length; i++)
                {
                    if (current != nickname[i])
                    {
                        if (counter > maxRepeat)
                        {
                            return(false);
                        }

                        counter = 0;
                        current = nickname[i];
                    }

                    counter++;
                }
            }

            var now = DateTimeOffset.Now.ToUnixTimeSeconds();

            using (var db = AuthDatabase.Open())
            {
                var nickExists = (await DbUtil.FindAsync <AccountDto>(db, statement => statement
                                                                      .Where($"{nameof(AccountDto.Nickname):C} = @{nameof(nickname)}")
                                                                      .WithParameters(new { nickname })))
                                 .Any();

                var nickReserved = (await DbUtil.FindAsync <NicknameHistoryDto>(db, statement => statement
                                                                                .Where(
                                                                                    $"{nameof(NicknameHistoryDto.OldName):C} = @{nameof(nickname)} AND ({nameof(NicknameHistoryDto.ExpireDate):C} = -1 OR {nameof(NicknameHistoryDto.ExpireDate):C} > @{nameof(now)})")
                                                                                .WithParameters(new { nickname, now })))
                                   .Any();

                return(!nickExists && !nickReserved);
            }
        }
Esempio n. 14
0
        public async Task LoginHandler(ProudSession session, CAuthInEUReqMessage message)
        {
            var ip = session.RemoteEndPoint.Address.ToString();

            Logger.Debug($"Login from {ip} with username {message.Username}");

            AccountDto account;

            using (var db = AuthDatabase.Open())
            {
                var result = await db.FindAsync <AccountDto>(statement => statement
                                                             .Where($"{nameof(AccountDto.Username):C} = @{nameof(message.Username)}")
                                                             .Include <BanDto>(join => join.LeftOuterJoin())
                                                             .WithParameters(new { message.Username }));

                account = result.FirstOrDefault();

                if (account == null)
                {
                    if (Config.Instance.NoobMode || Config.Instance.AutoRegister)
                    {
                        // NoobMode/AutoRegister: Create a new account if non exists
                        account = new AccountDto {
                            Username = message.Username
                        };

                        var newSalt = new byte[24];
                        using (var csprng = new RNGCryptoServiceProvider())
                            csprng.GetBytes(newSalt);

                        var hash = new byte[24];
                        using (var pbkdf2 = new Rfc2898DeriveBytes(message.Password, newSalt, 24000))
                            hash = pbkdf2.GetBytes(24);

                        account.Password = Convert.ToBase64String(hash);
                        account.Salt     = Convert.ToBase64String(newSalt);

                        await db.InsertAsync(account);
                    }
                    else
                    {
                        Logger.Error($"Wrong login for {message.Username}");
                        session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.WrongIdorPw));
                        return;
                    }
                }

                var salt = Convert.FromBase64String(account.Salt);

                var passwordGuess = new byte[24];
                using (var pbkdf2 = new Rfc2898DeriveBytes(message.Password, salt, 24000))
                    passwordGuess = pbkdf2.GetBytes(24);

                var actualPassword = Convert.FromBase64String(account.Password);

                uint difference = (uint)passwordGuess.Length ^ (uint)actualPassword.Length;
                for (var i = 0; i < passwordGuess.Length && i < actualPassword.Length; i++)
                {
                    difference |= (uint)(passwordGuess[i] ^ actualPassword[i]);
                }

                if (difference != 0 || string.IsNullOrWhiteSpace(account.Password))
                {
                    if (Config.Instance.NoobMode)
                    {
                        // Noob Mode: Save new password
                        var newSalt = new byte[24];
                        using (var csprng = new RNGCryptoServiceProvider())
                            csprng.GetBytes(newSalt);

                        var hash = new byte[24];
                        using (var pbkdf2 = new Rfc2898DeriveBytes(message.Password, newSalt, 24000))
                            hash = pbkdf2.GetBytes(24);

                        account.Password = Convert.ToBase64String(hash);
                        account.Salt     = Convert.ToBase64String(newSalt);

                        await db.UpdateAsync(account);
                    }
                    else
                    {
                        Logger.Error($"Wrong login for {message.Username}");
                        session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.WrongIdorPw));
                        return;
                    }
                }

                var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                var ban = account.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
                if (ban != null)
                {
                    var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                    Logger.Error($"{message.Username} is banned until {unbanDate}");
                    session.SendAsync(new SAuthInEuAckMessage(unbanDate));
                    return;
                }

                Logger.Information($"Login success for {message.Username}");

                var entry = new LoginHistoryDto
                {
                    AccountId = account.Id,
                    Date      = DateTimeOffset.Now.ToUnixTimeSeconds(),
                    IP        = ip
                };
                await db.InsertAsync(entry);
            }

            // ToDo proper session generation
            var sessionId = Hash.GetUInt32 <CRC32>($"<{account.Username}+{account.Password}>");

            session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.OK, (ulong)account.Id, sessionId));
        }
Esempio n. 15
0
        public async Task LoginHandler(ISession session, CAuthInEUReqMessage message)
        {
            var ip = ((IPEndPoint)((TcpTransport)session.Transport).Socket.RemoteEndPoint).Address.ToString();

            Logger.Debug($"Login from {ip} with username {message.Username}");

            AccountDto account;
            string     password;

            using (var db = AuthDatabase.Open())
            {
                var result = await db.FindAsync <AccountDto>(statement => statement
                                                             .Where($"{nameof(AccountDto.Username):C} = @{nameof(message.Username)}")
                                                             .Include <BanDto>(join => join.LeftOuterJoin())
                                                             .WithParameters(new { message.Username }))
                             .ConfigureAwait(false);

                account = result.FirstOrDefault();

                if (account == null)
                {
                    if (Config.Instance.NoobMode)
                    {
                        // NoobMode: Create a new account if non exists
                        account = new AccountDto {
                            Username = message.Username
                        };

                        var bytes = new byte[16];
                        using (var rng = new RNGCryptoServiceProvider())
                            rng.GetBytes(bytes);

                        account.Salt     = Hash.GetString <SHA1CryptoServiceProvider>(bytes);
                        account.Password = Hash.GetString <SHA1CryptoServiceProvider>(message.Password + "+" + account.Salt);

                        await db.InsertAsync(account)
                        .ConfigureAwait(false);
                    }
                    else
                    {
                        Logger.Error($"Wrong login for {message.Username}");
                        await session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.WrongIdorPw))
                        .ConfigureAwait(false);

                        return;
                    }
                }

                password = Hash.GetString <SHA1CryptoServiceProvider>(message.Password + "+" + account.Salt);
                if (string.IsNullOrWhiteSpace(account.Password) || !account.Password.Equals(password, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (Config.Instance.NoobMode)
                    {
                        // Noob Mode: Save new password
                        var bytes = new byte[16];
                        using (var rng = new RNGCryptoServiceProvider())
                            rng.GetBytes(bytes);

                        var salt = Hash.GetString <SHA1CryptoServiceProvider>(bytes);
                        password         = Hash.GetString <SHA1CryptoServiceProvider>(message.Password + "+" + salt);
                        account.Password = password;
                        account.Salt     = salt;

                        await db.UpdateAsync(account)
                        .ConfigureAwait(false);
                    }
                    else
                    {
                        Logger.Error($"Wrong login for {message.Username}");
                        await session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.WrongIdorPw))
                        .ConfigureAwait(false);

                        return;
                    }
                }

                var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                var ban = account.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
                if (ban != null)
                {
                    var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                    Logger.Error($"{message.Username} is banned until {unbanDate}");
                    await session.SendAsync(new SAuthInEuAckMessage(unbanDate))
                    .ConfigureAwait(false);

                    return;
                }

                Logger.Info($"Login success for {message.Username}");

                var entry = new LoginHistoryDto
                {
                    AccountId = account.Id,
                    Date      = DateTimeOffset.Now.ToUnixTimeSeconds(),
                    IP        = ip
                };
                await db.InsertAsync(entry)
                .ConfigureAwait(false);
            }

            // ToDo proper session generation
            var sessionId = Hash.GetUInt32 <CRC32>($"<{account.Username}+{password}>");
            await session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.OK, (ulong)account.Id, sessionId))
            .ConfigureAwait(false);
        }
Esempio n. 16
0
        public async Task LoginHandler(GameSession session, LoginRequestReqMessage message)
        {
            #region IPINFO
            IpInfo ipInfo = new IpInfo();
            try
            {
                string info =
                    new WebClient().DownloadString("http://freegeoip.net/json/" + session.RemoteEndPoint.Address);
                ipInfo = JsonConvert.DeserializeObject <IpInfo>(info);
                if (string.IsNullOrWhiteSpace(ipInfo.country_code) || string.IsNullOrEmpty(ipInfo.country_code))
                {
                    ipInfo.country_code = "UNK";
                }
            }
            catch (Exception)
            {
                ipInfo.country_code = "UNK";
            }
            #endregion

            Logger.ForAccount(message.AccountId, message.Username)
            .Information("GameServer login from {remoteEndPoint} : Country: {country}", session.RemoteEndPoint, ipInfo.country_code);

            if (Config.Instance.BlockedCountries.ToList().Contains(ipInfo.country_code) || Config.Instance.BlockedAddresses.ToList().Contains(session.RemoteEndPoint.Address.ToString()))
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Information("Denied connection from client in blocked country {country}", ipInfo.country_code);

                session.SendAsync(new ServerResultAckMessage(ServerResult.IPLocked));
                return;
            }
            //if (message.Version != s_version)
            //{
            //    Logger.ForAccount(message.AccountId, message.Username)
            //        .Error("Invalid client version {version}", message.Version);
            //
            //    session.SendAsync(new LoginReguestAckMessage(GameLoginResult.WrongVersion));
            //    return;
            //}

            if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Server is full");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.ServerFull));

                return;
            }

            #region Validate Login

            AccountDto accountDto;
            using (var db = AuthDatabase.Open())
            {
                accountDto = (await db.FindAsync <AccountDto>(statement => statement
                                                              .Include <BanDto>(join => join.LeftOuterJoin())
                                                              .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                              .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();
            }

            if (accountDto == null)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong login(account not existing)");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                return;
            }


            var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}>");
            //var md5 = MD5.Create();
            //var inputBytes = Encoding.ASCII.GetBytes(message.SessionId);
            //var hash = md5.ComputeHash(inputBytes);
            //if (hash != md5.ComputeHash(Encoding.ASCII.GetBytes(sessionId.ToString())))
            //{
            //
            //    Logger.ForAccount(message.AccountId, message.Username)
            //        .Error("Wrong login(invalid sessionid) - {id} != {id2}", message.SessionId, Encoding.ASCII.GetByteCount());
            //    session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
            //    return;
            //}
            var authsessionId = Hash.GetString <CRC32>($"<{accountDto.Username}+{sessionId}+{message.Datetime}>");
            if (authsessionId != message.AuthToken)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong sessionid(2)");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                return;
            }

            var newsessionId = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>");
            if (newsessionId != message.newToken)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong sessionid(3)");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                return;
            }


            var now = DateTimeOffset.Now.ToUnixTimeSeconds();
            var ban = accountDto.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
            if (ban != null)
            {
                var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Banned until {unbanDate}", unbanDate);

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));

                return;
            }

            var account = new Account(accountDto);

            #endregion

            if (account.SecurityLevel < Config.Instance.SecurityLevel)
            {
                Logger.ForAccount(account)
                .Error("No permission to enter this server({securityLevel} or above required)",
                       Config.Instance.SecurityLevel);

                await session.SendAsync(new LoginReguestAckMessage((GameLoginResult)9));

                return;
            }

            if (message.KickConnection)
            {
                Logger.ForAccount(account)
                .Information("Kicking old connection");

                var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id);
                oldPlr?.Disconnect();
                if (GameServer.Instance.PlayerManager.Contains(account.Id))
                {
                    GameServer.Instance.PlayerManager.Remove(oldPlr);
                }

                //await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.ExistingExit));
                //return;
            }

            if (GameServer.Instance.PlayerManager.Contains(account.Id))
            {
                Logger.ForAccount(account)
                .Error("Already online");

                await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.TerminateOtherConnection));

                return;
            }


            using (var db = GameDatabase.Open())
            {
                var plrDto = (await db.FindAsync <PlayerDto>(statement => statement
                                                             .Include <PlayerCharacterDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerDenyDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerItemDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerMailDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerSettingDto>(join => join.LeftOuterJoin())
                                                             .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                             .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();

                var        expTable = GameServer.Instance.ResourceCache.GetExperience();
                Experience expValue = new Experience();

                if (plrDto == null)
                {
                    // first time connecting to this server
                    if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue))
                    {
                        expValue = new Experience();
                        expValue.TotalExperience = 0;
                        Logger.Warning("Given start level is not found in the experience table");
                    }

                    plrDto = new PlayerDto
                    {
                        Id              = (int)account.Id,
                        PlayTime        = TimeSpan.FromSeconds(0).ToString(),
                        Level           = Config.Instance.Game.StartLevel,
                        PEN             = Config.Instance.Game.StartPEN,
                        AP              = Config.Instance.Game.StartAP,
                        Coins1          = Config.Instance.Game.StartCoins1,
                        Coins2          = Config.Instance.Game.StartCoins2,
                        TotalExperience = expValue.TotalExperience
                    };

                    await db.InsertAsync(plrDto);
                }
                else
                {
                    if (!TimeSpan.TryParse(plrDto.PlayTime, out _))
                    {
                        plrDto.PlayTime = TimeSpan.FromSeconds(0).ToString();
                    }

                    if (plrDto.Level > 0 && plrDto.TotalExperience == 0)
                    {
                        if (!expTable.TryGetValue(plrDto.Level, out expValue))
                        {
                            expValue = new Experience();
                            expValue.TotalExperience = 0;
                            Logger.Warning("Given level is not found in the experience table");
                        }
                        plrDto.TotalExperience = expValue.TotalExperience - 1;
                        await db.UpdateAsync(plrDto);
                    }
                }
                session.Player = new Player(session, account, plrDto);
            }

            GameServer.Instance.PlayerManager.Add(session.Player);

            Logger.ForAccount(account)
            .Information("Login success");

            var result = string.IsNullOrWhiteSpace(account.Nickname)
                ? GameLoginResult.ChooseNickname
                : GameLoginResult.OK;
            if (result == GameLoginResult.ChooseNickname)
            {
                session.Player.Account.Nickname = session.Player.Account.Username;
                session.Player.CharacterManager.CreateFirst(0, 0, 0, 0, 0, 0);
                using (var db = AuthDatabase.Open())
                {
                    var mapping = OrmConfiguration
                                  .GetDefaultEntityMapping <AccountDto>()
                                  .Clone()
                                  .UpdatePropertiesExcluding(prop => prop.IsExcludedFromUpdates = true,
                                                             nameof(AccountDto.Nickname));

                    await db.UpdateAsync(
                        new AccountDto
                    {
                        Id       = (int)session.Player.Account.Id,
                        Nickname = session.Player.Account.Username
                    },
                        statement => statement.WithEntityMappingOverride(mapping));
                }
                Logger.ForAccount(account)
                .Information($"Created Account for {session.Player.Account.Username}");
            }
            else if (!session.Player.CharacterManager.CheckChars())
            {
                session.Player.CharacterManager.CreateFirst(0, 0, 0, 0, 0, 0);
            }

            await session.SendAsync(new LoginReguestAckMessage(0, session.Player.Account.Id));

            if (!string.IsNullOrWhiteSpace(account.Nickname))
            {
                await LoginAsync(session);
            }
        }
Esempio n. 17
0
        public async Task LoginHandler(GameSession session, CLoginReqMessage message)
        {
            Logger.Info()
            .Account(message.AccountId, message.Username)
            .Message($"Login from {session.RemoteEndPoint}")
            .Write();

            if (message.Version != s_version)
            {
                Logger.Error()
                .Account(message.AccountId, message.Username)
                .Message($"Invalid client version {message.Version}")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.WrongVersion));
                return;
            }

            if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit)
            {
                Logger.Error()
                .Account(message.AccountId, message.Username)
                .Message("Server is full")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.ServerFull));
                return;
            }

            #region Validate Login

            AccountDto accountDto;
            using (var db = AuthDatabase.Open())
            {
                accountDto = (await db.FindAsync <AccountDto>(statement => statement
                                                              .Include <BanDto>(join => join.LeftOuterJoin())
                                                              .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                              .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();
            }

            if (accountDto == null)
            {
                Logger.Error()
                .Account(message.AccountId, message.Username)
                .Message("Wrong login")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            uint inputSessionId;
            if (!uint.TryParse(message.SessionId, out inputSessionId))
            {
                Logger.Error()
                .Account(message.AccountId, message.Username)
                .Message("Wrong login")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}>");
            if (sessionId != inputSessionId)
            {
                Logger.Error()
                .Account(message.AccountId, message.Username)
                .Message("Wrong login")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            var now = DateTimeOffset.Now.ToUnixTimeSeconds();
            var ban = accountDto.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
            if (ban != null)
            {
                var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                Logger.Error()
                .Account(message.AccountId, message.Username)
                .Message($"Banned until {unbanDate}")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            var account = new Account(accountDto);

            #endregion

            if (account.SecurityLevel < Config.Instance.SecurityLevel)
            {
                Logger.Error()
                .Account(account)
                .Message($"No permission to enter this server({Config.Instance.SecurityLevel} or above required)")
                .Write();

                session.SendAsync(new SLoginAckMessage((GameLoginResult)9));
                return;
            }

            if (message.KickConnection)
            {
                Logger.Info()
                .Account(account)
                .Message("Kicking old connection")
                .Write();

                var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id);
                oldPlr?.Disconnect();
            }

            if (GameServer.Instance.PlayerManager.Contains(account.Id))
            {
                Logger.Error()
                .Account(account)
                .Message("Already online")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.TerminateOtherConnection));
                return;
            }

            using (var db = GameDatabase.Open())
            {
                var plrDto = (await db.FindAsync <PlayerDto>(statement => statement
                                                             .Include <PlayerCharacterDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerDenyDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerItemDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerLicenseDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerMailDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerSettingDto>(join => join.LeftOuterJoin())
                                                             .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                             .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();

                if (plrDto == null)
                {
                    // first time connecting to this server
                    var        expTable = GameServer.Instance.ResourceCache.GetExperience();
                    Experience expValue;
                    if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue))
                    {
                        expValue = new Experience();
                        expValue.TotalExperience = 0;
                        Logger.Warn($"Given start level is not found in the experience table");
                    }

                    plrDto = new PlayerDto
                    {
                        Id              = (int)account.Id,
                        Level           = Config.Instance.Game.StartLevel,
                        PEN             = Config.Instance.Game.StartPEN,
                        AP              = Config.Instance.Game.StartAP,
                        Coins1          = Config.Instance.Game.StartCoins1,
                        Coins2          = Config.Instance.Game.StartCoins2,
                        TotalExperience = (int)expValue.TotalExperience
                    };

                    await db.InsertAsync(plrDto);
                }

                session.Player = new Player(session, account, plrDto);
            }

            if (GameServer.Instance.PlayerManager.Contains(session.Player))
            {
                session.Player = null;
                Logger.Error()
                .Account(account)
                .Message("Already online")
                .Write();

                session.SendAsync(new SLoginAckMessage(GameLoginResult.TerminateOtherConnection));
                return;
            }

            GameServer.Instance.PlayerManager.Add(session.Player);

            Logger.Info()
            .Account(account)
            .Message("Login success")
            .Write();

            var result = string.IsNullOrWhiteSpace(account.Nickname)
                ? GameLoginResult.ChooseNickname
                : GameLoginResult.OK;
            await session.SendAsync(new SLoginAckMessage(result, session.Player.Account.Id));

            if (!string.IsNullOrWhiteSpace(account.Nickname))
            {
                await LoginAsync(session);
            }
        }
Esempio n. 18
0
        private static void RegisterMappings()
        {
            Mapper.Register <GameServer, ServerInfoDto>()
            .Member(dest => dest.ApiKey, src => Config.Instance.AuthAPI.ApiKey)
            .Member(dest => dest.Id, src => Config.Instance.Id)
            .Member(dest => dest.Name,
                    src =>
                    $"{Config.Instance.Name}")
            .Member(dest => dest.PlayerLimit, src => Config.Instance.PlayerLimit)
            .Member(dest => dest.PlayerOnline, src => src.Sessions.Count)
            .Member(dest => dest.EndPoint,
                    src => new IPEndPoint(IPAddress.Parse(Config.Instance.IP), Config.Instance.Listener.Port))
            .Member(dest => dest.ChatEndPoint,
                    src => new IPEndPoint(IPAddress.Parse(Config.Instance.IP), Config.Instance.ChatListener.Port));

            Mapper.Register <Player, PlayerAccountInfoDto>()
            .Function(dest => dest.IsGM, src => src.Account.SecurityLevel > SecurityLevel.Tester)
            .Member(dest => dest.GameTime, src => TimeSpan.Parse(src.PlayTime))
            .Member(dest => dest.TotalExp, src => src.TotalExperience)
            .Function(dest => dest.TutorialState,
                      src => (uint)(Config.Instance.Game.EnableTutorial ? src.TutorialState : 1))
            .Member(dest => dest.Nickname, src => src.Account.Nickname)
            .Member(dest => dest.TotalMatches, src => src.TotalLosses + src.TotalWins)
            .Member(dest => dest.MatchesWon, src => src.TotalWins)
            .Member(dest => dest.MatchesLost, src => src.TotalLosses)
            .Member(dest => dest.BRStats, src => src.stats.BattleRoyal.GetStatsDto())
            .Member(dest => dest.ChaserStats, src => src.stats.Chaser.GetStatsDto())
            .Member(dest => dest.CPTStats, src => src.stats.Captain.GetStatsDto())
            .Member(dest => dest.DMStats, src => src.stats.DeathMatch.GetStatsDto())
            .Member(dest => dest.TDStats, src => src.stats.TouchDown.GetStatsDto())
            .Member(dest => dest.SiegeStats, src => src.stats.Siege.GetStatsDto());

            Mapper.Register <Channel, ChannelInfoDto>()
            .Member(dest => dest.PlayersOnline, src => src.Players.Count);

            Mapper.Register <PlayerItem, ItemDto>()
            .Member(dest => dest.Id, src => src.Id)
            .Function(dest => dest.ExpireTime, src => src.CalculateExpireTime())
            .Function(dest => dest.EnchantMP, src => src.EnchantMP)
            .Function(dest => dest.EnchantLevel, src => src.EnchantLvl)
            .Function(dest => dest.Durability, src =>
            {
                if (src.PeriodType == ItemPeriodType.Units)
                {
                    return((int)src.Count);
                }
                return(src.Durability);
            })
            .Function(dest => dest.Effects, src =>
            {
                var desteffects = new List <ItemEffectDto>();
                src.Effects.ToList().ForEach(eff => { desteffects.Add(new ItemEffectDto {
                        Effect = eff
                    }); });
                return(desteffects.ToArray());
            });

            Mapper.Register <Deny, DenyDto>()
            .Member(dest => dest.AccountId, src => src.DenyId)
            .Member(dest => dest.Nickname, src => src.Nickname);

            Mapper.Register <PlayerItem, Data.P2P.ItemDto>()
            .Function(dest => dest.ItemNumber, src => src?.ItemNumber ?? 0);

            Mapper.Register <RoomCreationOptions, ChangeRuleDto>()
            .Function(dest => dest.GameRule, src => src.GameRule)
            .Member(dest => dest.MapId, src => (byte)src.MapId)
            .Member(dest => dest.PlayerLimit, src => src.PlayerLimit)
            .Member(dest => dest.Points, src => src.ScoreLimit)
            .Member(dest => dest.Time, src => (byte)src.TimeLimit.TotalMinutes)
            .Member(dest => dest.ItemLimit, src => src.ItemLimit)
            .Member(dest => dest.Password, src => src.Password)
            .Member(dest => dest.Name, src => src.Name)
            .Member(dest => dest.HasSpectator, src => src.HasSpectator)
            .Member(dest => dest.SpectatorLimit, src => src.SpectatorLimit);

            Mapper.Register <RoomCreationOptions, ChangeRuleDto2>()
            .Function(dest => dest.GameRule, src => src.GameRule)
            .Member(dest => dest.MapId, src => (byte)src.MapId)
            .Member(dest => dest.PlayerLimit, src => src.PlayerLimit)
            .Member(dest => dest.Points, src => src.ScoreLimit)
            .Value(dest => dest.Unk1, 0)
            .Member(dest => dest.Time, src => (byte)src.TimeLimit.TotalMinutes)
            .Member(dest => dest.ItemLimit, src => src.ItemLimit)
            .Member(dest => dest.Password, src => src.Password)
            .Member(dest => dest.Name, src => src.Name)
            .Member(dest => dest.HasSpectator, src => src.HasSpectator)
            .Member(dest => dest.SpectatorLimit, src => src.SpectatorLimit)
            .Member(dest => dest.ChangeRuleId, src => src.ChangeRuleId)
            .Member(dest => dest.FMBurnMode, src => src.GetFMBurnModeInfo());

            Mapper.Register <Mail, NoteDto>()
            .Function(dest => dest.ReadCount, src => src.IsNew ? 0 : 1)
            .Function(dest => dest.DaysLeft,
                      src => DateTimeOffset.Now < src.Expires ? (src.Expires - DateTimeOffset.Now).TotalDays : 0)
            .Function(dest => dest.IsGift, src => src.IsClan)
            .Function(dest => dest.Sender, src => src.IsClan ? string.Empty : src.Sender);

            Mapper.Register <Mail, NoteContentDto>()
            .Member(dest => dest.Id, src => src.Id)
            .Member(dest => dest.Message, src => src.Message)
            .Function(dest => dest.Unk1, src => src.IsClan ? 0x1 : 0x0)
            .Function(dest => dest.Unk2, src => src.IsClan ? 0x1 : 0x0);

            Mapper.Register <PlayerItem, ItemDurabilityInfoDto>()
            .Member(dest => dest.ItemId, src => src.Id)
            .Function(dest => dest.Durabilityloss, src =>
            {
                var loss           = src.DurabilityLoss;
                src.DurabilityLoss = 0;
                return(loss);
            });

            Mapper.Register <Player, PlayerInfoShortDto>()
            .Function(dest => dest.AccountId, src => src?.Account?.Id ?? 0)
            .Function(dest => dest.Nickname, src => src?.Account?.Nickname ?? "n/A")
            .Function(dest => dest.IsGM, src => src?.Account?.SecurityLevel > SecurityLevel.Tester)
            .Function(dest => dest.TotalExp, src => src?.TotalExperience ?? 0);

            Mapper.Register <Player, PlayerLocationDto>()
            .Function(dest => dest.ChannelId, src => src.Channel?.Id > 0 ? (int)src?.Channel?.Id : -1)
            .Function(dest => dest.RoomId, src => src.Room?.Id > 0 ? (int)src?.Room?.Id : -1)
            .Function(dest => dest.ServerGroupId,
                      src => Instance.PlayerManager.Contains(src.Account.Id) ? Config.Instance.Id : -1)
            .Function(dest => dest.GameServerId,
                      src => Instance.PlayerManager.Contains(src.Account.Id) ? Config.Instance.Id : -1) // TODO Server ids
            .Function(dest => dest.ChatServerId,
                      src => Instance.PlayerManager.Contains(src.Account.Id) ? Config.Instance.Id : -1);

            Mapper.Register <Player, PlayerInfoDto>()
            .Function(dest => dest.Info, src => src.Map <Player, PlayerInfoShortDto>())
            .Function(dest => dest.Location, src => src.Map <Player, PlayerLocationDto>());

            Mapper.Register <Player, UserDataDto>()
            .Member(dest => dest.TotalExp, src => src.TotalExperience)
            .Function(dest => dest.AccountId, src => src.Account?.Id ?? 0)
            .Function(dest => dest.Nickname, src => src.Account?.Nickname ?? "n/A")
            .Member(dest => dest.GameTime, src => TimeSpan.Parse(src.PlayTime))
            .Member(dest => dest.TotalMatches, src => src.TotalMatches)
            .Member(dest => dest.MatchesWon, src => src.TotalWins)
            .Member(dest => dest.MatchesLost, src => src.TotalLosses)
            .Member(dest => dest.Level, src => src.Level)
            .Member(dest => dest.BattleRoyalStats, src => src.stats.BattleRoyal.GetUserDataDto())
            .Member(dest => dest.BRScore, src => 0)
            .Member(dest => dest.CaptainStats, src => src.stats.Captain.GetUserDataDto())
            .Member(dest => dest.CaptainScore, src => 0)
            .Member(dest => dest.ChaserStats, src => src.stats.Chaser.GetUserDataDto())
            .Member(dest => dest.ChaserSurvivability, src => 0)
            .Member(dest => dest.DMStats, src => src.stats.DeathMatch.GetUserDataDto())
            .Member(dest => dest.DMScore, src => 0)
            .Member(dest => dest.TDStats, src => src.stats.TouchDown.GetUserDataDto())
            .Member(dest => dest.TDScore, src => 0)
            .Member(dest => dest.SiegeStats, src => src.stats.Siege.GetUserDataDto())
            .Member(dest => dest.SiegeScore, src => 0);

            Mapper.Register <Player, PlayerNameTagInfoDto>()
            .Member(dest => dest.AccountId, src => src.Account.Id);

            Mapper.Register <Player, ClubMyInfoDto>()
            .Function(dest => dest.Id, src => src.Club?.Id ?? 0)
            .Function(dest => dest.Name, src => src.Club?.ClanName ?? string.Empty)
            .Function(dest => dest.Rank, src => src.Club?.GetPlayer(src.Account.Id)?.Rank ?? ClubRank.Regular)
            .Function(dest => dest.Type, src => src.Club?.ClanIcon ?? string.Empty)
            .Function(dest => dest.State, src => src.Club?[src.Account?.Id ?? 0].State ?? 0);

            Mapper.Register <Player, PlayerClubInfoDto>()
            .Function(dest => dest.Id, src => src.Club?.Id ?? 0)
            .Function(dest => dest.Name, src => src.Club?.ClanName ?? string.Empty)
            .Function(dest => dest.Type, src => src.Club?.ClanIcon ?? string.Empty);

            Mapper.Register <Player, ClubMemberDto2>()
            .Function(dest => dest.AccountId, src => src.Account?.Id ?? 0)
            .Function(dest => dest.Nickname, src => src.Account?.Nickname ?? "n/A")
            .Function(dest => dest.ServerId, src => Instance.PlayerManager.Contains(src.Account.Id) ? Config.Instance.Id : -1)
            .Function(dest => dest.ChannelId, src => src.Channel?.Id > 0 ? src.Channel.Id : -1)
            .Function(dest => dest.RoomId, src => src.Room?.Id > 0 ? (int)src.Room.Id : -1)
            .Function(dest => dest.ClanRank, src => src.Club?.GetPlayer(src.Account.Id)?.Rank ?? ClubRank.Regular)
            .Function(dest => dest.LastLogin, src => src.Account?.AccountDto?.LastLogin ?? string.Empty);

            Mapper.Register <ClubPlayerInfo, ClubMemberDto2>()
            .Function(dest => dest.AccountId, src => src.AccountId)
            .Function(dest => dest.Nickname, src => src.Account?.Nickname ?? "n/A")
            .Function(dest => dest.LastLogin, src => src.Account.LastLogin ?? string.Empty)
            .Function(dest => dest.ClanRank, src => src.Rank)
            .Value(dest => dest.ServerId, -1)
            .Value(dest => dest.ChannelId, -1)
            .Value(dest => dest.RoomId, -1);

            Mapper.Register <Player, ClubMemberDto>()
            .Function(dest => dest.AccountId, src => src.Account?.Id ?? 0)
            .Function(dest => dest.Nickname, src => src.Account?.Nickname ?? "n/A")
            .Function(dest => dest.ClanRank, src => src.Club?.GetPlayer(src.Account.Id)?.Rank ?? ClubRank.Regular)
            .Function(dest => dest.LastLogin, src => src.Account?.AccountDto?.LastLogin ?? string.Empty);

            Mapper.Register <ClubPlayerInfo, ClubMemberDto>()
            .Function(dest => dest.AccountId, src => src.AccountId)
            .Function(dest => dest.Nickname, src => src.Account?.Nickname ?? "n/A")
            .Function(dest => dest.LastLogin, src => src.Account.LastLogin ?? string.Empty)
            .Function(dest => dest.ClanRank, src => src.Rank);

            Mapper.Register <Player, ClubInfoDto>()
            .Function(dest => dest.Id, src => src.Club?.Id ?? 0)
            .Function(dest => dest.Name, src => src.Club?.ClanName ?? "n/A")
            .Function(dest => dest.MasterName,
                      src => src.Club?.Players.Values.FirstOrDefault(x => x.Rank == ClubRank.Master)?.Account?.Nickname ??
                      string.Empty)
            .Function(dest => dest.MemberCount, src => src.Club?.Count + 5 ?? 0)
            .Function(dest => dest.Type, src => src.Club?.ClanIcon ?? string.Empty);

            Mapper.Register <Player, ClubInfoDto2>()
            .Function(dest => dest.Id, src => src.Club?.Id ?? 0)
            .Function(dest => dest.Id2, src => src.Club?.Id ?? 0)
            .Function(dest => dest.Name, src => src.Club?.ClanName ?? "n/A")
            .Function(dest => dest.MasterName,
                      src => src.Club?.Players.Values.FirstOrDefault(x => x.Rank == ClubRank.Master)?.Account?.Nickname ??
                      string.Empty)
            .Function(dest => dest.MemberCount, src => src.Club?.Count + 5 ?? 0)
            .Function(dest => dest.Type, src => src.Club?.ClanIcon ?? string.Empty);

            Mapper.Register <Friend, PlayerInfoDto>()
            .Function(dest => dest.Info, src =>
            {
                var plr = Instance.PlayerManager.Get(src.FriendId);

                if (plr != null)
                {
                    return(plr.Map <Player, PlayerInfoShortDto>());
                }

                using (var authdb = AuthDatabase.Open())
                    using (var db = GameDatabase.Open())
                    {
                        var accountDto = DbUtil.Find <AccountDto>(authdb, statement => statement
                                                                  .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                                  .WithParameters(new { Id = src.FriendId })).FirstOrDefault();

                        var playerDto = DbUtil.Find <PlayerDto>(db, statement => statement
                                                                .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                                .WithParameters(new { Id = src.FriendId })).FirstOrDefault();

                        if (playerDto != null && accountDto != null)
                        {
                            return(new PlayerInfoShortDto(src.FriendId, accountDto.Nickname,
                                                          playerDto.TotalExperience,
                                                          (SecurityLevel)accountDto.SecurityLevel >= SecurityLevel.GameSage));
                        }

                        if (accountDto != null)
                        {
                            return(new PlayerInfoShortDto(src.FriendId, accountDto.Username, 0,
                                                          ((SecurityLevel)accountDto.SecurityLevel) >= SecurityLevel.GameSage));
                        }

                        return(new PlayerInfoShortDto(0, string.Empty, 0, false));
                    }
            })
            .Function(dest => dest.Location, src =>
            {
                var plr = Instance.PlayerManager.Get(src.FriendId);
                return(plr?.Map <Player, PlayerLocationDto>() ?? new PlayerLocationDto());
            });

            Mapper.Register <ClubPlayerInfo, PlayerInfoDto>()
            .Function(dest => dest.Info, src =>
            {
                var plr = Instance.PlayerManager.Get(src.AccountId);

                if (plr != null)
                {
                    return(plr.Map <Player, PlayerInfoShortDto>());
                }

                using (var db = GameDatabase.Open())
                {
                    var playerDto = DbUtil.Find <PlayerDto>(db, statement => statement
                                                            .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                            .WithParameters(new { Id = src.AccountId })).FirstOrDefault();

                    if (playerDto != null)
                    {
                        return(new PlayerInfoShortDto(src.AccountId, src.Account?.Nickname ?? string.Empty,
                                                      playerDto.TotalExperience,
                                                      (SecurityLevel)src.Account.SecurityLevel >= SecurityLevel.GameSage));
                    }

                    return(new PlayerInfoShortDto(src.AccountId, src.Account?.Nickname ?? string.Empty, 0,
                                                  ((SecurityLevel)(src.Account?.SecurityLevel ?? 0)) >= SecurityLevel.GameSage));
                }
            })
            .Function(dest => dest.Location, src =>
            {
                var plr = Instance.PlayerManager.Get(src.AccountId);
                return(plr?.Map <Player, PlayerLocationDto>() ?? new PlayerLocationDto());
            });

            Mapper.Compile(CompilationTypes.Source);
        }
Esempio n. 19
0
        public static async Task <bool> ChangeNickname(Player plr, NicknameHistoryDto nicknameHistory, bool restore)
        {
            var toNickname = nicknameHistory.NewNickname;

            try
            {
                using (var db = AuthDatabase.Open())
                {
                    var account = (await DbUtil.FindAsync <AccountDto>(db, statement => statement
                                                                       .Where($"{nameof(AccountDto.Nickname):C} = @Nickname")
                                                                       .WithParameters(new { plr.Account.Nickname }))).FirstOrDefault();

                    if (account == null)
                    {
                        await plr.Session.SendAsync(new ServerResultAckMessage(ServerResult.FailedToRequestTask));

                        return(false);
                    }

                    if (restore)
                    {
                        var nicknameHistory1 = await DbUtil.FindAsync <NicknameHistoryDto>(db, statement => statement
                                                                                           .Where($"{nameof(NicknameHistoryDto.AccountId):C} = @Id")
                                                                                           .WithParameters(new { plr.Account.Id }));

                        var firstchange = nicknameHistory1.FirstOrDefault();
                        if (firstchange == null)
                        {
                            await plr.Session.SendAsync(new ServerResultAckMessage(ServerResult.NicknameUnavailable));

                            return(false);
                        }

                        account.Nickname     = firstchange.OldName;
                        plr.Account.Nickname = firstchange.OldName;

                        foreach (var history in nicknameHistory1)
                        {
                            await DbUtil.DeleteAsync(db, history);
                        }

                        await plr.Session.SendAsync(new ItemUseChangeNickCancelAckMessage(0));
                    }
                    else
                    {
                        if (!await AuthService.IsNickAvailableAsync(toNickname))
                        {
                            await plr.Session.SendAsync(new ServerResultAckMessage(ServerResult.NicknameUnavailable));

                            return(false);
                        }

                        account.Nickname     = toNickname;
                        plr.Account.Nickname = toNickname;
                        DbUtil.Insert(db, nicknameHistory);
                        await plr.Session.SendAsync(new ItemUseChangeNickAckMessage
                        {
                            Result = 0,
                            Unk2   = 0,
                            Unk3   = toNickname
                        });
                    }

                    DbUtil.Update(db, account);
                    return(true);
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());
                await plr.Session.SendAsync(new ServerResultAckMessage(ServerResult.FailedToRequestTask));

                return(false);
            }
        }
Esempio n. 20
0
        public async Task LoginHandler(GameSession session, LoginRequestReqMessage message)
        {
            Logger.ForAccount(message.AccountId, message.Username)
            .Information("Login from {remoteEndPoint}", session.RemoteEndPoint);

            //if (message.Version != s_version)
            //{
            //    Logger.ForAccount(message.AccountId, message.Username)
            //        .Error("Invalid client version {version}", message.Version);
            //
            //    session.SendAsync(new LoginReguestAckMessage(GameLoginResult.WrongVersion));
            //    return;
            //}

            if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Server is full");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.ServerFull));
                return;
            }

            #region Validate Login

            AccountDto accountDto;
            using (var db = AuthDatabase.Open())
            {
                accountDto = (await db.FindAsync <AccountDto>(statement => statement
                                                              .Include <BanDto>(join => join.LeftOuterJoin())
                                                              .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                              .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();
            }

            if (accountDto == null)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong login");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            uint inputSessionId;
            if (!uint.TryParse(message.SessionId, out inputSessionId))
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong login");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}>");
            if (sessionId != inputSessionId)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong sessionid(1)");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
                return;
            }
            string datetime      = $"{DateTimeOffset.Now.DateTime}";
            var    authsessionId = Hash.GetString <CRC32>($"<{accountDto.Username}+{sessionId}+{message.Datetime}>");
            if (authsessionId != message.AuthToken)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong sessionid(2)");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            var newsessionId = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>");
            if (newsessionId != message.newToken)
            {
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Wrong sessionid(3)");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
                return;
            }


            var now = DateTimeOffset.Now.ToUnixTimeSeconds();
            var ban = accountDto.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now);
            if (ban != null)
            {
                var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0));
                Logger.ForAccount(message.AccountId, message.Username)
                .Error("Banned until {unbanDate}", unbanDate);

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout));
                return;
            }

            var account = new Account(accountDto);

            #endregion

            if (account.SecurityLevel < Config.Instance.SecurityLevel)
            {
                Logger.ForAccount(account)
                .Error("No permission to enter this server({securityLevel} or above required)", Config.Instance.SecurityLevel);

                session.SendAsync(new LoginReguestAckMessage((GameLoginResult)9));
                return;
            }

            if (message.KickConnection)
            {
                Logger.ForAccount(account)
                .Information("Kicking old connection");

                var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id);
                oldPlr?.Disconnect();
            }

            if (GameServer.Instance.PlayerManager.Contains(account.Id))
            {
                Logger.ForAccount(account)
                .Error("Already online");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.TerminateOtherConnection));
                return;
            }

            using (var db = GameDatabase.Open())
            {
                var plrDto = (await db.FindAsync <PlayerDto>(statement => statement
                                                             .Include <PlayerCharacterDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerDenyDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerItemDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerMailDto>(join => join.LeftOuterJoin())
                                                             .Include <PlayerSettingDto>(join => join.LeftOuterJoin())
                                                             .Where($"{nameof(PlayerDto.Id):C} = @Id")
                                                             .WithParameters(new { Id = message.AccountId })))
                             .FirstOrDefault();

                if (plrDto == null)
                {
                    // first time connecting to this server
                    var        expTable = GameServer.Instance.ResourceCache.GetExperience();
                    Experience expValue;
                    if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue))
                    {
                        expValue = new Experience();
                        expValue.TotalExperience = 0;
                        Logger.Warning("Given start level is not found in the experience table");
                    }

                    plrDto = new PlayerDto
                    {
                        Id              = (int)account.Id,
                        Level           = Config.Instance.Game.StartLevel,
                        PEN             = Config.Instance.Game.StartPEN,
                        AP              = Config.Instance.Game.StartAP,
                        Coins1          = Config.Instance.Game.StartCoins1,
                        Coins2          = Config.Instance.Game.StartCoins2,
                        TotalExperience = (int)expValue.TotalExperience
                    };

                    await db.InsertAsync(plrDto);
                }

                session.Player = new Player(session, account, plrDto);
            }

            if (GameServer.Instance.PlayerManager.Contains(session.Player))
            {
                session.Player = null;
                Logger.ForAccount(account)
                .Error("Already online");

                session.SendAsync(new LoginReguestAckMessage(GameLoginResult.TerminateOtherConnection));
                return;
            }

            GameServer.Instance.PlayerManager.Add(session.Player);

            Logger.ForAccount(account)
            .Information("Login success");

            var result = string.IsNullOrWhiteSpace(account.Nickname)
                ? GameLoginResult.ChooseNickname
                : GameLoginResult.OK;
            if (result == GameLoginResult.ChooseNickname)
            {
                session.Player.Account.Nickname = session.Player.Account.Username;
                session.Player.CharacterManager.CreateFirst(0, 0, 0, 0, 0, 0);
                using (var db = AuthDatabase.Open())
                {
                    var mapping = OrmConfiguration
                                  .GetDefaultEntityMapping <AccountDto>()
                                  .Clone()
                                  .UpdatePropertiesExcluding(prop => prop.IsExcludedFromUpdates = true, nameof(AccountDto.Nickname));

                    await db.UpdateAsync(new AccountDto { Id = (int)session.Player.Account.Id, Nickname = session.Player.Account.Username },
                                         statement => statement.WithEntityMappingOverride(mapping));
                }
                Logger.ForAccount(account)
                .Information($"Created Account for {session.Player.Account.Username}");
            }
            else if (!session.Player.CharacterManager.CheckChars())
            {
                session.Player.CharacterManager.CreateFirst(0, 0, 0, 0, 0, 0);
            }


            await session.SendAsync(new LoginReguestAckMessage(0, session.Player.Account.Id));

            if (!string.IsNullOrWhiteSpace(account.Nickname))
            {
                await LoginAsync(session);
            }
        }
    public override void ChannelRead(IChannelHandlerContext context, object messageData)
    {
        var buffer = messageData as IByteBuffer;

        byte[] data = buffer.ToArray();

        RmiMessage __msg    = new RmiMessage(data, data.Length);
        short      magic    = 0;
        ByteArray  _message = new ByteArray();

        if (__msg.Read(ref magic) &&
            magic == Magic &&
            __msg.Read(ref _message))
        {
            RmiMessage  message = new RmiMessage(_message);
            MessageType coreID  = 0;
            if (message.Read(ref coreID))
            {
                switch (coreID)
                {
                case MessageType.Rmi:
                {
                    short RmiID = 0;
                    if (message.Read(ref RmiID))
                    {
                        switch (RmiID)
                        {
                        case 15:
                        {
                            AccountDto account;
                            string     Username = "";
                            string     Password = "";
                            bool       register = false;

                            if (message.Read(ref Username) &&
                                message.Read(ref Password) &&
                                message.Read(ref register))
                            {
                                using (var db = AuthDatabase.Open())
                                {
                                    Logger.Information("Authentication login from {endpoint}", context.Channel.RemoteAddress.ToString());

                                    if (Username.Length > 5 && Password.Length > 5)
                                    {
                                        var result = db.Find <AccountDto>(statement => statement
                                                                          .Where($"{nameof(AccountDto.Username):C} = @{nameof(Username)}")
                                                                          .Include <BanDto>(join => join.LeftOuterJoin())
                                                                          .WithParameters(new { Username }));

                                        account = result.FirstOrDefault();

                                        if (account == null)
                                        {
                                            account = new AccountDto {
                                                Username = Username
                                            };

                                            var newSalt = new byte[24];
                                            using (var csprng = new RNGCryptoServiceProvider())
                                                csprng.GetBytes(newSalt);

                                            var hash = new byte[24];
                                            using (var pbkdf2 = new Rfc2898DeriveBytes(Password, newSalt, 24000))
                                                hash = pbkdf2.GetBytes(24);

                                            account.Password = Convert.ToBase64String(hash);

                                            account.Salt = Convert.ToBase64String(newSalt);

                                            db.InsertAsync(account);
                                        }

                                        var salt = Convert.FromBase64String(account.Salt);

                                        var passwordGuess = new byte[24];
                                        using (var pbkdf2 = new Rfc2898DeriveBytes(Password, salt, 24000))
                                            passwordGuess = pbkdf2.GetBytes(24);

                                        var actualPassword = Convert.FromBase64String(account.Password);

                                        uint difference = (uint)passwordGuess.Length ^ (uint)actualPassword.Length;

                                        for (var i = 0; i < passwordGuess.Length && i < actualPassword.Length; i++)
                                        {
                                            difference |= (uint)(passwordGuess[i] ^ actualPassword[i]);
                                        }

                                        if (difference != 0 || string.IsNullOrWhiteSpace(account.Password))
                                        {
                                            Logger.Error("Wrong authentication credentials for {username} / {endpoint}", Username, context.Channel.RemoteAddress.ToString());
                                            RmiMessage ack = new RmiMessage();
                                            ack.Write(false);
                                            ack.Write("Login failed");
                                            RmiSend(context, 16, ack);
                                        }
                                        else
                                        {
                                            account.LoginToken = AuthHash.GetHash256($"{context.Channel.RemoteAddress.ToString()}-{account.Username}-{account.Password}").ToLower();
                                            account.LastLogin  = $"{DateTimeOffset.Now}";
                                            account.AuthToken  = "";
                                            account.newToken   = "";
                                            db.UpdateAsync(account);

                                            RmiMessage ack = new RmiMessage();
                                            ack.Write(true);
                                            ack.Write(account.LoginToken);
                                            RmiSend(context, 16, ack);
                                            Logger.Information("Authentication success for {username}", Username);
                                        }
                                    }
                                    else
                                    {
                                        Logger.Error("Wrong authentication credentials for {username} / {endpoint}", Username, context.Channel.RemoteAddress.ToString());
                                        RmiMessage ack = new RmiMessage();
                                        ack.Write(false);
                                        ack.Write("Invalid length of username/password");
                                        RmiSend(context, 16, ack);
                                    }
                                }
                            }
                            else
                            {
                                Logger.Error("Wrong login for {endpoint}", context.Channel.RemoteAddress.ToString());
                                RmiMessage ack = new RmiMessage();
                                ack.Write(false);
                                ack.Write("Invalid loginpacket");
                                RmiSend(context, 16, ack);
                            }
                            break;
                        }

                        case 17:
                            context.CloseAsync();
                            break;

                        default:
                            Logger.Error("Received unknown rmiID{rmi} from {endpoint}", RmiID, context.Channel.RemoteAddress.ToString());
                            break;
                        }
                    }
                    break;
                }

                case MessageType.Notify:
                {
                    string info = "";
                    message.Read(ref info);
                    Logger.Information("Received info! -> {received}", info);
                    break;
                }

                default:
                    Logger.Error("Received unknown coreID{coreid} from {endpoint}", coreID, context.Channel.RemoteAddress.ToString());
                    break;
                }
            }
        }
        else
        {
            Logger.Error("Received invalid packetstruct from {endpoint}", context.Channel.RemoteAddress.ToString());
            context.CloseAsync();
        }
    }