@@ -1,5 +1,6 @@ | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Threading; | |||
using Teknik.Utilities.Cryptography; | |||
@@ -33,6 +34,7 @@ namespace Teknik.Configuration | |||
private string _CdnHost; | |||
private string _IPBlacklistFile; | |||
private string _ReferrerBlacklistFile; | |||
private List<string> _PublicKeys; | |||
private UserConfig _UserConfig; | |||
private ContactConfig _ContactConfig; | |||
private EmailConfig _EmailConfig; | |||
@@ -68,6 +70,8 @@ namespace Teknik.Configuration | |||
public string IPBlacklistFile { get { return _IPBlacklistFile;} set { _IPBlacklistFile = value; }} | |||
public string ReferrerBlacklistFile { get { return _ReferrerBlacklistFile;} set { _ReferrerBlacklistFile = value; }} | |||
public List<string> PublicKeys { get { return _PublicKeys; } set { _PublicKeys = value; } } | |||
// User Configuration | |||
public UserConfig UserConfig { get { return _UserConfig; } set { _UserConfig = value; } } | |||
@@ -143,6 +147,7 @@ namespace Teknik.Configuration | |||
CdnHost = string.Empty; | |||
IPBlacklistFile = string.Empty; | |||
ReferrerBlacklistFile = string.Empty; | |||
PublicKeys = new List<string>(); | |||
UserConfig = new UserConfig(); | |||
EmailConfig = new EmailConfig(); | |||
ContactConfig = new ContactConfig(); |
@@ -138,8 +138,7 @@ namespace Teknik.Areas.Upload.Controllers | |||
return Json(new { error = new { message = "Exception while uploading file: " + ex.GetFullMessage(true) } }); | |||
} | |||
} | |||
// User did not supply key | |||
[HttpGet] | |||
[AllowAnonymous] | |||
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)] | |||
@@ -301,6 +300,9 @@ namespace Teknik.Areas.Upload.Controllers | |||
} | |||
#endregion | |||
// Set Last Modified | |||
Response.GetTypedHeaders().LastModified = dateUploaded; | |||
// We accept ranges | |||
Response.Headers.Add("Accept-Ranges", "0-" + contentLength); | |||
@@ -310,6 +312,9 @@ namespace Teknik.Areas.Upload.Controllers | |||
// Notify the client the content length we'll be outputting | |||
Response.Headers.Add("Content-Length", length.ToString()); | |||
// Set the content type of this response | |||
Response.Headers.Add("Content-Type", contentType); | |||
// Create content disposition | |||
var cd = new System.Net.Mime.ContentDisposition | |||
{ | |||
@@ -333,12 +338,12 @@ namespace Teknik.Areas.Upload.Controllers | |||
byte[] keyBytes = Encoding.UTF8.GetBytes(key); | |||
byte[] ivBytes = Encoding.UTF8.GetBytes(iv); | |||
return new BufferedFileStreamResult(contentType, (response) => ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fs, false, keyBytes, ivBytes), (int)length, _config.UploadConfig.ChunkSize), false); | |||
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fs, false, keyBytes, ivBytes), (int)length, _config.UploadConfig.ChunkSize), false); | |||
} | |||
else // Otherwise just send it | |||
{ | |||
// Send the file | |||
return new BufferedFileStreamResult(contentType, (response) => ResponseHelper.StreamToOutput(response, true, fs, (int)length, _config.UploadConfig.ChunkSize), false); | |||
return new BufferedFileStreamResult(contentType, async (response) => await ResponseHelper.StreamToOutput(response, true, fs, (int)length, _config.UploadConfig.ChunkSize), false); | |||
} | |||
} | |||
catch (Exception ex) | |||
@@ -376,6 +381,9 @@ namespace Teknik.Areas.Upload.Controllers | |||
Inline = true | |||
}; | |||
// Set the content type of this response | |||
Response.Headers.Add("Content-Type", upload.ContentType); | |||
Response.Headers.Add("Content-Disposition", cd.ToString()); | |||
// Read in the file |
@@ -55,6 +55,7 @@ namespace Teknik.Middleware | |||
} | |||
httpContext.Response.Headers.Append("Access-Control-Allow-Origin", origin); | |||
httpContext.Response.Headers.Append("Vary", "Origin"); | |||
return _next(httpContext); | |||
} |
@@ -0,0 +1,61 @@ | |||
using Microsoft.AspNetCore.Builder; | |||
using Microsoft.AspNetCore.Http; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Teknik.Configuration; | |||
namespace Teknik.Middleware | |||
{ | |||
public class SecurityHeadersMiddleware | |||
{ | |||
private readonly RequestDelegate _next; | |||
public SecurityHeadersMiddleware(RequestDelegate next) | |||
{ | |||
_next = next; | |||
} | |||
public Task Invoke(HttpContext httpContext, Config config) | |||
{ | |||
IHeaderDictionary headers = httpContext.Response.Headers; | |||
// Access Control | |||
headers.Append("Access-Control-Allow-Credentials", "true"); | |||
headers.Append("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS"); | |||
headers.Append("Access-Control-Allow-Headers", "Authorization, Accept, Origin, Content-Type, X-Requested-With, Connection, Transfer-Encoding"); | |||
// HSTS | |||
headers.Append("strict-transport-security", "max-age=31536000; includeSubdomains; preload"); | |||
// XSS Protection | |||
headers.Append("X-XSS-Protection", "1; mode=block"); | |||
// Content Type Options | |||
headers.Append("X-Content-Type-Options", "nosniff"); | |||
// Public Key Pinning | |||
string keys = string.Empty; | |||
foreach (string key in config.PublicKeys) | |||
{ | |||
keys += $"pin-sha256=\"{key}\";"; | |||
} | |||
headers.Append("Public-Key-Pins", $"max-age=300; includeSubDomains; {keys}"); | |||
// Referrer Policy | |||
headers.Append("Referrer-Policy", "no-referrer, strict-origin-when-cross-origin"); | |||
return _next(httpContext); | |||
} | |||
} | |||
// Extension method used to add the middleware to the HTTP request pipeline. | |||
public static class SecurityHeadersMiddlewareExtensions | |||
{ | |||
public static IApplicationBuilder UseSecurityHeaders(this IApplicationBuilder builder) | |||
{ | |||
return builder.UseMiddleware<SecurityHeadersMiddleware>(); | |||
} | |||
} | |||
} |
@@ -144,7 +144,7 @@ namespace Teknik | |||
} | |||
else | |||
{ | |||
app.UseHsts(); | |||
//app.UseHsts(); | |||
} | |||
// Performance Monitor the entire request | |||
@@ -154,6 +154,7 @@ namespace Teknik | |||
app.UseBlacklist(); | |||
app.UseCORS(); | |||
app.UseCSP(); | |||
app.UseSecurityHeaders(); | |||
// Cache Responses | |||
app.UseResponseCaching(); |