Ejemplo n.º 1
0
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var request = context.HttpContext.Request;

            if (!request.Body.CanSeek && !_options.SuppressReadBuffering)
            {
                BufferingHelper.EnableRewind(request);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            try
            {
                var result =
                    MessagePackSerializer.NonGeneric.Deserialize(context.ModelType, request.Body, _options.FormatterResolver);
                var formatterResult = await InputFormatterResult.SuccessAsync(result);



                return(formatterResult);
            }
            catch (Exception e)
            {
                SystemLogger.Instance.LogDebug($"Could not deserialize object {e}");
                throw;
            }
        }
Ejemplo n.º 2
0
        private async void OnNetConnectionStatusUpdated(object sender, NetStatusUpdatedEventArgs args)
        {
            var ncs = args.NetStatusCode;

            if (ncs == NetStatusCodeType.NetConnectionConnectSuccess)
            {
                _Stream                = new NetStream();
                _Stream.Attached      += OnAttached;
                _Stream.StatusUpdated += OnNetStreamStatusUpdated;
                _Stream.AudioStarted  += OnAudioStarted;
                _Stream.VideoStarted  += OnVideoStarted;

                _BufferingHelper = new BufferingHelper(_Stream);

                // createStream
                await _Stream.AttachAsync(_Connection);

                // nlPlayNotice(チャンネル/ユーザー生放送のライブ配信のみ)
                await _ConnectionImpl.PostConnectionProcess(_Connection);
            }
            else if ((ncs & NetStatusCodeType.Level2Mask) == NetStatusCodeType.NetConnectionConnect)
            {
                Close();
                Stopped?.Invoke(new NicovideoRtmpClientStoppedEventArgs());
            }
        }
Ejemplo n.º 3
0
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var request = context.HttpContext.Request;

            if (!request.Body.CanSeek && !_options.SuppressReadBuffering)
            {
                BufferingHelper.EnableRewind(request);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            using (MemoryStream stream = new MemoryStream())
            {
                await request.Body.CopyToAsync(stream);

                stream.Position = 0;
                var result = MessagePackSerializer.NonGeneric.Deserialize(context.ModelType, stream, _options.FormatterResolver);
                return(await InputFormatterResult.SuccessAsync(result));
            }
        }
        /// <inheritdoc />
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(
            InputFormatterContext context,
            Encoding encoding)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            var request = context.HttpContext.Request;

            var suppressInputFormatterBuffering = _options?.SuppressInputFormatterBuffering ?? _suppressInputFormatterBuffering;

            if (!request.Body.CanSeek && !suppressInputFormatterBuffering)
            {
                // XmlSerializer does synchronous reads. In order to avoid blocking on the stream, we asynchronously
                // read everything into a buffer, and then seek back to the beginning.
                BufferingHelper.EnableRewind(request);
                Debug.Assert(request.Body.CanSeek);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            try
            {
                using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), encoding))
                {
                    var type = GetSerializableType(context.ModelType);

                    var serializer = GetCachedSerializer(type);

                    var deserializedObject = serializer.Deserialize(xmlReader);

                    // Unwrap only if the original type was wrapped.
                    if (type != context.ModelType)
                    {
                        if (deserializedObject is IUnwrappable unwrappable)
                        {
                            deserializedObject = unwrappable.Unwrap(declaredType: context.ModelType);
                        }
                    }

                    return(InputFormatterResult.Success(deserializedObject));
                }
            }
            // XmlSerializer wraps actual exceptions (like FormatException or XmlException) into an InvalidOperationException
            // https://github.com/dotnet/corefx/blob/master/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs#L652
            catch (InvalidOperationException exception) when(exception.InnerException is FormatException || exception.InnerException is XmlException)
            {
                throw new InputFormatterException(Resources.ErrorDeserializingInputData, exception);
            }
        }
Ejemplo n.º 5
0
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            if (context.ModelType == typeof(RequestMessage))
            {
                var request = context.HttpContext.Request;
                if (!request.Body.CanSeek)
                {
                    BufferingHelper.EnableRewind(request);
                    Debug.Assert(request.Body.CanSeek);

                    await request.Body.DrainAsync(CancellationToken.None);

                    request.Body.Seek(0L, SeekOrigin.Begin);
                }

                using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), encoding))
                {
                    var inputRequestMessage = RequestMessageFactory.CreateRequestMessage(xmlReader);

                    if ((_messageMode == MessageMode.Cipher || _messageMode == MessageMode.Compatible) &&
                        inputRequestMessage is RequestEncryptMessage)
                    {
                        var encryptMessage = inputRequestMessage as RequestEncryptMessage;
                        var plainMessage   = String.Empty;
                        var sMsgSignature  = context.HttpContext.Request.Query["msg_signature"];
                        var sTimeStamp     = context.HttpContext.Request.Query["timestamp"];
                        var sNonce         = context.HttpContext.Request.Query["nonce"];
                        var ret            = _crypt.DecryptMsg(sMsgSignature, sTimeStamp, sNonce, encryptMessage.EncryptMessage, ref plainMessage);
                        if (ret == 0)
                        {
                            using (var stringStream = new MemoryStream(encoding.GetBytes(plainMessage)))
                                using (var stringReader = CreateXmlReader(stringStream, encoding))
                                {
                                    inputRequestMessage = RequestMessageFactory.CreateRequestMessage(stringReader);
                                }
                        }
                    }

                    return(InputFormatterResult.Success(inputRequestMessage));
                }
            }

            return(await base.ReadRequestBodyAsync(context, encoding));
        }
        /// <summary>
        /// Ensure we can read the <paramref name="request"/> body without messing up JSON etc. deserialization. Body
        /// will be read at least twice in most receivers.
        /// </summary>
        /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param>
        /// <returns>A <see cref="Task"/> that on completion will have prepared the request body.</returns>
        public async Task PrepareRequestBody(HttpRequest request)
        {
            if (!request.Body.CanSeek)
            {
                BufferingHelper.EnableRewind(request);
                Debug.Assert(request.Body.CanSeek);

                await request.Body.DrainAsync(CancellationToken.None);
            }

            // Always start at the beginning.
            request.Body.Seek(0L, SeekOrigin.Begin);
        }
        /// <inheritdoc />
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(
            InputFormatterContext context,
            Encoding encoding)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            var request = context.HttpContext.Request;

            if (!request.Body.CanSeek && !_suppressInputFormatterBuffering)
            {
                // XmlSerializer does synchronous reads. In order to avoid blocking on the stream, we asynchronously
                // read everything into a buffer, and then seek back to the beginning.
                BufferingHelper.EnableRewind(request);
                Debug.Assert(request.Body.CanSeek);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), encoding))
            {
                var type = GetSerializableType(context.ModelType);

                var serializer = GetCachedSerializer(type);

                var deserializedObject = serializer.Deserialize(xmlReader);

                // Unwrap only if the original type was wrapped.
                if (type != context.ModelType)
                {
                    if (deserializedObject is IUnwrappable unwrappable)
                    {
                        deserializedObject = unwrappable.Unwrap(declaredType: context.ModelType);
                    }
                }

                return(InputFormatterResult.Success(deserializedObject));
            }
        }
Ejemplo n.º 8
0
        private void Close()
        {
            if (_MediaStreamSource != null)
            {
                _MediaStreamSource.Starting        -= OnStarting;
                _MediaStreamSource.SampleRequested -= OnSampleRequested;

                _MediaStreamSource = null;
            }
            if (_Stream != null)
            {
                _Stream.Attached      -= OnAttached;
                _Stream.StatusUpdated -= OnNetStreamStatusUpdated;
                _Stream.AudioStarted  -= OnAudioStarted;
                _Stream.VideoStarted  -= OnVideoStarted;
                _Stream = null;
            }
            if (_BufferingHelper != null)
            {
                _BufferingHelper.Stop();
                _BufferingHelper = null;
            }


            if (_Connection != null)
            {
                _Connection.StatusUpdated -= OnNetConnectionStatusUpdated;
                try
                {
                    _Connection.Close();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                }
                finally
                {
                    _Connection = null;
                }
            }

            _IsClosed = true;

            Debug.WriteLine($"RTMP : {ClientId} closed.");
        }
        /// <summary>
        /// Ensure we can read the <paramref name="request"/> body without messing up JSON etc. deserialization. Body
        /// will be read at least twice in most WebHook receivers.
        /// </summary>
        /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param>
        /// <returns>A <see cref="Task"/> that on completion will have prepared the request body.</returns>
        public static async Task PrepareRequestBody(HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (!request.Body.CanSeek)
            {
                BufferingHelper.EnableRewind(request);
                Debug.Assert(request.Body.CanSeek);

                await request.Body.DrainAsync(CancellationToken.None);
            }

            // Always start at the beginning.
            request.Body.Seek(0L, SeekOrigin.Begin);
        }
Ejemplo n.º 10
0
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
        {
            EnsureArg.IsNotNull(context);

            var request = context.HttpContext.Request;

            if (!request.Body.CanSeek)
            {
                BufferingHelper.EnableRewind(request);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            var result = MessagePackSerializer.NonGeneric.Deserialize(context.ModelType, request.Body, _resolver);

            return(await InputFormatterResult.SuccessAsync(result));
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Ensure the <paramref name="request"/> <see cref="HttpRequest.Body"/> can be read multiple times. Normally
 /// buffers request bodies in memory; writes requests larger than <paramref name="bufferThreshold"/> bytes to
 /// disk.
 /// </summary>
 /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param>
 /// <param name="bufferThreshold">
 /// The maximum size in bytes of the in-memory <see cref="System.Buffers.ArrayPool{Byte}"/> used to buffer the
 /// stream. Larger request bodies are written to disk.
 /// </param>
 /// <param name="bufferLimit">
 /// The maximum size in bytes of the request body. An attempt to read beyond this limit will cause an
 /// <see cref="System.IO.IOException"/>.
 /// </param>
 /// <remarks>
 /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c>
 /// environment variable, if any. If that environment variable is not defined, these files are written to the
 /// current user's temporary folder. Files are automatically deleted at the end of their associated requests.
 /// </remarks>
 public static void EnableBuffering(this HttpRequest request, int bufferThreshold, long bufferLimit)
 {
     BufferingHelper.EnableRewind(request, bufferThreshold, bufferLimit);
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Ensure the <paramref name="request"/> <see cref="HttpRequest.Body"/> can be read multiple times. Normally
 /// buffers request bodies in memory; writes requests larger than 30K bytes to disk.
 /// </summary>
 /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param>
 /// <remarks>
 /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c>
 /// environment variable, if any. If that environment variable is not defined, these files are written to the
 /// current user's temporary folder. Files are automatically deleted at the end of their associated requests.
 /// </remarks>
 public static void EnableBuffering(this HttpRequest request)
 {
     BufferingHelper.EnableRewind(request);
 }
Ejemplo n.º 13
0
        /// <inheritdoc />
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(
            InputFormatterContext context,
            Encoding encoding)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            var request = context.HttpContext.Request;

            if (!request.Body.CanSeek && !_suppressInputFormatterBuffering)
            {
                // JSON.Net does synchronous reads. In order to avoid blocking on the stream, we asynchronously
                // read everything into a buffer, and then seek back to the beginning.
                BufferingHelper.EnableRewind(request);
                Debug.Assert(request.Body.CanSeek);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            using (var streamReader = context.ReaderFactory(request.Body, encoding))
            {
                using (var jsonReader = new JsonTextReader(streamReader))
                {
                    jsonReader.ArrayPool  = _charPool;
                    jsonReader.CloseInput = false;

                    var       successful = true;
                    Exception exception  = null;
                    void ErrorHandler(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs eventArgs)
                    {
                        successful = false;

                        // Handle path combinations such as "" + "Property", "Parent" + "Property", or "Parent" + "[12]".
                        var key = eventArgs.ErrorContext.Path;

                        if (!string.IsNullOrEmpty(context.ModelName))
                        {
                            if (string.IsNullOrEmpty(eventArgs.ErrorContext.Path))
                            {
                                key = context.ModelName;
                            }
                            else if (eventArgs.ErrorContext.Path[0] == '[')
                            {
                                key = context.ModelName + eventArgs.ErrorContext.Path;
                            }
                            else
                            {
                                key = context.ModelName + "." + eventArgs.ErrorContext.Path;
                            }
                        }

                        var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path);

                        context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata);

                        _logger.JsonInputException(eventArgs.ErrorContext.Error);

                        exception = eventArgs.ErrorContext.Error;

                        // Error must always be marked as handled
                        // Failure to do so can cause the exception to be rethrown at every recursive level and
                        // overflow the stack for x64 CLR processes
                        eventArgs.ErrorContext.Handled = true;
                    }

                    var type           = context.ModelType;
                    var jsonSerializer = CreateJsonSerializer();
                    jsonSerializer.Error += ErrorHandler;
                    object model;
                    try
                    {
                        model = jsonSerializer.Deserialize(jsonReader, type);
                    }
                    finally
                    {
                        // Clean up the error handler since CreateJsonSerializer() pools instances.
                        jsonSerializer.Error -= ErrorHandler;
                        ReleaseJsonSerializer(jsonSerializer);
                    }

                    if (successful)
                    {
                        if (model == null && !context.TreatEmptyInputAsDefaultValue)
                        {
                            // Some nonempty inputs might deserialize as null, for example whitespace,
                            // or the JSON-encoded value "null". The upstream BodyModelBinder needs to
                            // be notified that we don't regard this as a real input so it can register
                            // a model binding error.
                            return(InputFormatterResult.NoValue());
                        }
                        else
                        {
                            return(InputFormatterResult.Success(model));
                        }
                    }

                    if (!(exception is JsonException || exception is OverflowException))
                    {
                        var exceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception);
                        exceptionDispatchInfo.Throw();
                    }

                    return(InputFormatterResult.Failure());
                }
            }
        }
Ejemplo n.º 14
0
        public async Task Invoke(HttpContext httpContext)
        {
            BufferingHelper.EnableRewind(httpContext.Request);

            if (!httpContext.Request.Headers.Keys.Contains("Signature") ||
                !httpContext.Request.Headers.Keys.Contains("SignatureCertChainUrl"))
            {
                _logger.LogError(SignatureHeadersMissing);

                httpContext.Response.StatusCode = 400; // Bad Request
                await httpContext.Response.WriteAsync(SignatureHeadersMissing);

                return;
            }

            var sigCertChainUrl = httpContext.Request.Headers["SignatureCertChainUrl"];
            var certChainUrl    = sigCertChainUrl.Any()
                ? sigCertChainUrl.First()
                : string.Empty;

            if (string.IsNullOrWhiteSpace(certChainUrl))
            {
                _logger.LogError(SignatureChainUrlEmpty);

                httpContext.Response.StatusCode = 400; // Bad Request
                await httpContext.Response.WriteAsync(SignatureChainUrlEmpty);

                return;
            }

            // https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem
            var certUri = new Uri(certChainUrl);

            if (!((certUri.Port == 443 || certUri.IsDefaultPort) &&
                  certUri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)))
            {
                _logger.LogError(MustUseHttps);

                httpContext.Response.StatusCode = 400; // Bad Request
                await httpContext.Response.WriteAsync(MustUseHttps);

                return;
            }

            if (!certUri.Host.Equals(ValidHostName, StringComparison.OrdinalIgnoreCase))
            {
                _logger.LogError(InvalidHostName);

                httpContext.Response.StatusCode = 400; // Bad Request
                await httpContext.Response.WriteAsync(InvalidHostName);

                return;
            }

            if (!certUri.AbsolutePath.StartsWith("/echo.api/"))
            {
                _logger.LogError(InvalidCertificatePath);

                httpContext.Response.StatusCode = 400; // Bad Request
                await httpContext.Response.WriteAsync(InvalidCertificatePath);

                return;
            }

            using (var client = new WebClient())
            {
                var certData    = client.DownloadData(certUri);
                var certificate = new X509Certificate2(certData);

                if (certificate.NotBefore > DateTime.UtcNow)
                {
                    _logger.LogError(CertificateNotYetEffective);

                    httpContext.Response.StatusCode = 400; // Bad Request
                    await httpContext.Response.WriteAsync(CertificateNotYetEffective);

                    return;
                }

                if (certificate.NotAfter <= DateTime.UtcNow)
                {
                    _logger.LogError(CertificateExpired);

                    httpContext.Response.StatusCode = 400; // Bad Request
                    await httpContext.Response.WriteAsync(CertificateExpired);

                    return;
                }

                if (!certificate.Subject.Contains("CN=echo-api.amazon.com"))
                {
                    _logger.LogError(CertificateInvalidIssuer);

                    httpContext.Response.StatusCode = 400; // Bad Request
                    await httpContext.Response.WriteAsync(CertificateInvalidIssuer);

                    return;
                }

                // ToDo: All certificates in the chain combine to create a
                // chain of trust to a trusted root CA certificate
                var certificateChain = new X509Chain
                {
                    ChainPolicy =
                    {
                        RevocationMode = X509RevocationMode.NoCheck
                    }
                };

                var hasChainToTrustedCA = certificateChain.Build(certificate);

                if (!hasChainToTrustedCA)
                {
                    _logger.LogError(InvalidCertificateChain);

                    httpContext.Response.StatusCode = 400; // Bad Request
                    await httpContext.Response.WriteAsync(InvalidCertificateChain);

                    return;
                }

                try
                {
                    var signature       = httpContext.Request.Headers["Signature"];
                    var signatureString = signature.Any()
                        ? signature.First()
                        : string.Empty;

                    _logger.LogInformation($"Sig = >>{signatureString}<<");

                    byte[] signatureDecoded = Convert.FromBase64String(signatureString);

                    var hasher = SHA1.Create();
                    var body   = await httpContext.Request.ReadHttpRequestBodyAsync();

                    httpContext.Request.Body.Position = 0; // Reset

                    var hashedBody = hasher.ComputeHash(Encoding.UTF8.GetBytes(body));

                    using (var rsaPublicKey = certificate.GetRSAPublicKey())
                    {
                        var isHashValid = rsaPublicKey.VerifyHash(hashedBody, signatureDecoded, HashAlgorithmName.SHA1,
                                                                  RSASignaturePadding.Pkcs1);

                        _logger.LogInformation($"Is Hash Valid Response: {isHashValid}");

                        if (rsaPublicKey == null || !isHashValid)
                        {
                            _logger.LogError(InvalidCertificateKey);

                            httpContext.Response.StatusCode = 400; // Bad Request
                            await httpContext.Response.WriteAsync(InvalidCertificateKey);

                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message);
                    httpContext.Response.StatusCode = 400; // Bad Request
                    await httpContext.Response.WriteAsync(ex.Message);

                    return;
                }
            }

            _logger.LogInformation("******************* VALIDATED *******************");

            await _next(httpContext);
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Ensure the <paramref name="request"/> <see cref="ProtoRequest.Body"/> can be read multiple times. Normally
 /// buffers request bodies in memory; writes requests larger than 30K bytes to disk.
 /// </summary>
 /// <param name="request">The <see cref="ProtoRequest"/> to prepare.</param>
 /// <param name="bufferLimit">
 /// The maximum size in bytes of the request body. An attempt to read beyond this limit will cause an
 /// <see cref="System.IO.IOException"/>.
 /// </param>
 /// <remarks>
 /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c>
 /// environment variable, if any. If that environment variable is not defined, these files are written to the
 /// current user's temporary folder. Files are automatically deleted at the end of their associated requests.
 /// </remarks>
 public static void EnableBuffering(this ProtoRequest request, long bufferLimit)
 {
     BufferingHelper.EnableRewind(request, bufferLimit: bufferLimit);
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Ensure the <paramref name="request"/> <see cref="ProtoRequest.Body"/> can be read multiple times. Normally
 /// buffers request bodies in memory; writes requests larger than <paramref name="bufferThreshold"/> bytes to
 /// disk.
 /// </summary>
 /// <param name="request">The <see cref="ProtoRequest"/> to prepare.</param>
 /// <param name="bufferThreshold">
 /// The maximum size in bytes of the in-memory <see cref="System.Buffers.ArrayPool{Byte}"/> used to buffer the
 /// stream. Larger request bodies are written to disk.
 /// </param>
 /// <remarks>
 /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c>
 /// environment variable, if any. If that environment variable is not defined, these files are written to the
 /// current user's temporary folder. Files are automatically deleted at the end of their associated requests.
 /// </remarks>
 public static void EnableBuffering(this ProtoRequest request, int bufferThreshold)
 {
     BufferingHelper.EnableRewind(request, bufferThreshold);
 }