You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WCF on Linux - Kerberos Authentication with UpnEndpointIdentity seems to be sending the wrong name-type to the KDC. #31040
So I'm really struggling with getting a .NET Core app running on Linux because of Kerberos. The app is a client that is communicating with a WCF service running on a windows server. The Service runs under a service account, so the client specifies a UpnEndpointIdentity. This works great on windows, but when trying to run it on Ubuntu, I'm getting GSSAPI errors. Specifically this:
System.ServiceModel.Security.SecurityNegotiationException: Authentication failed, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090020): GSSAPI operation failed with error - Unspecified GSS failure. Minor code may provide more information (Server not found in Kerberos database).
I'm no Kerberos expert, but I've started to dig into the Wireshark traces and it looks like on windows it's sending a request to the KDC with an sname name-type of kRB5-NT-SRV-HST (3). On Ubuntu, it's instead sending name-type: kRB5-NT-PRINCIPAL (1). The KDC is rejecting the request with KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, which makes sense since the client is asking for a host instead of a principal.
Also, I'm able to correctly acquire a service ticket using kgetcred for the UPN, and I can see it correctly sent in the wireshark trace. Is this a bug in .NET Cores interaction with GSSAPI, or WCF, or am I just missing something? @davidsh Wrote some of this code so I'm hoping he can help.
I'm happy to provide the Wireshark traces if that will help, or any more details needed.
We made a great deal of fixes for Kerberos related scenarios in .NET Core 3.0. These fixes are not all backported to .NET Core 2.1/2.2.
What exact version of .NET Core are you using? Please show dotnet --info output. If running .NET Core 2.1 or 2.2, please update to the very latest servicing release.
I suggest you try .NET Core 3.0 to see if it works better. However, we still have some limitations with UPNs compared with our SPN support. See: #16576.
Also, in order to fully diagnose this, please attach a repro client/server solution so that we can try it out.
Here is the output from KR5_TRACE (I've replaced our domain with Corp.Test.Lcl):
[2986] 1570024870.140256: ccselect module hostname chose cache FILE:/tmp/krb5cc_1000 with client principal jpwingfield@corp.test.lcl for server principal svcAXBCPDV/corp.test.lcl@test.lcl
[2986] 1570024870.140257: Getting credentials jpwingfield@corp.test.lcl -> svcAXBCPDV/corp.test.lcl@ using ccache FILE:/tmp/krb5cc_1000
[2986] 1570024870.140258: Retrieving jpwingfield@corp.test.lcl -> svcAXBCPDV/corp.test.lcl@ from FILE:/tmp/krb5cc_1000 with result: -1765328243/Matching credential not found (filename: /tmp/krb5cc_1000)
[2986] 1570024870.140259: Retrying jpwingfield@corp.test.lcl -> svcAXBCPDV/corp.test.lcl@corp.test.lcl with result: -1765328243/Matching credential not found (filename: /tmp/krb5cc_1000)
[2986] 1570024870.140260: Server has referral realm; starting with svcAXBCPDV/corp.test.lcl@corp.test.lcl
[2986] 1570024870.140261: Retrieving jpwingfield@corp.test.lcl -> krbtgt/corp.test.lcl@corp.test.lcl from FILE:/tmp/krb5cc_1000 with result: 0/Success
[2986] 1570024870.140262: Starting with TGT for client realm: jpwingfield@corp.test.lcl -> krbtgt/corp.test.lcl@corp.test.lcl
[2986] 1570024870.140263: Requesting tickets for svcAXBCPDV/corp.test.lcl@corp.test.lcl, referrals on
[2986] 1570024870.140264: Generated subkey for TGS request: aes256-cts/1635
[2986] 1570024870.140265: etypes requested in TGS request: aes256-cts, aes128-cts, aes256-sha2, aes128-sha2, des3-cbc-sha1, rc4-hmac, camellia128-cts, camellia256-cts
[2986] 1570024870.140267: Encoding request body and padata into FAST request
[2986] 1570024870.140268: Sending request (6800 bytes) to corp.test.lcl
[2986] 1570024870.140269: Resolving hostname CLWDSPD02.corp.test.lcl
[2986] 1570024870.140270: Initiating TCP connection to stream 10.10.7.3:88
[2986] 1570024870.140271: Sending TCP request to stream 10.10.7.3:88
[2986] 1570024870.140272: Received answer (102 bytes) from stream 10.10.7.3:88
[2986] 1570024870.140273: Terminating TCP connection to stream 10.10.7.3:88
[2986] 1570024870.140274: Sending DNS URI query for _kerberos.corp.test.lcl.
[2986] 1570024870.140275: No URI records found
[2986] 1570024870.140276: Sending DNS SRV query for _kerberos-master._udp.corp.test.lcl.
[2986] 1570024870.140277: Sending DNS SRV query for _kerberos-master._tcp.corp.test.lcl.
[2986] 1570024870.140278: No SRV records found
[2986] 1570024870.140279: Response was not from master KDC
[2986] 1570024870.140280: TGS request result: -1765328377/Server not found in Kerberos database
[2986] 1570024870.140281: Local realm referral failed; trying fallback realm test.lcl
[2986] 1570024870.140282: Retrieving jpwingfield@corp.test.lcl -> krbtgt/test.lcl@test.lcl from FILE:/tmp/krb5cc_1000 with result: -1765328243/Matching credential not found (filename: /tmp/krb5cc_1000)
[2986] 1570024870.140283: Retrieving jpwingfield@corp.test.lcl -> krbtgt/corp.test.lcl@corp.test.lcl from FILE:/tmp/krb5cc_1000 with result: 0/Success
[2986] 1570024870.140284: Starting with TGT for client realm: jpwingfield@corp.test.lcl -> krbtgt/corp.test.lcl@corp.test.lcl
[2986] 1570024870.140285: Retrieving jpwingfield@corp.test.lcl -> krbtgt/test.lcl@test.lcl from FILE:/tmp/krb5cc_1000 with result: -1765328243/Matching credential not found (filename: /tmp/krb5cc_1000)
[2986] 1570024870.140286: Requesting TGT krbtgt/test.lcl@corp.test.lcl using TGT krbtgt/corp.test.lcl@corp.test.lcl
[2986] 1570024870.140287: Generated subkey for TGS request: aes256-cts/7285
[2986] 1570024870.140288: etypes requested in TGS request: aes256-cts, aes128-cts, aes256-sha2, aes128-sha2, des3-cbc-sha1, rc4-hmac, camellia128-cts, camellia256-cts
[2986] 1570024870.140290: Encoding request body and padata into FAST request
[2986] 1570024870.140291: Sending request (6782 bytes) to corp.test.lcl
[2986] 1570024870.140292: Resolving hostname CLWDSPD02.corp.test.lcl
[2986] 1570024870.140293: Initiating TCP connection to stream 10.10.7.3:88
[2986] 1570024870.140294: Sending TCP request to stream 10.10.7.3:88
[2986] 1570024870.140295: Received answer (93 bytes) from stream 10.10.7.3:88
[2986] 1570024870.140296: Terminating TCP connection to stream 10.10.7.3:88
[2986] 1570024870.140297: Sending DNS URI query for _kerberos.corp.test.lcl.
[2986] 1570024870.140298: No URI records found
[2986] 1570024870.140299: Sending DNS SRV query for _kerberos-master._udp.corp.test.lcl.
[2986] 1570024870.140300: Sending DNS SRV query for _kerberos-master._tcp.corp.test.lcl.
[2986] 1570024870.140301: No SRV records found
[2986] 1570024870.140302: Response was not from master KDC
[2986] 1570024870.140303: TGS request result: -1765328377/Server not found in Kerberos database
10.10.7.3 is the KDC. svcAXBCPDV@corp.test.lcl is the UPN that the WCF service is running under, and the UPN we're providing on the client. This matches what I'm seeing in Wireshark almost exactly.
One note: the additional query for krbtgt/test.lcl@test.lcl is strange. That's not happening on windows.
The name-type is only ever really used as a hint in the AD KDC. Can you confirm the name-string values actually match between the Windows and Linux requests? Often there's some canonicalization going on or there's a mixup in service type in the SPN.
WCF can't implement this for the HTTP transport because of a missing feature in HttpClientHandler compared with .NET Framework. The issue I've opened to request this missing feature is #25320. I suggest adding a thumbs up on the first comment to register that you need this. Currently SpnIdentity won't work either. Recently a sort of workaround was added to HttpClientHandler where you can indirectly specify an SPN by adding a HOST header with that SPN. But that is just a hack which won't work in some scenarios. Rather than WCF implement a partial solution which will only work sometimes and will cause confusion, I would prefer that issue #25320 is addressed. If you want to do this yourself, WCF has an extensibility point so you can do this yourself. There's a blog post which outlines the general approach that someone wrote up. There's also a pretty good example here of how to use this by providing a delegating handler. In your delegating handler you would add a Host header before you call SendAsync on the wrapped handler.
That I can't answer without debugging or reviewing code. The fully qualified name is most likely just what's being passed to the API and is _that_ value because of what @mconnew is suggesting.
In the Windows dump, you can see it's using the name-type "kRB5-NT-PRINCIPAL" which can be either an SPN or a UPN. In the Linux dump, it's using the type "kRB5-NT-SRV-HST" which I believe can't be used for UPN's.
Edit: I was wrong. According to the RFC in section 5.5:
name-type
This field specifies the type of name that follows. Pre-defined
values for this field are specified in Section 6.2. The name-type
SHOULD be treated as a hint. Ignoring the name type, no two names
can be the same (i.e., at least one of the components, or the
realm, must be different).
In the Linux dump, it's using the type "kRB5-NT-SRV-HST" which I believe can't be used for UPN's.
We currently always use this type instead of kRB5-NT-PRINCIPAL. That is because it is the only thing that works correctly with SPNEGO protocol and can handle Kerberos to NTLM fallback.
I'll have a minimal project with client and server to share tomorrow. This is really the most basic situation ever though. Generate new Wcf Service, host under a service account, bind a corefx client to it, run corefx project under Linux. I just want to make sure it reproduces in this minimal form on our infrastructure before sending it over.
I was just wondering if there is a solution for this problem somewhere?
Although I do not have the knowledge on display in this thread, I do have very similar problems. I have a very simple .netcore (3.1.401) console app, comparable to the app that is referenced above - trying to make requests to a WCF service (net.tcp/AX) from a CentOS 7 environment. Kerberos is setup - to my knowledge - correctly (not by me, by professionals within this area of expertise) and the code itself is quite similar to @jonwingfield 's. Just a simple "authenticate and get some data, please".
I've used svcutil to generate the code needed from the WSDL, and used a so called CustomerServiceClient using credentials and context that should be correct.
I believe I am not capable of hitting the service at all, I am stopped at the exactly same point with a very similar KRB5 trace as above, and the exact same stacktrace from the program itself:
System.ServiceModel.Security.SecurityNegotiationException: Authentication failed, see inner exception. ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> System.ComponentModel.Win32Exception (0x80090020): GSSAPI operation failed with error - Unspecified GSS failure. Minor code may provide more information (**Server not found in Kerberos database**).
Of course I will supply logs & code if necessary, I was just wondering if there is a magic solution or at least further development that I can explore.
Server not found in Kerberos database means the SPN of the target server used by the client doesn't match anything on record in AD. Find out what SPN is being used and update the client to use it, or update the AD service account with the SPN that's actually being used.
@joakimobstfelder, look at the generated code for where an EndpointAddress is constructed. One of the parameters passed to the EndpointAddress constructor will be an EndpointIdentity. Depending on how the server is being run, it could be either an SpnEndpointIdentity or a UpnEndpointIdentity. This needs to be set correctly. If it's using the EndpointAddress overload where an identity isn't provided, the the spn that the client will use is based on the hostname your provide to WCF.
You can check which Spn/Upn is being used by the service by looking at the wsdl in a text editor. It should be quite obvious. If it isn't, feel free to provide the wsdl and I'll take a look.
Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.
This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.
Activity
davidsh commentedon Oct 2, 2019
We made a great deal of fixes for Kerberos related scenarios in .NET Core 3.0. These fixes are not all backported to .NET Core 2.1/2.2.
What exact version of .NET Core are you using? Please show
dotnet --infooutput. If running .NET Core 2.1 or 2.2, please update to the very latest servicing release.I suggest you try .NET Core 3.0 to see if it works better. However, we still have some limitations with UPNs compared with our SPN support. See: #16576.
Also, in order to fully diagnose this, please attach a repro client/server solution so that we can try it out.
jonwingfield commentedon Oct 2, 2019
Hi @davidsh and thanks for the quick response. We're on .NET Core 3.0. We noticed a lot of changes for Windows Auth in 3.0 so we immediately upgraded.
I'll work on getting a repro put together. In the meantime, should we try
SpnEndpointIdentityas a workaround? That seems like a reasonable option?davidsh commentedon Oct 2, 2019
Yes, that would be a good workaround potentially.
Also, please show a KRB5_TRACE for your application. It will show useful output.
Run this command before running your application:
export KRB5_TRACE=/dev/stdoutdavidsh commentedon Oct 2, 2019
cc: @mconnew
jonwingfield commentedon Oct 2, 2019
Here is the output from KR5_TRACE (I've replaced our domain with Corp.Test.Lcl):
10.10.7.3 is the KDC. svcAXBCPDV@corp.test.lcl is the UPN that the WCF service is running under, and the UPN we're providing on the client. This matches what I'm seeing in Wireshark almost exactly.
One note: the additional query for krbtgt/test.lcl@test.lcl is strange. That's not happening on windows.
SteveSyfuhs commentedon Oct 2, 2019
The name-type is only ever really used as a hint in the AD KDC. Can you confirm the
name-stringvalues actually match between the Windows and Linux requests? Often there's some canonicalization going on or there's a mixup in service type in the SPN.mconnew commentedon Oct 2, 2019
WCF can't implement this for the HTTP transport because of a missing feature in HttpClientHandler compared with .NET Framework. The issue I've opened to request this missing feature is #25320. I suggest adding a thumbs up on the first comment to register that you need this. Currently SpnIdentity won't work either. Recently a sort of workaround was added to HttpClientHandler where you can indirectly specify an SPN by adding a HOST header with that SPN. But that is just a hack which won't work in some scenarios. Rather than WCF implement a partial solution which will only work sometimes and will cause confusion, I would prefer that issue #25320 is addressed. If you want to do this yourself, WCF has an extensibility point so you can do this yourself. There's a blog post which outlines the general approach that someone wrote up. There's also a pretty good example here of how to use this by providing a delegating handler. In your delegating handler you would add a Host header before you call SendAsync on the wrapped handler.
jonwingfield commentedon Oct 3, 2019
@SteveSyfuhs
They're slightly different. On Ubuntu, it's sending this in the request-body:
On Windows, it's:
Could it be the extra sname string for the realm? I'm using the same UPN in both (svcAXBCPDV@corp.test.lcl).
SteveSyfuhs commentedon Oct 3, 2019
jonwingfield commentedon Oct 3, 2019
@SteveSyfuhs but why is it being sent this way? Are there details in GSSAPI that are causing it to be handled differently?
SteveSyfuhs commentedon Oct 3, 2019
mconnew commentedon Oct 3, 2019
In the Windows dump, you can see it's using the name-type "kRB5-NT-PRINCIPAL" which can be either an SPN or a UPN. In the Linux dump, it's using the type "kRB5-NT-SRV-HST" which I believe can't be used for UPN's.
Edit: I was wrong. According to the RFC in section 5.5:
davidsh commentedon Oct 3, 2019
We currently always use this type instead of kRB5-NT-PRINCIPAL. That is because it is the only thing that works correctly with SPNEGO protocol and can handle Kerberos to NTLM fallback.
See:
https://github.com/dotnet/corefx/blob/eff9fbf446468ca411bf5e0475916f316eea7223/src/Native/Unix/System.Net.Security.Native/pal_gssapi.c#L157-L179
Long term, we need to probably adjust this if we know that we are using a UPN and not SPN.
jonwingfield commentedon Oct 4, 2019
@davidsh Is this known to work with UPNs though?
I'll have a minimal project with client and server to share tomorrow. This is really the most basic situation ever though. Generate new Wcf Service, host under a service account, bind a corefx client to it, run corefx project under Linux. I just want to make sure it reproduces in this minimal form on our infrastructure before sending it over.
davidsh commentedon Oct 4, 2019
Probably not. See related issue #16576
11 remaining items
joakimobstfelder commentedon Aug 27, 2020
Hi!
I was just wondering if there is a solution for this problem somewhere?
Although I do not have the knowledge on display in this thread, I do have very similar problems. I have a very simple .netcore (3.1.401) console app, comparable to the app that is referenced above - trying to make requests to a WCF service (net.tcp/AX) from a CentOS 7 environment. Kerberos is setup - to my knowledge - correctly (not by me, by professionals within this area of expertise) and the code itself is quite similar to @jonwingfield 's. Just a simple "authenticate and get some data, please".
I've used svcutil to generate the code needed from the WSDL, and used a so called CustomerServiceClient using credentials and context that should be correct.
I believe I am not capable of hitting the service at all, I am stopped at the exactly same point with a very similar KRB5 trace as above, and the exact same stacktrace from the program itself:
System.ServiceModel.Security.SecurityNegotiationException: Authentication failed, see inner exception. ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> System.ComponentModel.Win32Exception (0x80090020): GSSAPI operation failed with error - Unspecified GSS failure. Minor code may provide more information (**Server not found in Kerberos database**).Of course I will supply logs & code if necessary, I was just wondering if there is a magic solution or at least further development that I can explore.
Cheers, Joakim
SteveSyfuhs commentedon Aug 27, 2020
As mentioned in the comment above: #31040 (comment)
Server not found in Kerberos database means the SPN of the target server used by the client doesn't match anything on record in AD. Find out what SPN is being used and update the client to use it, or update the AD service account with the SPN that's actually being used.
mconnew commentedon Sep 1, 2020
@joakimobstfelder, look at the generated code for where an EndpointAddress is constructed. One of the parameters passed to the EndpointAddress constructor will be an EndpointIdentity. Depending on how the server is being run, it could be either an SpnEndpointIdentity or a UpnEndpointIdentity. This needs to be set correctly. If it's using the EndpointAddress overload where an identity isn't provided, the the spn that the client will use is based on the hostname your provide to WCF.
You can check which Spn/Upn is being used by the service by looking at the wsdl in a text editor. It should be quite obvious. If it isn't, feel free to provide the wsdl and I'll take a look.
dotnet-policy-service commentedon Mar 4, 2025
Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.
This process is part of our issue cleanup automation.
dotnet-policy-service commentedon Mar 18, 2025
This issue will now be closed since it had been marked
no-recent-activitybut received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.