/// <summary> /// Evaluate the accuracy of our stopguessing service by sending user logins and malicious traffic /// </summary> /// <returns></returns> public void Run() { _logger.WriteStatus("In RunInBackground"); _logger.WriteStatus("Priming password-tracking with known common passwords"); _simPasswords.PrimeWithKnownPasswordsAsync(_binomialLadderFilter, 40); _logger.WriteStatus("Finished priming password-tracking with known common passwords"); _logger.WriteStatus("Creating IP Pool"); _ipPool = new IpPool(_experimentalConfiguration); _logger.WriteStatus("Generating simualted account records"); _simAccounts = new SimulatedAccounts(_ipPool, _simPasswords, _logger); _simAccounts.Generate(_experimentalConfiguration); _logger.WriteStatus("Creating login-attempt generator"); _attemptGenerator = new SimulatedLoginAttemptGenerator(_experimentalConfiguration, _simAccounts, _ipPool, _simPasswords); _logger.WriteStatus("Finiished creating login-attempt generator"); foreach ( ConcurrentStreamWriter writer in new[] { _AttackAttemptsWithValidPasswords, _LegitimateAttemptsWithValidPasswords, _OtherAttempts }) { lock (writer) { writer.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}" + "\t{11}\t{12}\t{13}\t{14}\t{15}\t{16}\t{17}\t{18}\t{19}\t{20}\t{21}\t{22}\t{23}\t{24}\t{25}", "Password", "UserID", "IP", "DeviceCookie", "IsFrequentlyGuessedPw", "IsPasswordCorrect", "IsFromAttackAttacker", "IsAGuess", "IPInOposingPool", "IsClientAProxyIP", "TypeOfMistake", "DecayedInvalidAttemptsPerPassword", "DecayedMaxConsecutiveIncorrectAttemptsPerAccount", "DecayedSuccessfulLogins", "DecayedAccountFailuresInfrequentPassword", "DecayedAccountFailuresFrequentPassword", "DecayedRepeatAccountFailuresInfrequentPassword", "DecayedRepeatAccountFailuresFrequentPassword", "DecayedPasswordFailuresNoTypoInfrequentPassword", "DecayedPasswordFailuresNoTypoFrequentPassword", "DecayedPasswordFailuresTypoInfrequentPassword", "DecayedPasswordFailuresTypoFrequentPassword", "DecayedRepeatPasswordFailuresNoTypoInfrequentPassword", "DecayedRepeatPasswordFailuresNoTypoFrequentPassword", "DecayedRepeatPasswordFailuresTypoInfrequentPassword", "DecayedRepeatPasswordFailuresTypoFrequentPassword" )); } } TimeSpan testTimeSpan = _experimentalConfiguration.TestTimeSpan; double ticksBetweenLogins = ((double)testTimeSpan.Ticks) / (double)_experimentalConfiguration.TotalLoginAttemptsToIssue; int interlockedCount = 0; Parallel.For(0L, (long)_experimentalConfiguration.TotalLoginAttemptsToIssue, (count, pls) => //) TaskParalllel.RepeatWithWorkers(_experimentalConfiguration.TotalLoginAttemptsToIssue, //async (count, cancelToken) => // (count) => { interlockedCount = Interlocked.Add(ref interlockedCount, 1); if (interlockedCount % 10000 == 0) { _logger.WriteStatus("Login Attempt {0:N0}", interlockedCount); } DateTime eventTimeUtc = StartTimeUtc.AddTicks((long)(ticksBetweenLogins * interlockedCount)); SimulatedLoginAttempt simAttempt; if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.FractionOfLoginAttemptsFromAttacker) { switch (_experimentalConfiguration.AttackersStrategy) { case ExperimentalConfiguration.AttackStrategy.UseUntilLikelyPopular: simAttempt = _attemptGenerator.MaliciousLoginAttemptBreadthFirstAvoidMakingPopular(eventTimeUtc); break; case ExperimentalConfiguration.AttackStrategy.Weighted: simAttempt = _attemptGenerator.MaliciousLoginAttemptWeighted(eventTimeUtc); break; case ExperimentalConfiguration.AttackStrategy.BreadthFirst: default: simAttempt = _attemptGenerator.MaliciousLoginAttemptBreadthFirst(eventTimeUtc); break; } } else { simAttempt = _attemptGenerator.BenignLoginAttempt(eventTimeUtc); } // Get information about the client's IP SimIpHistory ipHistory = _ipHistoryCache.GetOrAdd(simAttempt.AddressOfClientInitiatingRequest, (ip) => new SimIpHistory( _experimentalConfiguration.BlockingOptions .NumberOfFailuresToTrackForGoingBackInTimeToIdentifyTypos)); //SimIpHistory ipHistory = await _ipHistoryCache.GetAsync(simAttempt.AddressOfClientInitiatingRequest, cancelToken); double[] scores = ipHistory.GetAllScores(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc); simAttempt.UpdateSimulatorState(this, ipHistory); double decayingInvalidPasswordAttempts = 0d; if (simAttempt.IsPasswordValid) { DecayingDouble incorrectPasswordAttempts; if (_incorrectPasswordCounts.TryGetValue(simAttempt.Password, out incorrectPasswordAttempts)) { decayingInvalidPasswordAttempts = incorrectPasswordAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc); } } else { decayingInvalidPasswordAttempts = 1d; DecayingDouble incorrectPasswordAttempts; if (_incorrectPasswordCounts.TryGetValue(simAttempt.Password, out incorrectPasswordAttempts)) { decayingInvalidPasswordAttempts += incorrectPasswordAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc); } _incorrectPasswordCounts[simAttempt.Password] = new DecayingDouble(decayingInvalidPasswordAttempts, simAttempt.TimeOfAttemptUtc); } var ipInfo = _ipPool.GetIpAddressDebugInfo(simAttempt.AddressOfClientInitiatingRequest); string outputString = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}\t{13}", simAttempt.Password, simAttempt.SimAccount?.UsernameOrAccountId ?? "<null>", simAttempt.AddressOfClientInitiatingRequest, simAttempt.DeviceCookieHadPriorSuccessfulLoginForThisAccount ? "HadCookie" : "NoCookie", simAttempt.IsFrequentlyGuessedPassword ? "Frequent" : "Infrequent", simAttempt.IsPasswordValid ? "Correct" : "Incorrect", simAttempt.IsFromAttacker ? "FromAttacker" : "FromUser", simAttempt.IsGuess ? "IsGuess" : "NotGuess", simAttempt.IsFromAttacker ? (ipInfo.UsedByBenignUsers ? "IsInBenignPool" : "NotUsedByBenign") : (ipInfo.UsedByAttackers ? "IsInAttackersIpPool" : "NotUsedByAttacker"), ipInfo.IsPartOfProxy ? "ProxyIP" : "NotAProxy", string.IsNullOrEmpty(simAttempt.MistakeType) ? "-" : simAttempt.MistakeType, decayingInvalidPasswordAttempts, simAttempt.SimAccount?.MaxConsecutiveIncorrectAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc) ?? 0d, string.Join("\t", scores.Select(s => s.ToString(CultureInfo.InvariantCulture)).ToArray()) ); if (simAttempt.IsFromAttacker && simAttempt.IsPasswordValid) { lock (_AttackAttemptsWithValidPasswords) { _AttackAttemptsWithValidPasswords.WriteLine(outputString); //_AttackAttemptsWithValidPasswords.Flush(); } } else if (!simAttempt.IsFromAttacker && simAttempt.IsPasswordValid) { lock (_LegitimateAttemptsWithValidPasswords) { _LegitimateAttemptsWithValidPasswords.WriteLine(outputString); //_LegitiamteAttemptsWithValidPasswords.Flush(); } } else { lock (_OtherAttempts) { _OtherAttempts.WriteLine(outputString); //_OtherAttempts.Flush(); } } }); //(e) => { //}, //cancellationToken: cancellationToken).ConfigureAwait(false); foreach ( ConcurrentStreamWriter writer in new [] { _AttackAttemptsWithValidPasswords, _LegitimateAttemptsWithValidPasswords, _OtherAttempts }) { writer.Close(); } //_memoryUsageLimiter.Dispose(); }
public void UpdateSimulatorState(Simulator simulator, SimIpHistory ipHistory) { IsRepeatFailure = (SimAccount == null) ? simulator._recentIncorrectPasswords.AddMember(UserNameOrAccountId + "\n" + Password) : simulator._userAccountController.AddIncorrectPhaseTwoHashAsync(SimAccount, Password, TimeOfAttemptUtc).Result; int passwordsHeightOnBinomialLadder = IsPasswordValid ? simulator._binomialLadderFilter.GetHeight(Password) : simulator._binomialLadderFilter.Step(Password); IsFrequentlyGuessedPassword = passwordsHeightOnBinomialLadder + 1 >= simulator._binomialLadderFilter.MaxHeight; if (SimAccount != null) { DeviceCookieHadPriorSuccessfulLoginForThisAccount = simulator._userAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBeforeAsync( SimAccount, CookieProvidedByBrowser).Result; } if (IsPasswordValid) { // Determine if any of the outcomes for login attempts from the client IP for this request were the result of typos, // as this might impact our decision about whether or not to block this client IP in response to its past behaviors. ipHistory.AdjustBlockingScoreForPastTyposTreatedAsFullFailures(simulator, SimAccount, TimeOfAttemptUtc, Password); if (SimAccount != null) { simulator._userAccountController.RecordHashOfDeviceCookieUsedDuringSuccessfulLoginBackground( SimAccount, CookieProvidedByBrowser, TimeOfAttemptUtc); } } if (!IsPasswordValid && !IsRepeatFailure && SimAccount != null) { ipHistory.RecentPotentialTypos.Add(new SimLoginAttemptSummaryForTypoAnalysis() { WhenUtc = TimeOfAttemptUtc, Password = Password, UsernameOrAccountId = UserNameOrAccountId, WasPasswordFrequent = IsFrequentlyGuessedPassword }); } DecayingDouble decayingOneFromThisInstant = new DecayingDouble(1, TimeOfAttemptUtc); TimeSpan halfLife = simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife; if (IsPasswordValid) { ipHistory.SuccessfulLogins.AddInPlace(halfLife, decayingOneFromThisInstant); } else if (SimAccount == null) { if (IsRepeatFailure) { if (IsFrequentlyGuessedPassword) { ipHistory.RepeatAccountFailuresFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.RepeatAccountFailuresInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } else { if (IsFrequentlyGuessedPassword) { ipHistory.AccountFailuresFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.AccountFailuresInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } } else { if (IsRepeatFailure) { if (IsFrequentlyGuessedPassword) { ipHistory.RepeatPasswordFailuresNoTypoFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.RepeatPasswordFailuresNoTypoInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } else { if (IsFrequentlyGuessedPassword) { ipHistory.PasswordFailuresNoTypoFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.PasswordFailuresNoTypoInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } } }
/// <summary> /// Evaluate the accuracy of our stopguessing service by sending user logins and malicious traffic /// </summary> /// <returns></returns> public async Task Run(CancellationToken cancellationToken = default(CancellationToken)) { _logger.WriteStatus("In RunInBackground"); _logger.WriteStatus("Priming password-tracking with known common passwords"); _simPasswords.PrimeWithKnownPasswordsAsync(_binomialLadderFilter, 40); _logger.WriteStatus("Finished priming password-tracking with known common passwords"); _logger.WriteStatus("Creating IP Pool"); _ipPool = new IpPool(_experimentalConfiguration); _logger.WriteStatus("Generating simualted account records"); _simAccounts = new SimulatedAccounts(_ipPool, _simPasswords, _logger); await _simAccounts.GenerateAsync(_experimentalConfiguration, cancellationToken); _logger.WriteStatus("Creating login-attempt generator"); _attemptGenerator = new SimulatedLoginAttemptGenerator(_experimentalConfiguration, _simAccounts, _ipPool, _simPasswords); _logger.WriteStatus("Finiished creating login-attempt generator"); foreach (TextWriter writer in new TextWriter[] { _AttackAttemptsWithValidPasswords, _LegitiamteAttemptsWithValidPasswords, _OtherAttempts }) { writer.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", //,{9} "Password", "UserID", "IP", "IsFrequentlyGuessedPw", "IsPasswordCorrect", "IsFromAttackAttacker", "IsAGuess", "IPInOposingPool", "IsClientAProxyIP", "TypeOfMistake" //string.Join(",") ); } TimeSpan testTimeSpan = _experimentalConfiguration.TestTimeSpan; double ticksBetweenLogins = ((double)testTimeSpan.Ticks) / (double)_experimentalConfiguration.TotalLoginAttemptsToIssue; await TaskParalllel.RepeatWithWorkers(_experimentalConfiguration.TotalLoginAttemptsToIssue, async (count, cancelToken) => { if (count % 10000 == 0) { _logger.WriteStatus("Login Attempt {0:N0}", count); } DateTime eventTimeUtc = StartTimeUtc.AddTicks((long)(ticksBetweenLogins *count)); SimulatedLoginAttempt simAttempt; if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.FractionOfLoginAttemptsFromAttacker) { switch (_experimentalConfiguration.AttackersStrategy) { case ExperimentalConfiguration.AttackStrategy.UseUntilLikelyPopular: simAttempt = _attemptGenerator.MaliciousLoginAttemptBreadthFirstAvoidMakingPopular(eventTimeUtc); break; case ExperimentalConfiguration.AttackStrategy.Weighted: simAttempt = _attemptGenerator.MaliciousLoginAttemptWeighted(eventTimeUtc); break; case ExperimentalConfiguration.AttackStrategy.BreadthFirst: default: simAttempt = _attemptGenerator.MaliciousLoginAttemptBreadthFirst(eventTimeUtc); break; } } else { simAttempt = _attemptGenerator.BenignLoginAttempt(eventTimeUtc); } // Get information about the client's IP SimIpHistory ipHistory = await _ipHistoryCache.GetAsync(simAttempt.AddressOfClientInitiatingRequest, cancelToken); double[] scores = ipHistory.GetAllScores(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc); simAttempt.UpdateSimulatorState(this, ipHistory); var ipInfo = _ipPool.GetIpAddressDebugInfo(simAttempt.AddressOfClientInitiatingRequest); string outputString = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", simAttempt.Password, simAttempt.SimAccount?.UsernameOrAccountId ?? "<null>", simAttempt.AddressOfClientInitiatingRequest, simAttempt.IsFrequentlyGuessedPassword ? "Frequent" : "Infrequent", simAttempt.IsPasswordValid ? "Correct" : "Incorrect", simAttempt.IsFromAttacker ? "FromAttacker" : "FromUser", simAttempt.IsGuess ? "IsGuess" : "NotGuess", simAttempt.IsFromAttacker ? (ipInfo.UsedByBenignUsers ? "IsInBenignPool" : "NotUsedByBenign") : (ipInfo.UsedByAttackers ? "IsInAttackersIpPool" : "NotUsedByAttacker"), ipInfo.IsPartOfProxy ? "ProxyIP" : "NotAProxy", string.IsNullOrEmpty(simAttempt.MistakeType) ? "-" : simAttempt.MistakeType, string.Join(",", scores.Select(s => s.ToString(CultureInfo.InvariantCulture)).ToArray()) ); if (simAttempt.IsFromAttacker && simAttempt.IsPasswordValid) { await _AttackAttemptsWithValidPasswords.WriteLineAsync(outputString); await _AttackAttemptsWithValidPasswords.FlushAsync(); } else if (!simAttempt.IsFromAttacker && simAttempt.IsPasswordValid) { await _LegitiamteAttemptsWithValidPasswords.WriteLineAsync(outputString); await _LegitiamteAttemptsWithValidPasswords.FlushAsync(); } else { await _OtherAttempts.WriteLineAsync(outputString); await _OtherAttempts.FlushAsync(); } }, //(e) => { //}, cancellationToken : cancellationToken); _memoryUsageLimiter.Dispose(); }
public void UpdateSimulatorState(Simulator simulator, SimIpHistory ipHistory) { IsRepeatFailure = !IsPasswordValid && ( (SimAccount == null) ? simulator._recentIncorrectPasswords.AddMember(UserNameOrAccountId + "\n" + Password) : simulator._userAccountController.AddIncorrectPhaseTwoHash(SimAccount, Password, TimeOfAttemptUtc) ); int passwordsHeightOnBinomialLadder = (IsPasswordValid || IsRepeatFailure) ? simulator._binomialLadderFilter.GetHeight(Password) : simulator._binomialLadderFilter.Step(Password); IsFrequentlyGuessedPassword = passwordsHeightOnBinomialLadder >= simulator._experimentalConfiguration.BlockingOptions.BinomialLadderFrequencyThreshdold_T; DeviceCookieHadPriorSuccessfulLoginForThisAccount = SimAccount != null && simulator._userAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBefore(SimAccount, CookieProvidedByBrowser); if (SimAccount != null && IsPasswordValid) { // Determine if any of the outcomes for login attempts from the client IP for this request were the result of typos, // as this might impact our decision about whether or not to block this client IP in response to its past behaviors. ipHistory.AdjustBlockingScoreForPastTyposTreatedAsFullFailures(simulator, SimAccount, TimeOfAttemptUtc, Password); simulator._userAccountController.RecordHashOfDeviceCookieUsedDuringSuccessfulLoginBackground( SimAccount, CookieProvidedByBrowser, TimeOfAttemptUtc); // Clear the count of consecutive failures SimAccount.ConsecutiveIncorrectAttempts.SetValue(0, this.TimeOfAttemptUtc); } else if (SimAccount != null && !IsRepeatFailure) { // Add the the account's consecutive failure count SimAccount.ConsecutiveIncorrectAttempts.AddInPlace( simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, 1d, this.TimeOfAttemptUtc); // Increase the max consecutive faiulre count if the current consecutive failure count exceeds it if (SimAccount.ConsecutiveIncorrectAttempts.GetValue( simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife) > SimAccount.MaxConsecutiveIncorrectAttempts.GetValue( simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife)) SimAccount.MaxConsecutiveIncorrectAttempts.SetValue(SimAccount.ConsecutiveIncorrectAttempts); } if (!IsPasswordValid && !IsRepeatFailure && SimAccount != null) { // This attempt is a non-repeat failure and could be a typo. Store it in the ste of potential typos. ipHistory.RecentPotentialTypos.Add(new SimLoginAttemptSummaryForTypoAnalysis() { WhenUtc = TimeOfAttemptUtc, Password = Password, UsernameOrAccountId = UserNameOrAccountId, WasPasswordFrequent = IsFrequentlyGuessedPassword }); } DecayingDouble decayingOneFromThisInstant = new DecayingDouble(1, TimeOfAttemptUtc); TimeSpan halfLife = simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife; if (IsPasswordValid) { ipHistory.SuccessfulLogins.AddInPlace(halfLife, decayingOneFromThisInstant); } else if (SimAccount == null) { if (IsRepeatFailure) { if (IsFrequentlyGuessedPassword) ipHistory.RepeatAccountFailuresFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); else ipHistory.RepeatAccountFailuresInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { if (IsFrequentlyGuessedPassword) ipHistory.AccountFailuresFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); else ipHistory.AccountFailuresInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } else { if (IsRepeatFailure) { if (IsFrequentlyGuessedPassword) ipHistory.RepeatPasswordFailuresNoTypoFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); else ipHistory.RepeatPasswordFailuresNoTypoInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { if (IsFrequentlyGuessedPassword) ipHistory.PasswordFailuresNoTypoFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); else ipHistory.PasswordFailuresNoTypoInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } }
public void UpdateSimulatorState(Simulator simulator, SimIpHistory ipHistory) { IsRepeatFailure = !IsPasswordValid && ( (SimAccount == null) ? simulator._recentIncorrectPasswords.AddMember(UserNameOrAccountId + "\n" + Password) : simulator._userAccountController.AddIncorrectPhaseTwoHash(SimAccount, Password, TimeOfAttemptUtc) ); int passwordsHeightOnBinomialLadder = (IsPasswordValid || IsRepeatFailure) ? simulator._binomialLadderFilter.GetHeight(Password) : simulator._binomialLadderFilter.Step(Password); IsFrequentlyGuessedPassword = passwordsHeightOnBinomialLadder >= simulator._experimentalConfiguration.BlockingOptions.BinomialLadderFrequencyThreshdold_T; DeviceCookieHadPriorSuccessfulLoginForThisAccount = SimAccount != null && simulator._userAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBefore(SimAccount, CookieProvidedByBrowser); if (SimAccount != null && IsPasswordValid) { // Determine if any of the outcomes for login attempts from the client IP for this request were the result of typos, // as this might impact our decision about whether or not to block this client IP in response to its past behaviors. ipHistory.AdjustBlockingScoreForPastTyposTreatedAsFullFailures(simulator, SimAccount, TimeOfAttemptUtc, Password); simulator._userAccountController.RecordHashOfDeviceCookieUsedDuringSuccessfulLoginBackground( SimAccount, CookieProvidedByBrowser, TimeOfAttemptUtc); // Clear the count of consecutive failures SimAccount.ConsecutiveIncorrectAttempts.SetValue(0, this.TimeOfAttemptUtc); } else if (SimAccount != null && !IsRepeatFailure) { // Add the the account's consecutive failure count SimAccount.ConsecutiveIncorrectAttempts.AddInPlace( simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, 1d, this.TimeOfAttemptUtc); // Increase the max consecutive faiulre count if the current consecutive failure count exceeds it if (SimAccount.ConsecutiveIncorrectAttempts.GetValue( simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife) > SimAccount.MaxConsecutiveIncorrectAttempts.GetValue( simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife)) { SimAccount.MaxConsecutiveIncorrectAttempts.SetValue(SimAccount.ConsecutiveIncorrectAttempts); } } if (!IsPasswordValid && !IsRepeatFailure && SimAccount != null) { // This attempt is a non-repeat failure and could be a typo. Store it in the ste of potential typos. ipHistory.RecentPotentialTypos.Add(new SimLoginAttemptSummaryForTypoAnalysis() { WhenUtc = TimeOfAttemptUtc, Password = Password, UsernameOrAccountId = UserNameOrAccountId, WasPasswordFrequent = IsFrequentlyGuessedPassword }); } DecayingDouble decayingOneFromThisInstant = new DecayingDouble(1, TimeOfAttemptUtc); TimeSpan halfLife = simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife; if (IsPasswordValid) { ipHistory.SuccessfulLogins.AddInPlace(halfLife, decayingOneFromThisInstant); } else if (SimAccount == null) { if (IsRepeatFailure) { if (IsFrequentlyGuessedPassword) { ipHistory.RepeatAccountFailuresFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.RepeatAccountFailuresInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } else { if (IsFrequentlyGuessedPassword) { ipHistory.AccountFailuresFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.AccountFailuresInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } } else { if (IsRepeatFailure) { if (IsFrequentlyGuessedPassword) { ipHistory.RepeatPasswordFailuresNoTypoFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.RepeatPasswordFailuresNoTypoInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } else { if (IsFrequentlyGuessedPassword) { ipHistory.PasswordFailuresNoTypoFrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } else { ipHistory.PasswordFailuresNoTypoInfrequentPassword.AddInPlace(halfLife, decayingOneFromThisInstant); } } } }