Use ImpersonationToken for IIS Windows Auth

This commit is contained in:
Brennan 2024-09-23 13:58:31 -07:00
Родитель 9afcb7286d
Коммит c13def5861
4 изменённых файлов: 55 добавлений и 5 удалений

Просмотреть файл

@ -513,7 +513,7 @@ http_get_authentication_information(
)
{
*pstrAuthType = SysAllocString(pInProcessHandler->QueryHttpContext()->GetUser()->GetAuthenticationType());
*pvToken = pInProcessHandler->QueryHttpContext()->GetUser()->GetPrimaryToken();
*pvToken = pInProcessHandler->QueryHttpContext()->GetUser()->GetImpersonationToken();
return S_OK;
}

Просмотреть файл

@ -815,11 +815,12 @@ FORWARDING_HANDLER::GetHeaders(
(_wcsicmp(m_pW3Context->GetUser()->GetAuthenticationType(), L"negotiate") == 0 ||
_wcsicmp(m_pW3Context->GetUser()->GetAuthenticationType(), L"ntlm") == 0))
{
if (m_pW3Context->GetUser()->GetPrimaryToken() != NULL &&
m_pW3Context->GetUser()->GetPrimaryToken() != INVALID_HANDLE_VALUE)
HANDLE impersonationToken = m_pW3Context->GetUser()->GetImpersonationToken();
if (impersonationToken != NULL &&
impersonationToken != INVALID_HANDLE_VALUE)
{
HANDLE hTargetTokenHandle = NULL;
RETURN_IF_FAILED(pServerProcess->SetWindowsAuthToken(m_pW3Context->GetUser()->GetPrimaryToken(),
RETURN_IF_FAILED(pServerProcess->SetWindowsAuthToken(impersonationToken,
&hTargetTokenHandle));
//

Просмотреть файл

@ -136,7 +136,7 @@ public sealed class RequiresIISAttribute : Attribute, ITestCondition
IsMet &= available;
if (!available)
{
SkipReason += $"The machine does have {module.Capability} available.";
SkipReason += $"The machine does not have {module.Capability} available.";
}
}
}

Просмотреть файл

@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Net;
using System.Net.Http;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
@ -58,4 +60,51 @@ public class WindowsAuthTests : IISFunctionalTestBase
Assert.StartsWith("Windows:", responseText);
Assert.Contains(Environment.UserName, responseText);
}
[ConditionalTheory]
[RequiresIIS(IISCapability.WindowsAuthentication)]
[MemberData(nameof(TestVariants))]
public async Task WindowsAuthWithImpersonationLevelTest(TestVariant variant)
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters(variant);
deploymentParameters.SetAnonymousAuth(enabled: false);
deploymentParameters.SetWindowsAuth();
// The default in hosting sets windows auth to true.
var deploymentResult = await DeployAsync(deploymentParameters);
var impersonationLevels = new TokenImpersonationLevel[]
{
TokenImpersonationLevel.None,
TokenImpersonationLevel.Identification,
TokenImpersonationLevel.Impersonation,
TokenImpersonationLevel.Delegation,
TokenImpersonationLevel.Anonymous
};
foreach (var impersonationLevel in impersonationLevels)
{
// TokenImpersonationLevel is not supported by HttpClient so we need to use HttpWebRequest to test it.
#pragma warning disable SYSLIB0014 // Type or member is obsolete
var request = HttpWebRequest.CreateHttp($"{deploymentResult.HttpClient.BaseAddress}Auth");
#pragma warning restore SYSLIB0014 // Type or member is obsolete
request.ImpersonationLevel = impersonationLevel;
request.Method = "GET";
request.UseDefaultCredentials = true;
using var response = request.GetResponse();
using var reader = new StreamReader(response.GetResponseStream());
var responseText = await reader.ReadToEndAsync();
try
{
Assert.StartsWith("Windows:", responseText);
Assert.Contains(Environment.UserName, responseText);
}
catch (Exception ex)
{
Assert.Fail($"'TokenImpersonationLevel.{impersonationLevel}' failed with: {ex.Message}");
}
}
}
}