Example #1
0
        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);
            }
        }
Example #2
0
        private static ICollection <string> BuildRecipientList(TargetElement target, ReaderElement reader, bool success, UserPrincipal user = null)
        {
            HashSet <string> list = new HashSet <string>(StringComparer.CurrentCultureIgnoreCase);

            if ((success && (target?.Audit?.NotifySuccess ?? false)) ||
                (!success && (target?.Audit?.NotifyFailure ?? false)))
            {
                Reporting.SplitRecipientsAndAddtoList(target?.Audit?.EmailAddresses, list);
            }

            if ((success && (reader?.Audit?.NotifySuccess ?? false)) ||
                (!success && (reader?.Audit?.NotifyFailure ?? false)))
            {
                Reporting.SplitRecipientsAndAddtoList(reader?.Audit?.EmailAddresses, list);
            }

            if ((success && (LapsConfigSection.Configuration?.Audit?.NotifySuccess ?? false)) ||
                (!success && (LapsConfigSection.Configuration?.Audit?.NotifyFailure ?? false)))
            {
                Reporting.SplitRecipientsAndAddtoList(LapsConfigSection.Configuration?.Audit?.EmailAddresses, list);
            }

            if (list.Remove("{user.EmailAddress}"))
            {
                if (!string.IsNullOrWhiteSpace(user?.EmailAddress))
                {
                    list.Add(user.EmailAddress);
                }
            }

            return(list);
        }
Example #3
0
        private static void SendEmail(IEnumerable <string> recipients, string subject, string body)
        {
            if (!Reporting.IsSmtpConfigured())
            {
                Logger.Trace("SMTP is not configured, discarding mail message");
                return;
            }

            using (SmtpClient client = new SmtpClient())
            {
                using (MailMessage message = new MailMessage())
                {
                    foreach (string recipient in recipients)
                    {
                        message.To.Add(recipient);
                    }

                    if (message.To.Count == 0)
                    {
                        Reporting.Logger.Trace($"Not sending notification email because there are no recipients");
                        return;
                    }

                    message.IsBodyHtml = true;
                    message.Subject    = subject;
                    message.Body       = body;

                    client.Send(message);
                }
            }
        }
Example #4
0
        private static Task HandleAuthNFailed <TMessage, TOptions>(AuthenticationFailedNotification <TMessage, TOptions> context)
        {
            Reporting.LogErrorEvent(EventIDs.OwinAuthNError, LogMessages.AuthNProviderError, context.Exception);
            context.HandleResponse();
            context.Response.Redirect($"/Home/AuthNError?message={HttpUtility.UrlEncode(context.Exception?.Message ?? "Unknown error")}");

            return(Task.FromResult(0));
        }
Example #5
0
        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);
        }
Example #6
0
        private static Task FindClaimIdentityInDirectoryOrFail <TMessage, TOptions>(SecurityTokenValidatedNotification <TMessage, TOptions> context)
        {
            ClaimsIdentity user = context.AuthenticationTicket.Identity;

            string sid = user.FindUserPrincipalByClaim(Startup.ClaimType, Startup.ClaimName)?.Sid?.Value;

            if (sid == null)
            {
                string message = string.Format(LogMessages.UserNotFoundInDirectory, user.ToClaimList());
                Reporting.LogErrorEvent(EventIDs.SsoIdentityNotFound, message, null);

                context.HandleResponse();
                context.Response.Redirect($"/Home/AuthNError?message={HttpUtility.UrlEncode(UIMessages.SsoIdentityNotFound)}");
                return(Task.CompletedTask);
            }

            user.AddClaim(new Claim(ClaimTypes.PrimarySid, sid));

            Reporting.LogSuccessEvent(EventIDs.UserAuthenticated, string.Format(LogMessages.AuthenticatedAndMappedUser, user.ToClaimList()));

            return(Task.CompletedTask);
        }
Example #7
0
        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);
            }
        }
Example #8
0
        public void ConfigureOpenIDConnect(IAppBuilder app)
        {
            Startup.CanLogout = true;

            Startup.ClaimName = ConfigurationManager.AppSettings["oidc:claimName"] ?? ClaimTypes.Upn;

            if (Enum.TryParse(ConfigurationManager.AppSettings["oidc:claimType"], out IdentityType claimType))
            {
                Startup.ClaimType = claimType;
            }
            else
            {
                Startup.ClaimType = IdentityType.UserPrincipalName;
            }

            AntiForgeryConfig.UniqueClaimTypeIdentifier = ConfigurationManager.AppSettings["oidc:uniqueClaimTypeIdentifier"] ?? ClaimTypes.PrimarySid;

            string responseType = ConfigurationManager.AppSettings["oidc:responseType"] ?? OpenIdConnectResponseType.IdToken;

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                CookieManager      = new SystemWebCookieManager(),
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId                  = this.clientId,
                ClientSecret              = this.clientSecret,
                Authority                 = this.authority,
                RedirectUri               = this.redirectUri,
                ResponseType              = responseType,
                Scope                     = OpenIdConnectScope.OpenIdProfile,
                PostLogoutRedirectUri     = this.postLogoutRedirectUri ?? new Uri(new Uri(this.redirectUri.Trim('/', '\\')), "Home/LogOut").ToString(),
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType   = "name",
                    SaveSigninToken = true
                },

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        try
                        {
                            OpenIdConnectConfiguration config = await n.Options.ConfigurationManager.GetConfigurationAsync(n.Request.CallCancelled).ConfigureAwait(false);

                            TokenClient tokenClient     = new TokenClient(config.TokenEndpoint, this.clientId, this.clientSecret);
                            TokenResponse tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, this.redirectUri).ConfigureAwait(false);

                            if (tokenResponse.IsError)
                            {
                                throw new Exception(tokenResponse.Error);
                            }

                            UserInfoClient userInfoClient     = new UserInfoClient(config.UserInfoEndpoint);
                            UserInfoResponse userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
                            List <Claim> claims = new List <Claim>();
                            claims.AddRange(userInfoResponse.Claims);
                            claims.Add(new Claim("id_token", tokenResponse.IdentityToken));
                            claims.Add(new Claim("access_token", tokenResponse.AccessToken));

                            if (!string.IsNullOrEmpty(tokenResponse.RefreshToken))
                            {
                                claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
                            }

                            n.AuthenticationTicket.Identity.AddClaims(claims);
                        }
                        catch (Exception ex)
                        {
                            Reporting.LogErrorEvent(EventIDs.OidcAuthZCodeError, LogMessages.AuthZCodeFlowError, ex);
                            n.Response.Redirect($"/Home/AuthNError?message={HttpUtility.UrlEncode(ex.Message)}");
                        }
                    },
                    SecurityTokenValidated = n =>
                    {
                        ClaimsIdentity user = n.AuthenticationTicket.Identity;
                        user.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        return(Startup.FindClaimIdentityInDirectoryOrFail(n));
                    },
                    RedirectToIdentityProvider = n =>
                    {
                        // If signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                        {
                            Claim idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenClaim != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenClaim.Value;
                            }
                        }

                        logger.Trace($"Redirecting to IdP for {n.ProtocolMessage.RequestType}");
                        return(Task.CompletedTask);
                    },
                    AuthenticationFailed = Startup.HandleAuthNFailed
                },
            });
        }