/// <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 SoftWatcher(IJob job, Regex regex, int priority, string hardLocation, string softLocation, bool rewrite = true, bool addHardReseterFile = false) { //Add watch on the soft location job.WatchWebRequests(PipeLineStages.AuthenticateRequest, regex, priority, (count, httpApp) => { if (addHardReseterFile && Interlocked.CompareExchange(ref _resetterLock, 0, 1) == 0) { var resetter = new HardResetFileHandler(); resetter.Delete(); var path = HttpRuntime.AppDomainAppPath; resetter.HardLocation = path + hardLocation.Trim('/'); resetter.SoftLocation = path + softLocation.Trim('/'); resetter.Save(); } //change the Url to point to the hardLocation //for the request to work as expected var rewritePath = httpApp.Request.Url.AbsolutePath.Length > softLocation.Length ? hardLocation + httpApp.Request.Url.AbsolutePath.Substring(softLocation.Length) : hardLocation; //Request is for a physical file, if it's //a usercontrol etc, we need to TransferRequest //otherwise, it's a css etc. and we need to //transmitFile and set the correct mime type //otherwise, UmbracoModule will try and return //a content item for the request, resulting in //a 404 status code if (!string.IsNullOrEmpty(httpApp.Context.Request.CurrentExecutionFilePathExtension)) { //Request is for a usercontrol etc. transfer //the request and leave the watcher if (httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".aspx") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".ascx") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".asmx") || httpApp.Context.Request.CurrentExecutionFilePathExtension.Equals(".ashx")) { //add the querystring to pass onto the usercontrol etc. //we can't do it on creating the variable as it //causes issues with transmit file httpApp.Context.Server.TransferRequest(rewritePath + httpApp.Request.Url.Query, true); return(new WatchResponse(WatchResponse.Cycles.Stop)); } //Request is for a css etc. file, transmit //the file and set correct mime type var mimeType = MimeMapping.GetMimeMapping(rewritePath); httpApp.Context.Response.ContentType = mimeType; httpApp.Context.Response.TransmitFile(httpApp.Context.Server.MapPath(rewritePath)); httpApp.Context.Response.End(); return(new WatchResponse(WatchResponse.Cycles.Stop)); } //we can add querystring here as the request is not for //a physical file and may be needed for any 'sub' requests rewritePath += httpApp.Request.Url.Query; //We're not a physical usercontrol etc. file, so we can just //rewrite the path to the hard location. we need to add the //access token to context so we can allow the request to pass //through on the watch for the hard location httpApp.Context.Items.Add(_allowKey, true); if (rewrite || regex.IsMatch(softLocation)) { httpApp.Context.RewritePath(rewritePath); return(new WatchResponse(WatchResponse.Cycles.Restart)); } httpApp.Context.Response.Redirect(rewritePath); return(new WatchResponse(WatchResponse.Cycles.Stop)); }); }