Implement ITlsHandshakeFeature for HttpSys (#7284)
This commit is contained in:
parent
3fd8a97af2
commit
06d7fe73a9
|
|
@ -6,10 +6,12 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
|
|
@ -24,6 +26,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
IHttpResponseFeature,
|
||||
IHttpSendFileFeature,
|
||||
ITlsConnectionFeature,
|
||||
ITlsHandshakeFeature,
|
||||
// ITlsTokenBindingFeature, TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
||||
IHttpBufferingFeature,
|
||||
IHttpRequestLifetimeFeature,
|
||||
|
|
@ -336,6 +339,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
return Request.IsHttps ? this : null;
|
||||
}
|
||||
|
||||
internal ITlsHandshakeFeature GetTlsHandshakeFeature()
|
||||
{
|
||||
return Request.IsHttps ? this : null;
|
||||
}
|
||||
|
||||
/* TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
||||
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId() => Request.GetProvidedTokenBindingId();
|
||||
|
||||
|
|
@ -482,6 +491,20 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
set => Request.MaxRequestBodySize = value;
|
||||
}
|
||||
|
||||
SslProtocols ITlsHandshakeFeature.Protocol => Request.Protocol;
|
||||
|
||||
CipherAlgorithmType ITlsHandshakeFeature.CipherAlgorithm => Request.CipherAlgorithm;
|
||||
|
||||
int ITlsHandshakeFeature.CipherStrength => Request.CipherStrength;
|
||||
|
||||
HashAlgorithmType ITlsHandshakeFeature.HashAlgorithm => Request.HashAlgorithm;
|
||||
|
||||
int ITlsHandshakeFeature.HashStrength => Request.HashStrength;
|
||||
|
||||
ExchangeAlgorithmType ITlsHandshakeFeature.KeyExchangeAlgorithm => Request.KeyExchangeAlgorithm;
|
||||
|
||||
int ITlsHandshakeFeature.KeyExchangeStrength => Request.KeyExchangeStrength;
|
||||
|
||||
internal async Task OnResponseStart()
|
||||
{
|
||||
if (_responseStarted)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Authentication.Core" />
|
||||
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions" />
|
||||
<Reference Include="Microsoft.AspNetCore.Hosting" />
|
||||
<Reference Include="Microsoft.Net.Http.Headers" />
|
||||
<Reference Include="Microsoft.Win32.Registry" />
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
|
|
@ -83,6 +84,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
User = _nativeRequestContext.GetUser();
|
||||
|
||||
if (IsHttps)
|
||||
{
|
||||
GetTlsHandshakeResults();
|
||||
}
|
||||
|
||||
// GetTlsTokenBindingInfo(); TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
||||
|
||||
// Finished directly accessing the HTTP_REQUEST structure.
|
||||
|
|
@ -232,6 +238,60 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
internal WindowsPrincipal User { get; }
|
||||
|
||||
public SslProtocols Protocol { get; private set; }
|
||||
|
||||
public CipherAlgorithmType CipherAlgorithm { get; private set; }
|
||||
|
||||
public int CipherStrength { get; private set; }
|
||||
|
||||
public HashAlgorithmType HashAlgorithm { get; private set; }
|
||||
|
||||
public int HashStrength { get; private set; }
|
||||
|
||||
public ExchangeAlgorithmType KeyExchangeAlgorithm { get; private set; }
|
||||
|
||||
public int KeyExchangeStrength { get; private set; }
|
||||
|
||||
private void GetTlsHandshakeResults()
|
||||
{
|
||||
var handshake = _nativeRequestContext.GetTlsHandshake();
|
||||
|
||||
Protocol = handshake.Protocol;
|
||||
// The OS considers client and server TLS as different enum values. SslProtocols choose to combine those for some reason.
|
||||
// We need to fill in the client bits so the enum shows the expected protocol.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/schannel/ns-schannel-_secpkgcontext_connectioninfo
|
||||
// Compare to https://referencesource.microsoft.com/#System/net/System/Net/SecureProtocols/_SslState.cs,8905d1bf17729de3
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if ((Protocol & SslProtocols.Ssl2) != 0)
|
||||
{
|
||||
Protocol |= SslProtocols.Ssl2;
|
||||
}
|
||||
if ((Protocol & SslProtocols.Ssl3) != 0)
|
||||
{
|
||||
Protocol |= SslProtocols.Ssl3;
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
if ((Protocol & SslProtocols.Tls) != 0)
|
||||
{
|
||||
Protocol |= SslProtocols.Tls;
|
||||
}
|
||||
if ((Protocol & SslProtocols.Tls11) != 0)
|
||||
{
|
||||
Protocol |= SslProtocols.Tls11;
|
||||
}
|
||||
if ((Protocol & SslProtocols.Tls12) != 0)
|
||||
{
|
||||
Protocol |= SslProtocols.Tls12;
|
||||
}
|
||||
|
||||
CipherAlgorithm = handshake.CipherType;
|
||||
CipherStrength = (int)handshake.CipherStrength;
|
||||
HashAlgorithm = handshake.HashType;
|
||||
HashStrength = (int)handshake.HashStrength;
|
||||
KeyExchangeAlgorithm = handshake.KeyExchangeType;
|
||||
KeyExchangeStrength = (int)handshake.KeyExchangeStrength;
|
||||
}
|
||||
|
||||
// Populates the client certificate. The result may be null if there is no client cert.
|
||||
// TODO: Does it make sense for this to be invoked multiple times (e.g. renegotiate)? Client and server code appear to
|
||||
// enable this, but it's unclear what Http.Sys would do.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
|
||||
|
|
@ -19,6 +20,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{ typeof(IHttpResponseFeature), _identityFunc },
|
||||
{ typeof(IHttpSendFileFeature), _identityFunc },
|
||||
{ typeof(ITlsConnectionFeature), ctx => ctx.GetTlsConnectionFeature() },
|
||||
{ typeof(ITlsHandshakeFeature), ctx => ctx.GetTlsHandshakeFeature() },
|
||||
// { typeof(ITlsTokenBindingFeature), ctx => ctx.GetTlsTokenBindingFeature() }, TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
||||
{ typeof(IHttpBufferingFeature), _identityFunc },
|
||||
{ typeof(IHttpRequestLifetimeFeature), _identityFunc },
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
|
@ -15,40 +19,38 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
public class HttpsTests
|
||||
{
|
||||
private const string Address = "https://localhost:9090/";
|
||||
|
||||
[ConditionalFact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
||||
[ConditionalFact]
|
||||
public async Task Https_200OK_Success()
|
||||
{
|
||||
using (Utilities.CreateHttpsServer(httpContext =>
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, httpContext =>
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(Address);
|
||||
string response = await SendRequestAsync(address);
|
||||
Assert.Equal(string.Empty, response);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
||||
[ConditionalFact]
|
||||
public async Task Https_SendHelloWorld_Success()
|
||||
{
|
||||
using (Utilities.CreateHttpsServer(httpContext =>
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, httpContext =>
|
||||
{
|
||||
byte[] body = Encoding.UTF8.GetBytes("Hello World");
|
||||
httpContext.Response.ContentLength = body.Length;
|
||||
return httpContext.Response.Body.WriteAsync(body, 0, body.Length);
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(Address);
|
||||
string response = await SendRequestAsync(address);
|
||||
Assert.Equal("Hello World", response);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
||||
[ConditionalFact]
|
||||
public async Task Https_EchoHelloWorld_Success()
|
||||
{
|
||||
using (Utilities.CreateHttpsServer(httpContext =>
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, httpContext =>
|
||||
{
|
||||
string input = new StreamReader(httpContext.Request.Body).ReadToEnd();
|
||||
Assert.Equal("Hello World", input);
|
||||
|
|
@ -58,15 +60,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(Address, "Hello World");
|
||||
string response = await SendRequestAsync(address, "Hello World");
|
||||
Assert.Equal("Hello World", response);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
||||
[ConditionalFact]
|
||||
public async Task Https_ClientCertNotSent_ClientCertNotPresent()
|
||||
{
|
||||
using (Utilities.CreateHttpsServer(async httpContext =>
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, async httpContext =>
|
||||
{
|
||||
var tls = httpContext.Features.Get<ITlsConnectionFeature>();
|
||||
Assert.NotNull(tls);
|
||||
|
|
@ -75,15 +77,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
Assert.Null(tls.ClientCertificate);
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(Address);
|
||||
string response = await SendRequestAsync(address);
|
||||
Assert.Equal(string.Empty, response);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")]
|
||||
[ConditionalFact(Skip = "Manual test only, client certs are not always available.")]
|
||||
public async Task Https_ClientCertRequested_ClientCertPresent()
|
||||
{
|
||||
using (Utilities.CreateHttpsServer(async httpContext =>
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, async httpContext =>
|
||||
{
|
||||
var tls = httpContext.Features.Get<ITlsConnectionFeature>();
|
||||
Assert.NotNull(tls);
|
||||
|
|
@ -94,7 +96,37 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
X509Certificate2 cert = FindClientCert();
|
||||
Assert.NotNull(cert);
|
||||
string response = await SendRequestAsync(Address, cert);
|
||||
string response = await SendRequestAsync(address, cert);
|
||||
Assert.Equal(string.Empty, response);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Https_SetsITlsHandshakeFeature()
|
||||
{
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, httpContext =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var tlsFeature = httpContext.Features.Get<ITlsHandshakeFeature>();
|
||||
Assert.NotNull(tlsFeature);
|
||||
Assert.True(tlsFeature.Protocol > SslProtocols.None, "Protocol");
|
||||
Assert.True(Enum.IsDefined(typeof(SslProtocols), tlsFeature.Protocol), "Defined"); // Mapping is required, make sure it's current
|
||||
Assert.True(tlsFeature.CipherAlgorithm > CipherAlgorithmType.Null, "Cipher");
|
||||
Assert.True(tlsFeature.CipherStrength > 0, "CipherStrength");
|
||||
Assert.True(tlsFeature.HashAlgorithm > HashAlgorithmType.None, "HashAlgorithm");
|
||||
Assert.True(tlsFeature.HashStrength >= 0, "HashStrength"); // May be 0 for some algorithms
|
||||
Assert.True(tlsFeature.KeyExchangeAlgorithm > ExchangeAlgorithmType.None, "KeyExchangeAlgorithm");
|
||||
Assert.True(tlsFeature.KeyExchangeStrength > 0, "KeyExchangeStrength");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return httpContext.Response.WriteAsync(ex.ToString());
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(address);
|
||||
Assert.Equal(string.Empty, response);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,4 +10,9 @@
|
|||
<Reference Include="System.Net.Http.WinHttpHandler" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!--Imitate IIS Express so we can use it's cert bindings-->
|
||||
<PackageTags>214124cd-d05b-4309-9af9-9caa44b2b74a</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
// ports during dynamic port allocation.
|
||||
private const int BasePort = 5001;
|
||||
private const int MaxPort = 8000;
|
||||
private const int BaseHttpsPort = 44300;
|
||||
private const int MaxHttpsPort = 44399;
|
||||
private static int NextPort = BasePort;
|
||||
private static int NextHttpsPort = BaseHttpsPort;
|
||||
private static object PortLock = new object();
|
||||
internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
|
||||
internal static readonly int WriteRetryLimit = 1000;
|
||||
|
|
@ -148,17 +151,37 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
throw new Exception("Failed to locate a free port.");
|
||||
}
|
||||
|
||||
internal static IServer CreateHttpsServer(RequestDelegate app)
|
||||
internal static IServer CreateDynamicHttpsServer(out string baseAddress, RequestDelegate app)
|
||||
{
|
||||
return CreateServer("https", "localhost", 9090, string.Empty, app);
|
||||
return CreateDynamicHttpsServer("/", out var root, out baseAddress, options => { }, app);
|
||||
}
|
||||
|
||||
internal static IServer CreateServer(string scheme, string host, int port, string path, RequestDelegate app)
|
||||
internal static IServer CreateDynamicHttpsServer(string basePath, out string root, out string baseAddress, Action<HttpSysOptions> configureOptions, RequestDelegate app)
|
||||
{
|
||||
var server = CreatePump();
|
||||
server.Features.Get<IServerAddressesFeature>().Addresses.Add(UrlPrefix.Create(scheme, host, port, path).ToString());
|
||||
server.StartAsync(new DummyApplication(app), CancellationToken.None).Wait();
|
||||
return server;
|
||||
lock (PortLock)
|
||||
{
|
||||
while (NextHttpsPort < MaxHttpsPort)
|
||||
{
|
||||
var port = NextHttpsPort++;
|
||||
var prefix = UrlPrefix.Create("https", "localhost", port, basePath);
|
||||
root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port;
|
||||
baseAddress = prefix.ToString();
|
||||
|
||||
var server = CreatePump();
|
||||
server.Features.Get<IServerAddressesFeature>().Addresses.Add(baseAddress);
|
||||
configureOptions(server.Listener.Options);
|
||||
try
|
||||
{
|
||||
server.StartAsync(new DummyApplication(app), CancellationToken.None).Wait();
|
||||
return server;
|
||||
}
|
||||
catch (HttpSysException)
|
||||
{
|
||||
}
|
||||
}
|
||||
NextHttpsPort = BaseHttpsPort;
|
||||
}
|
||||
throw new Exception("Failed to locate a free port.");
|
||||
}
|
||||
|
||||
internal static Task WithTimeout(this Task task) => task.TimeoutAfter(DefaultTimeout);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Authentication;
|
||||
|
||||
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||
{
|
||||
internal static unsafe class HttpApiTypes
|
||||
|
|
@ -426,12 +428,24 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
internal char* pMutualAuthData;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct HTTP_SSL_PROTOCOL_INFO
|
||||
{
|
||||
internal SslProtocols Protocol;
|
||||
internal CipherAlgorithmType CipherType;
|
||||
internal uint CipherStrength;
|
||||
internal HashAlgorithmType HashType;
|
||||
internal uint HashStrength;
|
||||
internal ExchangeAlgorithmType KeyExchangeType;
|
||||
internal uint KeyExchangeStrength;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct HTTP_REQUEST_INFO
|
||||
{
|
||||
internal HTTP_REQUEST_INFO_TYPE InfoType;
|
||||
internal uint InfoLength;
|
||||
internal HTTP_REQUEST_AUTH_INFO* pInfo;
|
||||
internal void* pInfo;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
|||
|
|
@ -184,10 +184,13 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
{
|
||||
var info = &requestInfo[i];
|
||||
if (info != null
|
||||
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth
|
||||
&& info->pInfo->AuthStatus == HttpApiTypes.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
||||
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth)
|
||||
{
|
||||
return true;
|
||||
var authInfo = (HttpApiTypes.HTTP_REQUEST_AUTH_INFO*)info->pInfo;
|
||||
if (authInfo->AuthStatus == HttpApiTypes.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -202,22 +205,44 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
{
|
||||
var info = &requestInfo[i];
|
||||
if (info != null
|
||||
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth
|
||||
&& info->pInfo->AuthStatus == HttpApiTypes.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
||||
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth)
|
||||
{
|
||||
// Duplicates AccessToken
|
||||
var identity = new WindowsIdentity(info->pInfo->AccessToken, GetAuthTypeFromRequest(info->pInfo->AuthType));
|
||||
var authInfo = (HttpApiTypes.HTTP_REQUEST_AUTH_INFO*)info->pInfo;
|
||||
if (authInfo->AuthStatus == HttpApiTypes.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
||||
{
|
||||
// Duplicates AccessToken
|
||||
var identity = new WindowsIdentity(authInfo->AccessToken, GetAuthTypeFromRequest(authInfo->AuthType));
|
||||
|
||||
// Close the original
|
||||
UnsafeNclNativeMethods.SafeNetHandles.CloseHandle(info->pInfo->AccessToken);
|
||||
// Close the original
|
||||
UnsafeNclNativeMethods.SafeNetHandles.CloseHandle(authInfo->AccessToken);
|
||||
|
||||
return new WindowsPrincipal(identity);
|
||||
return new WindowsPrincipal(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new WindowsPrincipal(WindowsIdentity.GetAnonymous()); // Anonymous / !IsAuthenticated
|
||||
}
|
||||
|
||||
internal HttpApiTypes.HTTP_SSL_PROTOCOL_INFO GetTlsHandshake()
|
||||
{
|
||||
var requestInfo = NativeRequestV2->pRequestInfo;
|
||||
var infoCount = NativeRequestV2->RequestInfoCount;
|
||||
|
||||
for (int i = 0; i < infoCount; i++)
|
||||
{
|
||||
var info = &requestInfo[i];
|
||||
if (info != null
|
||||
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslProtocol)
|
||||
{
|
||||
var authInfo = (HttpApiTypes.HTTP_SSL_PROTOCOL_INFO*)info->pInfo;
|
||||
return *authInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private static string GetAuthTypeFromRequest(HttpApiTypes.HTTP_REQUEST_AUTH_TYPE input)
|
||||
{
|
||||
switch (input)
|
||||
|
|
|
|||
Loading…
Reference in New Issue