/// <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); }
public static void Start() { var resetter = new HardResetFileHandler(); if (resetter.SoftLocation == null) { return; } var curUmbVersion = Umbraco.Core.Configuration.UmbracoVersion.GetSemanticVersion().ToString(); if (!curUmbVersion.Equals(ApplicationSettings.UmbracoVersion, StringComparison.InvariantCultureIgnoreCase)) { return; } if (!Directory.Exists(resetter.HardLocation)) { LogHelper.Error <HardReset>($"Unable to find directory at location {resetter.HardLocation} for renaming to {Path.GetFileName(resetter.SoftLocation)}", null); return; } if (Directory.Exists(resetter.SoftLocation)) { try { DeleteDirectory(resetter.SoftLocation); } catch (Exception ex) { LogHelper.Error <HardReset>($"Unable to delete directory {resetter.SoftLocation}", ex); return; } } var webConfig = new WebConfigFileHandler { UmbracoPath = "~/" + Path.GetFileName(resetter.SoftLocation) }; ConfigurationManager.AppSettings.Set("umbracoPath", webConfig.UmbracoPath); var paths = webConfig.UmbracoReservedPaths; var regex = new Regex("^(~?)(/?)" + Path.GetFileName(resetter.HardLocation) + "(/?)$", RegexOptions.IgnoreCase); for (var i = 0; i < paths.Length; i++) { if (regex.IsMatch(paths[i])) { paths[i] = regex.Replace(paths[i], webConfig.UmbracoPath); } } webConfig.UmbracoReservedPaths = paths; ConfigurationManager.AppSettings.Set("umbracoReservedPaths", string.Join(",", paths)); webConfig.SetLocationPath(Path.GetFileName(resetter.HardLocation).Trim('/'), webConfig.UmbracoPath.TrimStart('~', '/').TrimEnd('/')); try { Directory.Move(resetter.HardLocation, resetter.SoftLocation); } catch (Exception ex) { LogHelper.Error <HardReset>($"Unable to rename directory from {resetter.SoftLocation} to {resetter.HardLocation}", ex); return; } try { resetter.Delete(); } catch (Exception ex) { LogHelper.Error <HardReset>($"Unable to delete the Hard Resetter File located at {resetter.FilePath}", ex); return; } try { webConfig.Save(); } catch (Exception ex) { LogHelper.Error <HardReset>("Failed to save changes to the website's web.config file", ex); Directory.Move(resetter.SoftLocation, resetter.HardLocation); } }
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)); }); }