245 lines
9.6 KiB
C#
245 lines
9.6 KiB
C#
|
using Microsoft.AspNetCore.Mvc;
|
|||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
|||
|
using Microsoft.Extensions.Primitives;
|
|||
|
using ServiceInside.Controllers;
|
|||
|
using ServiceShared;
|
|||
|
using ServiceShared.Https;
|
|||
|
using ServiceShared.Models.Response;
|
|||
|
using ServiceShared.Models.Response.Exception;
|
|||
|
|
|||
|
namespace ServiceInside.Filter
|
|||
|
{
|
|||
|
public class TrustedHeader : ActionFilterAttribute, IAsyncResultFilter, IAsyncAuthorizationFilter
|
|||
|
{
|
|||
|
private static Log.Types _LogType = Log.Types.INFO;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Sets the log type
|
|||
|
/// </summary>
|
|||
|
/// <param name="Log.Types">Log.Types</param>
|
|||
|
public static void SetLog(Log.Types logType)
|
|||
|
{
|
|||
|
_LogType = logType;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Validates request header
|
|||
|
/// </summary>
|
|||
|
/// <param name="context">Current context</param>
|
|||
|
/// <returns></returns>
|
|||
|
public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context)
|
|||
|
{
|
|||
|
if (context.HttpContext == null ||
|
|||
|
context.HttpContext.Request == null ||
|
|||
|
context.HttpContext.Request.Headers == null ||
|
|||
|
context.HttpContext.Request.Body == null ||
|
|||
|
context.HttpContext.Request.ContentLength <= 0 ||
|
|||
|
!context.HttpContext.Request.Headers.ContainsKey("User-Agent") ||
|
|||
|
!context.HttpContext.Request.Headers.ContainsKey("Content-Type") ||
|
|||
|
!context.HttpContext.Request.Headers.ContainsKey("Client-Hash") ||
|
|||
|
!context.HttpContext.Request.Headers.ContainsKey("Client-Key") ||
|
|||
|
!context.HttpContext.Request.IsHttps)
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// User Agent validator
|
|||
|
StringValues userAgent = new StringValues();
|
|||
|
if (!context.HttpContext.Request.Headers.TryGetValue("User-Agent", out userAgent) ||
|
|||
|
!Request.ValidUserAgent(userAgent))
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Content Type validator
|
|||
|
StringValues contentType = new StringValues();
|
|||
|
if (!context.HttpContext.Request.Headers.TryGetValue("Content-Type", out contentType) ||
|
|||
|
contentType.ToString() != "application/json")
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Client hash validator
|
|||
|
StringValues clientHash = new StringValues();
|
|||
|
if (!context.HttpContext.Request.Headers.TryGetValue("Client-Hash", out clientHash) ||
|
|||
|
!Request.ValidHeaderHash(clientHash.ToString()))
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Client Public Key validator
|
|||
|
StringValues clientKey = new StringValues();
|
|||
|
if (!context.HttpContext.Request.Headers.TryGetValue("Client-Key", out clientKey))
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
// check if valid base64 encoded
|
|||
|
byte[] publicKey = Convert.FromBase64String(clientKey.ToString());
|
|||
|
}
|
|||
|
catch
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
}
|
|||
|
|
|||
|
// Check if client signature in headers
|
|||
|
if (context.RouteData != null &&
|
|||
|
context.RouteData.Values != null &&
|
|||
|
context.RouteData.Values.ContainsKey("controller"))
|
|||
|
{
|
|||
|
string controllerName = (string?)context.RouteData.Values["controller"];
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(controllerName) && controllerName.ToLower() != "exchange")
|
|||
|
{
|
|||
|
if (!context.HttpContext.Request.Headers.ContainsKey("Client-Signature") ||
|
|||
|
!context.HttpContext.Request.Headers.ContainsKey("Client-Signature-Key"))
|
|||
|
{
|
|||
|
context.Result = new JsonResult(new InvalidClientException());
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Logs request in debug mode
|
|||
|
/// </summary>
|
|||
|
/// <param name="context"></param>
|
|||
|
/// <param name="next"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
|
|||
|
{
|
|||
|
if (_LogType == Log.Types.DEBUG)
|
|||
|
{
|
|||
|
string headers = "";
|
|||
|
|
|||
|
foreach (var header in context.HttpContext.Request.Headers)
|
|||
|
{
|
|||
|
headers += header.Key + "=" + header.Value + "\r\n";
|
|||
|
}
|
|||
|
|
|||
|
string message = "";
|
|||
|
|
|||
|
if (context != null &&
|
|||
|
context.HttpContext != null &&
|
|||
|
context.HttpContext.Connection != null &&
|
|||
|
context.HttpContext.Connection.RemoteIpAddress != null)
|
|||
|
{
|
|||
|
message = context.HttpContext.Connection.RemoteIpAddress.ToString() + " " +
|
|||
|
context.ActionDescriptor.DisplayName + "\r\nHeaders:" + headers;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
Log.Debug(message);
|
|||
|
}
|
|||
|
|
|||
|
await next();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Adds Trusted Headers to the response
|
|||
|
/// </summary>
|
|||
|
/// <param name="context"></param>
|
|||
|
public override void OnActionExecuted(ActionExecutedContext context)
|
|||
|
{
|
|||
|
base.OnActionExecuted(context);
|
|||
|
|
|||
|
if (context != null && context.HttpContext != null && context.HttpContext.Response != null &&
|
|||
|
context.HttpContext.Response.Headers != null && context.Controller != null)
|
|||
|
{
|
|||
|
BaseController controller = (BaseController)context.Controller;
|
|||
|
string signatureData = null;
|
|||
|
|
|||
|
if (context.Result != null)
|
|||
|
{
|
|||
|
JsonResult jsonResult = (JsonResult)context.Result;
|
|||
|
|
|||
|
if (jsonResult != null && jsonResult.Value != null && jsonResult.Value.GetType() == typeof(EncryptedResponse))
|
|||
|
{
|
|||
|
EncryptedResponse encryptedResponse = ((EncryptedResponse)jsonResult.Value);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(encryptedResponse.encrypted_content))
|
|||
|
{
|
|||
|
signatureData = encryptedResponse.encrypted_content;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
signatureData = encryptedResponse.descriptor;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// User Agent
|
|||
|
if (!context.HttpContext.Response.Headers.ContainsKey("User-Agent"))
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers.Add("User-Agent", "BefundAppServer");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers["User-Agent"] = "BefundAppServer";
|
|||
|
}
|
|||
|
|
|||
|
// Content Type
|
|||
|
if (!context.HttpContext.Response.Headers.ContainsKey("Content-Type"))
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers.Add("Content-Type", "application/json");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers["Content-Type"] = "application/json";
|
|||
|
}
|
|||
|
|
|||
|
// Server Hash
|
|||
|
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Hash"))
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers.Add("Server-Hash", Request.GeServerHash());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers["Server-Hash"] = Request.GeServerHash();
|
|||
|
}
|
|||
|
|
|||
|
// Server Key
|
|||
|
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Key"))
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers.Add("Server-Key", controller.GetServerPublicKey());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers["Server-Key"] = controller.GetServerPublicKey();
|
|||
|
}
|
|||
|
|
|||
|
if(!string.IsNullOrEmpty(signatureData))
|
|||
|
{
|
|||
|
// Server Signature
|
|||
|
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Signature"))
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers.Add("Server-Signature", controller.GetServerSignature(signatureData));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers["Server-Signature"] = controller.GetServerSignature(signatureData);
|
|||
|
}
|
|||
|
|
|||
|
// Server Signature Key
|
|||
|
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Signature-Key"))
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers.Add("Server-Signature-Key", controller.GetServerSignatureKey());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
context.HttpContext.Response.Headers["Server-Signature-Key"] = controller.GetServerSignatureKey();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|