Skip to content

Commit

Permalink
Use managed ntlm on linux-bionic (#95274)
Browse files Browse the repository at this point in the history
* Use managed ntlm on linux-bionic

* Fix failing unit test

* Fix compilation

* Enable more tests on ubuntu-bionic

* Change runtime identifier check to regex

* Revert "Change runtime identifier check to regex"

This reverts commit 82c1136.

* add hyphen to startswith

* Update src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs

Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>

---------

Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
  • Loading branch information
rzikm and am11 authored Nov 29, 2023
1 parent 2046432 commit c0dfcfd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,19 @@ private static string GetGssApiDisplayStatus(Status majorStatus, Status minorSta

private static string? GetGssApiDisplayStatus(Status status, bool isMinor)
{
if (!System.Net.NegotiateAuthenticationPal.HasSystemNetSecurityNative)
{
// avoid calling into libSystem.Net.Security.Native.
return null;
}

GssBuffer displayBuffer = default(GssBuffer);

try
{
Interop.NetSecurityNative.Status minStat;
Interop.NetSecurityNative.Status displayCallStatus = isMinor ?
DisplayMinorStatus(out minStat, status, ref displayBuffer):
DisplayMinorStatus(out minStat, status, ref displayBuffer) :
DisplayMajorStatus(out minStat, status, ref displayBuffer);
return (Status.GSS_S_COMPLETE != displayCallStatus) ? null : Marshal.PtrToStringUTF8(displayBuffer._data);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

namespace System.Net.Test.Common
{
public static partial class Capability
{
public static bool IsNtlmInstalled()
{
// GSS on Linux does not work with OpenSSL 3.0. Fix was submitted to gss-ntlm but it will take a while to make to
// all supported distributions. The second part of the check should be removed when it does.
return Interop.NetSecurityNative.IsNtlmInstalled() && (!PlatformDetection.IsOpenSslSupported || PlatformDetection.OpenSslVersion.Major < 3);
return
// Linux bionic uses managed NTLM implementation
(OperatingSystem.IsLinux() && RuntimeInformation.RuntimeIdentifier.StartsWith("linux-bionic-", StringComparison.Ordinal)) ||
// GSS on Linux does not work with OpenSSL 3.0. Fix was submitted to gss-ntlm but it will take a while to make to
// all supported distributions. The second part of the check should be removed when it does.
Interop.NetSecurityNative.IsNtlmInstalled() && (!PlatformDetection.IsOpenSslSupported || PlatformDetection.OpenSslVersion.Major < 3);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ namespace System.Net
{
internal partial class NegotiateAuthenticationPal
{
private static readonly Lazy<bool> _hasSystemNetSecurityNative = new Lazy<bool>(CheckHasSystemNetSecurityNative);
internal static bool HasSystemNetSecurityNative => _hasSystemNetSecurityNative.Value;
private static bool UseManagedNtlm { get; } =
AppContext.TryGetSwitch("System.Net.Security.UseManagedNtlm", out bool useManagedNtlm) ?
useManagedNtlm :
OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsMacCatalyst();
OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsMacCatalyst() ||
(OperatingSystem.IsLinux() && RuntimeInformation.RuntimeIdentifier.StartsWith("linux-bionic-", StringComparison.OrdinalIgnoreCase));

public static NegotiateAuthenticationPal Create(NegotiateAuthenticationClientOptions clientOptions)
{
Expand All @@ -34,7 +37,7 @@ public static NegotiateAuthenticationPal Create(NegotiateAuthenticationClientOpt
return ManagedNtlmNegotiateAuthenticationPal.Create(clientOptions);

case NegotiationInfoClass.Negotiate:
return new ManagedSpnegoNegotiateAuthenticationPal(clientOptions, supportKerberos: true);
return new ManagedSpnegoNegotiateAuthenticationPal(clientOptions, supportKerberos: HasSystemNetSecurityNative);
}
}

Expand Down Expand Up @@ -559,7 +562,8 @@ private NegotiateAuthenticationStatusCode InitializeSecurityContext(
{
if (NetEventSource.Log.IsEnabled())
{
string protocol = _packageType switch {
string protocol = _packageType switch
{
Interop.NetSecurityNative.PackageType.NTLM => "NTLM",
Interop.NetSecurityNative.PackageType.Kerberos => "Kerberos",
_ => "SPNEGO"
Expand Down Expand Up @@ -635,7 +639,8 @@ private NegotiateAuthenticationStatusCode InitializeSecurityContext(
{
if (NetEventSource.Log.IsEnabled())
{
string protocol = _packageType switch {
string protocol = _packageType switch
{
Interop.NetSecurityNative.PackageType.NTLM => "NTLM",
Interop.NetSecurityNative.PackageType.Kerberos => "Kerberos",
_ => isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos"
Expand Down Expand Up @@ -764,5 +769,18 @@ internal static NegotiateAuthenticationStatusCode GetErrorCode(Interop.NetSecuri
}
}
}

public static bool CheckHasSystemNetSecurityNative()
{
try
{
return Interop.NetSecurityNative.IsNtlmInstalled();
}
catch (Exception e) when (e is EntryPointNotFoundException || e is DllNotFoundException || e is TypeInitializationException)
{
// libSystem.Net.Security.Native is not available
return false;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public void Constructor_Overloads_Validation()
}

[Fact]
[SkipOnPlatform(TestPlatforms.LinuxBionic, "https://github.com/dotnet/runtime/issues/93104")]
public void RemoteIdentity_ThrowsOnUnauthenticated()
{
NegotiateAuthenticationClientOptions clientOptions = new NegotiateAuthenticationClientOptions { Credential = s_testCredentialRight, TargetName = "HTTP/foo" };
Expand Down Expand Up @@ -66,7 +65,6 @@ public void RemoteIdentity_ThrowsOnDisposed()
}

[Fact]
[SkipOnPlatform(TestPlatforms.LinuxBionic, "https://github.com/dotnet/runtime/issues/93104")]
public void Package_Unsupported()
{
NegotiateAuthenticationClientOptions clientOptions = new NegotiateAuthenticationClientOptions { Package = "INVALID", Credential = s_testCredentialRight, TargetName = "HTTP/foo" };
Expand Down Expand Up @@ -98,7 +96,6 @@ public void Package_Unsupported_NTLM()

[Fact]
[SkipOnPlatform(TestPlatforms.Windows, "The test is specific to GSSAPI / Managed implementations of NegotiateAuthentication")]
[SkipOnPlatform(TestPlatforms.LinuxBionic, "https://github.com/dotnet/runtime/issues/93104")]
public void DefaultNetworkCredentials_NTLM_DoesNotThrow()
{
NegotiateAuthenticationClientOptions clientOptions = new NegotiateAuthenticationClientOptions { Package = "NTLM", Credential = CredentialCache.DefaultNetworkCredentials, TargetName = "HTTP/foo" };
Expand Down Expand Up @@ -169,7 +166,7 @@ public static IEnumerable<object[]> TestCredentials()
yield return new object[] { new NetworkCredential("rightusername", "rightpassword") };
yield return new object[] { new NetworkCredential("rightusername", "rightpassword", "rightdomain") };
yield return new object[] { new NetworkCredential("rightusername@rightdomain.com", "rightpassword") };
}
}

[ConditionalTheory(nameof(IsNtlmAvailable))]
[MemberData(nameof(TestCredentials))]
Expand Down

0 comments on commit c0dfcfd

Please sign in to comment.