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