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

Fix NTLM authentication from macOS to Windows machines #54101

Merged
merged 5 commits into from
Jun 14, 2021

Conversation

filipnavara
Copy link
Member

The GSSAPI implementation on macOS has partially broken NTLM implementation. It only supports NTLMv2 with the message integrity code (MIC) as specified by the MS-NLMP specification. The MIC is calculated using HMAC-MD5 authentication code over the exchanged NTLM messages with a key named ExportedSessionKey. The proper generation of ExportedSessionKey requires the implementation to negotiate correct capabilities, namely NTLMSSP_NEGOTIATE_KEY_EXCH and at least one of NTLMSSP_NEGOTIATE_SIGN or NTLMSSP_NEGOTIATE_SEAL flags. By default the macOS implementation negotiates NTLMSSP_NEGOTIATE_KEY_EXCH and sends MIC but fails to set one of the additional flags that would make the key exchange valid. This results in violation of the following part of the NTLM specification:

A session key MUST always exist to generate the MIC (section 3.1.5.1.2) in the authenticate message. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client.

Adding the GSS_C_INTEG_FLAG flag forces macOS to properly negotiate all the necessary flags (NTLMSSP_NEGOTIATE_ALWAYS_SIGN and NTLMSSP_NEGOTIATE_SIGN) to make the MIC exchange valid. This in turn enables the whole NTLM exchange to be recognized as valid by Windows server side.

The gss-ntlmssp package on Linux interprets the GSS_C_INTEG_FLAG flag as additional negotiation of NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_KEY_EXCH. That should not hurt anything and in fact it may improve security depending on specific configuration. The flag was already specified when NTLM was used by System.Net.Mail.SmtpClient.

Fixes #887

The GSSAPI implementation on macOS has partially broken NTLM implementation. It only supports NTLMv2 with the message integrity code (MIC) as specified by the MS-NLMP specification. The MIC is calculated using HMAC-MD5 authentication code over the exchanged NTLM messages with a key named ExportedSessionKey. The proper generation of ExportedSessionKey requires the implementation to negotiate correct capabilities, namely NTLMSSP_NEGOTIATE_KEY_EXCH and at least one of NTLMSSP_NEGOTIATE_SIGN or NTLMSSP_NEGOTIATE_SEAL flags. By default the macOS implementation negotiates NTLMSSP_NEGOTIATE_KEY_EXCH and sends MIC but fails to set one of the additional flags that would make the key exchange valid. This results in violation of the following part of the NTLM specification:

"A session key MUST always exist to generate the MIC (section 3.1.5.1.2) in the authenticate message. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client."

Adding the GSS_C_INTEG_FLAG flag forces macOS to properly negitiate all the necessary flags (NTLMSSP_NEGOTIATE_ALWAYS_SIGN and NTLMSSP_NEGOTIATE_SIGN) to make the MIC exchange valid. This in turn enables the whole NTLM exchange to be recognized as valid by Windows server side.

The gss-ntlmssp package on Linux interprets the GSS_C_INTEG_FLAG flag as additional negotiation of NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_KEY_EXCH. That should not hurt anything and in fact it may improve security depending on specific configuration. The flag was already specified when NTLM was used by System.Net.Mail.SmtpClient.
…platforms

Notably this is expected to fail on Android and tvOS where GSSAPI is not available.

The test machine is single purpose virtual machine running in Azure with clean Windows Server 2019 installation and all the patches. It hosts IIS with single static page behind an NT authentication. The test account and the machine itself is disposable and does NOT contain any sensitive data. Nevertheless I don't expect this test to be merged.
@ghost
Copy link

ghost commented Jun 12, 2021

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

Issue Details

The GSSAPI implementation on macOS has partially broken NTLM implementation. It only supports NTLMv2 with the message integrity code (MIC) as specified by the MS-NLMP specification. The MIC is calculated using HMAC-MD5 authentication code over the exchanged NTLM messages with a key named ExportedSessionKey. The proper generation of ExportedSessionKey requires the implementation to negotiate correct capabilities, namely NTLMSSP_NEGOTIATE_KEY_EXCH and at least one of NTLMSSP_NEGOTIATE_SIGN or NTLMSSP_NEGOTIATE_SEAL flags. By default the macOS implementation negotiates NTLMSSP_NEGOTIATE_KEY_EXCH and sends MIC but fails to set one of the additional flags that would make the key exchange valid. This results in violation of the following part of the NTLM specification:

A session key MUST always exist to generate the MIC (section 3.1.5.1.2) in the authenticate message. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client.

Adding the GSS_C_INTEG_FLAG flag forces macOS to properly negotiate all the necessary flags (NTLMSSP_NEGOTIATE_ALWAYS_SIGN and NTLMSSP_NEGOTIATE_SIGN) to make the MIC exchange valid. This in turn enables the whole NTLM exchange to be recognized as valid by Windows server side.

The gss-ntlmssp package on Linux interprets the GSS_C_INTEG_FLAG flag as additional negotiation of NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_KEY_EXCH. That should not hurt anything and in fact it may improve security depending on specific configuration. The flag was already specified when NTLM was used by System.Net.Mail.SmtpClient.

Fixes #887

Author: filipnavara
Assignees: -
Labels:

area-System.Net.Security

Milestone: -

@filipnavara
Copy link
Member Author

Due to lack of sufficient testing infrastructure I opted to add a temporary test that connects to a Windows Server 2019 running in disposable Azure virtual machine. I do not intend to include the test permanently and I'll remove it before switching the PR from draft status.

@filipnavara
Copy link
Member Author

filipnavara commented Jun 12, 2021

The results from the CI on Linux are somewhat mixed:

  • Failed authentication on RedHat 7, Ubuntu 16.04, Ubuntu 18.04
  • Missing gss-ntlmssp package on Centos 8, Debian 10, Fedora 30, Alpine 3.12
  • Cannot find KDC for realm "emclientntlm.westus.cloudapp.azure.com" on SLES 15 (possibly missing package as well)
It's hard to say whether the failed authentication is result of the change or whether it never really worked in the first place (for a given server and parameters). I suppose it would be reasonable to open another PR just with the test for comparison (#54104).

The failures are result of the full domain name being used in the test. Specifying just emclientntlm instead works.

Predictably Windows and macOS passed just fine.

@filipnavara filipnavara marked this pull request as ready for review June 12, 2021 14:52
@wfurt
Copy link
Member

wfurt commented Jun 12, 2021

Linux should be covered somewhat by the "Enterprise tests". It would be interesting to know if the Ubuntu 18.04 would pass without the change or if there is some general incompatibility.
While we don't have automated run for macOS, one can build the docker container.
I'll build your change next week and I'll give it some try in my old setup.

@filipnavara
Copy link
Member Author

I run three variations of the PR on the CI servers and connecting to my virtual machine.

The Linux machines that have gss-ntlmssp installed successfully connected both with and without this PR when the NETBIOS name was used as domain. The same machines consistently didn't connect when full DNS name was used for the domain.

macOS now connects both with the NETBIOS domain name and the full DNS one.

It would be useful to run the enterprise tests but I expect them to work just fine.

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

@wfurt wfurt merged commit 17481fe into dotnet:main Jun 14, 2021
@filipnavara filipnavara deleted the ntauth-macos branch June 14, 2021 15:42
@filipnavara
Copy link
Member Author

Thanks for review! Glad to make it in the Preview 6 timeframe 😅

@ghost ghost locked as resolved and limited conversation to collaborators Jul 14, 2021
@karelz karelz added this to the 6.0.0 milestone Jul 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NTLM interop problems with MacOS
3 participants