internal bool ValidateRequest(NativeRequestContext requestMemory) { try { // Block potential DOS attacks if (requestMemory.UnknownHeaderCount > UnknownHeaderLimit) { SendError(requestMemory.RequestId, StatusCodes.Status400BadRequest, authChallenges: null); return(false); } if (!Options.Authentication.AllowAnonymous && !requestMemory.CheckAuthenticated()) { SendError(requestMemory.RequestId, StatusCodes.Status401Unauthorized, AuthenticationManager.GenerateChallenges(Options.Authentication.Schemes)); return(false); } } catch (Exception ex) { Log.RequestValidationFailed(Logger, ex, requestMemory.RequestId); return(false); } return(true); }
internal void AllocateNativeRequest(uint?size = null, ulong requestId = 0) { _nativeRequestContext?.ReleasePins(); _nativeRequestContext?.Dispose(); //Debug.Assert(size != 0, "unexpected size"); // We can't reuse overlapped objects uint newSize = size.HasValue ? size.Value : DefaultBufferSize; var backingBuffer = new byte[newSize + AlignmentPadding]; var boundHandle = Server.RequestQueue.BoundHandle; var nativeOverlapped = new SafeNativeOverlapped(boundHandle, boundHandle.AllocateNativeOverlapped(IOCallback, this, backingBuffer)); var requestAddress = Marshal.UnsafeAddrOfPinnedArrayElement(backingBuffer, 0); // TODO: // Apparently the HttpReceiveHttpRequest memory alignment requirements for non - ARM processors // are different than for ARM processors. We have seen 4 - byte - aligned buffers allocated on // virtual x64/x86 machines which were accepted by HttpReceiveHttpRequest without errors. In // these cases the buffer alignment may cause reading values at invalid offset. Setting buffer // alignment to 0 for now. // // _bufferAlignment = (int)(requestAddress.ToInt64() & 0x07); var bufferAlignment = 0; var nativeRequest = (HttpApiTypes.HTTP_REQUEST *)(requestAddress + bufferAlignment); // nativeRequest _nativeRequestContext = new NativeRequestContext(nativeOverlapped, bufferAlignment, nativeRequest, backingBuffer, requestId); }
internal Request(RequestContext requestContext, NativeRequestContext nativeRequestContext) { // TODO: Verbose log RequestContext = requestContext; _nativeRequestContext = nativeRequestContext; _contentBoundaryType = BoundaryType.None; RequestId = nativeRequestContext.RequestId; UConnectionId = nativeRequestContext.ConnectionId; SslStatus = nativeRequestContext.SslStatus; KnownMethod = nativeRequestContext.VerbId; Method = _nativeRequestContext.GetVerb(); RawUrl = nativeRequestContext.GetRawUrl(); var cookedUrl = nativeRequestContext.GetCookedUrl(); QueryString = cookedUrl.GetQueryString() ?? string.Empty; var prefix = requestContext.Server.Options.UrlPrefixes.GetPrefix((int)nativeRequestContext.UrlContext); var rawUrlInBytes = _nativeRequestContext.GetRawUrlInBytes(); var originalPath = RequestUriBuilder.DecodeAndUnescapePath(rawUrlInBytes); // 'OPTIONS * HTTP/1.1' if (KnownMethod == HttpApiTypes.HTTP_VERB.HttpVerbOPTIONS && string.Equals(RawUrl, "*", StringComparison.Ordinal)) { PathBase = string.Empty; Path = string.Empty; } // These paths are both unescaped already. else if (originalPath.Length == prefix.Path.Length - 1) { // They matched exactly except for the trailing slash. PathBase = originalPath; Path = string.Empty; } else { // url: /base/path, prefix: /base/, base: /base, path: /path // url: /, prefix: /, base: , path: / PathBase = originalPath.Substring(0, prefix.Path.Length - 1); Path = originalPath.Substring(prefix.Path.Length - 1); } ProtocolVersion = _nativeRequestContext.GetVersion(); Headers = new RequestHeaders(_nativeRequestContext); User = _nativeRequestContext.GetUser(); // GetTlsTokenBindingInfo(); TODO: https://github.com/aspnet/HttpSysServer/issues/231 // Finished directly accessing the HTTP_REQUEST structure. _nativeRequestContext.ReleasePins(); // TODO: Verbose log parameters }
internal RequestContext(HttpSysListener server, NativeRequestContext memoryBlob) { // TODO: Verbose log Server = server; _memoryBlob = memoryBlob; Request = new Request(this, _memoryBlob); Response = new Response(this); AllowSynchronousIO = server.Options.AllowSynchronousIO; }
internal unsafe bool ValidateAuth(NativeRequestContext requestMemory) { if (!Options.Authentication.AllowAnonymous && !requestMemory.CheckAuthenticated()) { SendError(requestMemory.RequestId, StatusCodes.Status401Unauthorized, AuthenticationManager.GenerateChallenges(Options.Authentication.Schemes)); return(false); } return(true); }
internal unsafe bool ValidateRequest(NativeRequestContext requestMemory) { // Block potential DOS attacks if (requestMemory.UnknownHeaderCount > UnknownHeaderLimit) { SendError(requestMemory.RequestId, StatusCodes.Status400BadRequest, authChallenges: null); return(false); } return(true); }
internal Request(RequestContext requestContext, NativeRequestContext nativeRequestContext) { // TODO: Verbose log RequestContext = requestContext; _nativeRequestContext = nativeRequestContext; _contentBoundaryType = BoundaryType.None; RequestId = nativeRequestContext.RequestId; UConnectionId = nativeRequestContext.ConnectionId; SslStatus = nativeRequestContext.SslStatus; KnownMethod = nativeRequestContext.VerbId; Method = _nativeRequestContext.GetVerb(); RawUrl = nativeRequestContext.GetRawUrl(); var cookedUrl = nativeRequestContext.GetCookedUrl(); QueryString = cookedUrl.GetQueryString() ?? string.Empty; var rawUrlInBytes = _nativeRequestContext.GetRawUrlInBytes(); var originalPath = RequestUriBuilder.DecodeAndUnescapePath(rawUrlInBytes); // 'OPTIONS * HTTP/1.1' if (KnownMethod == HttpApiTypes.HTTP_VERB.HttpVerbOPTIONS && string.Equals(RawUrl, "*", StringComparison.Ordinal)) { PathBase = string.Empty; Path = string.Empty; } else if (requestContext.Server.RequestQueue.Created) { var prefix = requestContext.Server.Options.UrlPrefixes.GetPrefix((int)nativeRequestContext.UrlContext); if (originalPath.Length == prefix.PathWithoutTrailingSlash.Length) { // They matched exactly except for the trailing slash. PathBase = originalPath; Path = string.Empty; } else { // url: /base/path, prefix: /base/, base: /base, path: /path // url: /, prefix: /, base: , path: / PathBase = originalPath.Substring(0, prefix.PathWithoutTrailingSlash.Length); // Preserve the user input casing Path = originalPath.Substring(prefix.PathWithoutTrailingSlash.Length); } } else { // When attaching to an existing queue, the UrlContext hint may not match our configuration. Search manualy. if (requestContext.Server.Options.UrlPrefixes.TryMatchLongestPrefix(IsHttps, cookedUrl.GetHost(), originalPath, out var pathBase, out var path)) { PathBase = pathBase; Path = path; }
internal Request(RequestContext requestContext, NativeRequestContext nativeRequestContext) { // TODO: Verbose log RequestContext = requestContext; _nativeRequestContext = nativeRequestContext; _contentBoundaryType = BoundaryType.None; RequestId = nativeRequestContext.RequestId; UConnectionId = nativeRequestContext.ConnectionId; SslStatus = nativeRequestContext.SslStatus; KnownMethod = nativeRequestContext.VerbId; Method = _nativeRequestContext.GetVerb(); RawUrl = nativeRequestContext.GetRawUrl(); var cookedUrl = nativeRequestContext.GetCookedUrl(); QueryString = cookedUrl.GetQueryString() ?? string.Empty; var rawUrlInBytes = _nativeRequestContext.GetRawUrlInBytes(); var originalPath = RequestUriBuilder.DecodeAndUnescapePath(rawUrlInBytes); PathBase = string.Empty; Path = originalPath; // 'OPTIONS * HTTP/1.1' if (KnownMethod == HttpApiTypes.HTTP_VERB.HttpVerbOPTIONS && string.Equals(RawUrl, "*", StringComparison.Ordinal)) { PathBase = string.Empty; Path = string.Empty; } else { var prefix = requestContext.Server.Options.UrlPrefixes.GetPrefix((int)nativeRequestContext.UrlContext); // Prefix may be null if the requested has been transfered to our queue if (!(prefix is null)) { if (originalPath.Length == prefix.PathWithoutTrailingSlash.Length) { // They matched exactly except for the trailing slash. PathBase = originalPath; Path = string.Empty; } else { // url: /base/path, prefix: /base/, base: /base, path: /path // url: /, prefix: /, base: , path: / PathBase = originalPath.Substring(0, prefix.PathWithoutTrailingSlash.Length); // Preserve the user input casing Path = originalPath.Substring(prefix.PathWithoutTrailingSlash.Length); } }
internal void AllocateNativeRequest(uint?size = null, ulong requestId = 0) { _nativeRequestContext?.ReleasePins(); _nativeRequestContext?.Dispose(); // We can't reuse overlapped objects var boundHandle = Server.RequestQueue.BoundHandle; var nativeOverlapped = new SafeNativeOverlapped(boundHandle, boundHandle.AllocateNativeOverlapped(IOCallback, this, pinData: null)); // nativeRequest _nativeRequestContext = new NativeRequestContext(nativeOverlapped, Server.MemoryPool, size, requestId); }
internal RequestHeaders(NativeRequestContext requestMemoryBlob) { _requestMemoryBlob = requestMemoryBlob; }