public void SubtractInPlace() { DecayingDouble d = new DecayingDouble(4, FirstDayOfCentury); // One day later the double should be 2, so subtracting 1 should yield 1 d.SubtractInPlace(OneDay, 1, OneDayLater); Assert.InRange(d.ValueAtTimeOfLastUpdate, .99999, 1.000001); }
public IpHistory( IPAddress address, BlockingAlgorithmOptions options) { Address = address; CurrentBlockScore = new DecayingDouble(); RecentPotentialTypos = new SmallCapacityConstrainedSet<LoginAttemptSummaryForTypoAnalysis>(options.NumberOfFailuresToTrackForGoingBackInTimeToIdentifyTypos); }
public void AddInPlace() { DecayingDouble d = new DecayingDouble(4, FirstDayOfCentury); // Two days later the double should be 1, so adding 1 should yield 4 d.AddInPlace(OneDay, 3, TwoDaysLater); Assert.InRange(d.ValueAtTimeOfLastUpdate, 3.99999, 4.000001); double shouldBeVeryCloseTo1 = d.GetValue(OneDay, FourDaysLater); Assert.InRange(shouldBeVeryCloseTo1, .99999, 1.000001); }
public DecayingDouble Add(TimeSpan halfLife, DecayingDouble amountToAdd) { if (!LastUpdatedUtc.HasValue) { return new DecayingDouble(ValueAtTimeOfLastUpdate + amountToAdd.ValueAtTimeOfLastUpdate, amountToAdd.LastUpdatedUtc); } else if (!amountToAdd.LastUpdatedUtc.HasValue) { return new DecayingDouble(ValueAtTimeOfLastUpdate + amountToAdd.ValueAtTimeOfLastUpdate, LastUpdatedUtc); } else if (LastUpdatedUtc.Value > amountToAdd.LastUpdatedUtc.Value) { return new DecayingDouble( ValueAtTimeOfLastUpdate + amountToAdd.GetValue(halfLife, LastUpdatedUtc.Value), LastUpdatedUtc.Value); } else { return new DecayingDouble(amountToAdd.ValueAtTimeOfLastUpdate + GetValue(halfLife, amountToAdd.LastUpdatedUtc.Value), amountToAdd.LastUpdatedUtc.Value); } }
public DecayingDouble Add(TimeSpan halfLife, DecayingDouble amountToAdd) { if (!LastUpdatedUtc.HasValue) { return(new DecayingDouble(ValueAtTimeOfLastUpdate + amountToAdd.ValueAtTimeOfLastUpdate, amountToAdd.LastUpdatedUtc)); } else if (!amountToAdd.LastUpdatedUtc.HasValue) { return(new DecayingDouble(ValueAtTimeOfLastUpdate + amountToAdd.ValueAtTimeOfLastUpdate, LastUpdatedUtc)); } else if (LastUpdatedUtc.Value > amountToAdd.LastUpdatedUtc.Value) { return(new DecayingDouble( ValueAtTimeOfLastUpdate + amountToAdd.GetValue(halfLife, LastUpdatedUtc.Value), LastUpdatedUtc.Value)); } else { return(new DecayingDouble(amountToAdd.ValueAtTimeOfLastUpdate + GetValue(halfLife, amountToAdd.LastUpdatedUtc.Value), amountToAdd.LastUpdatedUtc.Value)); } }
public DecayingDouble Subtract(TimeSpan halfLife, DecayingDouble amountToRemove) { if (!LastUpdatedUtc.HasValue) { return(new DecayingDouble(ValueAtTimeOfLastUpdate - amountToRemove.ValueAtTimeOfLastUpdate, amountToRemove.LastUpdatedUtc)); } else if (!amountToRemove.LastUpdatedUtc.HasValue) { return(new DecayingDouble(ValueAtTimeOfLastUpdate - amountToRemove.ValueAtTimeOfLastUpdate, LastUpdatedUtc)); } else if (LastUpdatedUtc.Value > amountToRemove.LastUpdatedUtc.Value) { return (new DecayingDouble( ValueAtTimeOfLastUpdate - amountToRemove.GetValue(halfLife, LastUpdatedUtc.Value), LastUpdatedUtc.Value)); } else { return(new DecayingDouble(amountToRemove.ValueAtTimeOfLastUpdate - GetValue(halfLife, amountToRemove.LastUpdatedUtc.Value), amountToRemove.LastUpdatedUtc.Value)); } }
public DecayingDouble Subtract(TimeSpan halfLife, DecayingDouble amountToRemove) { if (!LastUpdatedUtc.HasValue) { return new DecayingDouble(ValueAtTimeOfLastUpdate - amountToRemove.ValueAtTimeOfLastUpdate, amountToRemove.LastUpdatedUtc); } else if (!amountToRemove.LastUpdatedUtc.HasValue) { return new DecayingDouble(ValueAtTimeOfLastUpdate - amountToRemove.ValueAtTimeOfLastUpdate, LastUpdatedUtc); } else if (LastUpdatedUtc.Value > amountToRemove.LastUpdatedUtc.Value) { return new DecayingDouble( ValueAtTimeOfLastUpdate - amountToRemove.GetValue(halfLife, LastUpdatedUtc.Value), LastUpdatedUtc.Value); } else { return new DecayingDouble(amountToRemove.ValueAtTimeOfLastUpdate - GetValue(halfLife, amountToRemove.LastUpdatedUtc.Value), amountToRemove.LastUpdatedUtc.Value); } }
public void SubtractInPlace(TimeSpan halfLife, DecayingDouble amountToSubtract) => SubtractInPlace(halfLife, amountToSubtract.ValueAtTimeOfLastUpdate, amountToSubtract.LastUpdatedUtc);
public void AddInPlace(TimeSpan halfLife, DecayingDouble amountToAdd) => AddInPlace(halfLife, amountToAdd.ValueAtTimeOfLastUpdate, amountToAdd.LastUpdatedUtc);
//public DecayingDouble AllFailures(TimeSpan halfLife) => AccountFailures.Add(halfLife, PasswordFailures); //public DecayingDouble AccountFailuresSubsetWithInfrequentPassword(TimeSpan halfLife) => AccountFailures.Subtract(halfLife, AccountFailuresSubsetWithFrequentPassword); //public DecayingDouble PasswordFailuresSubsetWithInfrequentPassword(TimeSpan halfLife) => PasswordFailures.Subtract(halfLife, PasswordFailuresSubsetWithFrequentPassword); //public DecayingDouble PasswordFailuresSubsetWithoutTypo(TimeSpan halfLife) => PasswordFailures.Subtract(halfLife, PasswordFailuresSubsetWithTypo); //public DecayingDouble PasswordFailuresSubsetWithoutEitherFrequentPasswordOrTypo(TimeSpan halfLife) => PasswordFailures.Subtract(halfLife, PasswordFailuresSubsetWithTypoAndFrequentPassword); /// <summary> /// This analysis will examine the client IP's previous failed attempts to login to this account /// to determine if any failed attempts were due to typos. /// </summary> /// <param name="account">The account that the client is currently trying to login to.</param> /// <param name="whenUtc"></param> /// <param name="correctPassword">The correct password for this account. (We can only know it because /// the client must have provided the correct one this loginAttempt.)</param> /// <returns></returns> public void AdjustBlockingScoreForPastTyposTreatedAsFullFailures( Simulator simulator, SimulatedUserAccount account, DateTime whenUtc, string correctPassword) { SimLoginAttemptSummaryForTypoAnalysis[] recentPotentialTypos = RecentPotentialTypos.MostRecentFirst.ToArray(); foreach (SimLoginAttemptSummaryForTypoAnalysis potentialTypo in recentPotentialTypos) { if (account == null || potentialTypo.UsernameOrAccountId != account.UsernameOrAccountId) continue; // Use an edit distance calculation to determine if it was a likely typo bool likelyTypo = EditDistance.Calculate(potentialTypo.Password, correctPassword) <= simulator._experimentalConfiguration.BlockingOptions.MaxEditDistanceConsideredATypo; TimeSpan halfLife = simulator._experimentalConfiguration.BlockingOptions.BlockScoreHalfLife; DecayingDouble value = new DecayingDouble(1d, potentialTypo.WhenUtc); // Add this to the list of changed attempts if (potentialTypo.WasPasswordFrequent) { PasswordFailuresNoTypoFrequentPassword.SubtractInPlace(halfLife, value); PasswordFailuresTypoFrequentPassword.AddInPlace(halfLife, value); } RecentPotentialTypos.Remove(potentialTypo); } }
public void SubtractInPlace(TimeSpan halfLife, DecayingDouble amountToSubtract) => SubtractInPlace(halfLife, amountToSubtract.ValueAtTimeOfLastUpdate, amountToSubtract.LastUpdatedUtc);
public void AddInPlace(TimeSpan halfLife, DecayingDouble amountToAdd) => AddInPlace(halfLife, amountToAdd.ValueAtTimeOfLastUpdate, amountToAdd.LastUpdatedUtc);
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 SetValue(DecayingDouble source) { LastUpdatedUtc = source.LastUpdatedUtc; ValueAtTimeOfLastUpdate = source.ValueAtTimeOfLastUpdate; }
public void SetValue(DecayingDouble source) { LastUpdatedUtc = source.LastUpdatedUtc; ValueAtTimeOfLastUpdate = source.ValueAtTimeOfLastUpdate; }