public static void PerformAuditSuccessActions(LapRequestModel model, TargetElement target, ReaderElement reader, UserPrincipal user, ComputerPrincipal computer, SearchResult searchResult) { Dictionary <string, string> tokens = BuildTokenDictionary(target, reader, user, computer, searchResult, model.ComputerName); string logSuccessMessage = Reporting.LogSuccessTemplate ?? LogMessages.DefaultAuditSuccessText; string emailSuccessMessage = Reporting.EmailSuccessTemplate ?? $"<html><head/><body><pre>{LogMessages.DefaultAuditSuccessText}</pre></body></html>"; LogEventInfo logEvent = new LogEventInfo(LogLevel.Info, Reporting.Logger.Name, ReplaceTokens(tokens, logSuccessMessage, false)); logEvent.Properties.Add("EventID", EventIDs.PasswordAccessed); Reporting.Logger.Log(logEvent); try { ICollection <string> recipients = Reporting.BuildRecipientList(target, reader, true, user); if (recipients.Count > 0) { string subject = ReplaceTokens(tokens, LogMessages.AuditEmailSubjectSuccess, false); Reporting.SendEmail(recipients, subject, ReplaceTokens(tokens, emailSuccessMessage, true)); } } catch (Exception iex) { Reporting.LogErrorEvent(EventIDs.AuditErrorCannotSendSuccessEmail, "An error occurred sending the success audit email", iex); } }
private static bool IsUserThresholdExceeded(LapRequestModel model, UserPrincipal p, HttpRequestBase r, int threshold, int duration) { if (RateLimiter.IsThresholdExceeded(p, threshold, duration)) { Reporting.PerformAuditFailureActions(model, UIMessages.RateLimitError, EventIDs.RateLimitExceededUser, string.Format(LogMessages.RateLimitExceededUser, p.SamAccountName, r.UserHostAddress, threshold, duration), null, null, null, p, null); return(true); } return(false); }
public static bool IsRateLimitExceeded(LapRequestModel model, UserPrincipal p, HttpRequestBase r) { if (LapsConfigSection.Configuration.RateLimitIP.Enabled) { if (RateLimiter.IsIpThresholdExceeded(model, p, r, LapsConfigSection.Configuration.RateLimitIP.ReqPerMinute, 60) || RateLimiter.IsIpThresholdExceeded(model, p, r, LapsConfigSection.Configuration.RateLimitIP.ReqPerHour, 3600) || RateLimiter.IsIpThresholdExceeded(model, p, r, LapsConfigSection.Configuration.RateLimitIP.ReqPerDay, 86400)) { return(true); } } if (LapsConfigSection.Configuration.RateLimitUser.Enabled) { if (RateLimiter.IsUserThresholdExceeded(model, p, r, LapsConfigSection.Configuration.RateLimitUser.ReqPerMinute, 60) || RateLimiter.IsUserThresholdExceeded(model, p, r, LapsConfigSection.Configuration.RateLimitUser.ReqPerHour, 3600) || RateLimiter.IsUserThresholdExceeded(model, p, r, LapsConfigSection.Configuration.RateLimitUser.ReqPerDay, 86400)) { return(true); } } return(false); }
public static void PerformAuditFailureActions(LapRequestModel model, string userMessage, int eventID, string logMessage, Exception ex, TargetElement target, ReaderElement reader, UserPrincipal user, ComputerPrincipal computer) { Dictionary <string, string> tokens = BuildTokenDictionary(target, reader, user, computer, null, model.ComputerName, logMessage ?? userMessage); string logFailureMessage = Reporting.LogFailureTemplate ?? LogMessages.DefaultAuditFailureText; string emailFailureMessage = Reporting.EmailFailureTemplate ?? $"<html><head/><body><pre>{LogMessages.DefaultAuditFailureText}</pre></body></html>"; Reporting.LogErrorEvent(eventID, ReplaceTokens(tokens, logFailureMessage, false), ex); try { ICollection <string> recipients = Reporting.BuildRecipientList(target, reader, false); if (recipients.Count > 0) { string subject = ReplaceTokens(tokens, LogMessages.AuditEmailSubjectFailure, false); Reporting.SendEmail(recipients, subject, ReplaceTokens(tokens, emailFailureMessage, true)); } } catch (Exception iex) { Reporting.LogErrorEvent(EventIDs.AuditErrorCannotSendFailureEmail, "An error occurred sending the failure audit email", iex); } }
public ActionResult Get(LapRequestModel model) { if (!this.ModelState.IsValid) { return(this.View()); } UserPrincipal user = null; try { model.FailureReason = null; try { user = this.GetCurrentUser(); if (user == null) { throw new NoMatchingPrincipalException(); } } catch (NoMatchingPrincipalException ex) { return(this.LogAndReturnErrorResponse(model, UIMessages.SsoIdentityNotFound, EventIDs.SsoIdentityNotFound, null, ex)); } if (RateLimiter.IsRateLimitExceeded(model, user, this.Request)) { return(this.View("RateLimitExceeded")); } Reporting.LogSuccessEvent(EventIDs.UserRequestedPassword, string.Format(LogMessages.UserHasRequestedPassword, user.SamAccountName, model.ComputerName)); ComputerPrincipal computer = Directory.GetComputerPrincipal(model.ComputerName); if (computer == null) { return(this.LogAndReturnErrorResponse(model, UIMessages.ComputerNotFoundInDirectory, EventIDs.ComputerNotFound, string.Format(LogMessages.ComputerNotFoundInDirectory, user.SamAccountName, model.ComputerName))); } TargetElement target = this.GetMatchingTargetOrNull(computer); if (target == null) { return(this.AuditAndReturnErrorResponse( model: model, userMessage: UIMessages.NotAuthorized, eventID: EventIDs.AuthZFailedNoTargetMatch, logMessage: string.Format(LogMessages.NoTargetsExist, user.SamAccountName, computer.SamAccountName), user: user, computer: computer)); } foreach (ReaderElement reader in target.Readers.OfType <ReaderElement>()) { if (this.IsReaderAuthorized(reader, user)) { logger.Trace($"User {user.SamAccountName} matches reader principal {reader.Principal} is authorized to read passwords from target {target.Name}"); SearchResult searchResult = Directory.GetDirectoryEntry(computer, Directory.AttrSamAccountName, Directory.AttrMsMcsAdmPwd, Directory.AttrMsMcsAdmPwdExpirationTime); if (!searchResult.Properties.Contains(Directory.AttrMsMcsAdmPwd)) { return(this.LogAndReturnErrorResponse(model, UIMessages.NoLapsPassword, EventIDs.LapsPasswordNotPresent, string.Format(LogMessages.NoLapsPassword, computer.SamAccountName, user.SamAccountName))); } if (target.ExpireAfter != null) { LapController.UpdateTargetPasswordExpiry(target, computer); searchResult = Directory.GetDirectoryEntry(computer, Directory.AttrSamAccountName, Directory.AttrMsMcsAdmPwd, Directory.AttrMsMcsAdmPwdExpirationTime); } Reporting.PerformAuditSuccessActions(model, target, reader, user, computer, searchResult); return(this.View("Show", LapController.CreateLapEntryModel(searchResult))); } } return(this.AuditAndReturnErrorResponse( model: model, userMessage: UIMessages.NotAuthorized, eventID: EventIDs.AuthZFailedNoReaderPrincipalMatch, logMessage: string.Format(LogMessages.AuthZFailedNoReaderPrincipalMatch, user.SamAccountName, computer.SamAccountName), target: target, user: user, computer: computer)); } catch (Exception ex) { return(this.LogAndReturnErrorResponse(model, UIMessages.UnexpectedError, EventIDs.UnexpectedError, string.Format(LogMessages.UnhandledError, model.ComputerName, user?.SamAccountName ?? LogMessages.UnknownComputerPlaceholder), ex)); } }
private ViewResult LogAndReturnErrorResponse(LapRequestModel model, string userMessage, int eventID, string logMessage = null, Exception ex = null) { Reporting.LogErrorEvent(eventID, logMessage ?? userMessage, ex); model.FailureReason = userMessage; return(this.View("Get", model)); }
private ViewResult AuditAndReturnErrorResponse(LapRequestModel model, string userMessage, int eventID, string logMessage = null, Exception ex = null, TargetElement target = null, ReaderElement reader = null, UserPrincipal user = null, ComputerPrincipal computer = null) { Reporting.PerformAuditFailureActions(model, userMessage, eventID, logMessage, ex, target, reader, user, computer); model.FailureReason = userMessage; return(this.View("Get", model)); }