diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs b/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs index e6a9cef30777bd..f6ea2e8e743f0e 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs @@ -7,6 +7,7 @@ public static class EnterpriseTestConfiguration { public const string Realm = "LINUX.CONTOSO.COM"; public const string NegotiateAuthWebServer = "http://apacheweb.linux.contoso.com/auth/kerberos/"; + public const string NegotiateAuthWebServerNotDefaultPort = "http://apacheweb.linux.contoso.com:8081/auth/kerberos/"; public const string AlternativeService = "http://altweb.linux.contoso.com:8080/auth/kerberos/"; public const string NtlmAuthWebServer = "http://apacheweb.linux.contoso.com:8080/auth/ntlm/"; public const string DigestAuthWebServer = "http://apacheweb.linux.contoso.com/auth/digest/"; diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/apache2.conf b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/apache2.conf index 87c20f04f2ed1f..a26a52ed8a0c9f 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/apache2.conf +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/apache2.conf @@ -54,6 +54,7 @@ Listen 8080 Listen 80 +Listen 8081 # @@ -238,7 +239,7 @@ Group daemon # e-mailed. This address appears on some server-generated pages, such # as error documents. e.g. admin@your-domain.com # -ServerAdmin you@example.com +ServerAdmin webmaster@contoso.com # # ServerName gives the name and port that the server uses to identify itself. @@ -583,11 +584,18 @@ SSLRandomSeed startup builtin SSLRandomSeed connect builtin + - ServerAdmin webmaster@contoso.com DocumentRoot "/setup/altdocs" ServerName altservice.contoso.com:8080 + + + + + DocumentRoot "/setup/htdocs" + + diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/run.sh b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/run.sh index 6aa96948a10332..0b4a615157c0b7 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/run.sh +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/run.sh @@ -11,6 +11,7 @@ if [ "$1" == "-debug" ]; then fi if [ "$1" == "-DNTLM" ]; then + # NTLM/Winbind is aggressive and eats Negotiate so it cannot be combined with Kerberos ./setup-pdc.sh /usr/sbin/apache2 -DALTPORT "$@" shift diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/docker-compose.yml b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/docker-compose.yml index 6aebd7ee187a4c..c54adfb7caaea3 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/docker-compose.yml +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/docker-compose.yml @@ -41,7 +41,7 @@ services: hostname: altweb domainname: linux.contoso.com dns_search: linux.contoso.com - command: -DALTPORT + command: "-DALTPORT -DALTSPN" volumes: - shared-volume:/SHARED networks: diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs index 8ee91309381721..52edbb5a80cbac 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs @@ -13,6 +13,38 @@ namespace System.Net.Http { internal static partial class AuthenticationHelper { + private const string UsePortInSpnCtxSwitch = "System.Net.Http.UsePortInSpn"; + private const string UsePortInSpnEnvironmentVariable = "DOTNET_SYSTEM_NET_HTTP_USEPORTINSPN"; + + private static volatile int s_usePortInSpn = -1; + + private static bool UsePortInSpn + { + get + { + int usePortInSpn = s_usePortInSpn; + if (usePortInSpn != -1) + { + return usePortInSpn != 0; + } + + // First check for the AppContext switch, giving it priority over the environment variable. + if (AppContext.TryGetSwitch(UsePortInSpnCtxSwitch, out bool value)) + { + s_usePortInSpn = value ? 1 : 0; + } + else + { + // AppContext switch wasn't used. Check the environment variable. + s_usePortInSpn = + Environment.GetEnvironmentVariable(UsePortInSpnEnvironmentVariable) is string envVar && + (envVar == "1" || envVar.Equals("true", StringComparison.OrdinalIgnoreCase)) ? 1 : 0; + } + + return s_usePortInSpn != 0; + } + } + private static Task InnerSendAsync(HttpRequestMessage request, bool async, bool isProxyAuth, HttpConnectionPool pool, HttpConnection connection, CancellationToken cancellationToken) { return isProxyAuth ? @@ -110,7 +142,7 @@ private static async Task SendWithNtAuthAsync(HttpRequestMe hostName = result.HostName; } - if (!isProxyAuth && !authUri.IsDefaultPort) + if (!isProxyAuth && !authUri.IsDefaultPort && UsePortInSpn) { hostName = string.Create(null, stackalloc char[128], $"{hostName}:{authUri.Port}"); } diff --git a/src/libraries/System.Net.Http/tests/EnterpriseTests/HttpClientAuthenticationTest.cs b/src/libraries/System.Net.Http/tests/EnterpriseTests/HttpClientAuthenticationTest.cs index 9b93d53fb8fb82..c2c78d2a4fedd0 100644 --- a/src/libraries/System.Net.Http/tests/EnterpriseTests/HttpClientAuthenticationTest.cs +++ b/src/libraries/System.Net.Http/tests/EnterpriseTests/HttpClientAuthenticationTest.cs @@ -3,7 +3,7 @@ using System.Net.Test.Common; using System.Threading.Tasks; - +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Net.Http.Enterprise.Tests @@ -11,20 +11,31 @@ namespace System.Net.Http.Enterprise.Tests [ConditionalClass(typeof(EnterpriseTestConfiguration), nameof(EnterpriseTestConfiguration.Enabled))] public class HttpClientAuthenticationTest { + private const string AppContextSettingName = "System.Net.Http.UsePortInSpn"; + [Theory] [InlineData(EnterpriseTestConfiguration.NegotiateAuthWebServer, false)] - [InlineData(EnterpriseTestConfiguration.AlternativeService, false)] + [InlineData(EnterpriseTestConfiguration.NegotiateAuthWebServerNotDefaultPort, false)] + [InlineData(EnterpriseTestConfiguration.AlternativeService, false, true)] [InlineData(EnterpriseTestConfiguration.DigestAuthWebServer, true)] [InlineData(EnterpriseTestConfiguration.DigestAuthWebServer, false)] [InlineData(EnterpriseTestConfiguration.NtlmAuthWebServer, true)] - public async Task HttpClient_ValidAuthentication_Success(string url, bool useDomain) + public void HttpClient_ValidAuthentication_Success(string url, bool useDomain, bool useAltPort = false) { - using var handler = new HttpClientHandler(); - handler.Credentials = useDomain ? EnterpriseTestConfiguration.ValidDomainNetworkCredentials : EnterpriseTestConfiguration.ValidNetworkCredentials; - using var client = new HttpClient(handler); + RemoteExecutor.Invoke((url, useAltPort, useDomain) => + { + // This is safe as we have no parallel tests + if (!string.IsNullOrEmpty(useAltPort)) + { + AppContext.SetSwitch(AppContextSettingName, true); + } + using var handler = new HttpClientHandler(); + handler.Credentials = string.IsNullOrEmpty(useDomain) ? EnterpriseTestConfiguration.ValidNetworkCredentials : EnterpriseTestConfiguration.ValidDomainNetworkCredentials; + using var client = new HttpClient(handler); - using HttpResponseMessage response = await client.GetAsync(url); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); + using HttpResponseMessage response = client.GetAsync(url).GetAwaiter().GetResult(); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + }, url, useAltPort ? "true" : "" , useDomain ? "true" : "").Dispose(); } [ActiveIssue("https://github.com/dotnet/runtime/issues/416")] diff --git a/src/libraries/System.Net.Http/tests/EnterpriseTests/System.Net.Http.Enterprise.Tests.csproj b/src/libraries/System.Net.Http/tests/EnterpriseTests/System.Net.Http.Enterprise.Tests.csproj index 5d1c6c09b403ec..4af21d65d63e26 100644 --- a/src/libraries/System.Net.Http/tests/EnterpriseTests/System.Net.Http.Enterprise.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/EnterpriseTests/System.Net.Http.Enterprise.Tests.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser + true @@ -8,4 +9,4 @@ - \ No newline at end of file +