Skip to content

Commit aa3ae32

Browse files
committed
correctly retry access
1 parent d7953f6 commit aa3ae32

File tree

7 files changed

+63
-83
lines changed

7 files changed

+63
-83
lines changed

src/Servers/Connections.Abstractions/src/Features/ITlsFingerprintingFeature.cs renamed to src/Servers/Connections.Abstractions/src/Features/ITlsAccessFeature.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
namespace Microsoft.AspNetCore.Connections.Features;
1414

1515
/// <summary>
16-
/// Represents the details about the TLS fingerprinting.
16+
/// Allows to access underlying TLS data.
1717
/// </summary>
18-
public interface ITlsFingerprintingFeature
18+
public interface ITlsAccessFeature
1919
{
2020
/// <summary>
21-
/// Returns the TLS client hello details, if any.
21+
/// Returns the raw bytes of TLS client hello message.
2222
/// </summary>
23-
TLS_CLIENT_HELLO GetTlsClientHello();
23+
byte[]? GetTlsClientHelloMessageBytes();
2424
}

src/Servers/HttpSys/samples/TlsFeaturesObserve/Startup.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ public void Configure(IApplicationBuilder app)
2121
{
2222
context.Response.ContentType = "text/plain";
2323

24-
var tlsFingerprintingFeature = context.Features.Get<ITlsFingerprintingFeature>();
24+
var tlsFingerprintingFeature = context.Features.Get<ITlsAccessFeature>();
2525
if (tlsFingerprintingFeature is null)
2626
{
27-
await context.Response.WriteAsync(nameof(ITlsFingerprintingFeature) + " is not resolved from " + nameof(context));
27+
await context.Response.WriteAsync(nameof(ITlsAccessFeature) + " is not resolved from " + nameof(context));
2828
return;
2929
}
3030

31-
var tlsClientHello = tlsFingerprintingFeature.GetTlsClientHello();
32-
await context.Response.WriteAsync("TLS CLIENT HELLO: " + tlsClientHello);
31+
var tlsClientHello = tlsFingerprintingFeature.GetTlsClientHelloMessageBytes();
32+
await context.Response.WriteAsync("TLS CLIENT HELLO: bytearray.len=" + tlsClientHello.Length);
3333
});
3434
}
3535
}

src/Servers/HttpSys/src/RequestProcessing/Request.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,10 @@ private AspNetCore.HttpSys.Internal.SocketAddress LocalEndPoint
339339

340340
public SslProtocols Protocol { get; private set; }
341341

342-
public TLS_CLIENT_HELLO TlsClientHelloMessage { get; private set; }
342+
/// <summary>
343+
/// Raw bytes of TLS client hello message
344+
/// </summary>
345+
public byte[]? TlsClientHelloMessageBytes { get; private set; }
343346

344347
[Obsolete(Obsoletions.RuntimeTlsCipherAlgorithmEnumsMessage, DiagnosticId = Obsoletions.RuntimeTlsCipherAlgorithmEnumsDiagId, UrlFormat = Obsoletions.RuntimeSharedUrlFormat)]
345348
public CipherAlgorithmType CipherAlgorithm { get; private set; }
@@ -378,7 +381,7 @@ private void GetTlsHandshakeResults()
378381

379382
private void ParseTlsClientHello()
380383
{
381-
TlsClientHelloMessage = RequestContext.TryGetTlsClientHello();
384+
TlsClientHelloMessageBytes = RequestContext.GetTlsClientHelloMessageBytes();
382385
}
383386

384387
public X509Certificate2? ClientCertificate

src/Servers/HttpSys/src/RequestProcessing/RequestContext.FeatureCollection.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Security.Authentication;
99
using System.Security.Claims;
1010
using System.Security.Cryptography.X509Certificates;
11-
using Microsoft.AspNetCore.Connections.Abstractions.TLS;
1211
using Microsoft.AspNetCore.Connections.Features;
1312
using Microsoft.AspNetCore.Http;
1413
using Microsoft.AspNetCore.Http.Features;
@@ -25,7 +24,7 @@ internal partial class RequestContext :
2524
IHttpResponseBodyFeature,
2625
ITlsConnectionFeature,
2726
ITlsHandshakeFeature,
28-
ITlsFingerprintingFeature,
27+
ITlsAccessFeature,
2928
// ITlsTokenBindingFeature, TODO: https://github.com/aspnet/HttpSysServer/issues/231
3029
IHttpRequestLifetimeFeature,
3130
IHttpAuthenticationFeature,
@@ -384,7 +383,7 @@ string IHttpConnectionFeature.ConnectionId
384383
return Request.IsHttps ? this : null;
385384
}
386385

387-
internal ITlsFingerprintingFeature? GetTlsFingerprintingFeature()
386+
internal ITlsAccessFeature? GetTlsFingerprintingFeature()
388387
{
389388
return Request.IsHttps ? this : null;
390389
}
@@ -599,9 +598,9 @@ bool IHttpBodyControlFeature.AllowSynchronousIO
599598

600599
SslProtocols ITlsHandshakeFeature.Protocol => Request.Protocol;
601600

602-
TLS_CLIENT_HELLO ITlsFingerprintingFeature.GetTlsClientHello()
601+
byte[]? ITlsAccessFeature.GetTlsClientHelloMessageBytes()
603602
{
604-
return Request.TlsClientHelloMessage;
603+
return Request.TlsClientHelloMessageBytes;
605604
}
606605

607606
#pragma warning disable SYSLIB0058 // Type or member is obsolete

src/Servers/HttpSys/src/RequestProcessing/RequestContext.Log.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,5 @@ private static partial class Log
2323

2424
[LoggerMessage(LoggerEventIds.RequestParsingError, LogLevel.Debug, "Failed to invoke QueryTlsClientHello.", EventName = "TlsClientHelloRetrieveError")]
2525
public static partial void TlsClientHelloRetrieveError(ILogger logger, string message);
26-
27-
[LoggerMessage(LoggerEventIds.RequestParsingError, LogLevel.Debug, "Failed to parse TLS client hello message.", EventName = "TlsClientHelloParseError")]
28-
public static partial void TlsClientHelloParseError(ILogger logger, Exception exception);
2926
}
3027
}

src/Servers/HttpSys/src/RequestProcessing/RequestContext.cs

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
using System.Buffers;
55
using System.Runtime.InteropServices;
6-
using System.Security.Authentication;
76
using System.Security.Principal;
8-
using Microsoft.AspNetCore.Connections.Abstractions.TLS;
97
using Microsoft.AspNetCore.Http;
108
using Microsoft.AspNetCore.HttpSys.Internal;
119
using Microsoft.AspNetCore.WebUtilities;
@@ -222,7 +220,11 @@ internal void ForceCancelRequest()
222220
}
223221
}
224222

225-
internal unsafe TLS_CLIENT_HELLO TryGetTlsClientHello()
223+
/// <summary>
224+
/// Attempts to get the client hello message bytes from the http.sys.
225+
/// If not successful, will return `null`
226+
/// </summary>
227+
internal unsafe byte[]? GetTlsClientHelloMessageBytes()
226228
{
227229
if (!HttpApi.HttpGetRequestPropertySupported)
228230
{
@@ -231,84 +233,63 @@ internal unsafe TLS_CLIENT_HELLO TryGetTlsClientHello()
231233

232234
uint bytesReturnedValue = 0;
233235
uint* bytesReturned = &bytesReturnedValue;
236+
uint statusCode;
234237

235-
var buffer = new byte[256];
238+
var buffer = ArrayPool<byte>.Shared.Rent(256);
236239
try
237240
{
238241
fixed (byte* pBuffer = buffer)
239242
{
240-
var statusCode = HttpApi.HttpGetRequestProperty(
241-
Server.RequestQueue.Handle,
242-
RequestId,
243+
statusCode = HttpApi.HttpGetRequestProperty(
244+
Server.RequestQueue.Handle, RequestId,
243245
11 /* HTTP_REQUEST_PROPERTY.HttpRequestPropertyTlsClientHello */,
244-
qualifier: null,
245-
qualifierSize: 0,
246-
pBuffer,
247-
(uint)buffer.Length,
248-
bytesReturned: (IntPtr)bytesReturned,
249-
IntPtr.Zero);
250-
251-
if (statusCode is ErrorCodes.ERROR_MORE_DATA or ErrorCodes.ERROR_INSUFFICIENT_BUFFER)
246+
qualifier: null, qualifierSize: 0,
247+
pBuffer, (uint)buffer.Length,
248+
bytesReturned: (IntPtr)bytesReturned, IntPtr.Zero);
249+
250+
if (statusCode is ErrorCodes.ERROR_SUCCESS)
252251
{
253-
// The buffer is too small, we need to allocate a larger one.
254-
// Firstly, return the initial buffer to not leak
255-
// ArrayPool<byte>.Shared.Return(buffer);
252+
return buffer.AsSpan().ToArray();
253+
}
254+
}
255+
}
256+
finally
257+
{
258+
ArrayPool<byte>.Shared.Return(buffer);
259+
}
256260

257-
// then reallocate the buffer of size as `bytesReturned`
258-
buffer = new byte[(int)bytesReturned];
261+
// if buffer supplied is too small, `bytesReturned` will have proper size
262+
// so retry should succeed with the properly allocated buffer
263+
if (statusCode is ErrorCodes.ERROR_MORE_DATA or ErrorCodes.ERROR_INSUFFICIENT_BUFFER)
264+
{
265+
try
266+
{
267+
var correctSize = (int)bytesReturnedValue;
268+
buffer = ArrayPool<byte>.Shared.Rent(correctSize);
259269

260-
// and try again!
270+
fixed (byte* pBuffer = buffer)
271+
{
261272
statusCode = HttpApi.HttpGetRequestProperty(
262-
Server.RequestQueue.Handle,
263-
RequestId,
273+
Server.RequestQueue.Handle, RequestId,
264274
11 /* HTTP_REQUEST_PROPERTY.HttpRequestPropertyTlsClientHello */,
265-
qualifier: null,
266-
qualifierSize: 0,
267-
pBuffer,
268-
(uint)buffer.Length,
269-
bytesReturned: (IntPtr)bytesReturned,
270-
IntPtr.Zero);
271-
}
275+
qualifier: null, qualifierSize: 0,
276+
pBuffer, (uint)buffer.Length,
277+
bytesReturned: (IntPtr)bytesReturned, IntPtr.Zero);
272278

273-
if (statusCode == ErrorCodes.ERROR_SUCCESS)
274-
{
275-
try
276-
{
277-
var tlsMajorVersion = pBuffer[1];
278-
var tlsMinorVersion = pBuffer[2];
279-
280-
return new TLS_CLIENT_HELLO
281-
{
282-
ProtocolVersion = tlsMinorVersion switch
283-
{
284-
4 => SslProtocols.Tls13,
285-
3 => SslProtocols.Tls12,
286-
#pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete
287-
2 => SslProtocols.Tls11,
288-
1 => SslProtocols.Tls,
289-
#pragma warning restore SYSLIB0039
290-
#pragma warning disable CS0618 // Type or member is obsolete
291-
0 => SslProtocols.Ssl3,
292-
#pragma warning restore CS0618 // Type or member is obsolete
293-
_ => SslProtocols.None,
294-
}
295-
};
296-
}
297-
catch (Exception ex)
279+
if (statusCode is ErrorCodes.ERROR_SUCCESS)
298280
{
299-
Log.TlsClientHelloParseError(Logger, ex);
281+
return buffer.AsSpan(0, correctSize).ToArray();
300282
}
301283
}
302-
303-
// if not returned here, we got a non-success status code
304-
Log.TlsClientHelloRetrieveError(Logger, "Status code: " + statusCode);
305-
return default;
284+
}
285+
finally
286+
{
287+
ArrayPool<byte>.Shared.Return(buffer);
306288
}
307289
}
308-
finally
309-
{
310-
ArrayPool<byte>.Shared.Return(buffer);
311-
}
290+
291+
Log.TlsClientHelloRetrieveError(Logger, "Status code: " + statusCode);
292+
return default;
312293
}
313294

314295
internal unsafe HTTP_REQUEST_PROPERTY_SNI GetClientSni()

src/Servers/HttpSys/src/StandardFeatureCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal sealed class StandardFeatureCollection : IFeatureCollection
1919
{ typeof(IHttpResponseFeature), _identityFunc },
2020
{ typeof(IHttpResponseBodyFeature), _identityFunc },
2121
{ typeof(ITlsConnectionFeature), ctx => ctx.GetTlsConnectionFeature() },
22-
{ typeof(ITlsFingerprintingFeature), ctx => ctx.GetTlsFingerprintingFeature() },
22+
{ typeof(ITlsAccessFeature), ctx => ctx.GetTlsFingerprintingFeature() },
2323
{ typeof(IHttpRequestLifetimeFeature), _identityFunc },
2424
{ typeof(IHttpAuthenticationFeature), _identityFunc },
2525
{ typeof(IHttpRequestIdentifierFeature), _identityFunc },

0 commit comments

Comments
 (0)