public async Task TlsHandshakeRejectsTlsLessThan12() { await using (var server = new TestServer(context => { var tlsFeature = context.Features.Get <ITlsApplicationProtocolFeature>(); Assert.NotNull(tlsFeature); Assert.Equal(tlsFeature.ApplicationProtocol, SslApplicationProtocol.Http2.Protocol); return(context.Response.WriteAsync("hello world " + context.Request.Protocol)); }, new TestServiceContext(LoggerFactory), listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; listenOptions.UseHttps(_x509Certificate2, httpsOptions => { #pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete httpsOptions.SslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12; #pragma warning restore SYSLIB0039 }); })) { using (var connection = server.CreateConnection()) { var sslStream = new SslStream(connection.Stream); await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions { TargetHost = "localhost", RemoteCertificateValidationCallback = (_, __, ___, ____) => true, ApplicationProtocols = new List <SslApplicationProtocol> { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }, #pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete EnabledSslProtocols = SslProtocols.Tls11, // Intentionally less than the required 1.2 #pragma warning restore SYSLIB0039 }, CancellationToken.None); var reader = PipeReaderFactory.CreateFromStream(PipeOptions.Default, sslStream, CancellationToken.None); await WaitForConnectionErrorAsync(reader, ignoreNonGoAwayFrames : false, expectedLastStreamId : 0, expectedErrorCode : Http2ErrorCode.INADEQUATE_SECURITY); reader.Complete(); } } }
private async Task ProcessEventStream(IDuplexPipe application, HttpResponseMessage response, CancellationToken cancellationToken) { Log.StartReceive(_logger); using (response) using (var stream = await response.Content.ReadAsStreamAsync()) { var options = new PipeOptions(pauseWriterThreshold: 0, resumeWriterThreshold: 0); var reader = PipeReaderFactory.CreateFromStream(options, stream, cancellationToken); try { while (true) { var result = await reader.ReadAsync(); var buffer = result.Buffer; var consumed = buffer.Start; var examined = buffer.End; try { if (result.IsCanceled) { Log.ReceiveCanceled(_logger); break; } if (!buffer.IsEmpty) { Log.ParsingSSE(_logger, buffer.Length); var parseResult = _parser.ParseMessage(buffer, out consumed, out examined, out var message); FlushResult flushResult = default; switch (parseResult) { case ServerSentEventsMessageParser.ParseResult.Completed: Log.MessageToApplication(_logger, message.Length); flushResult = await _application.Output.WriteAsync(message); _parser.Reset(); break; case ServerSentEventsMessageParser.ParseResult.Incomplete: if (result.IsCompleted) { throw new FormatException("Incomplete message."); } break; } // We canceled in the middle of applying back pressure // or if the consumer is done if (flushResult.IsCanceled || flushResult.IsCompleted) { Log.EventStreamEnded(_logger); break; } } else if (result.IsCompleted) { break; } } finally { reader.AdvanceTo(consumed, examined); } } } catch (Exception ex) { _error = ex; } finally { _application.Output.Complete(_error); Log.ReceiveStopped(_logger); reader.Complete(); } } }
public void Start() { Contract.Assume(!m_processStarted); Encoding reportEncoding = Encoding.Unicode; SafeFileHandle childHandle = null; DetouredProcess detouredProcess = m_detouredProcess; bool useNonDefaultPipeReader = PipeReaderFactory.GetKind() != PipeReaderFactory.Kind.Default; using (m_reportReaderSemaphore.AcquireSemaphore()) { NamedPipeServerStream pipeStream = null; SafeFileHandle reportHandle = null; try { if (useNonDefaultPipeReader) { pipeStream = Pipes.CreateNamedPipeServerStream( PipeDirection.In, PipeOptions.Asynchronous, PipeOptions.None, out childHandle); } else { Pipes.CreateInheritablePipe( Pipes.PipeInheritance.InheritWrite, Pipes.PipeFlags.ReadSideAsync, readHandle: out reportHandle, writeHandle: out childHandle); } var setup = new FileAccessSetup { ReportPath = "#" + childHandle.DangerousGetHandle().ToInt64(), DllNameX64 = s_binaryPaths.DllNameX64, DllNameX86 = s_binaryPaths.DllNameX86, }; bool debugFlagsMatch = true; ArraySegment <byte> manifestBytes = new ArraySegment <byte>(); if (m_fileAccessManifest != null) { manifestBytes = m_fileAccessManifest.GetPayloadBytes(m_loggingContext, setup, FileAccessManifestStream, m_timeoutMins, ref debugFlagsMatch); } if (!debugFlagsMatch) { throw new BuildXLException("Mismatching build type for BuildXL and DetoursServices.dll."); } m_standardInputTcs = TaskSourceSlim.Create <bool>(); detouredProcess.Start( s_payloadGuid, manifestBytes, childHandle, s_binaryPaths.DllNameX64, s_binaryPaths.DllNameX86); // At this point, we believe calling 'kill' will result in an eventual callback for job teardown. // This knowledge is significant for ensuring correct cleanup if we did vs. did not start a process; // if started, we expect teardown to happen eventually and clean everything up. m_processStarted = true; ProcessId = detouredProcess.GetProcessId(); } catch (AccessViolationException) { int ramPercent = 0, availableRamMb = 0, availablePageFileMb = 0, totalPageFileMb = 0; MEMORYSTATUSEX memoryStatusEx = new MEMORYSTATUSEX(); if (GlobalMemoryStatusEx(memoryStatusEx)) { ramPercent = (int)memoryStatusEx.dwMemoryLoad; availableRamMb = new FileSize(memoryStatusEx.ullAvailPhys).MB; availablePageFileMb = new FileSize(memoryStatusEx.ullAvailPageFile).MB; totalPageFileMb = new FileSize(memoryStatusEx.ullTotalPageFile).MB; } string memUsage = $"RamPercent: {ramPercent}, AvailableRamMb: {availableRamMb}, AvailablePageFileMb: {availablePageFileMb}, TotalPageFileMb: {totalPageFileMb}"; Native.Tracing.Logger.Log.DetouredProcessAccessViolationException(m_loggingContext, (m_reports?.PipDescription ?? "") + " - " + memUsage); throw; } finally { // release memory m_fileAccessManifest = null; // Note that in the success path, childHandle should already be closed (by Start). if (childHandle != null && !childHandle.IsInvalid) { childHandle.Dispose(); } } StreamDataReceived reportLineReceivedCallback = m_reports == null ? null : ReportLineReceived; if (useNonDefaultPipeReader) { m_reportReader = PipeReaderFactory.CreateNonDefaultPipeReader( pipeStream, message => reportLineReceivedCallback(message), reportEncoding, m_bufferSize); } else { var reportFile = AsyncFileFactory.CreateAsyncFile( reportHandle, FileDesiredAccess.GenericRead, ownsHandle: true, kind: FileKind.Pipe); m_reportReader = new AsyncPipeReader( reportFile, reportLineReceivedCallback, reportEncoding, m_bufferSize, numOfRetriesOnCancel: m_numRetriesPipeReadOnCancel, debugPipeReporter: new AsyncPipeReader.DebugReporter(errorMsg => DebugPipeConnection($"ReportReader: {errorMsg}"))); } m_reportReader.BeginReadLine(); } // don't wait, we want feeding in of standard input to happen asynchronously Analysis.IgnoreResult(FeedStandardInputAsync(detouredProcess, m_standardInputReader, m_standardInputTcs)); }
public ProcessTreeContext( Guid payloadGuid, SafeHandle reportPipe, ArraySegment <byte> payload, string dllNameX64, string dllNameX86, int numRetriesPipeReadOnCancel, Action <string> debugPipeReporter, LoggingContext loggingContext) { // We cannot create this object in a wow64 process Contract.Assume( !ProcessUtilities.IsWow64Process(), "ProcessTreeContext:ctor - Cannot run injection server in a wow64 32 bit process"); SafeFileHandle childHandle = null; m_loggingContext = loggingContext; NamedPipeServerStream serverStream = null; bool useNonDefaultPipeReader = PipeReaderFactory.GetKind() != PipeReaderFactory.Kind.Default; // This object will be the server for the tree. CreateSourceFile the pipe server. try { SafeFileHandle injectorHandle = null; if (useNonDefaultPipeReader) { serverStream = Pipes.CreateNamedPipeServerStream( PipeDirection.In, PipeOptions.Asynchronous, PipeOptions.None, out childHandle); } else { // Create a pipe for the requests Pipes.CreateInheritablePipe(Pipes.PipeInheritance.InheritWrite, Pipes.PipeFlags.ReadSideAsync, out injectorHandle, out childHandle); } // Create the injector. This will duplicate the handles. Injector = ProcessUtilities.CreateProcessInjector(payloadGuid, childHandle, reportPipe, dllNameX86, dllNameX64, payload); if (useNonDefaultPipeReader) { m_injectionRequestReader = PipeReaderFactory.CreateNonDefaultPipeReader( serverStream, InjectCallback, Encoding.Unicode, BufferSize); } else { // Create the request reader. We don't start listening until requested var injectionRequestFile = AsyncFileFactory.CreateAsyncFile( injectorHandle, FileDesiredAccess.GenericRead, ownsHandle: true, kind: FileKind.Pipe); m_injectionRequestReader = new AsyncPipeReader( injectionRequestFile, InjectCallback, Encoding.Unicode, BufferSize, numOfRetriesOnCancel: numRetriesPipeReadOnCancel, debugPipeReporter: new AsyncPipeReader.DebugReporter(debugMsg => debugPipeReporter?.Invoke($"InjectionRequestReader: {debugMsg}"))); } } catch (Exception exception) { if (Injector != null) { Injector.Dispose(); Injector = null; } if (m_injectionRequestReader != null) { m_injectionRequestReader.Dispose(); m_injectionRequestReader = null; } throw new BuildXLException("Process Tree Context injector could not be created", exception); } finally { // Release memory. Since the child handle is duplicated, it can be released if (childHandle != null && !childHandle.IsInvalid) { childHandle.Dispose(); } } }