private async Task <IActionResult> VerifyContentDistributionRequest(WebSubSubscription subscription, HttpRequest request) { if (subscription.State != WebSubSubscriptionState.SubscribeValidated) { return(new NotFoundResult()); } if (String.IsNullOrWhiteSpace(subscription.Secret)) { return(null); } string signatureHeader = GetRequestHeader(request, WebSubConstants.SIGNATURE_HEADER_NAME, out IActionResult verificationResult); if (verificationResult != null) { return(verificationResult); } TrimmingTokenizer tokens = new TrimmingTokenizer(signatureHeader, _pairSeparators); if (tokens.Count != 2) { return(HandleInvalidSignatureHeader()); } TrimmingTokenizer.Enumerator tokensEnumerator = tokens.GetEnumerator(); tokensEnumerator.MoveNext(); StringSegment signatureHeaderKey = tokensEnumerator.Current; tokensEnumerator.MoveNext(); byte[] signatureHeaderExpectedHash = FromHex(tokensEnumerator.Current.Value, WebSubConstants.SIGNATURE_HEADER_NAME); if (signatureHeaderExpectedHash == null) { return(CreateBadHexEncodingResult(WebSubConstants.SIGNATURE_HEADER_NAME)); } byte[] payloadActualHash = await ComputeRequestBodyHashAsync(request, signatureHeaderKey, Encoding.UTF8.GetBytes(subscription.Secret)); if (payloadActualHash == null) { return(HandleInvalidSignatureHeader()); } if (!SecretEqual(signatureHeaderExpectedHash, payloadActualHash)) { return(CreateBadSignatureResult(WebSubConstants.SIGNATURE_HEADER_NAME)); } return(null); }
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (next == null) { throw new ArgumentNullException(nameof(next)); } if (!this.IsRequestApplicable(context.RouteData) && HttpMethods.IsPost(context.HttpContext.Request.Method)) { await next(); return; } IActionResult ErrorResult = base.EnsureSecureConnection(this.ReceiverName, context.HttpContext.Request); if (ErrorResult != null) { context.Result = ErrorResult; return; } string Header = base.GetRequestHeader(context.HttpContext.Request, BitbucketConstants.SignatureHeaderName, out ErrorResult); if (ErrorResult != null) { context.Result = ErrorResult; return; } TrimmingTokenizer Values = new TrimmingTokenizer(Header, SEPARATORS); TrimmingTokenizer.Enumerator Enumerator = Values.GetEnumerator(); Enumerator.MoveNext(); StringSegment HeaderKey = Enumerator.Current; if (Values.Count != 2 || !StringSegment.Equals(HeaderKey, BitbucketConstants.SignatureHeaderKey, StringComparison.OrdinalIgnoreCase)) { string ErrorMessage = string.Format(CultureInfo.CurrentCulture, Resources.SignatureFilter_BadHeaderValue, BitbucketConstants.SignatureHeaderName, BitbucketConstants.SignatureHeaderKey, "<value>"); base.Logger.LogError(1, ErrorMessage); context.Result = new BadRequestObjectResult(ErrorMessage); return; } Enumerator.MoveNext(); string HeaderValue = Enumerator.Current.Value; byte[] ExpectedHash = base.FromHex(HeaderValue, BitbucketConstants.SignatureHeaderName); if (ExpectedHash == null) { context.Result = base.CreateBadHexEncodingResult(BitbucketConstants.SignatureHeaderName); return; } byte[] Secret = this.GetSecret(this.ReceiverName, context.RouteData); if (Secret == null) { context.Result = new NotFoundResult(); return; } byte[] ActualHash = await base.ComputeRequestBodySha256HashAsync(context.HttpContext.Request, Secret); if (!BitbucketVerifySignatureFilter.SecretEqual(ExpectedHash, ActualHash)) { context.Result = base.CreateBadSignatureResult(BitbucketConstants.SignatureHeaderName); return; } await next(); }