public override bool Execute(IJob job, IAppConfiguration c) { job.UnwatchWebRequests(); job.UnexceptionWebRequest(); job.UnignoreWebRequest(); if (!c.Enable || !job.Environment.Enable) { return(true); } if (!(c is ElmahConfiguration config)) { job.WriteJournal(new JournalMessage("Error: Config passed into Elmah was not of the correct type")); return(false); } foreach (var error in _ipAccessControlService.InitIpAccessControl(config.IpAccessRules)) { job.WriteJournal(new JournalMessage($"Error: Invalid IP Address {error}, unable to add to exception list")); } if (config.Unauthorized.TransferType != TransferTypes.PlayDead) { job.ExceptionWebRequest(config.Unauthorized.Url); } var regex = job.PathToRegex("elmah.axd"); job.IgnoreWebRequest(regex); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, 300000, (count, httpApp) => { if (_ipAccessControlService.IsValid(config.IpAccessRules, httpApp.Context.Request)) { httpApp.Context.Items.Add(_allowKey, true); } return(new WatchResponse(WatchResponse.Cycles.Continue)); }); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, 300500, (count, httpApp) => { if ((bool?)httpApp.Context.Items[_allowKey] == true || (config.UmbracoUserEnable && AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp))) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } job.WriteJournal(new JournalMessage($"User with IP Address: {httpApp.Context.Request.UserHostAddress}; tried to access {httpApp.Context.Request.Url} Access was denied")); return(new WatchResponse(config.Unauthorized)); }); return(true); }
private void AddHardWatch(IJob job, BackofficeAccessConfiguration config) { var hardLocationRegex = new Regex("^((" + ApplicationSettings.UmbracoPath.TrimEnd('/') + "(/)?)|(" + ApplicationSettings.UmbracoPath + "[\\w-/]+\\.[\\w.]{2,5}))$", RegexOptions.IgnoreCase); foreach (var error in _ipAccessControlService.InitIpAccessControl(config.IpAccessRules)) { job.WriteJournal(new JournalMessage($"Error: Invalid IP Address {error}, unable to add to exception list")); } //Add watch on the on-disk UmbracoPath location to do the security checking of the user's ip job.ExceptionWebRequest(config.Unauthorized.Url); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, hardLocationRegex, 21000, (count, httpApp) => { if (AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } if (_ipAccessControlService.IsValid(config.IpAccessRules, httpApp.Context.Request.UserHostAddress)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } var url = new UmbracoUrlService().Url(config.Unauthorized.Url); if (url == null) { return(new WatchResponse(WatchResponse.Cycles.Stop)); } if (!string.IsNullOrEmpty(httpApp.Context.Request.CurrentExecutionFilePathExtension) && (httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".css") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".map") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".js") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".png") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".jpg") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".jpeg") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".gif") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".woff") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".woff2") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".ttf") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".otf") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".eot") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".svg"))) { httpApp.Context.Response.StatusCode = (int)HttpStatusCode.NotFound; return(new WatchResponse(WatchResponse.Cycles.Stop)); } job.WriteJournal(new JournalMessage($"User with IP Address: {httpApp.Context.Request.UserHostAddress}; tried to access the backoffice access url. Access was denied")); return(new WatchResponse(config.Unauthorized)); }); }
/// <inheritdoc /> public override bool Execute(IJob job, IConfiguration c) { job.UnwatchWebRequests(); job.UnexceptionWebRequest(); if (!c.Enable || !job.Environment.Enable) { return(true); } if (!(c is FrontendAccessConfiguration config)) { job.WriteJournal(new JournalMessage("Error: Config passed into Frontend Access was not of the correct type")); return(false); } var hardUmbracoLocation = ApplicationSettings.UmbracoPath; var regex = new Regex("^/$|^(/(?!" + hardUmbracoLocation.Trim('/') + ")[\\w-/_]+?)$", RegexOptions.IgnoreCase); foreach (var error in new IpAccessControlService().InitIpAccessControl(config.IpAccessRules)) { job.WriteJournal(new JournalMessage($"Error: Invalid IP Address {error}, unable to add to exception list")); } job.ExceptionWebRequest(config.Unauthorized.Url); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, 400000, (count, httpApp) => { if (_ipAccessControlService.IsValid(config.IpAccessRules, httpApp.Context.Request.UserHostAddress)) { httpApp.Context.Items.Add(_allowKey, true); } return(new WatchResponse(WatchResponse.Cycles.Continue)); }); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, 10500, (count, httpApp) => { if ((bool?)httpApp.Context.Items[_allowKey] == true || config.UmbracoUserEnable && AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } if (!httpApp.Context.Request.Url.LocalPath.Equals(config.Unauthorized.Url.Value)) { job.WriteJournal(new JournalMessage($"User with IP Address: {httpApp.Context.Request.UserHostAddress}; tried to access Page: {httpApp.Context.Request.Url}. Access was denied")); } return(new WatchResponse(config.Unauthorized)); }); return(true); }
/// <inheritdoc /> public override bool Execute(IJob job, IAppConfiguration c) { job.UnwatchWebRequests(); job.UnexceptionWebRequest(); if (!(c is FrontendAccessConfiguration config)) { job.WriteJournal(new JournalMessage("Error: Config passed into Frontend Access was not of the correct type")); return(false); } if (!c.Enable || !job.Environment.Enable) { return(true); } foreach (var error in _ipAccessControlService.InitIpAccessControl(config.IpAccessRules)) { job.WriteJournal(new JournalMessage($"Error: Invalid IP Address {error}, unable to add to exception list")); } if (config.Unauthorized.TransferType != TransferTypes.PlayDead) { job.ExceptionWebRequest(config.Unauthorized.Url); } //var ignores = // umbracoReservedUrls var regex = new Regex(@"^/([a-z0-9-_~&\+%/])*(\?([^\?])*)?$", RegexOptions.IgnoreCase); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, 400000, (count, httpApp) => { if (_ipAccessControlService.IsValid(config.IpAccessRules, httpApp.Context.Request)) { httpApp.Context.Items.Add(_allowKey, true); } return(new WatchResponse(WatchResponse.Cycles.Continue)); }); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, 400500, (count, httpApp) => { if ((bool?)httpApp.Context.Items[_allowKey] == true || (config.UmbracoUserEnable && AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp))) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } var url = new UmbracoUrlService().Url(config.Unauthorized.Url); if (url == null) { return(new WatchResponse(WatchResponse.Cycles.Error)); } if (httpApp.Context.Request.Url.LocalPath.Equals(url)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } job.WriteJournal(new JournalMessage($"User with IP Address: {httpApp.Context.Request.UserHostAddress}; tried to access Page: {httpApp.Context.Request.Url}. Access was denied")); return(new WatchResponse(config.Unauthorized)); }); return(true); }
/// <inheritdoc /> /// <summary> /// </summary> /// <param name="job"></param> /// <param name="c"></param> /// <returns></returns> public override bool Execute(IJob job, IAppConfiguration c) { job.UnwatchWebRequests(); job.UnexceptionWebRequest(); _reSetterLock = 0; if (!(c is BackofficeAccessConfiguration config)) { job.WriteJournal(new JournalMessage("Error: Config passed into Backoffice Access was not of the correct type")); return(false); } var defaultUmbracoLocation = ((BackofficeAccessConfiguration)DefaultConfiguration).BackendAccessUrl.EnsureStartsWith('/').EnsureEndsWith('/'); var onDiscUmbracoLocation = Configuration.UmbracoPath.EnsureStartsWith('/').EnsureEndsWith('/'); var virtualUmbracoLocation = config.Enable && job.Environment.Enable ? config.BackendAccessUrl.EnsureStartsWith('/').EnsureEndsWith('/') : defaultUmbracoLocation; var defaultUmbracoRegex = job.PathToRegex(defaultUmbracoLocation); var onDiscUmbracoRegex = job.PathToRegex(onDiscUmbracoLocation); var virtualUmbracoRegex = job.PathToRegex(virtualUmbracoLocation); job.IgnoreWebRequest(defaultUmbracoRegex); job.IgnoreWebRequest(onDiscUmbracoRegex); job.IgnoreWebRequest(virtualUmbracoRegex); if (!virtualUmbracoLocation.Equals(defaultUmbracoLocation, StringComparison.InvariantCultureIgnoreCase) && !onDiscUmbracoLocation.Equals(defaultUmbracoLocation, StringComparison.InvariantCultureIgnoreCase)) { SoftWatcher(job, new Regex("^(" + defaultUmbracoLocation + "backoffice([\\w-/_]+))", RegexOptions.IgnoreCase), 20000, onDiscUmbracoLocation, virtualUmbracoLocation, false); } if (config.Enable && job.Environment.Enable && config.Unauthorized.TransferType != TransferTypes.PlayDead) { job.ExceptionWebRequest(config.Unauthorized.Url); } if (!virtualUmbracoLocation.Equals(onDiscUmbracoLocation, StringComparison.InvariantCultureIgnoreCase)) { if (Interlocked.CompareExchange(ref _reSetterLock, 0, 1) == 0) { var path = HttpRuntime.AppDomainAppPath; var onDiscPath = path + onDiscUmbracoLocation.Trim('/'); var virtualPath = path + virtualUmbracoLocation.Trim('/'); var reSetter = new HardResetFileHandler(); if (reSetter.HardLocation != onDiscPath || reSetter.SoftLocation != virtualPath) { reSetter.Delete(); reSetter.HardLocation = onDiscPath; reSetter.SoftLocation = virtualPath; reSetter.Save(); } } SoftWatcher(job, virtualUmbracoRegex, 20100, onDiscUmbracoLocation, virtualUmbracoLocation, true); job.WatchWebRequests(PipeLineStages.AuthenticateRequest, new Regex($"^(({onDiscUmbracoLocation})|({onDiscUmbracoLocation.TrimEnd('/')}))$"), 20200, (count, httpApp) => { if ((bool?)httpApp.Context.Items[_allowKey] == true || !string.IsNullOrEmpty(httpApp.Context.Request.CurrentExecutionFilePathExtension) || AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } httpApp.Context.Response.StatusCode = (int)HttpStatusCode.NotFound; return(new WatchResponse(WatchResponse.Cycles.Stop)); }); } if (!config.Enable || !job.Environment.Enable) { return(true); } foreach (var error in _ipAccessControlService.InitIpAccessControl(config.IpAccessRules)) { job.WriteJournal(new JournalMessage($"Error: Invalid IP Address {error}, unable to add to exception list")); } job.WatchWebRequests(PipeLineStages.AuthenticateRequest, onDiscUmbracoRegex, 20300, (count, httpApp) => { if (AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp) || _ipAccessControlService.IsValid(config.IpAccessRules, httpApp.Context.Request)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } job.WriteJournal(new JournalMessage($"User with IP Address: {httpApp.Context.Request.UserHostAddress}; tried to access the backoffice access url. Access was denied")); return(new WatchResponse(config.Unauthorized)); }); return(true); }
private void AddSoftWatches(IJob job, BackofficeAccessConfiguration config) { var umbracoLocation = ((BackofficeAccessConfiguration)DefaultConfiguration).BackendAccessUrl.EnsureStartsWith('/').EnsureEndsWith('/'); var hardLocation = ApplicationSettings.UmbracoPath; var softLocation = (config.Enable && job.Environment.Enable) ? config.BackendAccessUrl.EnsureStartsWith('/').EnsureEndsWith('/') : umbracoLocation; #if TRACE Debug.WriteLine($"AddSoftWatches({job.Environment.Name}): hardLocation = {hardLocation}, softLocation = {softLocation}"); #endif //Match Umbraco path for badly written Umbraco Packages, that only work with hardcoded /umbraco/backoffice if (!softLocation.Equals(umbracoLocation, StringComparison.InvariantCultureIgnoreCase) && !hardLocation.Equals(umbracoLocation, StringComparison.InvariantCultureIgnoreCase)) { SoftWatcher(job, new Regex("^((" + umbracoLocation + "backoffice([\\w-/_]+))|(" + umbracoLocation + "[\\w-/_]+\\.[\\w.]{2,5}))$", RegexOptions.IgnoreCase), 20015, hardLocation, umbracoLocation); } if (softLocation.Equals(hardLocation, StringComparison.InvariantCultureIgnoreCase)) { return; } //A hard save is needed, so we need to hook up //the watches to route everything correctly //add watch on the soft location SoftWatcher(job, new Regex("^((" + softLocation.TrimEnd('/') + "(/)?)|(" + softLocation + "[\\w-/_]+\\.[\\w.]{2,5}))$", RegexOptions.IgnoreCase), 20010, hardLocation, softLocation, config.Unauthorized.TransferType.Equals(TransferTypes.Rewrite), true); if (config.Enable && job.Environment.Enable) { job.ExceptionWebRequest(config.Unauthorized.Url); } //Add watch on the hard location job.WatchWebRequests(PipeLineStages.AuthenticateRequest, new Regex("^((" + hardLocation.TrimEnd('/') + "(/)?)|(" + hardLocation + "[\\w-/]+\\.[\\w.]{2,5}))$", RegexOptions.IgnoreCase), 20020, (count, httpApp) => { //Check if request has our access token, if so, we're //rewriting the user to the hard location, so let //the request continue if ((bool?)httpApp.Context.Items[_allowKey] == true || !string.IsNullOrEmpty(httpApp.Context.Request.CurrentExecutionFilePathExtension)) { return(new WatchResponse(WatchResponse.Cycles.Continue)); } //If the requests has an authenticated umbraco user, //we need to redirect the request back to the //softLocation - This is most likely due to //clicking a link (i.e. content breadcrumb) //which isn't handle by the angular single page app if (AccessHelper.IsRequestAuthenticatedUmbracoUser(httpApp)) { //request has a authenticated user, we want to //redirect the user back to the soft location return(new WatchResponse(new TransferUrl { TransferType = TransferTypes.Redirect, Url = new UmbracoUrl { Type = UmbracoUrlTypes.Url, Value = httpApp.Context.Request.Url.AbsolutePath.Length > hardLocation.Length ? softLocation + httpApp.Context.Request.Url.AbsolutePath.Substring(hardLocation.Length) : softLocation } })); } //if we're disabled, then we just want //to change the status code to 404 if (!config.Enable || !job.Environment.Enable) { httpApp.Context.Response.StatusCode = (int)HttpStatusCode.NotFound; return(new WatchResponse(WatchResponse.Cycles.Stop)); } //We're Enabled, so we need to transfer to the unauthorised Url return(new WatchResponse(config.Unauthorized)); }); }