Exemplo n.º 1
0
        /// <summary>
        /// Returns the SHA256 HMAC of the given <paramref name="prefix"/> (if non-<see langword="null"/>) followed by
        /// the given <paramref name="request"/>'s body.
        /// </summary>
        /// <param name="request">The current <see cref="HttpRequest"/>.</param>
        /// <param name="secret">The key data used to initialize the <see cref="HMACSHA256"/>.</param>
        /// <param name="prefix">If non-<see langword="null"/>, additional <c>byte</c>s to include in the hash.</param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="byte"/> array containing the SHA256 HMAC of
        /// the <paramref name="prefix"/> followed by the <paramref name="request"/>'s body.
        /// </returns>
        protected virtual async Task <byte[]> GetRequestBodyHash_SHA256(
            HttpRequest request,
            byte[] secret,
            byte[] prefix)
        {
            await WebHookHttpRequestUtilities.PrepareRequestBody(request);

            using (var hasher = new HMACSHA256(secret))
            {
                try
                {
                    if (prefix != null && prefix.Length > 0)
                    {
                        hasher.TransformBlock(
                            inputBuffer: prefix,
                            inputOffset: 0,
                            inputCount: prefix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    var hash = hasher.ComputeHash(request.Body);
                    return(hash);
                }
                finally
                {
                    // Reset Position because JsonInputFormatter et cetera always start from current position.
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reads the XML HTTP request entity body.
        /// </summary>
        /// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="XElement"/> containing the HTTP request
        /// entity body.
        /// </returns>
        protected virtual async Task <XElement> ReadAsXmlAsync(ResourceExecutingContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var request = context.HttpContext.Request;

            if (request.Body == null ||
                !request.ContentLength.HasValue ||
                request.ContentLength.Value == 0L ||
                !HttpMethods.IsPost(request.Method) ||
                !WebHookHttpRequestUtilities.IsXml(request))
            {
                // Other filters will log and return errors about these conditions.
                return(null);
            }

            var modelState    = context.ModelState;
            var actionContext = new ActionContext(
                context.HttpContext,
                context.RouteData,
                context.ActionDescriptor,
                modelState);

            var valueProviderFactories = context.ValueProviderFactories;
            var valueProvider          = await CompositeValueProvider.CreateAsync(actionContext, valueProviderFactories);

            var bindingContext = DefaultModelBindingContext.CreateBindingContext(
                actionContext,
                valueProvider,
                _xElementMetadata,
                bindingInfo: null,
                modelName: ModelStateRootKey);

            // Read request body.
            await _bodyModelBinder.BindModelAsync(bindingContext);

            if (!bindingContext.ModelState.IsValid)
            {
                return(null);
            }

            if (!bindingContext.Result.IsModelSet)
            {
                throw new InvalidOperationException(Resources.VerifyOrganization_ModelBindingFailed);
            }

            // Success
            return((XElement)bindingContext.Result.Model);
        }
        /// <summary>
        /// Returns the SHA1 HMAC of the given <paramref name="request"/>'s body.
        /// </summary>
        /// <param name="request">The current <see cref="HttpRequest"/>.</param>
        /// <param name="secret">The key data used to initialize the <see cref="HMACSHA1"/>.</param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="byte"/> array containing the SHA1 HMAC of the
        /// <paramref name="request"/>'s body.
        /// </returns>
        protected virtual async Task <byte[]> GetRequestBodyHash_SHA1(HttpRequest request, byte[] secret)
        {
            await WebHookHttpRequestUtilities.PrepareRequestBody(request);

            using (var hasher = new HMACSHA1(secret))
            {
                try
                {
                    var hash = hasher.ComputeHash(request.Body);
                    return(hash);
                }
                finally
                {
                    // Reset Position because JsonInputFormatter et cetera always start from current position.
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var request = context.HttpContext.Request;

            switch (_requestMetadata.BodyType)
            {
            case WebHookBodyType.Form:
                if (!request.HasFormContentType)
                {
                    context.Result = CreateUnsupportedMediaTypeResult(Resources.VerifyBody_NoFormData);
                }
                break;

            case WebHookBodyType.Json:
                if (!WebHookHttpRequestUtilities.IsJson(request))
                {
                    context.Result = CreateUnsupportedMediaTypeResult(Resources.VerifyBody_NoJson);
                }
                break;

            case WebHookBodyType.Xml:
                if (!WebHookHttpRequestUtilities.IsXml(request))
                {
                    context.Result = CreateUnsupportedMediaTypeResult(Resources.VerifyBody_NoXml);
                }
                break;

            default:
                var message = string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.General_InvalidEnumValue,
                    nameof(WebHookBodyType),
                    _requestMetadata.BodyType);
                throw new InvalidOperationException(message);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Returns the SHA256 HMAC of the given <paramref name="prefix"/>, the given <paramref name="request"/>'s
        /// body, and the given <paramref name="suffix"/> (in that order).
        /// </summary>
        /// <param name="request">The current <see cref="HttpRequest"/>.</param>
        /// <param name="secret">The key data used to initialize the <see cref="HMACSHA256"/>.</param>
        /// <param name="prefix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// before the <paramref name="request"/>'s body.
        /// </param>
        /// <param name="suffix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// after the <paramref name="request"/>'s body.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="byte"/> array containing the SHA256 HMAC of
        /// the <paramref name="prefix"/>, the <paramref name="request"/>'s body, and the <paramref name="suffix"/>
        /// (in that order).
        /// </returns>
        protected virtual async Task <byte[]> ComputeRequestBodySha256HashAsync(
            HttpRequest request,
            byte[] secret,
            byte[] prefix,
            byte[] suffix)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (secret == null)
            {
                throw new ArgumentNullException(nameof(secret));
            }
            if (secret.Length == 0)
            {
                throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty);
            }

            await WebHookHttpRequestUtilities.PrepareRequestBody(request);

            using (var hasher = new HMACSHA256(secret))
            {
                try
                {
                    if (prefix != null && prefix.Length > 0)
                    {
                        hasher.TransformBlock(
                            inputBuffer: prefix,
                            inputOffset: 0,
                            inputCount: prefix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    // Split body into 4K chunks.
                    var buffer      = new byte[4096];
                    var inputStream = request.Body;
                    int bytesRead;
                    while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        hasher.TransformBlock(
                            buffer,
                            inputOffset: 0,
                            inputCount: bytesRead,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    if (suffix != null && suffix.Length > 0)
                    {
                        hasher.TransformBlock(
                            suffix,
                            inputOffset: 0,
                            inputCount: suffix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    hasher.TransformFinalBlock(Array.Empty <byte>(), inputOffset: 0, inputCount: 0);

                    return(hasher.Hash);
                }
                finally
                {
                    // Reset Position because JsonInputFormatter et cetera always start from current position.
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }