public async Task <R> Send <P, R>(HttpMethod method, string url, P obj, Func <HttpWebResponse, Task <R> > responseParser) { R result = default(R); await Retry.Do(retryTimes, retryDelay, async() => { var client = await GetHttpClient(url).ConfigureAwait(false); client.Method = method.ToString(); var data = JsonConvert.SerializeObject(obj); using (var content = new StringContent(data)) { client.ContentType = content.Headers.ContentType.ToString(); using (var output = await client.GetRequestStreamAsync().ConfigureAwait(false)) { await content.CopyToAsync(output).ConfigureAwait(false); } } using (var response = (HttpWebResponse)await client.GetResponseAsync().ConfigureAwait(false)) { if (!response.IsSuccessStatusCode()) { return(await LogBadResponse(response).ConfigureAwait(false)); } result = await responseParser(response).ConfigureAwait(false); } return(true); }, GeneralExceptionProcessor).ConfigureAwait(false); return(result); }
public async Task Invoke(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (!verifySuccess || (verifySuccess && (DateTime.Now - preverifyTime).TotalMinutes > 10)) { string msg = LicenseHelper.Verify(); if (!string.IsNullOrEmpty(msg)) { verifySuccess = false; context.Response.ContentType = "application/json"; context.Response.StatusCode = (int)HttpStatusCode.OK; var result = new ApiResult <string> { Code = ResultCode.License_Error, Msg = msg }; var sc = new StringContent(serializer.Serialize(result)); await sc.CopyToAsync(context.Response.Body); } else { verifySuccess = true; preverifyTime = DateTime.Now; await _next.Invoke(context); } } else { await _next.Invoke(context); } }
public Task ExecuteResultAsync(ActionContext context) { var stringContent = new StringContent(statement.ToJson(format), Encoding.UTF8, MediaTypes.Application.Json); if (statement.Attachments.Any(x => x.Payload != null)) { var multipart = new MultipartContent("mixed") { stringContent }; foreach (var attachment in statement.Attachments) { if (attachment.Payload != null) { var byteArrayContent = new ByteArrayContent(attachment.Payload); byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue(attachment.ContentType); byteArrayContent.Headers.Add(ApiHeaders.ContentTransferEncoding, "binary"); byteArrayContent.Headers.Add(ApiHeaders.XExperienceApiHash, attachment.SHA2); multipart.Add(byteArrayContent); } } return(multipart.CopyToAsync(context.HttpContext.Response.Body)); } return(stringContent.CopyToAsync(context.HttpContext.Response.Body)); }
public Task ExecuteResultAsync(ActionContext context) { var stringContent = new StringContent(result.ToJson(format), Encoding.UTF8, MediaTypes.Application.Json); var attachmentsWithPayload = result.Statements.SelectMany(x => x.Attachments.Where(a => a.Payload != null)); if (attachmentsWithPayload.Count() > 0) { string boundary = Guid.NewGuid().ToString(); using var multipart = new MultipartContent("mixed", boundary) { stringContent }; foreach (var attachment in attachmentsWithPayload) { var byteArrayContent = new ByteArrayContent(attachment.Payload); var attachmentMediaType = MediaTypeHeaderValue.Parse(attachment.ContentType); byteArrayContent.Headers.ContentType = attachmentMediaType; byteArrayContent.Headers.Add(ApiHeaders.ContentTransferEncoding, "binary"); byteArrayContent.Headers.Add(ApiHeaders.XExperienceApiHash, attachment.SHA2); multipart.Add(byteArrayContent); } // Write Content-Type header with Boundary parameter var mediaType = MediaTypeHeaderValue.Parse(MediaTypes.Multipart.Mixed); mediaType.Parameters.Add(new NameValueHeaderValue("boundary", boundary)); context.HttpContext.Response.ContentType = mediaType.ToString(); return(multipart.CopyToAsync(context.HttpContext.Response.Body)); } return(stringContent.CopyToAsync(context.HttpContext.Response.Body)); }
public async Task ExecuteResultAsync(ActionContext context) { StringContent content = new StringContent(JsonConvert.SerializeObject(this)); context.HttpContext.Response.Headers.Add("content-type", "application/json"); context.HttpContext.Response.StatusCode = (int)this.StatusCode; await content.CopyToAsync(context.HttpContext.Response.Body); }
public void CopyToAsync() { var sc = new StringContent("gt"); var dest = new MemoryStream(); var task = sc.CopyToAsync(dest); task.Wait(); Assert.AreEqual(2, dest.Length, "#1"); }
public void CopyToAsync_Invalid() { var sc = new StringContent(""); try { sc.CopyToAsync(null); Assert.Fail("#1"); } catch (ArgumentNullException) { } }
public async Task Ctor_UseCustomEncodingAndMediaType_EncodingUsedAndContentTypeHeaderUpdated() { // Use UTF-8 encoding to serialize a chinese string. string sourceString = "\u4f1a\u5458\u670d\u52a1"; var content = new StringContent(sourceString, Encoding.UTF8, "application/custom"); Assert.Equal("application/custom", content.Headers.ContentType.MediaType); Assert.Equal("utf-8", content.Headers.ContentType.CharSet); var destination = new MemoryStream(12); await content.CopyToAsync(destination); string destinationString = Encoding.UTF8.GetString(destination.ToArray(), 0, (int)destination.Length); Assert.Equal(sourceString, destinationString); }
public async Task ExecuteResultAsync(ActionContext context) { StringContent content = new StringContent(JsonConvert.SerializeObject(this)); context.HttpContext.Response.Headers.Add("content-type", "application/json"); if (this.AutoAssignHttpStatusCode && this.Validations?.Count > 0) { this.SetToUnprocessableEntity("Unprocessable entity"); context.HttpContext.Response.StatusCode = (int)this.HttpStatusCode; } else { context.HttpContext.Response.StatusCode = (int)this.HttpStatusCode; } await content.CopyToAsync(context.HttpContext.Response.Body); }
private async Task <StreamContent> CompressAsync(StringContent content) { var ms = new MemoryStream(); using (var gzipStream = new GZipStream(ms, CompressionMode.Compress, true)) { await content.CopyToAsync(gzipStream); await gzipStream.FlushAsync(); } ms.Position = 0; var compressedStreamContent = new StreamContent(ms); compressedStreamContent.Headers.ContentType = new MediaTypeHeaderValue(_contentType.MimeType()); compressedStreamContent.Headers.Add("Content-Encoding", "gzip"); return(compressedStreamContent); }
public async Task Ctor_DefineNoEncoding_DefaultEncodingUsed() { string sourceString = "\u00C4\u00E4\u00FC\u00DC"; var content = new StringContent(sourceString); Encoding defaultStringEncoding = Encoding.GetEncoding("utf-8"); // If no encoding is defined, the default encoding is used: utf-8 Assert.Equal("text/plain", content.Headers.ContentType.MediaType); Assert.Equal(defaultStringEncoding.WebName, content.Headers.ContentType.CharSet); // Make sure the default encoding is also used when serializing the content. var destination = new MemoryStream(); await content.CopyToAsync(destination); Assert.Equal(8, destination.Length); destination.Seek(0, SeekOrigin.Begin); string roundTrip = new StreamReader(destination, defaultStringEncoding).ReadToEnd(); Assert.Equal(sourceString, roundTrip); }
public async Task InvokeAsync(HttpContext context, IWebHostEnvironment webHostEnvironment) { var cancellationToken = context.RequestAborted; var requestEncoding = _options.RequestEncoding ?? Encoding.UTF8; var excludeUrls = _options.ExcludeUrls; var modifyResponse = excludeUrls == null || !excludeUrls.Any(bl => context.Request.Path.Value != null && context.Request.Path.Value.ToLowerInvariant().Contains(bl)); if (!modifyResponse) { await _next(context); return; } var responseBodyPooledStream = new DisposablePooledStream(_pooledStreamManager, nameof(I18NMiddleware)); context.Response.RegisterForDisposeAsync(responseBodyPooledStream); var httpResponseBodyFeature = context.Features.Get <IHttpResponseBodyFeature>(); var httpResponseFeature = context.Features.Get <IHttpResponseFeature>(); var streamResponseBodyFeature = new StreamResponseBodyFeature(responseBodyPooledStream); context.Features.Set <IHttpResponseBodyFeature>(streamResponseBodyFeature); await _next(context).ConfigureAwait(false); // Force dynamic content type in order reset Content-Length header. httpResponseFeature.Headers.ContentLength = null; var httpResponseBodyStream = (Stream)responseBodyPooledStream; httpResponseBodyStream.Seek(0, SeekOrigin.Begin); var contentType = GetRequestContentType(context); var validContentTypes = _options.ValidContentTypes; var replaceNuggets = validContentTypes != null && validContentTypes.Contains(contentType); if (replaceNuggets) { var requestCultureInfo = GetRequestCultureInfo(context); var cultureDictionary = _localizationManager.GetDictionary(requestCultureInfo, !_options.CacheEnabled); _logger?.LogDebug( $"Request path: {context.Request.Path}. Culture name: {cultureDictionary.CultureName}. Translations: {cultureDictionary.Translations.Count}."); var responseBody = await ReadResponseBodyAsStringAsync(httpResponseBodyStream, requestEncoding); string responseBodyTranslated; if (webHostEnvironment.IsDevelopment()) { var sw = new Stopwatch(); sw.Restart(); responseBodyTranslated = _nuggetReplacer.Replace(cultureDictionary, responseBody); sw.Stop(); _logger?.LogDebug($"Replaced body in {sw.ElapsedMilliseconds} ms."); const string i18NMiddlewareName = "X-" + nameof(I18NMiddleware) + "-Ms"; httpResponseFeature.Headers[i18NMiddlewareName] = sw.ElapsedMilliseconds.ToString(); } else { responseBodyTranslated = _nuggetReplacer.Replace(cultureDictionary, responseBody); } var stringContent = new StringContent(responseBodyTranslated, requestEncoding, contentType); #if NET50 await stringContent.CopyToAsync(httpResponseBodyFeature.Stream, cancellationToke); #else await stringContent.CopyToAsync(httpResponseBodyFeature.Stream); #endif return; } await httpResponseBodyStream.CopyToAsync(httpResponseBodyFeature.Stream, cancellationToken).ConfigureAwait(false); }
/// <summary> /// There are 2 paths through Run() /// /// The primary route is the PageHash JSON protocol that validates hash entries sent by the client /// performs relocations and soforth. /// /// The other sequence is to return a given file that the client wants to manually inspect. /// /// </summary> /// <param name="ctx"></param> /// <param name="name"></param> /// <param name="log"></param> /// <returns></returns> public async static Task Run(HttpContext ctx, string name, ILogger log) { Dictionary <string, string> entries = null; DeLocate rere = null; MemPageHash mph = null; StringContent failure = null; ulong BaseAddress = 0; long content_Len = 0L, RVA = 0L, SecOffset = 0L; var block = new Byte[0x1000]; MiniSection ms = MiniSection.Empty; string modName = string.Empty, targetName = string.Empty, hash = string.Empty; var req = ctx.Request; var resp = ctx.Response; resp.StatusCode = (int)HttpStatusCode.NoContent; try { content_Len = req.ContentLength ?? 0; entries = req.Query.ToDictionary(q => q.Key, q => (string)q.Value); // attempt to just dump back the binary we would of hashed if (req.Method == "GET") { if (!entries.ContainsKey("file") || string.IsNullOrWhiteSpace(entries["file"])) { log.LogWarning($"Get requests require a file parameter, none was sent."); resp.StatusCode = (int)HttpStatusCode.NotFound; return; } var return_file = entries["file"].ToLower(); var ret_file_base = Path.GetFileName(return_file); if (!GoldImages.DiskFiles.ContainsKey(ret_file_base)) { log.LogInformation($"Unknown file requested from client [{ret_file_base}]."); return; } var file_set = GoldImages.DiskFiles[ret_file_base]; foreach (var x in file_set) { if (x.Item3.Substring(2).Equals(return_file.Substring(2), StringComparison.InvariantCultureIgnoreCase)) { resp.StatusCode = (int)HttpStatusCode.OK; targetName = x.Item3; using (var fout = File.Open(targetName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { // return the file rerelocated if (entries.ContainsKey("mapped")) { fout.Read(block, 0, 0x1000); var e = Extract.IsBlockaPE(block); // PS sends this in base 10 var parsed = ulong.TryParse(entries["mapped"], out BaseAddress); log.LogInformation($"Requested relocation address of returned image [{BaseAddress:x}], performing relocations."); if (e.SizeOfHeaders < block.Length) { Buffer.BlockCopy(nullBuff, 0, block, (int)e.SizeOfHeaders, block.Length - (int)e.SizeOfHeaders); } if (e.ImageBase != BaseAddress) { var reRawData = Extract.ExtractRelocData(targetName); if (reRawData != null) { e.ReReState = rere = new DeLocate(e.ImageBase, reRawData); rere.RelocData.Processed = DeLocate.ProcessRelocs(reRawData, null); rere.RelocData.ProcessedArray = rere.RelocData.Processed.ToArray(); } AttemptDelocate(block, e, 0, 0, BaseAddress, rere); } // send header out await resp.Body.WriteAsync(block, 0, 0x1000).ConfigureAwait(false); // loop over the rest of the file RVA += 0x1000; do { for (int i = 0; i < e.NumberOfSections; i++) { if (RVA >= e.Sections[i].VirtualAddress && RVA < (e.Sections[i].VirtualAddress + e.Sections[i].VirtualSize)) { ms = e.Sections[i]; break; } } SecOffset = (RVA - ms.VirtualAddress); fout.Position = ms.RawFilePointer + (RVA - ms.VirtualAddress); fout.Read(block, 0, 0x1000); if (rere != null && e.ImageBase != BaseAddress) { AttemptDelocate(block, e, e.ImageBase - BaseAddress, RVA, e.ImageBase, rere); } await resp.Body.WriteAsync(block, 0, 0x1000).ConfigureAwait(false); RVA += 0x1000; } while (RVA < e.SizeOfImage); } else { await fout.CopyToAsync(resp.Body).ConfigureAwait(false); return; } } } } log.LogTrace("Get request serviced."); return; } } catch (Exception ex) { log.LogWarning($"Handling exception {ex}"); } if (req.Method != "POST") { log.LogWarning($"POST or GET allowed only, client sent {req.Method}"); return; } var rv = new HashSet <PageHashBlockResult>(); var cv = CODEVIEW_HEADER.Init(entries); try { var buffer = new byte[content_Len]; var bytesRead = 0; while (bytesRead < buffer.Length) { var count = await req.Body.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead); bytesRead += count; } log.Log <string>(LogLevel.Trace, new EventId(2, "Read"), $"read post body {bytesRead}", null, (state, ex) => $"{state}"); hash = Encoding.Default.GetString(buffer); // preconfigure return buffer so we will always return FALSE for failure mph = JsonConvert.DeserializeObject <MemPageHash>(hash); if (mph == null) { log.LogWarning($"Client sent a serialized JSON POST content that were unable to handle Data:[{hash}], len:[{content_Len}]"); return; } rv.Add(new PageHashBlockResult() { Address = mph.AllocationBase, HashCheckEquivalant = false }); foreach (var ph in mph.HashSet) { rv.Add(new PageHashBlockResult() { Address = ph.Address, HashCheckEquivalant = false }); } //configure failure case var rx = JsonConvert.SerializeObject(rv, Formatting.Indented); failure = new StringContent(rx, Encoding.Default, "application/json"); // after here we can send 200 back but everything is a fail resp.StatusCode = (int)HttpStatusCode.OK; // sanitation & isolation of file name portion of input string (hopefully:) modName = mph.ModuleName.Split(Path.DirectorySeparatorChar).LastOrDefault(); if (modName.Length <= 3 || modName.Contains("..")) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogWarning($"Client filename [{mph.ModuleName}] invalid or Likely dynamic code at address [{mph.BaseAddress}:x]"); return; } if (!string.IsNullOrWhiteSpace(modName) && modName.Any((x) => x == Path.AltDirectorySeparatorChar || InvalidFileNameChars.Contains(x) || char.IsSurrogate(x) || char.IsSymbol(x) || char.IsControl(x) || x == Path.VolumeSeparatorChar || x == Path.PathSeparator)) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogWarning($"Client filename invalid or possibly evil [{mph.ModuleName}]"); return; } // should be redundant given were already at the last '\\' modName = Path.GetFileName(modName); } catch (Exception ex) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogWarning($"Failure, check exception {ex}"); return; } cv.Name = modName.ToLower(); cv.TimeDateStamp = mph.TimeDateStamp; cv.VSize = mph.ImageSize; log.LogTrace($"Performing lookup on client requested dtails [{mph.ModuleName}] [{cv.TimeDateStamp:x}] [{cv.VSize:x}]"); if (cv.TimeDateStamp == 0 || cv.VSize == 0) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogWarning($"Client timestamp is out of range [{cv.TimeDateStamp:x}]"); return; } // if we do not have this binary locally cached // attempt to retrieve it var localGoldBinaryFound = GoldImages.DiskFiles.ContainsKey(cv.Name); // update targetname if we can find it in the local ngen cache if (localGoldBinaryFound) { log.LogTrace("Found candidates for client integrity check."); localGoldBinaryFound = false; var goldEntries = GoldImages.DiskFiles[cv.Name]; foreach (var ng in goldEntries.Where((x) => x.Item3.Substring(3).Equals(mph.ModuleName.Substring(3), StringComparison.InvariantCultureIgnoreCase))) { if (ng.Item1 == cv.VSize && ng.Item2 == cv.TimeDateStamp) { targetName = ng.Item3; localGoldBinaryFound = true; log.LogInformation($"Matched candiate for client [{targetName}]"); break; } } if (!localGoldBinaryFound) { foreach (var ng in goldEntries) { if (ng.Item1 == cv.VSize && ng.Item2 == cv.TimeDateStamp) { targetName = ng.Item3; localGoldBinaryFound = true; log.LogInformation($"Matched candiate for client {targetName}"); break; } } } } if (!localGoldBinaryFound) { if (!Program.Settings.Host.ProxyToExternalgRoot) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogInformation($"Unable to locate a candiate that fits required criteria to requeted info, find original media for client requested file {modName} and store into golden image filesystem.7"); return; } else // proxy is enabled { if (Program.Settings.External != null && !string.IsNullOrWhiteSpace(Program.Settings.External.gRoot)) { log.LogInformation($"Remote service call started"); resp.StatusCode = (int)HttpStatusCode.OK; try { await WebAPI.ProxyObject(hash, resp.Body); } catch (Exception ex) { log.LogWarning($"exceptoin in calling external gRoot server. {ex}"); resp.StatusCode = (int)HttpStatusCode.NotFound; } log.LogInformation($"External server handled request."); return; } } } // setup connection to desired originating input so we can hash it and determine if // the caller is investigating the same binary using (var fr = new FileStream(targetName, FileMode.Open, FileAccess.Read)) { fr.Read(block, 0, 0x1000); // parse the binary var e = Extract.IsBlockaPE(block); // fatal error if (e == null) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogWarning($"Corrupt image or some failure, unable to determine PE information for request {targetName}"); return; } if (e.SizeOfHeaders < block.Length) { Buffer.BlockCopy(nullBuff, 0, block, (int)e.SizeOfHeaders, block.Length - (int)e.SizeOfHeaders); } var LocalHeaderHash = Convert.ToBase64String(hasher.ComputeHash(block)); var HdrMatch = (mph.HdrHash == LocalHeaderHash); bool NeededHdrDelocate = false; if ((long)e.ImageBase != mph.AllocationBase && !HdrMatch) { var reRawData = Extract.ExtractRelocData(targetName); if (reRawData != null) { e.ReReState = rere = new DeLocate(e.ImageBase, reRawData); rere.RelocData.Processed = DeLocate.ProcessRelocs(reRawData, null); rere.RelocData.ProcessedArray = rere.RelocData.Processed.ToArray(); } AttemptDelocate(block, e, 0, 0, (ulong)mph.AllocationBase, rere); LocalHeaderHash = Convert.ToBase64String(hasher.ComputeHash(block)); HdrMatch = NeededHdrDelocate = (mph.HdrHash == LocalHeaderHash); } var rvenum = rv.GetEnumerator(); // we injected one for the header so move to it here rvenum.MoveNext(); rvenum.Current.HashCheckEquivalant = HdrMatch; // now we have structured access to the file VA's etc.. // go through each hash and match foreach (var h in mph.HashSet) { RVA = h.Address - mph.AllocationBase; if (RVA > uint.MaxValue || RVA < 0) { await failure.CopyToAsync(resp.Body).ConfigureAwait(false); log.LogWarning($"RVA in client JSON request seems invalid, aborting. {RVA:x}"); return; } for (int i = 0; i < e.NumberOfSections; i++) { if (RVA >= e.Sections[i].VirtualAddress && RVA < (e.Sections[i].VirtualAddress + e.Sections[i].VirtualSize)) { ms = e.Sections[i]; break; } } // since RVA is calculated from the AllocationBase, section VA may be anywhere above it // RawFilePointer to get file POS + (RVA - SectionVA) SecOffset = (RVA - ms.VirtualAddress); fr.Position = ms.RawFilePointer + (RVA - ms.VirtualAddress); // we should be file-aligned to the appropriate location to read a page and check the hash now fr.Read(block, 0, 0x1000); var localHashCheck = hasher.ComputeHash(block); var check64 = Convert.ToBase64String(localHashCheck); if (rvenum.MoveNext()) { rvenum.Current.HashCheckEquivalant = (check64 == h.Hash); } if (!rvenum.Current.HashCheckEquivalant && rere != null && e.ImageBase != (ulong)mph.AllocationBase) { AttemptDelocate(block, e, e.ImageBase - (ulong)mph.AllocationBase, RVA, e.ImageBase, rere); check64 = Convert.ToBase64String(hasher.ComputeHash(block)); rvenum.Current.HashCheckEquivalant = (check64 == h.Hash); } } } #if FALSE // find a better way todo this... if (Program.Settings.Host.ProxyFailedOrMissing) { if (rv.Any((x) => !x.HashCheckEquivalant)) { HttpResponseMessage prox_rv = null; log.LogInformation($"At least one hash check failed, ProxyFailedOrMissing check to double check results"); try { prox_rv = WebAPI.POST(hash).Result; } catch (Exception ex) { log.LogWarning($"Error in contacting remote server. {ex}"); } if (prox_rv == null) { return; } try { var prox_data = await prox_rv.Content.ReadAsByteArrayAsync(); var prox_r = JsonConvert.DeserializeObject <HashSet <PageHashBlockResult> >(Encoding.Default.GetString(prox_data)); HashSet <PageHashBlockResult> CombinedLookups = new HashSet <PageHashBlockResult>(); var enumer = rv.GetEnumerator(); enumer.MoveNext(); foreach (var pbr in prox_r) { if (enumer.Current.Address != pbr.Address) { log.LogInformation("Server and local results are not aligne, unable to corolate checks further"); break; } // build combined list checking if local passed, use it, if not use the server result, maybe it passed ? ;) CombinedLookups.Add(enumer.Current.HashCheckEquivalant ? enumer.Current : pbr); enumer.MoveNext(); } log.LogInformation($"Using combined lookups Orig Pass count[{rv.Count((x) => x.HashCheckEquivalant)}] New pass count [{CombinedLookups.Count((x) => x.HashCheckEquivalant)}]"); rv = CombinedLookups; } catch (Exception ex) { log.LogWarning($"Error in corolation processing {ex}"); } } } #endif // since we made it this far we should re-serialize our state since we currently are holding onto // and object that is used for a fast path error exit (all failed) var r = JsonConvert.SerializeObject(rv, Formatting.Indented); resp.StatusCode = 200; var success = new StringContent(r, Encoding.Default, "application/json").CopyToAsync(resp.Body).ConfigureAwait(false); log.LogInformation($"Finished client service call, hash check results sent."); }