Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure NegotiateAuthentication implementation #87930

Merged
merged 21 commits into from
Jul 18, 2023

Conversation

filipnavara
Copy link
Member

@filipnavara filipnavara commented Jun 22, 2023

Change NegotiateAuthentication implementation to use indirection through NegotiateAuthenticationPal to the actual implementation.

The PAL implementations are merged from different sources to follow the same structure:

  • NTAuthentication.Managed.cs -> NegotiateAuthenticationPal.Managed.cs + NegotiateAuthenticationPal.ManagedNtlm.cs + NegotiateAuthenticationPal.ManagedSpnego.cs
  • NTAuthentication.Common.cs + NegotiateStreamPal.Windows.cs -> NegotiateAuthenticationPal.Windows.cs
  • NTAuthentication.Common.cs + NegotiateStreamPal.Unix.cs -> NegotiateAuthenticationPal.Unix.cs

This split allows to delete ContextFlagsPal, SafeDeleteNegoContext, and SafeFreeNegoCredentials abstractions that were used in NegotiateStreamPal.

Additionally, a new app context option is added (System.Net.Security.UseManagedNtlm) to unconditionally turn on managed implementation of NTLM and SPNEGO on Unix-like platforms. On Linux systems without NTLM GSSAPI provider the managed NTLM and SPNEGO implementations are turned on by default, they can be turned off by setting the System.Net.Security.UseManagedNtlm option to false.

Contributes to #87665, #80846

…ugh NegotiateAuthenticationPal to the actual implementation.

The PAL implementation are merged from different sources to follow the same structure:
- NTAuthentication.Managed.cs -> NegotiateAuthenticationPal.Managed.cs
- NTAuthentication.Common.cs + NegotiateStreamPal.Windows.cs -> NegotiateAuthenticationPal.Windows.cs
- NTAuthentication.Common.cs + NegotiateStreamPal.Unix.cs -> NegotiateAuthenticationPal.Unix.cs

This split allows to delete ContextFlagsPal, SafeDeleteNegoContext, and SafeFreeNegoCredentials abstractions that were used in NegotiateStreamPal.
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Jun 22, 2023
@ghost
Copy link

ghost commented Jun 22, 2023

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

[NOT FOR REVIEW YET, JUST WANT TO RUN THROUGH CI]

Change NegotiateAuthentication implementation to use indirection through NegotiateAuthenticationPal to the actual implementation.

The PAL implementation are merged from different sources to follow the same structure:

  • NTAuthentication.Managed.cs -> NegotiateAuthenticationPal.Managed.cs
  • NTAuthentication.Common.cs + NegotiateStreamPal.Windows.cs -> NegotiateAuthenticationPal.Windows.cs
  • NTAuthentication.Common.cs + NegotiateStreamPal.Unix.cs -> NegotiateAuthenticationPal.Unix.cs

This split allows to delete ContextFlagsPal, SafeDeleteNegoContext, and SafeFreeNegoCredentials abstractions that were used in NegotiateStreamPal.

Author: filipnavara
Assignees: -
Labels:

area-System.Net.Security, community-contribution

Milestone: -

@filipnavara
Copy link
Member Author

filipnavara commented Jun 24, 2023

@wfurt While not quite polished and ready for review yet, this implements the changes for UseManagedNtlm switch on Unix-like platforms (Linux and macOS). It doesn't contain all the fallbacks to handle missing NTLM SSP, or missing GSSAPI (Linux Bionic). It, however, implements SPNEGO over managed NTLM + native Kerberos, which passes the loopback test.

Please let me know if the general direction makes sense to you. I'm still undecided whether it would make sense to have two switches (UseManagedNtlm and UseManagedSpnego) or just one (managed NTLM implying that SPNEGO is managed too and uses managed NTLM).

Comment on lines 27 to 44
{
try
{
if (!Interop.NetSecurityNative.IsNtlmInstalled())
{
_useManagedNtlm = !AppContext.TryGetSwitch("System.Net.Security.UseManagedNtlm", out bool useManagedNtlm) || useManagedNtlm;
}
else
{
_useManagedNtlm = AppContext.TryGetSwitch("System.Net.Security.UseManagedNtlm", out bool useManagedNtlm) && useManagedNtlm;
}
_isGssApiAvailable = true;
}
catch (EntryPointNotFoundException)
{
// GSSAPI shim may not be available on some platforms (Linux Bionic)
_isGssApiAvailable = false;
}
Copy link
Member Author

@filipnavara filipnavara Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I am not entirely keen on shipping the fallbacks this way.

I propose to change it to the following:

  • Add the optional System.Net.Security.UseManagedNtlm switch and default to false.
  • Do not fallback to managed NTLM/SPNEGO if the native GSSAPI is missing NTLM-SSP (ie. align behavior with .NET 7 and older).
  • Add ILLink script that links away ManagedNtlm and ManagedSpnego unless System.Net.Security.UseManagedNtlm is set.
  • Update NativeAOT linux-bionic builds to set System.Net.Security.UseManagedNtlm=true unconditionally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to fallback to managed only for NTLM and not Negotiate if NTLM-SSP is missing? We would not interfere with negotiation in any way but it would provide some legacy capability

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, this is implementation of the proposal above: aa22b0a
It mostly reverts all the fallback paths to .NET 7 behavior and only enables them with the AppContext switch.

Doing only managed NTLM without managed SPNEGO is feasible but not very practical. HTTP servers almost universally send either Negotiate only, or both Negotiate+NTLM. In both cases this would still fail the authentication because Negotiate gets the preference. There may be some SMTP server that supports only NTLM but that's really niche use case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, if you feel like we should do ManagedNtlm-only and not ManagedSpNego for !Interop.NetSecurityNative.IsNtlmInstalled() I can do it. It will just need a re-run of the whole test matrix to figure out what breaks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about #87568 and perhaps Azure functions were there is no control over installed packages. But I guess the AppContext should be good enough for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed the one extra commit mentioned above. It passed CI in #89051 test PR except for few legs that failed due to infra failures. They are now re-running 🤞

@filipnavara
Copy link
Member Author

I assume at this point we are pretty much out of luck for .NET 8, right @wfurt? I would like to wrap this up soon anyway...

@wfurt
Copy link
Member

wfurt commented Jul 17, 2023

sorry for the delay, I will look today. can you please resolve the conflict. I saw bunch of test failures but I did not go through them.

// 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 true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the property at all? Or keep it for future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that depends on the answer in #87930 (comment). In any case I would not remove it as part of this PR, it would be separate change. Mainly there's a concern about Windows with NTLM disabled, so there would still be use for it.

filipnavara and others added 2 commits July 17, 2023 22:40
…m has to be enabled explicitly; NativeAOT on Linux Bionic does that by default because it doesn't have GSSAPI and native shim
Copy link
Member

@wfurt wfurt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. thanks @filipnavara

@wfurt
Copy link
Member

wfurt commented Jul 18, 2023

test failures seems unrelated.

@wfurt
Copy link
Member

wfurt commented Jul 18, 2023

seems like another merge conflict from #88810 @filipnavara. I can merge in the morning.

@filipnavara
Copy link
Member Author

seems like another merge conflict from #88810 @filipnavara. I can merge in the morning.

Fixed.

@wfurt wfurt merged commit f7ad726 into dotnet:main Jul 18, 2023
141 of 144 checks passed
@wfurt
Copy link
Member

wfurt commented Jul 18, 2023

thanks @filipnavara

@filipnavara
Copy link
Member Author

Thanks for review!

@filipnavara filipnavara deleted the NegotiateAuthenticationPal branch July 18, 2023 14:11
@karelz karelz added this to the 8.0.0 milestone Aug 1, 2023
@dotMorten
Copy link

dotMorten commented Aug 25, 2023

@filipnavara @wfurt I just moved from .NET 7 to .NET 8 and my IWA tests on Android are now broken hitting this bit of code this PR added:

throw new PlatformNotSupportedException(SR.net_ntlm_not_possible_default_cred);

image

@filipnavara
Copy link
Member Author

filipnavara commented Aug 25, 2023

@dotMorten Can you file issue with some small repro? That use case was definitely not supported in .NET 7 either.

@dotMorten
Copy link

Yup working on it. Definitely a regression/change in behavior over 7

@wfurt
Copy link
Member

wfurt commented Aug 25, 2023

I'm wondering if it just failed to authenticate in the past and now it throws...? As @filipnavara said, there is no default identity on Android we can use for NTLM.

@ghost ghost locked as resolved and limited conversation to collaborators Sep 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Net.Security community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants