public async Task LoginHandler(ISession session, CAuthInEUReqMessage message)
        {
            var ip = ((IPEndPoint)((TcpProcessor)session.Processor).Socket.RemoteEndPoint).Address.ToString();

            _logger.Debug()
            .Message("Login from {0} with username {1}", ip, message.Username)
            .Write();

            var db      = AuthDatabase.Instance;
            var account = await db.Accounts.FirstOrDefaultAsync(acc => acc.Username == message.Username)
                          .ConfigureAwait(false);

            if (account == null)
            {
                if (Config.Instance.NoobMode)
                {
                    // NoobMode: Create a new account if non exists
                    using (var scope = new DataAccessScope())
                    {
                        account          = db.Accounts.Create();
                        account.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 scope.CompleteAsync()
                        .ConfigureAwait(false);
                    }
                }
                else
                {
                    _logger.Error()
                    .Message("Wrong login for {0}", message.Username)
                    .Write();
                    await session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.WrongIdorPw))
                    .ConfigureAwait(false);

                    return;
                }
            }

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

            if (!account.Password.Equals(password, StringComparison.InvariantCultureIgnoreCase))
            {
                if (Config.Instance.NoobMode)
                {
                    // Noob Mode: Save new password
                    using (var scope = new DataAccessScope())
                    {
                        var acc   = db.Accounts.GetReference(account.Id);
                        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);
                        acc.Password = password;
                        acc.Salt     = salt;

                        await scope.CompleteAsync()
                        .ConfigureAwait(false);
                    }
                }
                else
                {
                    _logger.Error()
                    .Message("Wrong login for {0}", message.Username)
                    .Write();
                    await session.SendAsync(new SAuthInEuAckMessage(AuthLoginResult.WrongIdorPw))
                    .ConfigureAwait(false);

                    return;
                }
            }

            var now = DateTimeOffset.Now.ToUnixTimeSeconds();
            var ban = await account.Bans.FirstOrDefaultAsync(b => b.Date + b.Duration > now)
                      .ConfigureAwait(false);

            if (ban != null)
            {
                var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + ban.Duration);
                _logger.Error()
                .Message("{0} is banned until {1}", message.Username, unbanDate)
                .Write();
                await session.SendAsync(new SAuthInEuAckMessage(unbanDate))
                .ConfigureAwait(false);

                return;
            }

            _logger.Info()
            .Message("Login success for {0}", message.Username)
            .Write();

            using (var scope = new DataAccessScope())
            {
                var entry = account.LoginHistory.Create();
                entry.Date = DateTimeOffset.Now.ToUnixTimeSeconds();
                entry.IP   = ip;

                await scope.CompleteAsync()
                .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. 2
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. 3
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);
        }