Browse Source

Remove the internal NWebSec package

pull/121/head
Kévin Chalet 10 years ago
parent
commit
657634c13e
  1. 11
      OpenIddict.sln
  2. 197
      external/NWebsec/ApplicationBuilderExtensions.cs
  3. 49
      external/NWebsec/Core/OwinEnvironment.cs
  4. 28
      external/NWebsec/Core/OwinKeys.cs
  5. 44
      external/NWebsec/Core/RequestHeaders.cs
  6. 47
      external/NWebsec/Core/ResponseHeaders.cs
  7. 37
      external/NWebsec/CspDirective.cs
  8. 114
      external/NWebsec/CspDirectiveExtensions.cs
  9. 161
      external/NWebsec/CspOptions.cs
  10. 40
      external/NWebsec/CspReportUriDirective.cs
  11. 13
      external/NWebsec/Exceptions/RedirectValidationException.cs
  12. 19
      external/NWebsec/Extensions/HttpContextExtensions.cs
  13. 53
      external/NWebsec/Fluent/IFluentInterface.cs
  14. 49
      external/NWebsec/FluentCspPluginTypesDirective.cs
  15. 45
      external/NWebsec/FluentCspSandboxDirective.cs
  16. 21
      external/NWebsec/Helpers/CspUpgradeHelper.cs
  17. 29
      external/NWebsec/Helpers/HeaderResultHandler.cs
  18. 12
      external/NWebsec/Helpers/IHeaderResultHandler.cs
  19. 11
      external/NWebsec/Helpers/X509/TlvTripletHeader.cs
  20. 252
      external/NWebsec/Helpers/X509/X509Helper.cs
  21. 124
      external/NWebsec/HpkpOptions.cs
  22. 33
      external/NWebsec/HpkpOptionsConfiguration.cs
  23. 52
      external/NWebsec/HstsOptions.cs
  24. 32
      external/NWebsec/HstsOptionsConfiguration.cs
  25. 52
      external/NWebsec/HttpHeaders/Configuration/CspConfiguration.cs
  26. 26
      external/NWebsec/HttpHeaders/Configuration/CspDirectiveConfiguration.cs
  27. 9
      external/NWebsec/HttpHeaders/Configuration/CspHeaderConfiguration.cs
  28. 20
      external/NWebsec/HttpHeaders/Configuration/CspPluginTypesDirectiveConfiguration.cs
  29. 19
      external/NWebsec/HttpHeaders/Configuration/CspReportUriDirectiveConfiguration.cs
  30. 15
      external/NWebsec/HttpHeaders/Configuration/CspSandboxDirectiveConfiguration.cs
  31. 11
      external/NWebsec/HttpHeaders/Configuration/CspUpgradeDirectiveConfiguration.cs
  32. 16
      external/NWebsec/HttpHeaders/Configuration/HpkpConfiguration.cs
  33. 15
      external/NWebsec/HttpHeaders/Configuration/HstsConfiguration.cs
  34. 30
      external/NWebsec/HttpHeaders/Configuration/ICspConfiguration.cs
  35. 42
      external/NWebsec/HttpHeaders/Configuration/ICspDirectiveBasicConfiguration.cs
  36. 19
      external/NWebsec/HttpHeaders/Configuration/ICspDirectiveConfiguration.cs
  37. 26
      external/NWebsec/HttpHeaders/Configuration/ICspDirectiveUnsafeInlineConfiguration.cs
  38. 9
      external/NWebsec/HttpHeaders/Configuration/ICspHeaderConfiguration.cs
  39. 24
      external/NWebsec/HttpHeaders/Configuration/ICspPluginTypesDirectiveConfiguration.cs
  40. 15
      external/NWebsec/HttpHeaders/Configuration/ICspReportUriDirectiveConfiguration.cs
  41. 49
      external/NWebsec/HttpHeaders/Configuration/ICspSandboxDirectiveConfiguration.cs
  42. 14
      external/NWebsec/HttpHeaders/Configuration/ICspUpgradeDirectiveConfiguration.cs
  43. 14
      external/NWebsec/HttpHeaders/Configuration/IHpkpCertConfiguration.cs
  44. 16
      external/NWebsec/HttpHeaders/Configuration/IHpkpConfiguration.cs
  45. 9
      external/NWebsec/HttpHeaders/Configuration/IHpkpPinConfiguration.cs
  46. 19
      external/NWebsec/HttpHeaders/Configuration/IHstsConfiguration.cs
  47. 18
      external/NWebsec/HttpHeaders/Configuration/IRedirectValidationConfiguration.cs
  48. 10
      external/NWebsec/HttpHeaders/Configuration/ISameHostHttpsRedirectConfiguration.cs
  49. 9
      external/NWebsec/HttpHeaders/Configuration/ISimpleBooleanConfiguration.cs
  50. 9
      external/NWebsec/HttpHeaders/Configuration/IXFrameOptionsConfiguration.cs
  51. 23
      external/NWebsec/HttpHeaders/Configuration/IXRobotsTagConfiguration.cs
  52. 11
      external/NWebsec/HttpHeaders/Configuration/IXXssProtectionConfiguration.cs
  53. 19
      external/NWebsec/HttpHeaders/Configuration/RedirectValidationConfiguration.cs
  54. 15
      external/NWebsec/HttpHeaders/Configuration/SameHostHttpsRedirectConfiguration.cs
  55. 9
      external/NWebsec/HttpHeaders/Configuration/SimpleBooleanConfiguration.cs
  56. 55
      external/NWebsec/HttpHeaders/Configuration/Validation/HpkpConfigurationValidator.cs
  57. 24
      external/NWebsec/HttpHeaders/Configuration/Validation/HstsConfigurationValidator.cs
  58. 51
      external/NWebsec/HttpHeaders/Configuration/Validation/Rfc2045MediaTypeValidator.cs
  59. 24
      external/NWebsec/HttpHeaders/Configuration/Validation/XRobotsTagConfigurationValidator.cs
  60. 9
      external/NWebsec/HttpHeaders/Configuration/XFrameOptionsConfiguration.cs
  61. 16
      external/NWebsec/HttpHeaders/Configuration/XRobotsTagConfiguration.cs
  62. 10
      external/NWebsec/HttpHeaders/Configuration/XXssProtectionConfiguration.cs
  63. 12
      external/NWebsec/HttpHeaders/Csp/CspSourceParseResult.cs
  64. 172
      external/NWebsec/HttpHeaders/Csp/CspUriSource.cs
  65. 15
      external/NWebsec/HttpHeaders/Csp/InvalidCspSourceException.cs
  66. 47
      external/NWebsec/HttpHeaders/HeaderConstants.cs
  67. 373
      external/NWebsec/HttpHeaders/HeaderGenerator.cs
  68. 25
      external/NWebsec/HttpHeaders/HeaderResult.cs
  69. 31
      external/NWebsec/HttpHeaders/IHeaderGenerator.cs
  70. 22
      external/NWebsec/HttpHeaders/XXssPolicy.cs
  71. 22
      external/NWebsec/HttpHeaders/XfoPolicy.cs
  72. 142
      external/NWebsec/IFluentCspOptions.cs
  73. 14
      external/NWebsec/IFluentCspPluginTypesDirective.cs
  74. 18
      external/NWebsec/IFluentCspReportUriDirective.cs
  75. 39
      external/NWebsec/IFluentCspSandboxDirective.cs
  76. 62
      external/NWebsec/IFluentHpkpOptions.cs
  77. 59
      external/NWebsec/IFluentHstsOptions.cs
  78. 26
      external/NWebsec/IFluentRedirectValidationOptions.cs
  79. 22
      external/NWebsec/IFluentXFrameOptions.cs
  80. 54
      external/NWebsec/IFluentXRobotsTagOptions.cs
  81. 27
      external/NWebsec/IFluentXXssProtectionOptions.cs
  82. 88
      external/NWebsec/Middleware/CspMiddleware.cs
  83. 39
      external/NWebsec/Middleware/HpkpMiddleware.cs
  84. 46
      external/NWebsec/Middleware/HstsMiddleware.cs
  85. 39
      external/NWebsec/Middleware/MiddleWareBase.cs
  86. 39
      external/NWebsec/Middleware/RedirectValidationMiddleware.cs
  87. 34
      external/NWebsec/Middleware/XContentTypeOptionsMiddleware.cs
  88. 34
      external/NWebsec/Middleware/XDownloadOptionsMiddleware.cs
  89. 36
      external/NWebsec/Middleware/XRobotsTagMiddleware.cs
  90. 34
      external/NWebsec/Middleware/XXssMiddleware.cs
  91. 33
      external/NWebsec/Middleware/XfoMiddleware.cs
  92. 21
      external/NWebsec/NWebsec.xproj
  93. 28
      external/NWebsec/NWebsecContext.cs
  94. 61
      external/NWebsec/RedirectValidationOptions.cs
  95. 83
      external/NWebsec/RedirectValidator.cs
  96. 27
      external/NWebsec/XFrameOptions.cs
  97. 58
      external/NWebsec/XRobotsTagOptions.cs
  98. 38
      external/NWebsec/XXssProtectionOptions.cs
  99. 39
      external/NWebsec/project.json
  100. 2
      samples/Mvc.Server/Startup.cs

11
OpenIddict.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict", "src\OpenIddict\OpenIddict.xproj", "{80A8D6CE-C29A-4602-9844-D51FEF9C33C8}"
EndProject
@ -23,10 +23,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.Core", "src\Open
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.Mvc", "src\OpenIddict.Mvc\OpenIddict.Mvc.xproj", "{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "external", "external", "{DE26CC68-28BA-44BB-B28E-43B949C6C606}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NWebsec", "external\NWebsec\NWebsec.xproj", "{38C8E88F-1D01-466F-B47D-6D67F13C1594}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.Security", "src\OpenIddict.Security\OpenIddict.Security.xproj", "{3744B1BC-3498-4958-B020-B2688A78B989}"
EndProject
Global
@ -67,10 +63,6 @@ Global
{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Release|Any CPU.Build.0 = Release|Any CPU
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Release|Any CPU.Build.0 = Release|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -88,7 +80,6 @@ Global
{D2450929-ED0E-420D-B475-327924F9701C} = {D544447C-D701-46BB-9A5B-C76C612A596B}
{E60CF8CA-6313-4359-BE43-AFCBB927EA30} = {D544447C-D701-46BB-9A5B-C76C612A596B}
{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84} = {D544447C-D701-46BB-9A5B-C76C612A596B}
{38C8E88F-1D01-466F-B47D-6D67F13C1594} = {DE26CC68-28BA-44BB-B28E-43B949C6C606}
{3744B1BC-3498-4958-B020-B2688A78B989} = {D544447C-D701-46BB-9A5B-C76C612A596B}
EndGlobalSection
EndGlobal

197
external/NWebsec/ApplicationBuilderExtensions.cs

@ -1,197 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using NWebsec.Core.HttpHeaders.Configuration.Validation;
using NWebsec.Middleware;
using NWebsec.Middleware.Middleware;
// ReSharper disable once CheckNamespace
namespace Microsoft.AspNetCore.Builder
{
public static class ApplicationBuilderExtensions
{
/// <summary>
/// Adds a middleware to the pipeline that validates redirects.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseRedirectValidation(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
var options = new RedirectValidationOptions();
return app.UseMiddleware<RedirectValidationMiddleware>(options);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that validates redirects.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseRedirectValidation(this IApplicationBuilder app, Action<IFluentRedirectValidationOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new RedirectValidationOptions();
configurer(options);
return app.UseMiddleware<RedirectValidationMiddleware>(options);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the Strict-Transport-Security header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseHsts(this IApplicationBuilder app, Action<IFluentHstsOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new HstsOptions();
configurer(options);
new HstsConfigurationValidator().Validate(options);
return app.UseMiddleware<HstsMiddleware>(options);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the Public-Key-Pins header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseHpkp(this IApplicationBuilder app, Action<IFluentHpkpOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new HpkpOptions();
configurer(options);
new HpkpConfigurationValidator().ValidateNumberOfPins(options.Config);
return app.UseMiddleware<HpkpMiddleware>(options, false);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the Public-Key-Pins-Report-Only header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseHpkpReportOnly(this IApplicationBuilder app, Action<IFluentHpkpOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new HpkpOptions();
configurer(options);
new HpkpConfigurationValidator().ValidateNumberOfPins(options.Config);
return app.UseMiddleware<HpkpMiddleware>(options, true);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the X-Content-Type-Options header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseXContentTypeOptions(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
return app.UseMiddleware<XContentTypeOptionsMiddleware>();
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the X-Download-Options header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseXDownloadOptions(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
return app.UseMiddleware<XDownloadOptionsMiddleware>();
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the X-Frame-Options header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseXfo(this IApplicationBuilder app, Action<IFluentXFrameOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new XFrameOptions();
configurer(options);
return app.UseMiddleware<XfoMiddleware>(options);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the X-Robots-Tag header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseXRobotsTag(this IApplicationBuilder app, Action<IFluentXRobotsTagOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new XRobotsTagOptions();
configurer(options);
return app.UseMiddleware<XRobotsTagMiddleware>(options);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the X-Xss-Protection header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseXXssProtection(this IApplicationBuilder app, Action<IFluentXXssProtectionOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new XXssProtectionOptions();
configurer(options);
return app.UseMiddleware<XXssMiddleware>(options);
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the Content-Security-Policy header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseCsp(this IApplicationBuilder app, Action<IFluentCspOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new CspOptions();
configurer(options);
return app.UseMiddleware<CspMiddleware>(options, false); //Last param indicates it's not reportOnly.
}
/// <summary>
/// Adds a middleware to the ASP.NET pipeline that sets the Content-Security-Policy-Report-Only header.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> to which the middleware is added.</param>
/// <param name="configurer">An <see cref="Action" /> that configures the options for the middleware.</param>
/// <returns>The <see cref="IApplicationBuilder" /> supplied in the app parameter.</returns>
public static IApplicationBuilder UseCspReportOnly(this IApplicationBuilder app, Action<IFluentCspOptions> configurer)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
var options = new CspOptions();
configurer(options);
return app.UseMiddleware<CspMiddleware>(options, true); //Last param indicates it's reportOnly.
}
}
}

49
external/NWebsec/Core/OwinEnvironment.cs

@ -1,49 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
using NWebsec.Core;
namespace NWebsec.Middleware.Core
{
//TODO Get rid of these?
internal class OwinEnvironment
{
private readonly IDictionary<string, object> _environment;
internal OwinEnvironment(IDictionary<string, object> env)
{
_environment = env;
RequestHeaders = new RequestHeaders((IDictionary<string, string[]>)_environment[OwinKeys.RequestHeaders]);
ResponseHeaders = new ResponseHeaders((IDictionary<string, string[]>)_environment[OwinKeys.ResponseHeaders]);
}
internal string RequestScheme => (string)_environment[OwinKeys.RequestScheme];
internal string RequestPathBase => (string)_environment[OwinKeys.RequestPathBase];
internal string RequestPath => (string)_environment[OwinKeys.RequestPath];
internal int ResponseStatusCode
{
get { return (int)_environment[OwinKeys.ResponseStatusCode]; }
set { _environment[OwinKeys.ResponseStatusCode] = value; }
}
internal RequestHeaders RequestHeaders { get; private set; }
internal ResponseHeaders ResponseHeaders { get; private set; }
internal NWebsecContext NWebsecContext
{
get
{
if (!_environment.ContainsKey(NWebsecContext.ContextKey))
{
_environment[NWebsecContext.ContextKey] = new NWebsecContext();
}
return _environment[NWebsecContext.ContextKey] as NWebsecContext;
}
}
}
}

28
external/NWebsec/Core/OwinKeys.cs

@ -1,28 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Middleware.Core
{
internal static class OwinKeys
{
//Request
internal static string RequestBody = "owin.RequestBody";
internal static string RequestHeaders = "owin.RequestHeaders";
internal static string RequestMethod = "owin.RequestMethod";
internal static string RequestPath = "owin.RequestPath";
internal static string RequestPathBase = "owin.RequestPathBase";
internal static string RequestProtocol = "owin.RequestProtocol";
internal static string RequestQueryString = "owin.RequestQueryString";
internal static string RequestScheme = "owin.RequestScheme";
//Response
internal static string ResponseBody = "owin.ResponseBody";
internal static string ResponseHeaders = "owin.ResponseHeaders";
internal static string ResponseStatusCode = "owin.ResponseStatusCode";
internal static string ResponseReasonPhrase = "owin.ResponseReasonPhrase";
internal static string ResponseProtocol = "owin.ResponseProtocol";
//Other
internal static string CallCancelled = "owin.CallCancelled";
internal static string Version = "owin.Version";
}
}

44
external/NWebsec/Core/RequestHeaders.cs

@ -1,44 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace NWebsec.Middleware.Core
{
internal class RequestHeaders
{
private readonly IDictionary<string, string[]> _headers;
internal RequestHeaders(IDictionary<string, string[]> headers)
{
_headers = headers;
}
public string Host
{
get
{
try
{
return _headers.ContainsKey("Host") ? _headers["Host"].Single() : null;
}
catch (Exception)
{
throw new Exception("Multiple Host headers detected: " + String.Join(" ", _headers["Host"]));
}
}
}
/// <summary>
/// Gets the value of a header
/// </summary>
/// <param name="headername"></param>
/// <returns>The header's values as a comma separated list, null if the header is not set.</returns>
public string GetHeaderValue(string headername)
{
string[] values;
return _headers.TryGetValue(headername, out values) ? String.Join(",", values) : null;
}
}
}

47
external/NWebsec/Core/ResponseHeaders.cs

@ -1,47 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace NWebsec.Middleware.Core
{
internal class ResponseHeaders
{
private readonly IDictionary<string, string[]> _headers;
internal ResponseHeaders(IDictionary<string, string[]> headers)
{
_headers = headers;
}
/// <summary>
/// Gets the value of the Location header if present. Otherwise returns null.
/// </summary>
public string Location
{
get
{
try
{
return _headers.ContainsKey("Location") ? _headers["Location"].Single() : null;
}
catch (Exception)
{
throw new Exception("Multiple Location headers detected: " + String.Join(" ", _headers["Location"]));
}
}
set { _headers["Location"] = new[] { value }; }
}
internal void SetHeader(string name, string value)
{
_headers[name] = new[] { value };
}
internal void RemoveHeader(string name)
{
_headers.Remove(name);
}
}
}

37
external/NWebsec/CspDirective.cs

@ -1,37 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class CspDirective : ICspDirectiveConfiguration
{
public CspDirective()
{
Enabled = true;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool Enabled { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool NoneSrc { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool SelfSrc { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool UnsafeInlineSrc { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool UnsafeEvalSrc { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public string Nonce { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<string> CustomSources { get; set; }
}
}

114
external/NWebsec/CspDirectiveExtensions.cs

@ -1,114 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Linq;
using NWebsec.Core.HttpHeaders.Configuration;
using NWebsec.Core.HttpHeaders.Csp;
namespace NWebsec.Middleware
{
public static class CspDirectiveExtensions
{
/// <summary>
/// Sets the "none" source for the CSP directive. This source cannot be combined with other sources on a CSP directive.
/// </summary>
/// <typeparam name="T">The type of the CSP directive configuration object.</typeparam>
/// <param name="directive">The CSP directive configuration object.</param>
/// <exception cref="InvalidOperationException">Thrown when sources have already been configured for the directive.</exception>
public static void None<T>(this T directive) where T : class, ICspDirectiveBasicConfiguration
{
if (directive == null) throw new ArgumentNullException("directive");
ValidateBeforeSettingNoneSource(directive);
directive.NoneSrc = true;
}
/// <summary>
/// Sets the "self" source for the CSP directive.
/// </summary>
/// <typeparam name="T">The type of the CSP directive configuration object.</typeparam>
/// <param name="directive">The CSP directive configuration object.</param>
/// <returns>The CSP directive configuration object.</returns>
public static T Self<T>(this T directive) where T : class, ICspDirectiveBasicConfiguration
{
if (directive == null) throw new ArgumentNullException("directive");
directive.SelfSrc = true;
return directive;
}
/// <summary>
/// Sets custom sources for the CSP directive.
/// </summary>
/// <typeparam name="T">The type of the CSP directive configuration object.</typeparam>
/// <param name="directive">The CSP directive configuration object.</param>
/// <param name="sources">One or more custom sources.</param>
/// <returns>The CSP directive configuration object.</returns>
public static T CustomSources<T>(this T directive, params string[] sources) where T : class, ICspDirectiveBasicConfiguration
{
if (directive == null) throw new ArgumentNullException("directive");
if (sources.Length == 0) throw new ArgumentException("You must supply at least one source.", "sources");
try
{
directive.CustomSources = sources.Select(s => CspUriSource.Parse(s).ToString()).ToArray();
}
catch (InvalidCspSourceException e)
{
throw new ArgumentException("Invalid source. Details: " + e.Message, "sources", e);
}
return directive;
}
/// <summary>
/// Sets the "unsafe-inline" source for the CSP directive.
/// </summary>
/// <typeparam name="T">The type of the CSP directive configuration object.</typeparam>
/// <param name="directive">The CSP directive configuration object.</param>
/// <returns>The CSP directive configuration object.</returns>
public static T UnsafeInline<T>(this T directive) where T : class, ICspDirectiveUnsafeInlineConfiguration
{
if (directive == null) throw new ArgumentNullException("directive");
directive.UnsafeInlineSrc = true;
return directive;
}
/// <summary>
/// Sets the "unsafe-eval" source for the CSP directive.
/// </summary>
/// <typeparam name="T">The type of the CSP directive configuration object.</typeparam>
/// <param name="directive">The CSP directive configuration object.</param>
/// <returns>The CSP directive configuration object.</returns>
public static T UnsafeEval<T>(this T directive) where T : class, ICspDirectiveConfiguration
{
if (directive == null) throw new ArgumentNullException("directive");
directive.UnsafeEvalSrc = true;
return directive;
}
private static void ValidateBeforeSettingNoneSource(ICspDirectiveBasicConfiguration directive)
{
if (directive.SelfSrc || (directive.CustomSources != null && directive.CustomSources.Any()))
{
throw new InvalidOperationException("It is a logical error to combine the \"None\" source with other sources.");
}
var unsafeInline = directive as ICspDirectiveUnsafeInlineConfiguration;
if (unsafeInline != null && unsafeInline.UnsafeInlineSrc)
{
throw new InvalidOperationException("It is a logical error to combine the \"None\" source with other sources.");
}
var unsafeEval = directive as ICspDirectiveConfiguration;
if (unsafeEval != null && unsafeEval.UnsafeEvalSrc)
{
throw new InvalidOperationException("It is a logical error to combine the \"None\" source with other sources.");
}
}
}
}

161
external/NWebsec/CspOptions.cs

@ -1,161 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class CspOptions : ICspConfiguration, IFluentCspOptions
{
public bool Enabled { get; set; } = true;
public ICspDirectiveConfiguration DefaultSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration ScriptSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration ObjectSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration StyleSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration ImgSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration MediaSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration FrameSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration FontSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration ConnectSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration BaseUriDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration ChildSrcDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration FormActionDirective { get; set; } = new CspDirective();
public ICspDirectiveConfiguration FrameAncestorsDirective { get; set; } = new CspDirective();
public ICspPluginTypesDirectiveConfiguration PluginTypesDirective { get; set; } = new FluentCspPluginTypesDirective();
public ICspSandboxDirectiveConfiguration SandboxDirective { get; set; } = new FluentCspSandboxDirective();
public ICspUpgradeDirectiveConfiguration UpgradeInsecureRequestsDirective { get; set; } = new CspUpgradeDirectiveConfiguration();
public ICspReportUriDirectiveConfiguration ReportUriDirective { get; set; } = new CspReportUriDirective();
public IFluentCspOptions DefaultSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(DefaultSrcDirective);
return this;
}
public IFluentCspOptions ScriptSources(Action<ICspDirectiveConfiguration> configurer)
{
configurer(ScriptSrcDirective);
return this;
}
public IFluentCspOptions ObjectSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(ObjectSrcDirective);
return this;
}
public IFluentCspOptions StyleSources(Action<ICspDirectiveUnsafeInlineConfiguration> configurer)
{
configurer(StyleSrcDirective);
return this;
}
public IFluentCspOptions ImageSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(ImgSrcDirective);
return this;
}
public IFluentCspOptions MediaSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(MediaSrcDirective);
return this;
}
public IFluentCspOptions FrameSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(FrameSrcDirective);
return this;
}
public IFluentCspOptions FontSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(FontSrcDirective);
return this;
}
public IFluentCspOptions ConnectSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(ConnectSrcDirective);
return this;
}
public IFluentCspOptions BaseUris(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(BaseUriDirective);
return this;
}
public IFluentCspOptions ChildSources(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(ChildSrcDirective);
return this;
}
public IFluentCspOptions FormActions(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(FormActionDirective);
return this;
}
public IFluentCspOptions FrameAncestors(Action<ICspDirectiveBasicConfiguration> configurer)
{
configurer(FrameAncestorsDirective);
return this;
}
public IFluentCspOptions PluginTypes(Action<IFluentCspPluginTypesDirective> configurer)
{
configurer((IFluentCspPluginTypesDirective)PluginTypesDirective);
return this;
}
public IFluentCspOptions Sandbox()
{
SandboxDirective.Enabled = true;
return this;
}
public IFluentCspOptions Sandbox(Action<IFluentCspSandboxDirective> configurer)
{
SandboxDirective.Enabled = true;
configurer((IFluentCspSandboxDirective)SandboxDirective);
return this;
}
public IFluentCspOptions UpgradeInsecureRequests(int httpsPort = 443)
{
if (httpsPort < 1 || httpsPort > 65535)
{
throw new ArgumentOutOfRangeException(nameof(httpsPort),"The port number must be in the range 1-65535.");
}
UpgradeInsecureRequestsDirective.Enabled = true;
UpgradeInsecureRequestsDirective.HttpsPort = httpsPort;
return this;
}
public IFluentCspOptions ReportUris(Action<IFluentCspReportUriDirective> configurer)
{
configurer((IFluentCspReportUriDirective)ReportUriDirective);
return this;
}
}
}

40
external/NWebsec/CspReportUriDirective.cs

@ -1,40 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using NWebsec.Core.HttpHeaders.Configuration;
using NWebsec.Core.HttpHeaders.Csp;
namespace NWebsec.Middleware
{
public class CspReportUriDirective : ICspReportUriDirectiveConfiguration, IFluentCspReportUriDirective
{
internal CspReportUriDirective()
{
Enabled = true;
}
public bool Enabled { get; set; }
public bool EnableBuiltinHandler { get; set; }
public IEnumerable<string> ReportUris { get; set; }
public void Uris(params string[] reportUris)
{
if (reportUris.Length == 0) throw new ArgumentException("You must supply at least one report URI.", "reportUris");
var reportUriList = new List<string>();
foreach (var reportUri in reportUris)
{
Uri uri;
if (!Uri.TryCreate(reportUri, UriKind.RelativeOrAbsolute, out uri))
{
throw new ArgumentException("Could not parse reportUri: " + reportUri);
}
reportUriList.Add(CspUriSource.EncodeUri(uri));
}
ReportUris = reportUriList.ToArray();
}
}
}

13
external/NWebsec/Exceptions/RedirectValidationException.cs

@ -1,13 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Core.Exceptions
{
public class RedirectValidationException : Exception
{
public RedirectValidationException(string message) : base(message)
{
}
}
}

19
external/NWebsec/Extensions/HttpContextExtensions.cs

@ -1,19 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
namespace NWebsec.Core.Extensions
{
public static class HttpContextExtensions
{
public static NWebsecContext GetNWebsecContext(this HttpContext context)
{
if (!context.Items.ContainsKey(NWebsecContext.ContextKey))
{
context.Items[NWebsecContext.ContextKey] = new NWebsecContext();
}
return context.Items[NWebsecContext.ContextKey] as NWebsecContext;
}
}
}

53
external/NWebsec/Fluent/IFluentInterface.cs

@ -1,53 +0,0 @@
//This code was lended from http://bit.ly/ifluentinterface, and is not covered by the regular NWebsec lisence.
using System;
using System.ComponentModel;
namespace NWebsec.Core.Fluent
{
/// <summary>
/// Interface that is used to build fluent interfaces and hides methods declared by <see cref="object" /> from
/// IntelliSense.
/// </summary>
/// <remarks>
/// Code that consumes implementations of this interface should expect one of two things:
/// <list type="number">
/// <item>
/// When referencing the interface from within the same solution (project reference), you will still see the
/// methods this interface is meant to hide.
/// </item>
/// <item>
/// When referencing the interface through the compiled output assembly (external reference), the standard
/// Object methods will be hidden as intended.
/// </item>
/// </list>
/// See http://bit.ly/ifluentinterface for more information.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IFluentInterface
{
/// <summary>
/// Redeclaration that hides the <see cref="object.GetType()" /> method from IntelliSense.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
Type GetType();
/// <summary>
/// Redeclaration that hides the <see cref="object.GetHashCode()" /> method from IntelliSense.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
int GetHashCode();
/// <summary>
/// Redeclaration that hides the <see cref="object.ToString()" /> method from IntelliSense.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
string ToString();
/// <summary>
/// Redeclaration that hides the <see cref="object.Equals(object)" /> method from IntelliSense.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
bool Equals(object obj);
}
}

49
external/NWebsec/FluentCspPluginTypesDirective.cs

@ -1,49 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Linq;
using NWebsec.Core.HttpHeaders.Configuration;
using NWebsec.Core.HttpHeaders.Configuration.Validation;
namespace NWebsec.Middleware
{
public class FluentCspPluginTypesDirective : CspPluginTypesDirectiveConfiguration, IFluentCspPluginTypesDirective
{
public FluentCspPluginTypesDirective()
{
Enabled = true;
}
#pragma warning disable CS0108 // Member hides inherited member; missing new keyword
public void MediaTypes(params string[] mediaTypes)
#pragma warning restore CS0108 // Member hides inherited member; missing new keyword
{
if (mediaTypes == null)
{
throw new ArgumentNullException(nameof(mediaTypes));
}
if (mediaTypes.Length == 0)
{
throw new ArgumentException("One or more parameter values expected.", nameof(mediaTypes));
}
var validator = new Rfc2045MediaTypeValidator();
var types = mediaTypes.Distinct().ToArray();
foreach (var mediaType in types)
{
try
{
validator.Validate(mediaType);
}
catch (Exception e)
{
throw new ArgumentException("Invalid argument. Details: " + e.Message, e);
}
}
base.MediaTypes = types;
}
}
}

45
external/NWebsec/FluentCspSandboxDirective.cs

@ -1,45 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
class FluentCspSandboxDirective : CspSandboxDirectiveConfiguration, IFluentCspSandboxDirective
{
public new IFluentCspSandboxDirective AllowForms()
{
base.AllowForms = true;
return this;
}
public new IFluentCspSandboxDirective AllowPointerLock()
{
base.AllowPointerLock = true;
return this;
}
public new IFluentCspSandboxDirective AllowPopups()
{
base.AllowPopups = true;
return this;
}
public new IFluentCspSandboxDirective AllowSameOrigin()
{
base.AllowSameOrigin = true;
return this;
}
public new IFluentCspSandboxDirective AllowScripts()
{
base.AllowScripts = true;
return this;
}
public new IFluentCspSandboxDirective AllowTopNavigation()
{
base.AllowTopNavigation = true;
return this;
}
}
}

21
external/NWebsec/Helpers/CspUpgradeHelper.cs

@ -1,21 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Linq;
using Microsoft.AspNetCore.Http;
namespace NWebsec.Middleware.Helpers
{
//Tested indirectly by CSP Middleware
internal class CspUpgradeHelper
{
internal static bool UaSupportsUpgradeInsecureRequests(HttpContext env)
{
var upgradeHeader = env.Request.Headers["Upgrade-Insecure-Requests"];
return upgradeHeader.Any(h => h.Equals("1", StringComparison.Ordinal));
}
}
}

29
external/NWebsec/Helpers/HeaderResultHandler.cs

@ -1,29 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
using NWebsec.Core.HttpHeaders;
namespace NWebsec.Core.Helpers
{
public class HeaderResultHandler : IHeaderResultHandler
{
public void HandleHeaderResult(HttpResponse response, HeaderResult result)
{
if (result == null)
{
return;
}
switch (result.Action)
{
case HeaderResult.ResponseAction.Set:
response.Headers[result.Name] = result.Value;
return;
case HeaderResult.ResponseAction.Remove:
response.Headers.Remove(result.Name);
return;
}
}
}
}

12
external/NWebsec/Helpers/IHeaderResultHandler.cs

@ -1,12 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
using NWebsec.Core.HttpHeaders;
namespace NWebsec.Core.Helpers
{
public interface IHeaderResultHandler
{
void HandleHeaderResult(HttpResponse response, HeaderResult result);
}
}

11
external/NWebsec/Helpers/X509/TlvTripletHeader.cs

@ -1,11 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.Helpers.X509
{
internal class TlvTripletHeader
{
public byte Tag { get; set; }
public int Length { get; set; }
public byte[] RawData { get; set; }
}
}

252
external/NWebsec/Helpers/X509/X509Helper.cs

@ -1,252 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace NWebsec.Core.Helpers.X509
{
public class X509Helper
{
private const byte AsnInteger = 0x02;
private const byte AsnBitString = 0x03;
private const byte AsnSequence = 0x30;
private const byte AsnOptional = 0xA0;
private static readonly byte[] AsnTags = { AsnInteger, AsnBitString, AsnSequence, AsnOptional };
//TODO cleanup. Perhaps a test or two.
//[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands"), SecuritySafeCritical]
public X509Certificate2 GetCertByThumbprint(string thumbprint, StoreLocation storeLocation, StoreName storeName)
{
X509Store certStore = null;
X509Certificate2Collection certs = null;
try
{
certStore = new X509Store(storeName, storeLocation);
certStore.Open(OpenFlags.ReadOnly);
certs = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (certs.Count > 1)
{
var message = string.Format("Something went horribly wrong, found more than one cert with thumbprint {0} in store location {1}, storename {2}", thumbprint, storeLocation, storeName);
throw new Exception(message);
}
if (certs.Count == 0)
{
var message = string.Format("No certificate with thumbprint {0} in store location {1}, storename {2}", thumbprint, storeLocation, storeName);
throw new ArgumentException(message);
}
//Returns new cert, all existing certs will be cleaned up
return certs[0];
}
catch
{
if (certs != null)
{
foreach (var cert in certs)
{
CleanupCert(cert);
}
}
if (certStore != null)
{
foreach (var cert in certStore.Certificates)
{
CleanupCert(cert);
}
#if DNX451
certStore.Close();
#elif NET451
certStore.Close();
#else
certStore.Dispose();
#endif
}
throw;
}
}
/// <summary>
/// Returns a string suitable for inclusion in an HPKP header, including hash algoritm.
/// </summary>
/// <param name="cert"></param>
/// <returns></returns>
public string GetSubjectPublicKeyInfoPinValue(X509Certificate2 cert)
{
var spki = GetRawSubjectPublicKeyInfo(cert);
using (var sha256 = SHA256.Create())
{
var hash = Convert.ToBase64String(sha256.ComputeHash(spki));
return string.Format("sha256=\"" + hash + "\"");
}
}
private static byte[] GetRawSubjectPublicKeyInfo(X509Certificate2 cert)
{
if (cert.Version != 3)
{
throw new ArgumentException("Only X.509 certificate version 3 is supported. This cert was version " + cert.Version);
}
var rawCert = cert.RawData;
using (var ms = new MemoryStream(rawCert))
{
//Get outer cert sequence header
var tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence, for start of certificate.");
//Console.WriteLine("Got certficate sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
//Get tbs cert sequence header
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence, for start of tbc cert.");
//Console.WriteLine("Got tbs certficate sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
//Get cert version integer header
tlv = ReadTlvTripletHeader(ms);
while (tlv.Tag == AsnOptional)
{
//Console.WriteLine("Got optional TLV, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
tlv = ReadTlvTripletHeader(ms);
}
if (tlv.Tag != AsnInteger) throw new Exception("Expected ASN integer cert version.");
//Console.WriteLine("Got the certficate version, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
var version = ms.ReadByte();
if (version == -1) throw new Exception("Could not read version byte");
//Console.WriteLine("Cert version: " + version);
//Get serial number
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnInteger) throw new Exception("Expected ASN integer serial number.");
//Console.WriteLine("Got the cert serial number, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
var serialNumber = new byte[tlv.Length];
var read = ms.Read(serialNumber, 0, serialNumber.Length);
if (read < serialNumber.Length) throw new Exception("Expected reading " + tlv.Length + " serial number bytes, got " + read);
//Skip signature sequence
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence signature.");
//Console.WriteLine("Got the cert signature sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
ms.Seek(tlv.Length, SeekOrigin.Current);
//Console.WriteLine("Skipped ahead " + tlv.Length + " bytes.");
//Skip issuer sequence
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence issuer.");
//Console.WriteLine("Got the cert issuer sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
ms.Seek(tlv.Length, SeekOrigin.Current);
//Console.WriteLine("Skipped ahead " + tlv.Length + " bytes.");
//Skip validity sequence
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence validity.");
//Console.WriteLine("Got the cert validity sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
ms.Seek(tlv.Length, SeekOrigin.Current);
//Console.WriteLine("Skipped ahead " + tlv.Length + " bytes.");
//Skip subject sequence
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence subject.");
//Console.WriteLine("Got the cert subject sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
ms.Seek(tlv.Length, SeekOrigin.Current);
//Console.WriteLine("Skipped ahead " + tlv.Length + " bytes.");
//Skip subject sequence
tlv = ReadTlvTripletHeader(ms);
if (tlv.Tag != AsnSequence) throw new Exception("Expected ASN sequence SPKI.");
//Console.WriteLine("Got the cert SPKI sequence, parsed length: " + tlv.Length + " " + BitConverter.ToString(tlv.RawData));
//New array for both tlv bits and content bits.
var spkiChunk = new byte[tlv.RawData.Length + tlv.Length];
Array.Copy(tlv.RawData, spkiChunk, tlv.RawData.Length);
read = ms.Read(spkiChunk, tlv.RawData.Length, tlv.Length);
if (read > tlv.Length) throw new Exception("Got " + read + " SPKI bytes, expected " + spkiChunk.Length);
return spkiChunk;
}
}
private static TlvTripletHeader ReadTlvTripletHeader(MemoryStream ms)
{
var firstBytes = new byte[2];
var read = ms.Read(firstBytes, 0, firstBytes.Length);
if (read < 1)
{
throw new Exception("No data read!");
}
if (!AsnTags.Any(t => t == firstBytes[0])) throw new Exception("Unexptected ASN.1 tag byte: " + BitConverter.ToString(firstBytes, 0, 1));
if (read < 2)
{
throw new Exception("No length byte read!");
}
if (firstBytes[1] < 0x80)
{
return new TlvTripletHeader() { Tag = firstBytes[0], Length = firstBytes[1], RawData = firstBytes };
}
//Handle multi-byte length.
var numberOfLengthBytes = firstBytes[1] - 0x80;
if (numberOfLengthBytes < 1) throw new Exception("Invalid length byte. Indicated multibyte length, with length 0.");
if (numberOfLengthBytes > 4) throw new NotSupportedException("Leading length byte indicates more than 4 length bytes, which is not supported. Indicated length bytes: " + numberOfLengthBytes);
//Get the bytes
var lengthBytes = new byte[numberOfLengthBytes];
var bytesRead = ms.Read(lengthBytes, 0, lengthBytes.Length);
if (bytesRead != lengthBytes.Length) throw new Exception(string.Format("Expected {0} length bytes, got {1}", lengthBytes.Length, bytesRead));
//Got the bytes, make an int.
var length = 0;
//Console.WriteLine("Adding length bytes: " + BitConverter.ToString(lengthBytes));
foreach (var lengthByte in lengthBytes)
{
//Shift existing bytes so they become more significant. Avoid platform dependent bit fiddling.
//Console.WriteLine("Length tweak starting: " + BitConverter.ToString(BitConverter.GetBytes(length)));
length = length * 256;
//Console.WriteLine("Shifted length to make room for next byte: " + BitConverter.ToString(BitConverter.GetBytes(length)));
length += lengthByte;
//Console.WriteLine("Added next byte: " + BitConverter.ToString(BitConverter.GetBytes(length)));
}
var rawbytes = new byte[firstBytes.Length + lengthBytes.Length];
Array.Copy(firstBytes, rawbytes, firstBytes.Length);
Array.Copy(lengthBytes, 0, rawbytes, firstBytes.Length, lengthBytes.Length);
return new TlvTripletHeader { Tag = firstBytes[0], Length = length, RawData = rawbytes };
}
private void CleanupCert(X509Certificate2 cert)
{
#if NET451
cert.Reset();
#elif DNX451
cert.Reset();
#else
cert.Dispose();
#endif
}
}
}

124
external/NWebsec/HpkpOptions.cs

@ -1,124 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using NWebsec.Core.Helpers.X509;
using NWebsec.Core.HttpHeaders.Configuration.Validation;
namespace NWebsec.Middleware
{
public class HpkpOptions : IFluentHpkpOptions
{
private readonly List<string> _pins;
private readonly HpkpConfigurationValidator _validator;
internal HpkpOptionsConfiguration Config { get; set; }
public HpkpOptions()
{
_pins = new List<string>();
Config = new HpkpOptionsConfiguration { Pins = _pins };
_validator = new HpkpConfigurationValidator();
}
// ReSharper disable once CSharpWarnings::CS0109
public IFluentHpkpOptions MaxAge(int days = 0, int hours = 0, int minutes = 0, int seconds = 0)
{
if (days < 0) throw new ArgumentOutOfRangeException("days", "Value must be equal to or larger than 0.");
if (hours < 0) throw new ArgumentOutOfRangeException("hours", "Value must be equal to or larger than 0.");
if (minutes < 0) throw new ArgumentOutOfRangeException("minutes", "Value must be equal to or larger than 0.");
if (seconds < 0) throw new ArgumentOutOfRangeException("seconds", "Value must be equal to or larger than 0.");
Config.MaxAge = new TimeSpan(days, hours, minutes, seconds);
return this;
}
public IFluentHpkpOptions IncludeSubdomains()
{
Config.IncludeSubdomains = true;
return this;
}
public IFluentHpkpOptions ReportUri(string reportUri)
{
try
{
_validator.ValidateReportUri(reportUri);
}
catch (Exception e)
{
throw new ArgumentException(e.Message, "reportUri");
}
Config.ReportUri = reportUri;
return this;
}
public IFluentHpkpOptions AllResponses()
{
Config.HttpsOnly = false;
return this;
}
public IFluentHpkpOptions Sha256Pins(params string[] pins)
{
foreach (var pin in pins)
{
try
{
_validator.ValidateRawPin(pin);
}
catch (Exception e)
{
throw new ArgumentException(e.Message, "pins");
}
var formattedPin = "sha256=\"" + pin + "\"";
if (!_pins.Contains(formattedPin))
{
_pins.Add(formattedPin);
}
}
return this;
}
public IFluentHpkpOptions PinCertificate(string thumbprint, StoreLocation storeLocation = StoreLocation.LocalMachine,
StoreName storeName = StoreName.My)
{
try
{
_validator.ValidateThumbprint(thumbprint);
}
catch (Exception e)
{
throw new ArgumentException(e.Message, thumbprint);
}
var helper = new X509Helper();
var cert = helper.GetCertByThumbprint(thumbprint, storeLocation, storeName);
var pin = helper.GetSubjectPublicKeyInfoPinValue(cert);
#if DNX451
cert.Reset();
#elif NET451
cert.Reset();
#else
cert.Dispose();
#endif
if (!_pins.Contains(pin))
{
_pins.Add(pin);
}
return this;
}
public IFluentHpkpOptions HttpsOnly()
{
Config.HttpsOnly = true;
return this;
}
}
}

33
external/NWebsec/HpkpOptionsConfiguration.cs

@ -1,33 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class HpkpOptionsConfiguration : IHpkpConfiguration
{
internal HpkpOptionsConfiguration()
{
MaxAge = TimeSpan.Zero;
HttpsOnly = true;
Pins = new string[0];
}
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<string> Pins { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public TimeSpan MaxAge { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IncludeSubdomains { get; set; }
public string ReportUri { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool HttpsOnly { get; set; }
}
}

52
external/NWebsec/HstsOptions.cs

@ -1,52 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Middleware
{
public class HstsOptions : HstsOptionsConfiguration, IFluentHstsOptions
{
// ReSharper disable once CSharpWarnings::CS0109
public new IFluentHstsOptions MaxAge(int days = 0, int hours = 0, int minutes = 0, int seconds = 0)
{
if (days < 0) throw new ArgumentOutOfRangeException(nameof(days), "Value must be equal to or larger than 0.");
if (hours < 0) throw new ArgumentOutOfRangeException(nameof(hours), "Value must be equal to or larger than 0.");
if (minutes < 0) throw new ArgumentOutOfRangeException(nameof(minutes), "Value must be equal to or larger than 0.");
if (seconds < 0) throw new ArgumentOutOfRangeException(nameof(seconds), "Value must be equal to or larger than 0.");
base.MaxAge = new TimeSpan(days, hours, minutes, seconds);
return this;
}
public new IFluentHstsOptions IncludeSubdomains()
{
base.IncludeSubdomains = true;
return this;
}
public new IFluentHstsOptions Preload()
{
base.Preload = true;
return this;
}
public new IFluentHstsOptions UpgradeInsecureRequests()
{
base.UpgradeInsecureRequests = true;
return this;
}
public IFluentHstsOptions AllResponses()
{
base.HttpsOnly = false;
return this;
}
public new IFluentHstsOptions HttpsOnly()
{
base.HttpsOnly = true;
return this;
}
}
}

32
external/NWebsec/HstsOptionsConfiguration.cs

@ -1,32 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.ComponentModel;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class HstsOptionsConfiguration : IHstsConfiguration
{
internal HstsOptionsConfiguration()
{
MaxAge = TimeSpan.Zero;
HttpsOnly = true;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public TimeSpan MaxAge { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IncludeSubdomains { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool Preload { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool HttpsOnly { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool UpgradeInsecureRequests { get; set; }
}
}

52
external/NWebsec/HttpHeaders/Configuration/CspConfiguration.cs

@ -1,52 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspConfiguration : ICspConfiguration
{
public CspConfiguration(bool initializeDirectives=true)
{
if (!initializeDirectives)
{
return;
}
DefaultSrcDirective = new CspDirectiveConfiguration();
ScriptSrcDirective = new CspDirectiveConfiguration();
ObjectSrcDirective = new CspDirectiveConfiguration();
StyleSrcDirective = new CspDirectiveConfiguration();
ImgSrcDirective = new CspDirectiveConfiguration();
MediaSrcDirective = new CspDirectiveConfiguration();
FrameSrcDirective = new CspDirectiveConfiguration();
FontSrcDirective = new CspDirectiveConfiguration();
ConnectSrcDirective = new CspDirectiveConfiguration();
BaseUriDirective = new CspDirectiveConfiguration();
ChildSrcDirective = new CspDirectiveConfiguration();
FormActionDirective = new CspDirectiveConfiguration();
FrameAncestorsDirective = new CspDirectiveConfiguration();
PluginTypesDirective = new CspPluginTypesDirectiveConfiguration();
SandboxDirective = new CspSandboxDirectiveConfiguration();
UpgradeInsecureRequestsDirective = new CspUpgradeDirectiveConfiguration();
ReportUriDirective = new CspReportUriDirectiveConfiguration();
}
public bool Enabled { get; set; }
public ICspDirectiveConfiguration DefaultSrcDirective { get; set; }
public ICspDirectiveConfiguration ScriptSrcDirective { get; set; }
public ICspDirectiveConfiguration ObjectSrcDirective { get; set; }
public ICspDirectiveConfiguration StyleSrcDirective { get; set; }
public ICspDirectiveConfiguration ImgSrcDirective { get; set; }
public ICspDirectiveConfiguration MediaSrcDirective { get; set; }
public ICspDirectiveConfiguration FrameSrcDirective { get; set; }
public ICspDirectiveConfiguration FontSrcDirective { get; set; }
public ICspDirectiveConfiguration ConnectSrcDirective { get; set; }
public ICspDirectiveConfiguration BaseUriDirective { get; set; }
public ICspDirectiveConfiguration ChildSrcDirective { get; set; }
public ICspDirectiveConfiguration FormActionDirective { get; set; }
public ICspDirectiveConfiguration FrameAncestorsDirective { get; set; }
public ICspPluginTypesDirectiveConfiguration PluginTypesDirective { get; set; }
public ICspSandboxDirectiveConfiguration SandboxDirective { get; set; }
public ICspUpgradeDirectiveConfiguration UpgradeInsecureRequestsDirective { get; set; }
public ICspReportUriDirectiveConfiguration ReportUriDirective { get; set; }
}
}

26
external/NWebsec/HttpHeaders/Configuration/CspDirectiveConfiguration.cs

@ -1,26 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspDirectiveConfiguration : ICspDirectiveConfiguration
{
private static readonly string[] EmptySources = new string[0];
public CspDirectiveConfiguration()
{
Enabled = true;
CustomSources = EmptySources;
}
public bool Enabled { get; set; }
public bool NoneSrc { get; set; }
public bool SelfSrc { get; set; }
public bool UnsafeInlineSrc { get; set; }
public bool UnsafeEvalSrc { get; set; }
public IEnumerable<string> CustomSources { get; set; }
public string Nonce { get; set; }
}
}

9
external/NWebsec/HttpHeaders/Configuration/CspHeaderConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspHeaderConfiguration : ICspHeaderConfiguration
{
public bool Enabled { get; set; }
}
}

20
external/NWebsec/HttpHeaders/Configuration/CspPluginTypesDirectiveConfiguration.cs

@ -1,20 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspPluginTypesDirectiveConfiguration : ICspPluginTypesDirectiveConfiguration
{
private static readonly string[] EmptySources = new string[0];
public bool Enabled { get; set; }
public IEnumerable<string> MediaTypes { get; set; }
public CspPluginTypesDirectiveConfiguration()
{
Enabled = true;
MediaTypes = EmptySources;
}
}
}

19
external/NWebsec/HttpHeaders/Configuration/CspReportUriDirectiveConfiguration.cs

@ -1,19 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspReportUriDirectiveConfiguration : ICspReportUriDirectiveConfiguration
{
public CspReportUriDirectiveConfiguration()
{
ReportUris = new string[0];
}
public bool Enabled { get; set; }
//TODO figure out what to do with this property
public bool EnableBuiltinHandler { get; set; }
public IEnumerable<string> ReportUris { get; set; }
}
}

15
external/NWebsec/HttpHeaders/Configuration/CspSandboxDirectiveConfiguration.cs

@ -1,15 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspSandboxDirectiveConfiguration : ICspSandboxDirectiveConfiguration
{
public bool Enabled { get; set; }
public bool AllowForms { get; set; }
public bool AllowPointerLock { get; set; }
public bool AllowPopups { get; set; }
public bool AllowSameOrigin { get; set; }
public bool AllowScripts { get; set; }
public bool AllowTopNavigation { get; set; }
}
}

11
external/NWebsec/HttpHeaders/Configuration/CspUpgradeDirectiveConfiguration.cs

@ -1,11 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class CspUpgradeDirectiveConfiguration : ICspUpgradeDirectiveConfiguration
{
public bool Enabled { get; set; }
public int HttpsPort { get; set; } = 443;
}
}

16
external/NWebsec/HttpHeaders/Configuration/HpkpConfiguration.cs

@ -1,16 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class HpkpConfiguration : IHpkpConfiguration
{
public IEnumerable<string> Pins { get; set; }
public TimeSpan MaxAge { get; set; }
public bool IncludeSubdomains { get; set; }
public string ReportUri { get; set; }
public bool HttpsOnly { get; set; }
}
}

15
external/NWebsec/HttpHeaders/Configuration/HstsConfiguration.cs

@ -1,15 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class HstsConfiguration : IHstsConfiguration
{
public TimeSpan MaxAge { get; set; }
public bool IncludeSubdomains { get; set; }
public bool Preload { get; set; }
public bool HttpsOnly { get; set; }
public bool UpgradeInsecureRequests { get; set; }
}
}

30
external/NWebsec/HttpHeaders/Configuration/ICspConfiguration.cs

@ -1,30 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface ICspConfiguration
{
bool Enabled { get; set; }
ICspDirectiveConfiguration DefaultSrcDirective { get; set; }
ICspDirectiveConfiguration ScriptSrcDirective { get; set; }
ICspDirectiveConfiguration ObjectSrcDirective { get; set; }
ICspDirectiveConfiguration StyleSrcDirective { get; set; }
ICspDirectiveConfiguration ImgSrcDirective { get; set; }
ICspDirectiveConfiguration MediaSrcDirective { get; set; }
ICspDirectiveConfiguration FrameSrcDirective { get; set; }
ICspDirectiveConfiguration FontSrcDirective { get; set; }
ICspDirectiveConfiguration ConnectSrcDirective { get; set; }
ICspReportUriDirectiveConfiguration ReportUriDirective { get; set; }
//CSP 2
ICspDirectiveConfiguration BaseUriDirective { get; set; }
ICspDirectiveConfiguration ChildSrcDirective { get; set; }
ICspDirectiveConfiguration FormActionDirective { get; set; }
ICspDirectiveConfiguration FrameAncestorsDirective { get; set; }
ICspPluginTypesDirectiveConfiguration PluginTypesDirective { get; set; }
ICspSandboxDirectiveConfiguration SandboxDirective { get; set; }
//Upgrade insecure requests
ICspUpgradeDirectiveConfiguration UpgradeInsecureRequestsDirective { get; set; }
}
}

42
external/NWebsec/HttpHeaders/Configuration/ICspDirectiveBasicConfiguration.cs

@ -1,42 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel;
using NWebsec.Core.Fluent;
namespace NWebsec.Core.HttpHeaders.Configuration
{
/// <summary>
/// Defines the properties required for CSP directive configuration.
/// </summary>
public interface ICspDirectiveBasicConfiguration : IFluentInterface
{
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
bool Enabled { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
bool NoneSrc { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
bool SelfSrc { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<string> CustomSources { get; set; }
}
}

19
external/NWebsec/HttpHeaders/Configuration/ICspDirectiveConfiguration.cs

@ -1,19 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.ComponentModel;
namespace NWebsec.Core.HttpHeaders.Configuration
{
/// <summary>
/// Defines the properties required for CSP directive configuration.
/// </summary>
public interface ICspDirectiveConfiguration : ICspDirectiveUnsafeInlineConfiguration
{
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
bool UnsafeEvalSrc { get; set; }
}
}

26
external/NWebsec/HttpHeaders/Configuration/ICspDirectiveUnsafeInlineConfiguration.cs

@ -1,26 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.ComponentModel;
namespace NWebsec.Core.HttpHeaders.Configuration
{
/// <summary>
/// Defines the properties required for CSP directive configuration.
/// </summary>
public interface ICspDirectiveUnsafeInlineConfiguration : ICspDirectiveBasicConfiguration
{
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
bool UnsafeInlineSrc { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
string Nonce { get; set; }
}
}

9
external/NWebsec/HttpHeaders/Configuration/ICspHeaderConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface ICspHeaderConfiguration
{
bool Enabled { get; set; }
}
}

24
external/NWebsec/HttpHeaders/Configuration/ICspPluginTypesDirectiveConfiguration.cs

@ -1,24 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
/// <summary>
/// Defines the properties required for CSP sandbox directive configuration.
/// </summary>
public interface ICspPluginTypesDirectiveConfiguration
{
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool Enabled { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
IEnumerable<string> MediaTypes { get; set; }
}
}

15
external/NWebsec/HttpHeaders/Configuration/ICspReportUriDirectiveConfiguration.cs

@ -1,15 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface ICspReportUriDirectiveConfiguration
{
bool Enabled { get; set; }
bool EnableBuiltinHandler { get; set; }
IEnumerable<string> ReportUris { get; set; }
}
}

49
external/NWebsec/HttpHeaders/Configuration/ICspSandboxDirectiveConfiguration.cs

@ -1,49 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
/// <summary>
/// Defines the properties required for CSP sandbox directive configuration.
/// </summary>
public interface ICspSandboxDirectiveConfiguration
{
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool Enabled { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool AllowForms { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool AllowPointerLock { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool AllowPopups { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool AllowSameOrigin { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool AllowScripts { get; set; }
/// <summary>
/// Infrastructure. Not intended to be used by your code directly. An attempt to hide this from Intellisense has been
/// made.
/// </summary>
bool AllowTopNavigation { get; set; }
}
}

14
external/NWebsec/HttpHeaders/Configuration/ICspUpgradeDirectiveConfiguration.cs

@ -1,14 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
/// <summary>
/// Defines the properties required for CSP sandbox directive configuration.
/// </summary>
public interface ICspUpgradeDirectiveConfiguration
{
bool Enabled { get; set; }
int HttpsPort { get; set; }
}
}

14
external/NWebsec/HttpHeaders/Configuration/IHpkpCertConfiguration.cs

@ -1,14 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Security.Cryptography.X509Certificates;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IHpkpCertConfiguration
{
string ThumbPrint { get; set; }
StoreLocation StoreLocation { get; set; }
StoreName Storename { get; set; }
string SpkiPinValue { get; set; }
}
}

16
external/NWebsec/HttpHeaders/Configuration/IHpkpConfiguration.cs

@ -1,16 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IHpkpConfiguration
{
IEnumerable<string> Pins { get; set; }
TimeSpan MaxAge { get; set; }
bool IncludeSubdomains { get; set; }
string ReportUri { get; set; }
bool HttpsOnly { get; set; }
}
}

9
external/NWebsec/HttpHeaders/Configuration/IHpkpPinConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IHpkpPinConfiguration
{
string Pin { get; set; }
}
}

19
external/NWebsec/HttpHeaders/Configuration/IHstsConfiguration.cs

@ -1,19 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IHstsConfiguration
{
TimeSpan MaxAge { get; set; }
bool IncludeSubdomains { get; set; }
bool Preload { get; set; }
bool HttpsOnly { get; set; }
bool UpgradeInsecureRequests { get; set; }
}
}

18
external/NWebsec/HttpHeaders/Configuration/IRedirectValidationConfiguration.cs

@ -1,18 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IRedirectValidationConfiguration
{
bool Enabled { get; set; }
/// <summary>
/// URIs allowed for redirect. Strings in this list should be created with Uri.AbsoluteUri to assure consistency.
/// </summary>
IEnumerable<string> AllowedUris { get; set; }
ISameHostHttpsRedirectConfiguration SameHostRedirectConfiguration { get; set; }
}
}

10
external/NWebsec/HttpHeaders/Configuration/ISameHostHttpsRedirectConfiguration.cs

@ -1,10 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface ISameHostHttpsRedirectConfiguration
{
bool Enabled { get; set; }
int[] Ports { get; set; }
}
}

9
external/NWebsec/HttpHeaders/Configuration/ISimpleBooleanConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface ISimpleBooleanConfiguration
{
bool Enabled { get; set; }
}
}

9
external/NWebsec/HttpHeaders/Configuration/IXFrameOptionsConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IXFrameOptionsConfiguration
{
XfoPolicy Policy { get; set; }
}
}

23
external/NWebsec/HttpHeaders/Configuration/IXRobotsTagConfiguration.cs

@ -1,23 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IXRobotsTagConfiguration
{
bool Enabled { get; set; }
bool NoIndex { get; set; }
bool NoFollow { get; set; }
bool NoSnippet { get; set; }
bool NoArchive { get; set; }
bool NoOdp { get; set; }
bool NoTranslate { get; set; }
bool NoImageIndex { get; set; }
}
}

11
external/NWebsec/HttpHeaders/Configuration/IXXssProtectionConfiguration.cs

@ -1,11 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public interface IXXssProtectionConfiguration
{
XXssPolicy Policy { get; set; }
bool BlockMode { get; set; }
}
}

19
external/NWebsec/HttpHeaders/Configuration/RedirectValidationConfiguration.cs

@ -1,19 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace NWebsec.Core.HttpHeaders.Configuration
{
internal class RedirectValidationConfiguration : IRedirectValidationConfiguration
{
public RedirectValidationConfiguration()
{
AllowedUris = new string[0];
SameHostRedirectConfiguration = new SameHostHttpsRedirectConfiguration();
}
public bool Enabled { get; set; }
public IEnumerable<string> AllowedUris { get; set; }
public ISameHostHttpsRedirectConfiguration SameHostRedirectConfiguration { get; set; }
}
}

15
external/NWebsec/HttpHeaders/Configuration/SameHostHttpsRedirectConfiguration.cs

@ -1,15 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class SameHostHttpsRedirectConfiguration : ISameHostHttpsRedirectConfiguration
{
public SameHostHttpsRedirectConfiguration()
{
Ports = new int[0];
}
public bool Enabled { get; set; }
public int[] Ports { get; set; }
}
}

9
external/NWebsec/HttpHeaders/Configuration/SimpleBooleanConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class SimpleBooleanConfiguration : ISimpleBooleanConfiguration
{
public bool Enabled { get; set; }
}
}

55
external/NWebsec/HttpHeaders/Configuration/Validation/HpkpConfigurationValidator.cs

@ -1,55 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace NWebsec.Core.HttpHeaders.Configuration.Validation
{
public class HpkpConfigurationValidator
{
private static readonly string[] ValidSchemes = { "http", "https" };
public void ValidateNumberOfPins(IHpkpConfiguration hpkpConfig)
{
if (hpkpConfig.MaxAge > TimeSpan.Zero && hpkpConfig.Pins.Count() < 2)
{
throw new Exception("You must supply two or more HPKP pins. One should represent a certificate currently in use, you should also include a backup pin for a cert/key not (yet) in use.");
}
}
public void ValidateRawPin(string pin)
{
var bytes = Convert.FromBase64String(pin);
if (bytes.Length != 32)
{
throw new Exception("Expected a 256 bit pin value, it was " + bytes.Length * 8 + " bits: " + pin);
}
}
public void ValidateThumbprint(string thumbPrint)
{
if (Regex.IsMatch(thumbPrint, "^([a-fA-F0-9]{2} ?){19}[a-fA-F0-9]{2}$"))
{
return;
}
throw new Exception("Malformed thumbprint, expected 20 HEX octets without any leading or trailing whitespace, was: " + thumbPrint);
}
public void ValidateReportUri(string reportUri)
{
Uri result;
if (!Uri.TryCreate(reportUri, UriKind.Absolute, out result))
{
throw new Exception("Report URIs must be absolute URIs. This is not: " + reportUri);
}
if (!ValidSchemes.Any(s => s.Equals(result.Scheme)))
{
throw new Exception("Report URIs must have the http or https scheme. Got: " + reportUri);
}
}
}
}

24
external/NWebsec/HttpHeaders/Configuration/Validation/HstsConfigurationValidator.cs

@ -1,24 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Core.HttpHeaders.Configuration.Validation
{
public class HstsConfigurationValidator
{
public void Validate(IHstsConfiguration hstsConfig)
{
if (!hstsConfig.Preload) return;
if (hstsConfig.UpgradeInsecureRequests)
{
throw new Exception("The Preload setting cannot be combined with the UpgradeInsecureRequests setting. Use one or the other.");
}
if (hstsConfig.MaxAge.TotalSeconds < 10886400 || !hstsConfig.IncludeSubdomains)
{
throw new Exception("HSTS max age must be at least 18 weeks and includesubdomains must be enabled to use the preload directive.");
}
}
}
}

51
external/NWebsec/HttpHeaders/Configuration/Validation/Rfc2045MediaTypeValidator.cs

@ -1,51 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace NWebsec.Core.HttpHeaders.Configuration.Validation
{
public class Rfc2045MediaTypeValidator
{
private static readonly string[] ValidTypes = { "application", "audio", "image","model", "text", "video" };
public void Validate(string mediaType)
{
if (String.IsNullOrEmpty(mediaType)) throw new ArgumentException("String was null or empty", "mediaType");
var components = mediaType.Split(new[] { '/' }, 2);
var type = components[0];
if (!ValidTypes.Any(t => t.Equals(type, StringComparison.OrdinalIgnoreCase)))
{
var message = String.Format("Media type \"{0}\" did not match any of the expected types: {1}", mediaType, String.Join(", ", ValidTypes));
throw new Exception(message);
}
if (components.Length != 2)
{
throw new Exception("Invalid format for media type. Expected \"type/subtype\" but was: " + mediaType);
}
var subType = components[1];
if (!Regex.IsMatch(subType, @"^[\x00-\x7F]*$"))
{
throw new Exception("Subtype contained characters from outside the US-ASCII range, was: " + subType);
}
if (Regex.IsMatch(subType, @"[\x00-\x20\x7F]+"))
{
throw new Exception("Subtype contained the space character, or an ASCII control character.");
}
var escapedTspecials = @"[()<>@,;:""\\/[\]?=]+";
if (Regex.IsMatch(subType, escapedTspecials))
{
throw new Exception("Subtype contained one of the forbidden tspecial characters: " + Regex.Unescape(escapedTspecials));
}
}
}
}

24
external/NWebsec/HttpHeaders/Configuration/Validation/XRobotsTagConfigurationValidator.cs

@ -1,24 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Core.HttpHeaders.Configuration.Validation
{
public class XRobotsTagConfigurationValidator
{
public void Validate(IXRobotsTagConfiguration xRobotsConfig)
{
if (!xRobotsConfig.Enabled) return;
if (xRobotsConfig.NoArchive ||
xRobotsConfig.NoFollow ||
xRobotsConfig.NoImageIndex ||
xRobotsConfig.NoIndex ||
xRobotsConfig.NoOdp ||
xRobotsConfig.NoSnippet ||
xRobotsConfig.NoTranslate) return;
throw new Exception(
"One or more directives must be enabled when header is enabled. Enable directives or disable header.");
}
}
}

9
external/NWebsec/HttpHeaders/Configuration/XFrameOptionsConfiguration.cs

@ -1,9 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class XFrameOptionsConfiguration : IXFrameOptionsConfiguration
{
public XfoPolicy Policy { get; set; }
}
}

16
external/NWebsec/HttpHeaders/Configuration/XRobotsTagConfiguration.cs

@ -1,16 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class XRobotsTagConfiguration : IXRobotsTagConfiguration
{
public bool Enabled { get; set; }
public bool NoIndex { get; set; }
public bool NoFollow { get; set; }
public bool NoSnippet { get; set; }
public bool NoArchive { get; set; }
public bool NoOdp { get; set; }
public bool NoTranslate { get; set; }
public bool NoImageIndex { get; set; }
}
}

10
external/NWebsec/HttpHeaders/Configuration/XXssProtectionConfiguration.cs

@ -1,10 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Configuration
{
public class XXssProtectionConfiguration : IXXssProtectionConfiguration
{
public XXssPolicy Policy { get; set; }
public bool BlockMode { get; set; }
}
}

12
external/NWebsec/HttpHeaders/Csp/CspSourceParseResult.cs

@ -1,12 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders.Csp
{
internal class CspSourceParseResult
{
public string Scheme { get; set; }
public string Host { get; set; }
public string Port { get; set; }
public string PathAndQuery { get; set; }
}
}

172
external/NWebsec/HttpHeaders/Csp/CspUriSource.cs

@ -1,172 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace NWebsec.Core.HttpHeaders.Csp
{
public class CspUriSource
{
private const string HostRegex = @"^(\*\.)?([\p{Ll}\p{Lu}0-9\-]+)(\.[\p{Ll}\p{Lu}0-9\-]+)*$";
private static readonly string SchemeOnlyRegex = "^[a-zA-Z]*[a-zA-Z0-9" + Regex.Escape("+.-") + "]:$";
private static readonly string[] KnownSchemes = { "http", "https", "ws", "wss" };
private readonly string _source;
private CspUriSource(string source)
{
_source = source;
}
// Returns the source as a string encoded according to the CSP spec.
public override string ToString()
{
return _source;
}
public static string EncodeUri(Uri uri)
{
if (!uri.IsAbsoluteUri)
{
var uriString = uri.IsWellFormedOriginalString() ? uri.ToString() : Uri.EscapeUriString(uri.ToString());
return EscapeReservedCspChars(uriString);
}
var host = uri.Host;
var encodedHost = EncodeHostname(host);
var needsReplacement = !host.Equals(encodedHost);
var authority = uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped);
if (needsReplacement)
{
authority = authority.Replace(host, encodedHost);
}
if (uri.PathAndQuery.Equals("/"))
{
return authority;
}
return authority + EscapeReservedCspChars(uri.PathAndQuery);
}
public static CspUriSource Parse(string source)
{
if (String.IsNullOrEmpty(source)) throw new ArgumentException("Value was null or empty", "source");
if (source.Equals("*")) return new CspUriSource(source);
Uri uriResult; //TODO figure out what happened to known schemes.
if (Uri.TryCreate(source, UriKind.Absolute, out uriResult) && KnownSchemes.Contains(uriResult.Scheme))
{
return new CspUriSource(EncodeUri(uriResult));
}
//Scheme only source
if (Regex.IsMatch(source, SchemeOnlyRegex)) return new CspUriSource(source.ToLower());
var parseResult = ParseSourceComponents(source);
var sb = new StringBuilder();
if (!String.IsNullOrEmpty(parseResult.Scheme))
{
if (!Regex.IsMatch(parseResult.Scheme, SchemeOnlyRegex))
{
throw new InvalidCspSourceException("Invalid scheme in CSP source: " + source);
}
sb.Append(parseResult.Scheme.ToLower()).Append("//");
}
if (String.IsNullOrEmpty(parseResult.Host))
{
throw new InvalidCspSourceException("Could not parse host in CSP source: " + source);
}
if (!Regex.IsMatch(parseResult.Host, HostRegex))
{
throw new InvalidCspSourceException("Invalid host in CSP source: " + source);
}
sb.Append(EncodeHostname(parseResult.Host.ToLower()));
if (!String.IsNullOrEmpty(parseResult.Port))
{
if (!ValidatePort(parseResult.Port))
{
throw new InvalidCspSourceException("Invalid port in CSP source: " + source);
}
sb.Append(":").Append(parseResult.Port);
}
if (!String.IsNullOrEmpty(parseResult.PathAndQuery))
{
sb.Append(EscapeReservedCspChars(Uri.EscapeUriString(parseResult.PathAndQuery)));
}
return new CspUriSource(sb.ToString());
}
private static CspSourceParseResult ParseSourceComponents(string uri)
{
const string regex = @"^((?<scheme>.*?:)\/\/)?" + // match anything up to ://
@"(?<host>.*?[^:\/])" + //then match anything up to a : or /
@"(:(?<port>(.*?[^\/])))?" + //then match port if exists up to a /
@"(?<pathAndQuery>\/.*)?$"; //grab the rest
var re = new Regex(regex, RegexOptions.ExplicitCapture);
var result = re.Match(uri);
if (!result.Success)
{
throw new InvalidCspSourceException("Malformed CSP source: " + uri);
}
return new CspSourceParseResult
{
Scheme = result.Groups["scheme"].Value,
Host = result.Groups["host"].Value,
Port = result.Groups["port"].Value,
PathAndQuery = result.Groups["pathAndQuery"].Value
};
}
private static string EncodeHostname(string hostname)
{
var idn = new IdnMapping();
return idn.GetAscii(hostname);
}
private static string EscapeReservedCspChars(string pathAndQuery)
{
char[] encodeChars = { ';', ',' };
if (pathAndQuery.IndexOfAny(encodeChars) == -1)
{
return pathAndQuery;
}
var sb = new StringBuilder(pathAndQuery);
sb.Replace(";", "%3B");
sb.Replace(",", "%2C");
return sb.ToString();
}
private static bool ValidatePort(string port)
{
if (port.Equals("*")) return true;
int portNumber;
var isInt = Int32.TryParse(port, out portNumber);
return isInt && portNumber > 0 && portNumber <= 65535;
}
}
}

15
external/NWebsec/HttpHeaders/Csp/InvalidCspSourceException.cs

@ -1,15 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
namespace NWebsec.Core.HttpHeaders.Csp
{
//[Serializable]
public class InvalidCspSourceException : Exception
{
public InvalidCspSourceException(string s)
: base(s)
{
}
}
}

47
external/NWebsec/HttpHeaders/HeaderConstants.cs

@ -1,47 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders
{
public class HeaderConstants
{
public static readonly string XFrameOptionsHeader = "X-Frame-Options";
public static readonly string XRobotsTagHeader = "X-Robots-Tag";
public static readonly string StrictTransportSecurityHeader = "Strict-Transport-Security";
public static readonly string XContentTypeOptionsHeader = "X-Content-Type-Options";
public static readonly string XDownloadOptionsHeader = "X-Download-Options";
public static readonly string XXssProtectionHeader = "X-XSS-Protection";
public static readonly string ContentSecurityPolicyHeader = "Content-Security-Policy";
public static readonly string ContentSecurityPolicyReportOnlyHeader = "Content-Security-Policy-Report-Only";
public static readonly string HpkpHeader = "Public-Key-Pins";
public static readonly string HpkpReportOnlyHeader = "Public-Key-Pins-Report-Only";
public static readonly string[] CspSourceList =
{
"'none'",
"'self'",
"'unsafe-inline'",
"'unsafe-eval'"
};
public static readonly string[] CspDirectives =
{
"default-src",
"script-src",
"object-src",
"style-src",
"img-src",
"media-src",
"frame-src",
"font-src",
"connect-src",
"report-uri"
};
public static readonly string[] CspSchemes =
{
"data:",
"https:",
"http:"
};
}
}

373
external/NWebsec/HttpHeaders/HeaderGenerator.cs

@ -1,373 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Core.HttpHeaders
{
public class HeaderGenerator : IHeaderGenerator
{
public HeaderResult CreateXRobotsTagResult(IXRobotsTagConfiguration xRobotsTagConfig,
IXRobotsTagConfiguration oldXRobotsTagConfig = null)
{
if (oldXRobotsTagConfig != null && oldXRobotsTagConfig.Enabled && xRobotsTagConfig.Enabled == false)
{
return new HeaderResult(HeaderResult.ResponseAction.Remove, HeaderConstants.XRobotsTagHeader);
}
if (xRobotsTagConfig.Enabled == false)
{
return null;
}
var sb = new StringBuilder();
sb.Append(xRobotsTagConfig.NoIndex ? "noindex, " : String.Empty);
sb.Append(xRobotsTagConfig.NoFollow ? "nofollow, " : String.Empty);
sb.Append(xRobotsTagConfig.NoSnippet && !xRobotsTagConfig.NoIndex ? "nosnippet, " : String.Empty);
sb.Append(xRobotsTagConfig.NoArchive && !xRobotsTagConfig.NoIndex ? "noarchive, " : String.Empty);
sb.Append(xRobotsTagConfig.NoOdp && !xRobotsTagConfig.NoIndex ? "noodp, " : String.Empty);
sb.Append(xRobotsTagConfig.NoTranslate && !xRobotsTagConfig.NoIndex ? "notranslate, " : String.Empty);
sb.Append(xRobotsTagConfig.NoImageIndex ? "noimageindex" : String.Empty);
var value = sb.ToString().TrimEnd(' ', ',');
if (value.Length == 0) return null;
return new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.XRobotsTagHeader, value);
}
public HeaderResult CreateHstsResult(IHstsConfiguration hstsConfig)
{
if (hstsConfig.MaxAge < TimeSpan.Zero) return null;
if (hstsConfig.Preload && (hstsConfig.MaxAge.TotalSeconds < 10886400 || !hstsConfig.IncludeSubdomains))
{
return null;
}
var seconds = (int)hstsConfig.MaxAge.TotalSeconds;
var includeSubdomains = (hstsConfig.IncludeSubdomains ? "; includeSubdomains" : "");
var preload = (hstsConfig.Preload ? "; preload" : "");
var value = string.Format("max-age={0}{1}{2}", seconds, includeSubdomains, preload);
return new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.StrictTransportSecurityHeader,
value);
}
public HeaderResult CreateXContentTypeOptionsResult(ISimpleBooleanConfiguration xContentTypeOptionsConfig,
ISimpleBooleanConfiguration oldXContentTypeOptionsConfig = null)
{
if (oldXContentTypeOptionsConfig != null && oldXContentTypeOptionsConfig.Enabled &&
!xContentTypeOptionsConfig.Enabled)
{
return new HeaderResult(HeaderResult.ResponseAction.Remove, HeaderConstants.XContentTypeOptionsHeader);
}
return xContentTypeOptionsConfig.Enabled
? new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.XContentTypeOptionsHeader, "nosniff")
: null;
}
public HeaderResult CreateXDownloadOptionsResult(ISimpleBooleanConfiguration xDownloadOptionsConfig,
ISimpleBooleanConfiguration oldXDownloadOptionsConfig = null)
{
if (oldXDownloadOptionsConfig != null && oldXDownloadOptionsConfig.Enabled &&
!xDownloadOptionsConfig.Enabled)
{
return new HeaderResult(HeaderResult.ResponseAction.Remove, HeaderConstants.XDownloadOptionsHeader);
}
return xDownloadOptionsConfig.Enabled
? new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.XDownloadOptionsHeader, "noopen")
: null;
}
public HeaderResult CreateXXssProtectionResult(IXXssProtectionConfiguration xXssProtectionConfig,
IXXssProtectionConfiguration oldXXssProtectionConfig = null)
{
if (oldXXssProtectionConfig != null && oldXXssProtectionConfig.Policy != XXssPolicy.Disabled &&
xXssProtectionConfig.Policy == XXssPolicy.Disabled)
{
return new HeaderResult(HeaderResult.ResponseAction.Remove, HeaderConstants.XXssProtectionHeader);
}
string value;
switch (xXssProtectionConfig.Policy)
{
case XXssPolicy.Disabled:
return null;
case XXssPolicy.FilterDisabled:
value = "0";
break;
case XXssPolicy.FilterEnabled:
value = (xXssProtectionConfig.BlockMode ? "1; mode=block" : "1");
break;
default:
throw new NotImplementedException("Somebody apparently forgot to implement support for: " +
xXssProtectionConfig.Policy);
}
return new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.XXssProtectionHeader, value);
}
public HeaderResult CreateXfoResult(IXFrameOptionsConfiguration xfoConfig,
IXFrameOptionsConfiguration oldXfoConfig = null)
{
if (oldXfoConfig != null && oldXfoConfig.Policy != XfoPolicy.Disabled &&
xfoConfig.Policy == XfoPolicy.Disabled)
{
return new HeaderResult(HeaderResult.ResponseAction.Remove, HeaderConstants.XFrameOptionsHeader);
}
switch (xfoConfig.Policy)
{
case XfoPolicy.Disabled:
return null;
case XfoPolicy.Deny:
return new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.XFrameOptionsHeader, "Deny");
case XfoPolicy.SameOrigin:
return new HeaderResult(HeaderResult.ResponseAction.Set, HeaderConstants.XFrameOptionsHeader,
"SameOrigin");
default:
throw new NotImplementedException("Apparently someone forgot to implement support for: " +
xfoConfig.Policy);
}
}
public HeaderResult CreateHpkpResult(IHpkpConfiguration hpkpConfig, bool reportOnly)
{
if (hpkpConfig.MaxAge < TimeSpan.Zero || hpkpConfig.Pins == null || !hpkpConfig.Pins.Any()) return null;
var headerName = reportOnly ? HeaderConstants.HpkpReportOnlyHeader : HeaderConstants.HpkpHeader;
var seconds = (int)hpkpConfig.MaxAge.TotalSeconds;
//Unpinning. Save a few bytes by ignoring other directives.
if (seconds == 0)
{
return new HeaderResult(HeaderResult.ResponseAction.Set, headerName, "max-age=" + seconds);
}
var sb = new StringBuilder();
sb.Append("max-age=").Append(seconds).Append(";");
if (hpkpConfig.IncludeSubdomains)
{
sb.Append("includeSubdomains;");
}
foreach (var pin in hpkpConfig.Pins)
{
sb.Append("pin-").Append(pin).Append(";");
}
if (string.IsNullOrEmpty(hpkpConfig.ReportUri))
{
sb.Remove(sb.Length - 1, 1);
}
else
{
sb.Append("report-uri=\"").Append(hpkpConfig.ReportUri).Append("\"");
}
var value = sb.ToString();
return new HeaderResult(HeaderResult.ResponseAction.Set, headerName, value);
}
public HeaderResult CreateCspResult(ICspConfiguration cspConfig, bool reportOnly,
string builtinReportHandlerUri = null, ICspConfiguration oldCspConfig = null)
{
var headerValue = cspConfig.Enabled ? CreateCspHeaderValue(cspConfig, builtinReportHandlerUri) : null;
if (oldCspConfig != null && oldCspConfig.Enabled)
{
if (!cspConfig.Enabled || headerValue == null)
{
return new HeaderResult(HeaderResult.ResponseAction.Remove,
(reportOnly ? HeaderConstants.ContentSecurityPolicyReportOnlyHeader : HeaderConstants.ContentSecurityPolicyHeader));
}
}
if (!cspConfig.Enabled || headerValue == null)
{
return null;
}
return new HeaderResult(HeaderResult.ResponseAction.Set,
(reportOnly ? HeaderConstants.ContentSecurityPolicyReportOnlyHeader : HeaderConstants.ContentSecurityPolicyHeader), headerValue);
}
private string CreateCspHeaderValue(ICspConfiguration config, string builtinReportHandlerUri = null)
{
var sb = new StringBuilder();
AppendDirective(sb, "default-src", GetDirectiveList(config.DefaultSrcDirective));
AppendDirective(sb, "script-src", GetDirectiveList(config.ScriptSrcDirective));
AppendDirective(sb, "object-src", GetDirectiveList(config.ObjectSrcDirective));
AppendDirective(sb, "style-src", GetDirectiveList(config.StyleSrcDirective));
AppendDirective(sb, "img-src", GetDirectiveList(config.ImgSrcDirective));
AppendDirective(sb, "media-src", GetDirectiveList(config.MediaSrcDirective));
AppendDirective(sb, "frame-src", GetDirectiveList(config.FrameSrcDirective));
AppendDirective(sb, "font-src", GetDirectiveList(config.FontSrcDirective));
AppendDirective(sb, "connect-src", GetDirectiveList(config.ConnectSrcDirective));
AppendDirective(sb, "base-uri", GetDirectiveList(config.BaseUriDirective));
AppendDirective(sb, "child-src", GetDirectiveList(config.ChildSrcDirective));
AppendDirective(sb, "form-action", GetDirectiveList(config.FormActionDirective));
AppendDirective(sb, "frame-ancestors", GetDirectiveList(config.FrameAncestorsDirective));
AppendDirective(sb, "plugin-types", GetPluginTypesDirectiveList(config.PluginTypesDirective));
AppendDirective(sb, "sandbox", GetSandboxDirectiveList(config.SandboxDirective));
AppendUpgradeDirective(sb, "upgrade-insecure-requests", config.UpgradeInsecureRequestsDirective);
if (sb.Length == 0) return null;
AppendDirective(sb, "report-uri",
GetReportUriList(config.ReportUriDirective, builtinReportHandlerUri));
//Get rid of trailing ;
sb.Length--;
return sb.ToString();
}
private void AppendDirective(StringBuilder sb, string directiveName, List<string> sources)
{
if (sources == null) return;
sb.Append(directiveName);
foreach (var source in sources)
{
sb.Append(' ').Append(source);
}
sb.Append(';');
}
private void AppendUpgradeDirective(StringBuilder sb, string directiveName, ICspUpgradeDirectiveConfiguration config)
{
if (!config.Enabled) return;
sb.Append(directiveName);
sb.Append(';');
}
private List<string> GetDirectiveList(ICspDirectiveConfiguration directive)
{
if (directive == null || !directive.Enabled)
return null;
var sources = new List<string>();
if (directive.NoneSrc)
{
sources.Add("'none'");
}
if (directive.SelfSrc)
{
sources.Add("'self'");
}
if (directive.UnsafeInlineSrc)
{
sources.Add("'unsafe-inline'");
}
if (!String.IsNullOrEmpty(directive.Nonce))
{
var nonce = $"'nonce-{directive.Nonce}'";
sources.Add(nonce);
}
if (directive.UnsafeEvalSrc)
{
sources.Add("'unsafe-eval'");
}
if (directive.CustomSources != null)
{
sources.AddRange(directive.CustomSources);
}
return sources.Count > 0 ? sources : null;
}
private List<string> GetPluginTypesDirectiveList(ICspPluginTypesDirectiveConfiguration directive)
{
if (directive == null || !directive.Enabled || !directive.MediaTypes.Any())
return null;
//We know there are MediaTypes, so not null.
return new List<string>(directive.MediaTypes);
}
private List<string> GetSandboxDirectiveList(ICspSandboxDirectiveConfiguration directive)
{
if (directive == null || !directive.Enabled)
return null;
var sources = new List<string>();
if (directive.AllowForms)
{
sources.Add("allow-forms");
}
if (directive.AllowPointerLock)
{
sources.Add("allow-pointer-lock");
}
if (directive.AllowPopups)
{
sources.Add("allow-popups");
}
if (directive.AllowSameOrigin)
{
sources.Add("allow-same-origin");
}
if (directive.AllowScripts)
{
sources.Add("allow-scripts");
}
if (directive.AllowTopNavigation)
{
sources.Add("allow-top-navigation");
}
return sources; //We want to return empty list and not null
}
private List<string> GetReportUriList(ICspReportUriDirectiveConfiguration directive,
string builtinReportHandlerUri = null)
{
if (directive == null || !directive.Enabled)
return null;
var reportUris = new List<string>();
if (directive.EnableBuiltinHandler)
{
reportUris.Add(builtinReportHandlerUri);
}
if (directive.ReportUris != null)
{
reportUris.AddRange(directive.ReportUris);
}
return reportUris.Count > 0 ? reportUris : null;
}
}
}

25
external/NWebsec/HttpHeaders/HeaderResult.cs

@ -1,25 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders
{
public class HeaderResult
{
public enum ResponseAction
{
Set = 0,
Remove = 1
}
public HeaderResult(ResponseAction action, string name, string value = null)
{
Action = action;
Name = name;
Value = value;
}
public ResponseAction Action { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
}

31
external/NWebsec/HttpHeaders/IHeaderGenerator.cs

@ -1,31 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Core.HttpHeaders
{
public interface IHeaderGenerator
{
HeaderResult CreateXRobotsTagResult(IXRobotsTagConfiguration xRobotsTagConfig,
IXRobotsTagConfiguration oldXRobotsTagConfig = null);
HeaderResult CreateHstsResult(IHstsConfiguration hstsConfig);
HeaderResult CreateXContentTypeOptionsResult(ISimpleBooleanConfiguration xContentTypeOptionsConfig,
ISimpleBooleanConfiguration oldXContentTypeOptionsConfig = null);
HeaderResult CreateXDownloadOptionsResult(ISimpleBooleanConfiguration xDownloadOptionsConfig,
ISimpleBooleanConfiguration oldXDownloadOptionsConfig = null);
HeaderResult CreateXXssProtectionResult(IXXssProtectionConfiguration xXssProtectionConfig,
IXXssProtectionConfiguration oldXXssProtectionConfig = null);
HeaderResult CreateXfoResult(IXFrameOptionsConfiguration xfoConfig,
IXFrameOptionsConfiguration oldXfoConfig = null);
HeaderResult CreateCspResult(ICspConfiguration cspConfig, bool reportOnly,
string builtinReportHandlerUri = null, ICspConfiguration oldCspConfig = null);
HeaderResult CreateHpkpResult(IHpkpConfiguration hpkpConfig, bool reportOnly);
}
}

22
external/NWebsec/HttpHeaders/XXssPolicy.cs

@ -1,22 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders
{
public enum XXssPolicy
{
/// <summary>Specifies that the X-Xss-Protection header should not be set in the HTTP response.</summary>
Disabled,
/// <summary>
/// Specifies that the X-Xss-Protection header should be set in the HTTP response, explicitly disabling the IE XSS
/// filter.
/// </summary>
FilterDisabled,
/// <summary>
/// Specifies that the X-Xss-Protection header should be set in the HTTP response, explicitly enabling the IE XSS
/// filter.
/// </summary>
FilterEnabled
}
}

22
external/NWebsec/HttpHeaders/XfoPolicy.cs

@ -1,22 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
namespace NWebsec.Core.HttpHeaders
{
public enum XfoPolicy
{
/// <summary>Specifies that the X-Frame-Options header should not be set in the HTTP response.</summary>
Disabled,
/// <summary>
/// Specifies that the X-Frame-Options header should be set in the HTTP response, instructing the browser to not
/// display the page when it is loaded in an iframe.
/// </summary>
Deny,
/// <summary>
/// Specifies that the X-Frame-Options header should be set in the HTTP response, instructing the browser to
/// display the page when it is loaded in an iframe - but only if the iframe is from the same origin as the page.
/// </summary>
SameOrigin
}
}

142
external/NWebsec/IFluentCspOptions.cs

@ -1,142 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using NWebsec.Core.Fluent;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for Content-Security-Options.
/// </summary>
public interface IFluentCspOptions : IFluentInterface
{
/// <summary>
/// Configures the default-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions DefaultSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the script-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions ScriptSources(Action<ICspDirectiveConfiguration> configurer);
/// <summary>
/// Configures the object-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions ObjectSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the style-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions StyleSources(Action<ICspDirectiveUnsafeInlineConfiguration> configurer);
/// <summary>
/// Configures the image-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions ImageSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the media-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions MediaSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the frame-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions FrameSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the font-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions FontSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the connect-src directive (CSP 1.0).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions ConnectSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the base-uri directive (CSP 2).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions BaseUris(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the child-src directive (CSP 2).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions ChildSources(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the form-action directive (CSP 2).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions FormActions(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the fram-ancestors directive (CSP 2).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions FrameAncestors(Action<ICspDirectiveBasicConfiguration> configurer);
/// <summary>
/// Configures the plugin-types directive (CSP 2).
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the media types for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions PluginTypes(Action<IFluentCspPluginTypesDirective> configurer);
/// <summary>
/// Enables the sandbox directive (CSP 2) without further ado.
/// </summary>
/// <remarks>Support for this directive was optional in CSP 1.0, but is mandatory as of CSP 2.</remarks>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions Sandbox();
/// <summary>
/// Configures the sandbox directive (CSP 2) with one or more sources.
/// </summary>
/// <remarks>Support for this directive was optional in CSP 1.0, but is mandatory as of CSP 2.</remarks>
/// <param name="configurer">An <see cref="Action"/> that configures the sources for the directive.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions Sandbox(Action<IFluentCspSandboxDirective> configurer);
/// <summary>
/// Enables the upgrade-insecure-requests directive and redirects conformant UAs to HTTPS.
/// </summary>
/// <remarks>This directive is not part of CSP 1.0 or CSP 2, but is described in a separate specification.</remarks>
/// <param name="httpsPort">The HTTPS port. Defaults to 443.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions UpgradeInsecureRequests(int httpsPort = 443);
/// <summary>
/// Configures the report-uri directive (CSP 1.0). Support for absolute URIs was introduced in CSP 2.
/// </summary>
/// <param name="configurer">An <see cref="Action"/> that configures the report URIs.</param>
/// <returns>The current <see cref="CspOptions" /> instance.</returns>
IFluentCspOptions ReportUris(Action<IFluentCspReportUriDirective> configurer);
}
}

14
external/NWebsec/IFluentCspPluginTypesDirective.cs

@ -1,14 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
public interface IFluentCspPluginTypesDirective : IFluentInterface
{
/// <summary>
/// Sets the media types for the CSP plugin-types directive.
/// </summary>
void MediaTypes(params string[] pluginType);
}
}

18
external/NWebsec/IFluentCspReportUriDirective.cs

@ -1,18 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure report URIs.
/// </summary>
public interface IFluentCspReportUriDirective : IFluentInterface
{
/// <summary>
/// Sets report URIs for the CSP directive.
/// </summary>
/// <param name="reportUris">One or more report URIs.</param>
void Uris(params string[] reportUris);
}
}

39
external/NWebsec/IFluentCspSandboxDirective.cs

@ -1,39 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
public interface IFluentCspSandboxDirective : IFluentInterface
{
/// <summary>
/// Sets the 'allow-forms' source for the CSP sandbox directive.
/// </summary>
IFluentCspSandboxDirective AllowForms();
/// <summary>
/// Sets the 'allow-pointer-lock' source for the CSP sandbox directive.
/// </summary>
IFluentCspSandboxDirective AllowPointerLock();
/// <summary>
/// Sets the 'allow-popups' source for the CSP sandbox directive.
/// </summary>
IFluentCspSandboxDirective AllowPopups();
/// <summary>
/// Sets the 'allow-same-origin' source for the CSP sandbox directive.
/// </summary>
IFluentCspSandboxDirective AllowSameOrigin();
/// <summary>
/// Sets the 'allow-scripts' source for the CSP sandbox directive.
/// </summary>
IFluentCspSandboxDirective AllowScripts();
/// <summary>
/// Sets the 'allow-top-navigation' source for the CSP sandbox directive.
/// </summary>
IFluentCspSandboxDirective AllowTopNavigation();
}
}

62
external/NWebsec/IFluentHpkpOptions.cs

@ -1,62 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Security.Cryptography.X509Certificates;
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for Http Strict Transport Security.
/// </summary>
public interface IFluentHpkpOptions : IFluentInterface
{
/// <summary>
/// Specifies the max age for the HPKP header.
/// </summary>
/// <param name="days">The number of days added to max age.</param>
/// <param name="hours">The number of hours added to max age.</param>
/// <param name="minutes">The number of minutes added to max age.</param>
/// <param name="seconds">The number of seconds added to max age.</param>
/// <returns>The current instance.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown if a negative value was supplied in any of the parameters.</exception>
IFluentHpkpOptions MaxAge(int days = 0, int hours = 0, int minutes = 0, int seconds = 0);
/// <summary>
/// Enables the IncludeSubdomains directive in the HPKP header.
/// </summary>
/// <returns>The current instance.</returns>
IFluentHpkpOptions IncludeSubdomains();
/// <summary>
/// Specifies a report URI where the browser can send HPKP violations.
/// </summary>
/// <param name="reportUri">The report URI, which is an absolute URI with scheme http or https.</param>
/// <returns>The current instance.</returns>
IFluentHpkpOptions ReportUri(string reportUri);
/// <summary>
/// Specifies that the HPKP header should also be set for HTTP responses. The header is always set for HTTPS responses.
/// </summary>
/// <remarks>The HPKP standard specifies that the header should only be set over secure connections, which is the default behavior.
/// This configuration option exists to accomodate websites running behind an SSL terminator.</remarks>
/// <returns>The current instance.</returns>
IFluentHpkpOptions AllResponses();
/// <summary>
/// Specifies one or more certificate pins to include in the HPKP header. A certificate pin is the Base64 encoded SHA-256 hash value of a certficate's SPKI.
/// </summary>
/// <param name="pins">One or more certficate pin values.</param>
/// <returns>The current instance.</returns>
IFluentHpkpOptions Sha256Pins(params string[] pins);
/// <summary>
/// Specifies a certificate that should be pinned in the HPKP header.
/// </summary>
/// <param name="thumbprint">The certificate thumbprint.</param>
/// <param name="storeLocation">The <see cref="StoreLocation"/> for the certificate. The default is <see cref="StoreLocation.LocalMachine"/>.</param>
/// <param name="storeName">The <see cref="StoreName"/> for the certificate. The default is <see cref="StoreName.My"/>.</param>
/// <returns>The current instance.</returns>
IFluentHpkpOptions PinCertificate(string thumbprint, StoreLocation storeLocation = StoreLocation.LocalMachine, StoreName storeName = StoreName.My);
}
}

59
external/NWebsec/IFluentHstsOptions.cs

@ -1,59 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for Http Strict Transport Security.
/// </summary>
public interface IFluentHstsOptions : IFluentInterface
{
/// <summary>
/// Specifies the max age for the HSTS header.
/// </summary>
/// <param name="days">The number of days added to max age.</param>
/// <param name="hours">The number of hours added to max age.</param>
/// <param name="minutes">The number of minutes added to max age.</param>
/// <param name="seconds">The number of seconds added to max age.</param>
/// <returns>The current instance.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown if a negative value was supplied in any of the parameters.</exception>
IFluentHstsOptions MaxAge(int days = 0, int hours = 0, int minutes = 0, int seconds = 0);
/// <summary>
/// Enables the IncludeSubdomains directive in the Hsts header.
/// </summary>
/// <returns>The current instance.</returns>
IFluentHstsOptions IncludeSubdomains();
/// <summary>
/// Enables the Preload directive in the HSTS header. MaxAge must be at least 18 weeks, and IncludeSubdomains must be enabled.
/// </summary>
/// <remarks>Read more about preloaded HSTS sites at <a href="https://www.chromium.org/hsts">www.chromium.org/sts</a></remarks>
/// <returns>The current instance.</returns>
IFluentHstsOptions Preload();
/// <summary>
/// Sets the HSTS header only when the user agent signals that it supports the upgrade-insecure-requests CSP directive.
/// </summary>
/// <remarks>This setting is intended to be used in combination with the upgrade-insecure-requests CSP directive.</remarks>
/// <returns>The current instance.</returns>
IFluentHstsOptions UpgradeInsecureRequests();
/// <summary>
/// Specifies that the HSTS header should also be set for HTTP responses. The header is always set for HTTPS responses.
/// </summary>
/// <remarks>The HSTS standard specifies that the header should only be set over secure connections, which is the default behavior.
/// This configuration option exists to accomodate websites running behind an SSL terminator.</remarks>
/// <returns>The current instance.</returns>
IFluentHstsOptions AllResponses();
/// <summary>
/// Specifies that the HSTS header should be set for HTTPS responses only.
/// </summary>
/// <returns>The current instance.</returns>
[Obsolete("This method is deprecated as the default has been changed to HTTPS only.", false)]
IFluentHstsOptions HttpsOnly();
}
}

26
external/NWebsec/IFluentRedirectValidationOptions.cs

@ -1,26 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for redirect validation.
/// </summary>
public interface IFluentRedirectValidationOptions : IFluentInterface
{
/// <summary>
/// Configures the allowed redirect destinations. These must be well formed absolute URIs.
/// </summary>
/// <param name="uris">Allowed redirect destinations.</param>
/// <returns>The current instance.</returns>
IFluentRedirectValidationOptions AllowedDestinations(params string[] uris);
/// <summary>
/// Allows same host redirects to HTTPS.
/// </summary>
/// <param name="httpsPorts">Allowed destination port(s) for redirects to HTTPS. The default HTTPS port (443) is assumed if no values are configured.</param>
/// <returns>The current instance.</returns>
IFluentRedirectValidationOptions AllowSameHostRedirectsToHttps(params int[] httpsPorts);
}
}

22
external/NWebsec/IFluentXFrameOptions.cs

@ -1,22 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for X-Frame-Options.
/// </summary>
public interface IFluentXFrameOptions : IFluentInterface
{
/// <summary>
/// Enables the Deny directive.
/// </summary>
void Deny();
/// <summary>
/// Enables the SameOrigin directive.
/// </summary>
void SameOrigin();
}
}

54
external/NWebsec/IFluentXRobotsTagOptions.cs

@ -1,54 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for X-Robots-Tag.
/// </summary>
public interface IFluentXRobotsTagOptions : IFluentInterface
{
/// <summary>
/// Enables the noindex directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoIndex();
/// <summary>
/// Enables the nofollow directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoFollow();
/// <summary>
/// Enables the nosnippet directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoSnippet();
/// <summary>
/// Enables the noarchive directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoArchive();
/// <summary>
/// Enables the noodp directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoOdp();
/// <summary>
/// Enables the notranslate directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoTranslate();
/// <summary>
/// Enables the noimageindex directive.
/// </summary>
/// <returns>The current instance.</returns>
IFluentXRobotsTagOptions NoImageIndex();
}
}

27
external/NWebsec/IFluentXXssProtectionOptions.cs

@ -1,27 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.Fluent;
namespace NWebsec.Middleware
{
/// <summary>
/// Fluent interface to configure options for X-Xss-Protection.
/// </summary>
public interface IFluentXXssProtectionOptions : IFluentInterface
{
/// <summary>
/// Configures the header to explicitly disable protection.
/// </summary>
void Disabled();
/// <summary>
/// Configures the header to explicitly enable protection.
/// </summary>
void Enabled();
/// <summary>
/// Configures the header to explicitly enable protection with block mode.
/// </summary>
void EnabledWithBlockMode();
}
}

88
external/NWebsec/Middleware/CspMiddleware.cs

@ -1,88 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.Extensions;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
using NWebsec.Middleware.Helpers;
namespace NWebsec.Middleware.Middleware
{
public class CspMiddleware
{
private readonly ICspConfiguration _config;
private readonly HeaderResult _headerResult;
private readonly bool _reportOnly;
private readonly RequestDelegate _next;
public CspMiddleware(RequestDelegate next, ICspConfiguration options, bool reportOnly)
{
_next = next;
_config = options;
_reportOnly = reportOnly;
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateCspResult(_config, reportOnly);
}
public async Task Invoke(HttpContext context)
{
if (HandleUpgradeInsecureRequest(context))
{
return;
}
SetCspHeaders(context);
if (_next != null)
{
await _next(context);
}
}
internal bool HandleUpgradeInsecureRequest(HttpContext context)
{
//Already on https.
if (context.Request.IsHttps) return false;
//CSP upgrade-insecure-requests is disabled
if (!_config.Enabled || !_config.UpgradeInsecureRequestsDirective.Enabled) return false;
if (!CspUpgradeHelper.UaSupportsUpgradeInsecureRequests(context)) return false;
var upgradeUri = new UriBuilder($"https://{context.Request.Host}")
{
Port = _config.UpgradeInsecureRequestsDirective.HttpsPort,
Path = context.Request.PathBase + context.Request.Path
};
//Redirect
context.Response.Headers["Vary"] = "Upgrade-Insecure-Requests";
context.Response.Headers["Location"] = upgradeUri.Uri.AbsoluteUri;
context.Response.StatusCode = 307;
return true;
}
internal void SetCspHeaders(HttpContext context)
{
if (_reportOnly)
{
context.GetNWebsecContext().CspReportOnly = _config;
}
else
{
context.GetNWebsecContext().Csp = _config;
}
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
context.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

39
external/NWebsec/Middleware/HpkpMiddleware.cs

@ -1,39 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware.Middleware
{
public class HpkpMiddleware : MiddlewareBase
{
private readonly IHpkpConfiguration _config;
private readonly HeaderResult _headerResult;
public HpkpMiddleware(RequestDelegate next, HpkpOptions options, bool reportOnly)
: base(next)
{
_config = options.Config;
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateHpkpResult(_config, reportOnly);
}
internal override void PreInvokeNext(HttpContext context)
{
if (_config.HttpsOnly && !context.Request.IsHttps)
{
return;
}
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
context.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

46
external/NWebsec/Middleware/HstsMiddleware.cs

@ -1,46 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
using NWebsec.Middleware.Helpers;
namespace NWebsec.Middleware.Middleware
{
public class HstsMiddleware : MiddlewareBase
{
private readonly IHstsConfiguration _config;
private readonly HeaderResult _headerResult;
private const string Https = "https";
public HstsMiddleware(RequestDelegate next, HstsOptions options)
: base(next)
{
_config = options;
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateHstsResult(_config);
}
internal override void PreInvokeNext(HttpContext context)
{
if (_config.HttpsOnly && !context.Request.IsHttps)
{
return;
}
if (_config.UpgradeInsecureRequests && !CspUpgradeHelper.UaSupportsUpgradeInsecureRequests(context))
{
return;
}
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
context.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

39
external/NWebsec/Middleware/MiddleWareBase.cs

@ -1,39 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace NWebsec.Middleware.Middleware
{
public class MiddlewareBase
{
private readonly RequestDelegate _next;
public MiddlewareBase(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
PreInvokeNext(context);
if (_next != null)
{
await _next(context);
}
PostInvokeNext(context);
}
internal virtual void PreInvokeNext(HttpContext context)
{
}
internal virtual void PostInvokeNext(HttpContext context)
{
}
}
}

39
external/NWebsec/Middleware/RedirectValidationMiddleware.cs

@ -1,39 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core;
namespace NWebsec.Middleware.Middleware
{
public class RedirectValidationMiddleware : MiddlewareBase
{
private readonly RedirectValidationOptions _config;
private readonly RedirectValidator _redirectValidator;
public RedirectValidationMiddleware(RequestDelegate next, RedirectValidationOptions options)
: base(next)
{
_config = options;
_redirectValidator = new RedirectValidator();
}
internal override void PostInvokeNext(HttpContext context)
{
var statusCode = context.Response.StatusCode;
if (!_redirectValidator.IsRedirectStatusCode(statusCode))
{
return;
}
var scheme = context.Request.Scheme;
var hostandport = context.Request.Host;
var requestUri = new Uri(scheme + "://" + hostandport);
_redirectValidator.ValidateRedirect(statusCode, context.Response.Headers["Location"], requestUri, _config);
}
}
}

34
external/NWebsec/Middleware/XContentTypeOptionsMiddleware.cs

@ -1,34 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.Extensions;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware.Middleware
{
public class XContentTypeOptionsMiddleware : MiddlewareBase
{
private readonly ISimpleBooleanConfiguration _config;
private readonly HeaderResult _headerResult;
public XContentTypeOptionsMiddleware(RequestDelegate next)
: base(next)
{
_config = new SimpleBooleanConfiguration { Enabled = true };
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateXContentTypeOptionsResult(_config);
}
internal override void PreInvokeNext(HttpContext owinEnvironment)
{
owinEnvironment.GetNWebsecContext().XContentTypeOptions = _config;
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
owinEnvironment.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

34
external/NWebsec/Middleware/XDownloadOptionsMiddleware.cs

@ -1,34 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.Extensions;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware.Middleware
{
public class XDownloadOptionsMiddleware : MiddlewareBase
{
private readonly ISimpleBooleanConfiguration _config;
private readonly HeaderResult _headerResult;
public XDownloadOptionsMiddleware(RequestDelegate next)
: base(next)
{
_config = new SimpleBooleanConfiguration { Enabled = true };
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateXDownloadOptionsResult(_config);
}
internal override void PreInvokeNext(HttpContext owinEnvironment)
{
owinEnvironment.GetNWebsecContext().XDownloadOptions = _config;
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
owinEnvironment.Response.Headers[_headerResult.Name]= _headerResult.Value;
}
}
}
}

36
external/NWebsec/Middleware/XRobotsTagMiddleware.cs

@ -1,36 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.Extensions;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware.Middleware
{
public class XRobotsTagMiddleware : MiddlewareBase
{
private readonly IXRobotsTagConfiguration _config;
private readonly HeaderResult _headerResult;
public XRobotsTagMiddleware(RequestDelegate next, XRobotsTagOptions options)
: base(next)
{
_config = options.Config;
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateXRobotsTagResult(_config);
}
internal override void PreInvokeNext(HttpContext owinEnvironment)
{
owinEnvironment.GetNWebsecContext().XRobotsTag = _config;
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
owinEnvironment.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

34
external/NWebsec/Middleware/XXssMiddleware.cs

@ -1,34 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.Extensions;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware.Middleware
{
public class XXssMiddleware : MiddlewareBase
{
private readonly IXXssProtectionConfiguration _config;
private readonly HeaderResult _headerResult;
public XXssMiddleware(RequestDelegate next, XXssProtectionOptions options)
: base(next)
{
_config = options;
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateXXssProtectionResult(_config);
}
internal override void PreInvokeNext(HttpContext owinEnvironment)
{
owinEnvironment.GetNWebsecContext().XXssProtection = _config;
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
owinEnvironment.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

33
external/NWebsec/Middleware/XfoMiddleware.cs

@ -1,33 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using NWebsec.Core.Extensions;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware.Middleware
{
public class XfoMiddleware : MiddlewareBase
{
private readonly IXFrameOptionsConfiguration _config;
private readonly HeaderResult _headerResult;
public XfoMiddleware(RequestDelegate next, XFrameOptions options)
: base(next)
{
_config = options;
var headerGenerator = new HeaderGenerator();
_headerResult = headerGenerator.CreateXfoResult(_config);
}
internal override void PreInvokeNext(HttpContext owinEnvironment)
{
owinEnvironment.GetNWebsecContext().XFrameOptions = _config;
if (_headerResult.Action == HeaderResult.ResponseAction.Set)
{
owinEnvironment.Response.Headers[_headerResult.Name] = _headerResult.Value;
}
}
}
}

21
external/NWebsec/NWebsec.xproj

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>38c8e88f-1d01-466f-b47d-6d67f13c1594</ProjectGuid>
<RootNamespace>NWebsec.Middleware</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

28
external/NWebsec/NWebsecContext.cs

@ -1,28 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Core
{
public class NWebsecContext
{
public static readonly string ContextKey = "nwebsec.Context";
public ISimpleBooleanConfiguration NoCacheHeaders { get; set; }
public ISimpleBooleanConfiguration XContentTypeOptions { get; set; }
public ISimpleBooleanConfiguration XDownloadOptions { get; set; }
public IXFrameOptionsConfiguration XFrameOptions { get; set; }
public IXRobotsTagConfiguration XRobotsTag { get; set; }
public IXXssProtectionConfiguration XXssProtection { get; set; }
public ICspConfiguration Csp { get; set; }
public ICspConfiguration CspReportOnly { get; set; }
public ConfigurationOverrides ConfigOverrides { get; set; }
}
public class ConfigurationOverrides
{
public ICspConfiguration CspOverride { get; set; }
public ICspConfiguration CspReportOnlyOverride { get; set; }
}
}

61
external/NWebsec/RedirectValidationOptions.cs

@ -1,61 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class RedirectValidationOptions : IRedirectValidationConfiguration, IFluentRedirectValidationOptions
{
public RedirectValidationOptions()
{
Enabled = true;
AllowedUris = new string[0];
SameHostRedirectConfiguration = new SameHostHttpsRedirectConfiguration();
}
public bool Enabled { get; set; }
public IEnumerable<string> AllowedUris { get; set; }
public ISameHostHttpsRedirectConfiguration SameHostRedirectConfiguration { get; set; }
public IFluentRedirectValidationOptions AllowedDestinations(params string[] uris)
{
if (uris.Length == 0) throw new ArgumentException("You must supply at least one redirect URI.");
var validatedUris = new List<string>();
foreach (var uri in uris)
{
Uri result;
if (!Uri.TryCreate(uri, UriKind.Absolute, out result))
{
throw new ArgumentException("Redirect URIs must be well formed absolute URIs. Offending URI: " + uri);
}
validatedUris.Add(result.AbsoluteUri);
}
AllowedUris = validatedUris.ToArray();
return this;
}
public IFluentRedirectValidationOptions AllowSameHostRedirectsToHttps(params int[] httpsPorts)
{
var invalidPorts = httpsPorts.Where(p => p < 1 || p > 65535).ToArray();
if (invalidPorts.Length > 0)
{
var ports = String.Join(" ", invalidPorts.Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray());
var invalidPortNumberMessage = "Invalid ports configured. Port number(s) must be in the range 1-65535. Offending ports: " + ports;
throw new ArgumentOutOfRangeException(invalidPortNumberMessage);
}
SameHostRedirectConfiguration.Enabled = true;
SameHostRedirectConfiguration.Ports = httpsPorts;
return this;
}
}
}

83
external/NWebsec/RedirectValidator.cs

@ -1,83 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System;
using System.Linq;
using NWebsec.Core.Exceptions;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Core
{
public class RedirectValidator
{
public void ValidateRedirect(int statusCode, string locationHeader, Uri requestAuthority,
IRedirectValidationConfiguration config)
{
if (!config.Enabled)
{
return;
}
//Not a redirect
if (!IsRedirectStatusCode(statusCode))
{
return;
}
//No location header
if (String.IsNullOrEmpty(locationHeader))
{
return;
}
Uri locationUri;
if (!Uri.TryCreate(locationHeader, UriKind.RelativeOrAbsolute, out locationUri))
{
throw new Exception("Unable to parse location header value as URI. Value was: " + locationHeader);
}
//Relative Uri
if (!locationUri.IsAbsoluteUri)
{
return;
}
// Same origin TODO look into URL encoding
if (locationUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped).Equals(requestAuthority.GetComponents(UriComponents.SchemeAndServer,UriFormat.SafeUnescaped)))
{
return;
}
//Same host https
if (config.SameHostRedirectConfiguration.Enabled && locationUri.Scheme.Equals("https") && requestAuthority.Host.Equals(locationUri.Host))
{
var sameHostConfig = config.SameHostRedirectConfiguration;
if (sameHostConfig.Ports.Length == 0 && locationUri.IsDefaultPort)
{
return;
}
if (sameHostConfig.Ports.Contains(locationUri.Port))
{
return;
}
throw new RedirectValidationException("A potentially dangerous redirect was detected. Allow same host redirects to this port number in configuration if the redirect was intended. Offending redirect: " + locationHeader);
}
// Allowed Uri
if (config.AllowedUris.Any(locationUri.AbsoluteUri.StartsWith))
{
return;
}
throw new RedirectValidationException(
"A potentially dangerous redirect was detected. Add the destination to the whitelist in configuration if the redirect was intended. Offending redirect: " +
locationHeader);
}
public bool IsRedirectStatusCode(int statusCode)
{
return statusCode >= 300 && statusCode < 400 && statusCode != 304;
}
}
}

27
external/NWebsec/XFrameOptions.cs

@ -1,27 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class XFrameOptions : IXFrameOptionsConfiguration, IFluentXFrameOptions
{
internal XFrameOptions()
{
Policy = XfoPolicy.Disabled;
}
public XfoPolicy Policy { get; set; }
public void Deny()
{
Policy = XfoPolicy.Deny;
}
public void SameOrigin()
{
Policy = XfoPolicy.SameOrigin;
}
}
}

58
external/NWebsec/XRobotsTagOptions.cs

@ -1,58 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class XRobotsTagOptions : IFluentXRobotsTagOptions
{
internal XRobotsTagOptions()
{
Config = new XRobotsTagConfiguration();
}
internal XRobotsTagConfiguration Config { get; private set; }
public IFluentXRobotsTagOptions NoIndex()
{
Config.NoIndex = Config.Enabled = true;
return this;
}
public IFluentXRobotsTagOptions NoFollow()
{
Config.NoFollow = Config.Enabled = true;
return this;
}
public IFluentXRobotsTagOptions NoSnippet()
{
Config.NoSnippet = Config.Enabled = true;
return this;
}
public IFluentXRobotsTagOptions NoArchive()
{
Config.NoArchive = Config.Enabled = true;
return this;
}
public IFluentXRobotsTagOptions NoOdp()
{
Config.NoOdp = Config.Enabled = true;
return this;
}
public IFluentXRobotsTagOptions NoTranslate()
{
Config.NoTranslate = Config.Enabled = true;
return this;
}
public IFluentXRobotsTagOptions NoImageIndex()
{
Config.NoImageIndex = Config.Enabled = true;
return this;
}
}
}

38
external/NWebsec/XXssProtectionOptions.cs

@ -1,38 +0,0 @@
// Copyright (c) André N. Klingsheim. See License.txt in the project root for license information.
using System.ComponentModel;
using NWebsec.Core.HttpHeaders;
using NWebsec.Core.HttpHeaders.Configuration;
namespace NWebsec.Middleware
{
public class XXssProtectionOptions : IXXssProtectionConfiguration, IFluentXXssProtectionOptions
{
internal XXssProtectionOptions()
{
Policy = XXssPolicy.Disabled;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public XXssPolicy Policy { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
public bool BlockMode { get; set; }
public void Disabled()
{
Policy = XXssPolicy.FilterDisabled;
}
public void Enabled()
{
Policy = XXssPolicy.FilterEnabled;
}
public void EnabledWithBlockMode()
{
Policy = XXssPolicy.FilterEnabled;
BlockMode = true;
}
}
}

39
external/NWebsec/project.json

@ -1,39 +0,0 @@
{
"version": "1.0.0-internal-*",
"description": "NWebsec middleware for ASP.NET 5 applications. NWebsec helps you set important security headers and detect potentially dangerous redirects. See project website for documentation.",
"authors": [ "André N. Klingsheim" ],
"packOptions": {
"title": "NWebsec.Middleware (ASP.NET 5)",
"releaseNotes": "This release includes core functions for the NWebsec security libaries.",
"owners": [ "André N. Klingsheim" ],
"copyright": "Copyright © 2014 - 2015",
"tags": [ "NWebsec Security AspNet AppSec" ],
"projectUrl": "https://docs.nwebsec.com/en/latest/",
"licenseUrl": "https://github.com/NWebsec/NWebsec/blob/master/LICENSE",
"iconUrl": "https://klings.blob.core.windows.net/nwebsecicon/nwebsec_nuget.png",
},
"shared": "**/**.cs",
"frameworks": {
"net451": { },
"netstandard1.3": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-rc2-24027",
"System.Runtime": "4.1.0-rc2-24027"
},
"imports": [
"dotnet5.4",
"portable-net451+win8"
]
}
},
"dependencies": {
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0-rc2-final"
}
}

2
samples/Mvc.Server/Startup.cs

@ -11,7 +11,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Mvc.Server.Models;
using Mvc.Server.Services;
using NWebsec.Middleware;
using NWebsec.AspNetCore.Middleware;
using OpenIddict;
using OpenIddict.Models;

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save