public void EvaluateReturnsIgnoreAppropriatelyWhenRequestIsAjax()
        {
            // Arrange.
            var mockRequest = new Mock <HttpRequestBase>();

            mockRequest.SetupGet(req => req.RawUrl).Returns("/getdata/");
            var requestEvaluator = new RequestEvaluator();

            // Act.
            RequestSecurity resultForNonAjaxRequest = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);

            var queryString = new NameValueCollection {
                { RequestEvaluator.XRequestedWithHeaderKey, RequestEvaluator.AjaxRequestHeaderValue }
            };

            mockRequest.Setup(req => req.QueryString).Returns(queryString);
            RequestSecurity resultForAjaxRequest = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);

            _fixture.Settings.IgnoreAjaxRequests = false;
            RequestSecurity resultForAjaxRequestWithIgnoreOff = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);

            // Assert.
            Assert.NotEqual(RequestSecurity.Ignore, resultForNonAjaxRequest);
            Assert.Equal(RequestSecurity.Ignore, resultForAjaxRequest);
            Assert.NotEqual(RequestSecurity.Ignore, resultForAjaxRequestWithIgnoreOff);
        }
        public void EvaluateReturnsIgnoreAppropriatelyWhenRequestPathIndicatesImage()
        {
            // Arrange.
            var pathsToTest = new[] {
                "/non-typical-image.psd",
                "/Media/Document.pdf",

                "/Images/SomeService/",
                "/Images/SomeService/?someKey=someValue",
                "/images/img-handler.ashx",
                "/images/img-handler.ashx?some-key=some-value",

                "/Manage/Images/indicator-alert.bmp",
                "/info/signs/sign1.gif",
                "/faavicon.ico",
                "/Media/logo.jpg",
                "/Media/other-logo.jpeg",
                "/SomeImage.png",
                "/drawings/machine.design.svg",
                "/Info/some-image.tiff",
                "/Info/another-image.tif",
                "/OtherResource.axd/resourceImage.webp",
                "/OddBall.xbm",

                "/Manage/Images/indicator-alert.bmp?someKey=someValue",
                "/info/signs/sign1.gif#hash",
                "/faavicon.ico?flag",
                "/Media/logo.jpg?some-key=some-value&other-key=other-value",
                "/Media/other-logo.jpeg?someKey=someValue#here",
                "/SomeImage.png?someKey=someValue&otherKey=otherValue#here-nor-there",
                "/drawings/machine.design.svg#hash.sub",
                "/Info/some-image.tiff?some.key=some.value",
                "/Info/another-image.tif?some.key=some.value#hash.sub",
                "/OtherResource.axd/resourceImage.webp?",
                "/OddBall.xbm?#"
            };
            var results          = new RequestSecurity[pathsToTest.Length];
            var mockRequest      = new Mock <HttpRequestBase>();
            var requestEvaluator = new RequestEvaluator();

            // Act.
            for (int index = 0; index < pathsToTest.Length; index++)
            {
                string path = pathsToTest[index];
                mockRequest.SetupGet(req => req.RawUrl).Returns(path);
                results[index] = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);
            }

            // Assert.
            for (int i = 0; i < 2; i++)
            {
                Assert.NotEqual(RequestSecurity.Ignore, results[i]);
            }

            for (int i = 2; i < results.Length; i++)
            {
                Assert.Equal(RequestSecurity.Ignore, results[i]);
            }
        }
Exemple #3
0
        /// <summary>
        /// EndRequest is used to trigger the appropriate redirection.  There are
        /// currently three scenarios that require special redirections.
        /// <list>
        ///     <item>
        ///         Request is unauthenticated and is being routed to the FormsLoginUrl
        ///         (typically caused by UrlAuthorizationModule).  This request needs to
        ///         be intercepted to change the 'ReturnUrl' parameter to 'serviceName'
        ///     </item>
        ///     <item>
        ///         Request contains a CAS ticket in the URL.  This request needs to be
        ///         redirected back to itself without the 'ticket' parameter in order to
        ///         avoid potential infinite automatic ticket validation loops for when
        ///         a the ticket in the URL has expired or was revoked and the Renew
        ///         configuration parameter is set.
        ///     </item>
        ///     <item>
        ///         Request is authenticated, but is not authorized to access the
        ///         requested resource (by UrlAuthorizationModule).  If the CAS is
        ///         configured with a NotAuthorizedUrl, the request is redirected to
        ///         that page.  Otherwise, it is redirected to the CAS login page with
        ///         a forced 'Renew' property (to prevent infinite redirect loops).
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnEndRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            if (RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("Starting EndRequest for " + request.RawUrl);

                if (RequestEvaluator.GetRequestRequiresGateway())
                {
                    logger.Info("  Performing Gateway Authentication");
                    CasAuthentication.GatewayAuthenticate(true);
                }
                else if (RequestEvaluator.GetUserDoesNotAllowSessionCookies())
                {
                    logger.Info("  Cookies not supported.  Redirecting to Cookies Required Page");
                    CasAuthentication.RedirectToCookiesRequiredPage();
                }
                else if (RequestEvaluator.GetRequestHasCasTicket())
                {
                    logger.Info("  Redirecting from login callback");
                    CasAuthentication.RedirectFromLoginCallback();
                }
                else if (RequestEvaluator.GetRequestHasGatewayParameter())
                {
                    logger.Info("  Redirecting from failed gateway callback");
                    CasAuthentication.RedirectFromFailedGatewayCallback();
                }
                else if (RequestEvaluator.GetRequestIsUnauthorized() && !String.IsNullOrEmpty(CasAuthentication.NotAuthorizedUrl))
                {
                    logger.Info("  Redirecting to Unauthorized Page");
                    CasAuthentication.RedirectToNotAuthorizedPage();
                }
                else if (RequestEvaluator.GetRequestIsUnauthorized())
                {
                    logger.Info("  Redirecting to CAS Login Page (Unauthorized without NotAuthorizedUrl defined)");
                    CasAuthentication.RedirectToLoginPage(true);
                }
                else if (RequestEvaluator.GetRequestIsUnAuthenticated())
                {
                    logger.Info("  Redirecting to CAS Login Page");
                    CasAuthentication.RedirectToLoginPage();
                }
                //Async post backs from UpdatePanels suppress the standard Forms Authentication redirect causing the above checks to fail.
                else if (RequestEvaluator.IsAsyncPostBackRequest() && !RequestEvaluator.CheckUrlAccessForCurrentPrincipal())
                {
                    context.Response.Redirect(UrlUtil.ConstructLoginRedirectUrl(false, CasAuthentication.Renew), false);
                }

                logger.Debug("Ending EndRequest for " + request.RawUrl);
            }
            else
            {
                logger.Debug("No EndRequest processing for " + request.RawUrl);
            }
        }
Exemple #4
0
        /// <summary>
        /// EndRequest is used to trigger the appropriate redirection.  There are
        /// currently three scenarios that require special redirections.
        /// <list>
        ///     <item>
        ///         Request is unauthenticated and is being routed to the FormsLoginUrl
        ///         (typically caused by UrlAuthorizationModule).  This request needs to
        ///         be intercepted to change the 'ReturnUrl' parameter to 'serviceName'
        ///     </item>
        ///     <item>
        ///         Request contains a CAS ticket in the URL.  This request needs to be
        ///         redirected back to itself without the 'ticket' parameter in order to
        ///         avoid potential infinite automatic ticket validation loops for when
        ///         a the ticket in the URL has expired or was revoked and the Renew
        ///         configuration parameter is set.
        ///     </item>
        ///     <item>
        ///         Request is authenticated, but is not authorized to access the
        ///         requested resource (by UrlAuthorizationModule).  If the CAS is
        ///         configured with a NotAuthorizedUrl, the request is redirected to
        ///         that page.  Otherwise, it is redirected to the CAS login page with
        ///         a forced 'Renew' property (to prevent infinite redirect loops).
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnEndRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            if (RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("Starting EndRequest for " + request.RawUrl);

                if (RequestEvaluator.GetRequestRequiresGateway())
                {
                    logger.Info("  Performing Gateway Authentication");
                    CasAuthentication.GatewayAuthenticate(true);
                }
                else if (RequestEvaluator.GetUserDoesNotAllowSessionCookies())
                {
                    logger.Info("  Cookies not supported.  Redirecting to Cookies Required Page");
                    CasAuthentication.RedirectToCookiesRequiredPage();
                }
                else if (RequestEvaluator.GetRequestHasCasTicket())
                {
                    logger.Info("  Redirecting from login callback");
                    CasAuthentication.RedirectFromLoginCallback();
                }
                else if (RequestEvaluator.GetRequestHasGatewayParameter())
                {
                    logger.Info("  Redirecting from failed gateway callback");
                    CasAuthentication.RedirectFromFailedGatewayCallback();
                }
                else if (RequestEvaluator.GetRequestIsUnauthorized() && !String.IsNullOrEmpty(CasAuthentication.NotAuthorizedUrl))
                {
                    logger.Info("  Redirecting to Unauthorized Page");
                    CasAuthentication.RedirectToNotAuthorizedPage();
                }
                else if (RequestEvaluator.GetRequestIsUnauthorized())
                {
                    logger.Info("  Redirecting to CAS Login Page (Unauthorized without NotAuthorizedUrl defined)");
                    CasAuthentication.RedirectToLoginPage(true);
                }
                else if (RequestEvaluator.GetRequestIsUnAuthenticated())
                {
                    logger.Info("  Redirecting to CAS Login Page");
                    CasAuthentication.RedirectToLoginPage();
                }

                logger.Debug("Ending EndRequest for " + request.RawUrl);
            }
            else
            {
                logger.Debug("No EndRequest processing for " + request.RawUrl);
            }
        }
        public void EvaluateReturnsInsecureWhenNoSettingsPathsMatchRequestPath()
        {
            // Arrange.
            var mockRequest = new Mock <HttpRequestBase>();

            mockRequest.SetupGet(req => req.RawUrl).Returns("/Info/AboutUs.aspx");
            var requestEvaluator = new RequestEvaluator();

            // Act.
            RequestSecurity security = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);

            // Assert.
            Assert.Equal(RequestSecurity.Insecure, security);
        }
        public void EvaluateReturnsIgnoreAppropriatelyWhenRequestPathIndicatesStyleSheet()
        {
            // Arrange.
            var pathsToTest = new[] {
                "/non-typical-image.psd",
                "/Media/Document.pdf",

                "/Styles/SomeService/",
                "/StyleSheets/SomeService/?someKey=someValue",
                "/styles/img-handler.ashx",
                "/stylesheets/img-handler.ashx?some-key=some-value",

                "/normalize.css",
                "/Media/Styles/Site.css",

                "/normalize.css?someKey=someValue",
                "/Media/Styles/Site.css#hash",
                "/normalize.css?flag",
                "/Media/Styles/Site.css?some-key=some-value&other-key=other-value",
                "/normalize.css?someKey=someValue#here",
                "/Media/Styles/Site.css?someKey=someValue&otherKey=otherValue#here-nor-there",
                "/normalize.alternative.css#hash.sub",
                "/Media/Styles/Site.css?some.key=some.value",
                "/normalize.css?some.key=some.value#hash.sub",
                "/Media/Styles/Site.css/resourceImage.webp?",
                "/normalize.css?#"
            };
            var results          = new RequestSecurity[pathsToTest.Length];
            var mockRequest      = new Mock <HttpRequestBase>();
            var requestEvaluator = new RequestEvaluator();

            // Act.
            for (int index = 0; index < pathsToTest.Length; index++)
            {
                string path = pathsToTest[index];
                mockRequest.SetupGet(req => req.RawUrl).Returns(path);
                results[index] = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);
            }

            // Assert.
            for (int i = 0; i < 2; i++)
            {
                Assert.NotEqual(RequestSecurity.Ignore, results[i]);
            }

            for (int i = 2; i < results.Length; i++)
            {
                Assert.Equal(RequestSecurity.Ignore, results[i]);
            }
        }
        public void EvaluateReturnsSecureWhenASecureSettingsPathMatchesRequestPath()
        {
            // Arrange.
            var mockRequest = new Mock <HttpRequestBase>();

            mockRequest.SetupGet(req => req.RawUrl).Returns("/login/");
            var requestEvaluator = new RequestEvaluator();

            // Act.
            RequestSecurity security = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);

            // Assert.
            Assert.Equal(RequestSecurity.Secure, security);
        }
        public void EvaluateReturnsIgnoreWhenModeIsOff()
        {
            // Arrange.
            var mockRequest = new Mock <HttpRequestBase>();
            var settings    = new Settings {
                Mode = Mode.Off
            };
            var requestEvaluator = new RequestEvaluator();

            // Act.
            RequestSecurity security = requestEvaluator.Evaluate(mockRequest.Object, settings);

            // Assert.
            Assert.Equal(RequestSecurity.Ignore, security);
        }
        /// <summary>
        /// Intercepts the beginning of the request pipeline.  This will detect SingleSignOut
        /// requests.  SingleSignOut requests are posted back to the serviceName URL that
        /// was passed when the CAS session was established.  Since the behavior of the script
        /// at that URL is unknown, a POST back by the CAS server could have unexpected
        /// consequences.  We want to prevent this request from authenticating and from
        /// executing the HttpHandler typically associated with that URL.  So we are handling
        /// this by sending back an HTTP 200 (OK) message with a blank body and short
        /// circuiting all event processing and firing EndRequest directly
        /// (via CompleteRequest()).
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnBeginRequest(object sender, EventArgs e)
        {
            // Validate the ticket coming back from the CAS server (NETC-55)
            if (!RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("BeginRequest bypassed for " + HttpContext.Current.Request.RawUrl);
                return;
            }

            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            logger.Debug("Starting BeginRequest for " + request.RawUrl);

            // Cleanup expired ServiceTickets in the ServiceTicketManager
            if (CasAuthentication.ServiceTicketManager != null)
            {
                CasAuthentication.ServiceTicketManager.RemoveExpiredTickets();
            }

            // Cleanup expired ProxyTicket mappings in the ProxyTicketManager
            if (CasAuthentication.ProxyTicketManager != null)
            {
                CasAuthentication.ProxyTicketManager.RemoveExpiredMappings();
            }

            // Detect & process inbound Single SignOut Requests from the CAS server
            if (CasAuthentication.ServiceTicketManager != null && CasAuthentication.ProcessIncomingSingleSignOutRequests && RequestEvaluator.GetRequestIsCasSingleSignOut())
            {
                logger.Info("Processing inbound Single Sign Out request.");
                CasAuthentication.ProcessSingleSignOutRequest();
                return;
            }

            // Detect & process inbound proxy callback verifications from the CAS server

            if (CasAuthentication.ProxyTicketManager != null && RequestEvaluator.GetRequestIsProxyResponse())
            {
                logger.Info("Processing Proxy Callback request");
                CasAuthentication.ProcessProxyCallbackRequest();
                return;
            }

            logger.Debug("Ending BeginRequest for " + request.RawUrl);
        }
Exemple #10
0
 public static IEnumerable <(double, string)> EvaluateExpression(string exp)
 {
     try
     {
         Console.WriteLine($"Evaluating: {exp}");
         var inputStream = new AntlrInputStream(exp);
         var lexer       = new DiceLexer(inputStream);
         var tokenStream = new CommonTokenStream(lexer);
         var parser      = new DiceParser(tokenStream);
         var context     = parser.request();
         var evaluator   = new RequestEvaluator();
         return(evaluator.Visit(context));
     }
     catch (Exception e)
     {
         Console.WriteLine(e);
         return(new[] { (0.0, "Failed to parse and evaluate") });
        public void EvaluateReturnsIgnoreWhenModeIsLocalOnlyAndRequestIsRemote()
        {
            // Arrange.
            var mockRequest = new Mock <HttpRequestBase>();

            mockRequest.SetupGet(req => req.IsLocal).Returns(false);
            var settings = new Settings {
                Mode = Mode.LocalOnly
            };
            var requestEvaluator = new RequestEvaluator();

            // Act.
            RequestSecurity security = requestEvaluator.Evaluate(mockRequest.Object, settings);

            // Assert.
            Assert.Equal(RequestSecurity.Ignore, security);
        }
Exemple #12
0
        /// <summary>
        /// Handles the authentication of the request.
        ///
        /// If the request contains a ticket, this will validate the ticket and create a
        /// FormsAuthenticationTicket and encrypted cookie container for it.  It will redirect
        /// to remove the ticket from the URL.  With Forms-based authentication, this is
        /// required to prevent the client from automatically/silently re-authenticating on a
        /// refresh or after logout.
        ///
        /// If the request does not contain a ticket, it checks for a FormsAuthentication
        /// cookie, decrypts it, extracts the FormsAuthenticationTicket, verifies that it
        /// exists in the StateProvider/ServiceTicketManager, and assigns a Principal to the
        /// thread and context.User properties.  All events after this request become
        /// authenticated.
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnAuthenticateRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            // Validate the ticket coming back from the CAS server
            if (!RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("AuthenticateRequest bypassed for " + request.RawUrl);
                return;
            }

            // Validate the ticket coming back from the CAS server
            if (RequestEvaluator.GetRequestHasCasTicket())
            {
                logger.Info("Processing Proxy Callback request");
                CasAuthentication.ProcessTicketValidation();
            }

            logger.Debug("Starting AuthenticateRequest for " + request.RawUrl);
            CasAuthentication.ProcessRequestAuthentication();
            logger.Debug("Ending AuthenticateRequest for " + request.RawUrl);
        }
        public void EvaluateReturnsIgnoreAppropriatelyWhenRequestIsSystemHandler()
        {
            // Arrange.
            var pathsToTest = new[] {
                "/",
                "/Default.aspx",
                "/Info/AboutUs.aspx",
                "/info/aboutus/",

                "/Manage/DownloadThatFile.axd",
                "/Info/WebResource.axd?i=C3E19B2A-15F0-4174-A245-20F08C1DF4B8",
                "/OtherResource.axd/additional/info",
                "/trace.axd#details"
            };
            var results          = new RequestSecurity[pathsToTest.Length];
            var mockRequest      = new Mock <HttpRequestBase>();
            var requestEvaluator = new RequestEvaluator();

            // Act.
            for (int index = 0; index < pathsToTest.Length; index++)
            {
                string path = pathsToTest[index];
                mockRequest.SetupGet(req => req.RawUrl).Returns(path);
                results[index] = requestEvaluator.Evaluate(mockRequest.Object, _fixture.Settings);
            }

            // Assert.
            for (int i = 0; i < 4; i++)
            {
                Assert.NotEqual(RequestSecurity.Ignore, results[i]);
            }

            for (int i = 4; i < results.Length; i++)
            {
                Assert.Equal(RequestSecurity.Ignore, results[i]);
            }
        }