diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs index 794df2d37..15372ff1b 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs @@ -30,6 +30,9 @@ namespace Orchard.SecureSocketsLayer.Drivers { protected override DriverResult Editor(SslSettingsPart part, IUpdateModel updater, dynamic shapeHelper) { if (updater.TryUpdateModel(part, Prefix, null, null)) { _signals.Trigger(SslSettingsPart.CacheKey); + if (!part.Enabled) part.SecureEverything = false; + if (!part.SecureEverything) part.SendStrictTransportSecurityHeaders = false; + if (!part.StrictTransportSecurityIncludeSubdomains) part.StrictTransportSecurityPreload = false; } return Editor(part, shapeHelper); diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs index fe4d0ff62..4d1f1b445 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs @@ -16,8 +16,7 @@ namespace Orchard.SecureSocketsLayer.Models { public class SslSettingsPart : ContentPart { public const string CacheKey = "SslSettingsPart"; - public string Urls - { + public string Urls { get { return this.As().Get("Urls"); } set { this.As().Set("Urls", value); } } @@ -57,5 +56,26 @@ namespace Orchard.SecureSocketsLayer.Models { get { return this.As().Get("InsecureHostName"); } set { this.As().Set("InsecureHostName", value); } } + + public bool SendStrictTransportSecurityHeaders { + get { return this.Retrieve(x => x.SendStrictTransportSecurityHeaders); } + set { this.Store(x => x.SendStrictTransportSecurityHeaders, value); } + } + + public bool StrictTransportSecurityIncludeSubdomains { + get { return this.Retrieve(x => x.StrictTransportSecurityIncludeSubdomains); } + set { this.Store(x => x.StrictTransportSecurityIncludeSubdomains, value); } + } + + [Required] + public int StrictTransportSecurityMaxAge { + get { return this.Retrieve(x => x.StrictTransportSecurityMaxAge, 31536000); } + set { this.Store(x => x.StrictTransportSecurityMaxAge, value); } + } + + public bool StrictTransportSecurityPreload { + get { return this.Retrieve(x => x.StrictTransportSecurityPreload); } + set { this.Store(x => x.StrictTransportSecurityPreload, value); } + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Orchard.SecureSocketsLayer.csproj b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Orchard.SecureSocketsLayer.csproj index 350a6397d..e1baa098b 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Orchard.SecureSocketsLayer.csproj +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Orchard.SecureSocketsLayer.csproj @@ -49,10 +49,18 @@ + + ..\..\..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll + True + ..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll True + + ..\..\..\packages\Owin.1.0\lib\net40\Owin.dll + True + @@ -96,6 +104,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/StrictTransportSecurityMiddlewareProvider.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/StrictTransportSecurityMiddlewareProvider.cs new file mode 100644 index 000000000..2b3d8c329 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/StrictTransportSecurityMiddlewareProvider.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using Orchard.ContentManagement; +using Orchard.Logging; +using Orchard.Owin; +using Orchard.SecureSocketsLayer.Models; +using Owin; + +namespace Orchard.SecureSocketsLayer.Services { + public class StrictTransportSecurityMiddlewareProvider : IOwinMiddlewareProvider { + private readonly IWorkContextAccessor _wca; + + public ILogger Logger { get; set; } + + public StrictTransportSecurityMiddlewareProvider(IWorkContextAccessor wca) { + _wca = wca; + + Logger = NullLogger.Instance; + } + + public IEnumerable GetOwinMiddlewares() { + return new[] { + new OwinMiddlewareRegistration { + Configure = app => + app.Use(async (context, next) => { + var sslSettings = _wca.GetContext().CurrentSite.As(); + + if (sslSettings.SendStrictTransportSecurityHeaders) { + string responseValue = "max-age=" + sslSettings.StrictTransportSecurityMaxAge; + + if (sslSettings.StrictTransportSecurityIncludeSubdomains) { + responseValue += "; includeSubDomains"; + } + + if (sslSettings.StrictTransportSecurityPreload) { + responseValue += "; preload"; + } + context.Response.Headers.Append("Strict-Transport-Security", responseValue); + } + + await next.Invoke(); + }) + } + }; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml index 9879a163e..c7aad106e 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml @@ -11,18 +11,47 @@
@Html.TextBoxFor(m => m.SecureHostName, new { @class = "textMedium" }) - @T("(Mandatory) The host name secured traffic should be redirected to (e.g. localhost:44300, secure.mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. secure.127-0-0-1.org.uk:4333).") + @Html.Hint(T("(Mandatory) The host name secured traffic should be redirected to (e.g. localhost:44300, secure.mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. secure.127-0-0-1.org.uk:4333)."))
@Html.TextBoxFor(m => m.InsecureHostName, new { @class = "textMedium" }) - @T("(Mandatory) The host name non-secured traffic should be redirected to (e.g. localhost:30321, mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. dev.127-0-0-1.org.uk:4333).") + @Html.Hint(T("(Mandatory) The host name non-secured traffic should be redirected to (e.g. localhost:30321, mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. dev.127-0-0-1.org.uk:4333)."))
@Html.EditorFor(m => m.SecureEverything) @Html.ValidationMessage("SecureEverything", "*")
+
+
+ @Html.EditorFor(m => m.SendStrictTransportSecurityHeaders) + + @Html.Hint(@T("More information about HSTS")) + @Html.ValidationMessage("SendStrictTransportSecurityHeaders", "*") +
+
+
+ + @Html.TextBoxFor(m => m.StrictTransportSecurityMaxAge, new { @class = "textMedium" }) + @Html.Hint(T("(Mandatory) Specify the max age of HSTS in seconds (e.g. 31536000 is one year). If you set this parameter to 0, the HSTS Header will immediately expire.")) +
+
+ @Html.EditorFor(m => m.StrictTransportSecurityIncludeSubdomains) + + @Html.ValidationMessage("StrictTransportSecurityIncludeSubdomains", "*") + @Html.Hint(T("Applies the HSTS rules to all of the site's subdomains.")) +
+
+
+ @Html.EditorFor(m => m.StrictTransportSecurityPreload) + + @Html.ValidationMessage("StrictTransportSecurityPreload", "*") + @Html.Hint(T("You can use this if you successfully submitted your domain to an HSTS preload service and serve all subdomains over HTTPS. If you send this directive, it can have PERMANENT CONSEQUENCES. Please read the details before sending the header with \"preload\".")) +
+
+
+
@Html.EditorFor(m => m.CustomEnabled) @@ -34,11 +63,10 @@ @Html.TextAreaFor(m => m.Urls, new { @class = "textMedium", rows = "5" }) @Html.ValidationMessage("Urls", "*") - @T("Provide a list of urls, one per line. Urls can contains wildcard matches using '*', or root identifier like '~/'") - @T("Examples: http://mysite.com/mypage, ~/Profile/Edit, ~/Profile/*") + @Html.Hint(T("Provide a list of urls, one per line. Urls can contains wildcard matches using '*', or root identifier like '~/'")) + @Html.Hint(T("Examples: http://mysite.com/mypage, ~/Profile/Edit, ~/Profile/*"))
- - \ No newline at end of file + diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/packages.config b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/packages.config index 6729ced49..9d448f59b 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/packages.config +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/packages.config @@ -3,5 +3,7 @@ + + \ No newline at end of file