diff --git a/src/Servers/Connections.Abstractions/src/Features/ITlsHandshakeFeature.cs b/src/Servers/Connections.Abstractions/src/Features/ITlsHandshakeFeature.cs index 15a99e0efc32..99f82881643c 100644 --- a/src/Servers/Connections.Abstractions/src/Features/ITlsHandshakeFeature.cs +++ b/src/Servers/Connections.Abstractions/src/Features/ITlsHandshakeFeature.cs @@ -29,7 +29,7 @@ public interface ITlsHandshakeFeature /// Gets the host name from the "server_name" (SNI) extension of the client hello if present. /// See RFC 6066. /// - string? HostName => null; + string HostName => string.Empty; #endif /// diff --git a/src/Servers/Connections.Abstractions/src/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Servers/Connections.Abstractions/src/PublicAPI/net8.0/PublicAPI.Unshipped.txt index c689504701db..0bcc937fd8be 100644 --- a/src/Servers/Connections.Abstractions/src/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/Servers/Connections.Abstractions/src/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -6,7 +6,7 @@ Microsoft.AspNetCore.Connections.Features.IConnectionMetricsTagsFeature Microsoft.AspNetCore.Connections.Features.IConnectionMetricsTagsFeature.Tags.get -> System.Collections.Generic.ICollection>! Microsoft.AspNetCore.Connections.Features.IConnectionNamedPipeFeature Microsoft.AspNetCore.Connections.Features.IConnectionNamedPipeFeature.NamedPipe.get -> System.IO.Pipes.NamedPipeServerStream! -Microsoft.AspNetCore.Connections.Features.ITlsHandshakeFeature.HostName.get -> string? +Microsoft.AspNetCore.Connections.Features.ITlsHandshakeFeature.HostName.get -> string! Microsoft.AspNetCore.Connections.Features.ITlsHandshakeFeature.NegotiatedCipherSuite.get -> System.Net.Security.TlsCipherSuite? Microsoft.AspNetCore.Connections.IConnectionListenerFactorySelector Microsoft.AspNetCore.Connections.IConnectionListenerFactorySelector.CanBind(System.Net.EndPoint! endpoint) -> bool diff --git a/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs b/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs index 258d05ad5c87..575ebc259d25 100644 --- a/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs +++ b/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs @@ -79,11 +79,10 @@ internal static unsafe partial uint HttpCreateRequestQueue(HTTPAPI_VERSION versi [LibraryImport(HTTPAPI, SetLastError = true)] internal static unsafe partial uint HttpDelegateRequestEx(SafeHandle pReqQueueHandle, SafeHandle pDelegateQueueHandle, ulong requestId, - ulong delegateUrlGroupId, ulong propertyInfoSetSize, HTTP_DELEGATE_REQUEST_PROPERTY_INFO* pRequestPropertyBuffer); + ulong delegateUrlGroupId, uint propertyInfoSetSize, HTTP_DELEGATE_REQUEST_PROPERTY_INFO* pRequestPropertyBuffer); - [LibraryImport(HTTPAPI, SetLastError = true)] - internal static unsafe partial uint HttpQueryRequestProperty(SafeHandle requestQueueHandle, ulong requestId, HTTP_REQUEST_PROPERTY propertyId, - void* qualifier, ulong qualifierSize, void* output, ulong outputSize, ulong* bytesReturned, IntPtr overlapped); + internal delegate uint HttpGetRequestPropertyInvoker(SafeHandle requestQueueHandle, ulong requestId, HTTP_REQUEST_PROPERTY propertyId, + void* qualifier, uint qualifierSize, void* output, uint outputSize, uint* bytesReturned, IntPtr overlapped); internal delegate uint HttpSetRequestPropertyInvoker(SafeHandle requestQueueHandle, ulong requestId, HTTP_REQUEST_PROPERTY propertyId, void* input, uint inputSize, IntPtr overlapped); @@ -123,6 +122,7 @@ internal static HTTP_API_VERSION ApiVersion } internal static SafeLibraryHandle? HttpApiModule { get; private set; } + internal static HttpGetRequestPropertyInvoker? HttpGetRequestProperty { get; private set; } internal static HttpSetRequestPropertyInvoker? HttpSetRequestProperty { get; private set; } [MemberNotNullWhen(true, nameof(HttpSetRequestProperty))] internal static bool SupportsTrailers { get; private set; } @@ -147,6 +147,7 @@ private static void InitHttpApi(ushort majorVersion, ushort minorVersion) if (supported) { HttpApiModule = SafeLibraryHandle.Open(HTTPAPI); + HttpGetRequestProperty = HttpApiModule.GetProcAddress("HttpQueryRequestProperty", throwIfNotFound: false); HttpSetRequestProperty = HttpApiModule.GetProcAddress("HttpSetRequestProperty", throwIfNotFound: false); SupportsReset = HttpSetRequestProperty != null; SupportsTrailers = IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureResponseTrailers); diff --git a/src/Servers/HttpSys/src/RequestProcessing/Request.cs b/src/Servers/HttpSys/src/RequestProcessing/Request.cs index 229b9bd8032f..c75a5fa228a5 100644 --- a/src/Servers/HttpSys/src/RequestProcessing/Request.cs +++ b/src/Servers/HttpSys/src/RequestProcessing/Request.cs @@ -169,6 +169,7 @@ internal Request(RequestContext requestContext) User = RequestContext.GetUser(); + SniHostName = string.Empty; if (IsHttps) { GetTlsHandshakeResults(); @@ -327,7 +328,7 @@ private AspNetCore.HttpSys.Internal.SocketAddress LocalEndPoint internal WindowsPrincipal User { get; } - public string? SniHostName { get; private set; } + public string SniHostName { get; private set; } public SslProtocols Protocol { get; private set; } diff --git a/src/Servers/HttpSys/src/RequestProcessing/RequestContext.FeatureCollection.cs b/src/Servers/HttpSys/src/RequestProcessing/RequestContext.FeatureCollection.cs index 95148c3070ed..6694e9d22594 100644 --- a/src/Servers/HttpSys/src/RequestProcessing/RequestContext.FeatureCollection.cs +++ b/src/Servers/HttpSys/src/RequestProcessing/RequestContext.FeatureCollection.cs @@ -587,7 +587,7 @@ bool IHttpBodyControlFeature.AllowSynchronousIO int ITlsHandshakeFeature.KeyExchangeStrength => Request.KeyExchangeStrength; - string? ITlsHandshakeFeature.HostName => Request.SniHostName; + string ITlsHandshakeFeature.HostName => Request.SniHostName; IReadOnlyDictionary> IHttpSysRequestInfoFeature.RequestInfo => Request.RequestInfo; diff --git a/src/Servers/HttpSys/src/RequestProcessing/RequestContext.cs b/src/Servers/HttpSys/src/RequestProcessing/RequestContext.cs index 5120ce969ffa..8da0c7a33e37 100644 --- a/src/Servers/HttpSys/src/RequestProcessing/RequestContext.cs +++ b/src/Servers/HttpSys/src/RequestProcessing/RequestContext.cs @@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpSys.Internal; using Microsoft.Extensions.Logging; -using static Microsoft.AspNetCore.HttpSys.Internal.UnsafeNclNativeMethods; namespace Microsoft.AspNetCore.Server.HttpSys; @@ -228,25 +227,28 @@ internal void ForceCancelRequest() internal unsafe HttpApiTypes.HTTP_REQUEST_PROPERTY_SNI GetClientSni() { + if (HttpApi.HttpGetRequestProperty != null) + { var buffer = new byte[HttpApiTypes.SniPropertySizeInBytes]; fixed (byte* pBuffer = buffer) { - var statusCode = HttpApi.HttpQueryRequestProperty( + var statusCode = HttpApi.HttpGetRequestProperty( Server.RequestQueue.Handle, RequestId, HttpApiTypes.HTTP_REQUEST_PROPERTY.HttpRequestPropertySni, qualifier: null, qualifierSize: 0, (void*)pBuffer, - (ulong)buffer.Length, + (uint)buffer.Length, bytesReturned: null, IntPtr.Zero); - if (statusCode == ErrorCodes.ERROR_SUCCESS) + if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { return Marshal.PtrToStructure((IntPtr)pBuffer); } } + } return default; } diff --git a/src/Servers/HttpSys/test/FunctionalTests/HttpsTests.cs b/src/Servers/HttpSys/test/FunctionalTests/HttpsTests.cs index 7b7586491e5a..ea6a62c5f112 100644 --- a/src/Servers/HttpSys/test/FunctionalTests/HttpsTests.cs +++ b/src/Servers/HttpSys/test/FunctionalTests/HttpsTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Data.Common; using System.Diagnostics; using System.IO; using System.Net.Http; diff --git a/src/Servers/Kestrel/Core/src/Internal/TlsConnectionFeature.cs b/src/Servers/Kestrel/Core/src/Internal/TlsConnectionFeature.cs index 53c24c80677b..2e23dbe585a5 100644 --- a/src/Servers/Kestrel/Core/src/Internal/TlsConnectionFeature.cs +++ b/src/Servers/Kestrel/Core/src/Internal/TlsConnectionFeature.cs @@ -42,7 +42,7 @@ public X509Certificate2? ClientCertificate } } - public string? HostName { get; set; } + public string HostName { get; set; } = string.Empty; public ReadOnlyMemory ApplicationProtocol => _sslStream.NegotiatedApplicationProtocol.Protocol; diff --git a/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs b/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs index 25a23ee3f491..8520c6b47696 100644 --- a/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs +++ b/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs @@ -313,7 +313,7 @@ private Task DoOptionsBasedHandshakeAsync(ConnectionContext context, SslStream s { selector = (sender, name) => { - feature.HostName = name; + feature.HostName = name ?? string.Empty; var cert = _serverCertificateSelector(context, name); if (cert != null) { diff --git a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs index 4e9f90351f3f..a0a35eaaa6a5 100644 --- a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs +++ b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Authentication; using Microsoft.AspNetCore.Http; @@ -109,8 +108,8 @@ internal struct HTTP_REQUEST_PROPERTY_STREAM_ERROR internal uint ErrorCode; } - internal const int HTTP_REQUEST_PROPERTY_SNI_HOST_MAX_LENGTH = 255; - internal const int SniPropertySizeInBytes = (sizeof(ushort) * (HTTP_REQUEST_PROPERTY_SNI_HOST_MAX_LENGTH + 1)) + sizeof(ulong); + private const int HTTP_REQUEST_PROPERTY_SNI_HOST_MAX_LENGTH = 255; + internal const int SniPropertySizeInBytes = (sizeof(ushort) * (HTTP_REQUEST_PROPERTY_SNI_HOST_MAX_LENGTH + 1)) + sizeof(uint); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Size = SniPropertySizeInBytes)] internal struct HTTP_REQUEST_PROPERTY_SNI