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
+