dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.86k stars 4.62k forks source link

SmtpClient NTLM and Kerberos testing #19436

Open CIPop opened 7 years ago

CIPop commented 7 years ago

Per offline SCRUM discussion: add e2e NTLM/Kerberos testing for SmtpClient authentication. Example: https://github.com/dotnet/corefx/blob/master/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs

/cc: @karelz @Priya91

CIPop commented 7 years ago

Testing this would require Nego infrastructure (Active Directory, a SMTP server that understands NTLM/Kerberos, etc).

karelz commented 4 years ago

Triage: This will likely fall out of @davidsh's enterprise scenarios testing effort which is under way.

filipnavara commented 2 years ago

In the prototype branch for issue #70909 I added a test that runs against the fake Negotiate / NTLM server inside the loopback server. Obviously that's not going to cover Kerberos but it seems like an easiest path to get some coverage for the authentication code paths.

filipnavara commented 4 weeks ago

@jborean93 created a proof-of-concept for testing against custom local KDC much like we already do on Linux/macOS - https://github.com/jborean93/LocalKdc. Unlike the Unix-based system it needs admin access to run but that's still way better than needing separate infrastructure or restarting the machine.

Do we have some outerloop test infrastructure that is run with admin rights? I am looking for some prior art.

Even if we can make this working only for local testing it would be a huge improvement.

/cc @wfurt

filipnavara commented 4 weeks ago

Turns out, with fixed realm and 4 DNS records I can make this work as non-admin too: https://github.com/filipnavara/LocalKdc/pull/new/filipnavara-dev

I setup the following DNS records to point to localhost:

dc01                        3600    IN A        127.0.0.1
_kerberos._tcp              3600    IN SRV      1 1 88 dc01.filipnavara.dev.
_kerberos._tcp.dc._msdcs    3600    IN SRV      1 1 88 dc01.filipnavara.dev.
_ldap._tcp.dc._msdcs        3600    IN SRV      1 1 389 dc01.filipnavara.dev.
jborean93 commented 4 weeks ago

@SteveSyfuhs I know this is a long shot but is there any way at all to replicate how a domain joined computer account gets its ticket for authentication? I’m hoping there is so we can test out the acceptor/inbound context through SSPI with something like the local KDC setup. I know there is an auth package to list/purge tickets as exposed through klist.exe but that seems to be about it.

jborean93 commented 4 weeks ago

Looks like it is possible with an undocumented credential type SEC_WINNT_AUTH_DATA_TYPE_KEYTAB. I've created a test that follows the workflow of https://github.com/SteveSyfuhs/DelegatedAuthentication/blob/1b099b53bf1b966b364ceab0245f658ae8e641bb/src/Shared/KeytabCredential.cs. The acceptor can use the keytab bytes as the packed credential data and is able to process the output token from the initiator.

Definitely not documented but it could be worthwhile for testing purposes.

Also credit to James Forshaw for pointing out that example from Steve’s delegation repo.

SteveSyfuhs commented 4 weeks ago

..._KEYTAB is a supported mechanism but it's actually not how Windows does machine accounts. Machine accounts are functionally just normal user accounts that call LsaLogonUser. We have a supported mechanism to configure that using ksetup.exe /setcomputerpassword: https://github.com/MicrosoftDocs/windowsserverdocs/blob/main/WindowsServerDocs/administration/windows-commands/ksetup.md

jborean93 commented 4 weeks ago

..._KEYTAB is a supported mechanism but it's actually not how Windows does machine accounts

Is is possible to have this documented officially, would love to use it officially in some of my libraries that call SSPI.

We have a supported mechanism to configure that using ksetup.exe /setcomputerpassword:

Thanks for the info. Does that mean theoretically I could just provide in the SEC_WINNT_AUTH_IDENTITY_W with the service's SPN and password to use as an inbound credential for AcceptSecurityContext? In this case I'm looking into ways to test out the acceptor scenario without necessarily be running as SYSTEM/machine account. The keytab method works but is a bit more complex than just providing the password which I'm generating manually in the test KDC.

Edit: Just tested that and it does not work, the AcceptSecurityContext call fails with SEC_E_NO_CREDENTIALS. Must be some step missing in the SSPI calls that Windows does for a computer account on logon to work with this scenario. I'll continue to use the keytab setup for my testing.

SteveSyfuhs commented 4 weeks ago

You will also have to disable PAC validation since your KDC doesn't have a netlogon endpoint. You will have to run as SYSTEM still though.

Ultimately your approach works fine and it might be less hassle in the long run since you don't have to deal with key normalization.