Skip to content

WCF on Linux - Kerberos Authentication with UpnEndpointIdentity seems to be sending the wrong name-type to the KDC. #31040

Closed

Description

@jonwingfield

Hi,

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.

Thanks!

Activity

  1. davidsh commented on Oct 2, 2019

    @davidsh
    Contributor

    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.

  2. jonwingfield commented on Oct 2, 2019

    @jonwingfield
    Author

    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.

    .NET Core SDK (reflecting any global.json):
     Version:   3.0.100
     Commit:    04339c3a26
    
    Runtime Environment:
     OS Name:     ubuntu
     OS Version:  18.04
     OS Platform: Linux
     RID:         ubuntu.18.04-x64
     Base Path:   /usr/share/dotnet/sdk/3.0.100/
    
    Host (useful for support):
      Version: 3.0.0
      Commit:  95a0a61858
    
    .NET Core SDKs installed:
      2.2.402 [/usr/share/dotnet/sdk]
      3.0.100 [/usr/share/dotnet/sdk]
    
    .NET Core runtimes installed:
      Microsoft.AspNetCore.All 2.2.7 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
      Microsoft.AspNetCore.App 2.2.7 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
      Microsoft.AspNetCore.App 3.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
      Microsoft.NETCore.App 2.2.7 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
      Microsoft.NETCore.App 3.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
    
    To install additional .NET Core runtimes or SDKs:
      https://aka.ms/dotnet-download
    

    I'll work on getting a repro put together. In the meantime, should we try SpnEndpointIdentity as a workaround? That seems like a reasonable option?

  3. davidsh commented on Oct 2, 2019

    @davidsh
    Contributor

    In the meantime, should we try SpnEndpointIdentity as a workaround? That seems like a reasonable option?

    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/stdout
  4. davidsh commented on Oct 2, 2019

    @davidsh
    Contributor
  5. jonwingfield commented on Oct 2, 2019

    @jonwingfield
    Author

    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.

  6. SteveSyfuhs commented on Oct 2, 2019

    @SteveSyfuhs

    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.

  7. mconnew commented on Oct 2, 2019

    @mconnew
    Member

    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.

  8. jonwingfield commented on Oct 3, 2019

    @jonwingfield
    Author

    @SteveSyfuhs

    They're slightly different. On Ubuntu, it's sending this in the request-body:

    Frame 55: 1018 bytes on wire (8144 bits), 1018 bytes captured (8144 bits) on interface 0
    Ethernet II, Src: Cisco_3c:7a:00 (00:05:9a:3c:7a:00), Dst: Cimsys_33:44:55 (00:11:22:33:44:55)
    Internet Protocol Version 4, Src: 10.10.1.43, Dst: 10.10.7.3
    Transmission Control Protocol, Src Port: 50029, Dst Port: 88, Seq: 5841, Ack: 1, Len: 964
    [9 Reassembled TCP Segments (6804 bytes): dotnet/corefx#47(1366), dotnet/runtime#13860(94), dotnet/runtime#13861(1366), dotnet/corefx#50(94), dotnet/corefx#51(1366), dotnet/runtime#13862(94), dotnet/corefx#53(1366), dotnet/runtime#13863(94), dotnet/corefx#55(964)]
    Kerberos
        Record Mark: 6800 bytes
        tgs-req
            pvno: 5
            msg-type: krb-tgs-req (12)
            padata: 2 items
            req-body
                Padding: 0
                kdc-options: 50010000 (forwardable, proxiable, canonicalize)
                realm: CORP.TEST.LCL
                sname
                    name-type: kRB5-NT-SRV-HST (3)
                    sname-string: 2 items
                        SNameString: svcAXBCPDV
                        SNameString: corp.test.lcl
                till: 2019-10-01 10:56:05 (UTC)
                nonce: 1122014012
                etype: 8 items
                    ENCTYPE: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
                    ENCTYPE: eTYPE-AES128-CTS-HMAC-SHA1-96 (17)
                    ENCTYPE: eTYPE-AES256-CTS-HMAC-SHA384-192 (20)
                    ENCTYPE: eTYPE-AES128-CTS-HMAC-SHA256-128 (19)
                    ENCTYPE: eTYPE-DES3-CBC-SHA1 (16)
                    ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5 (23)
                    ENCTYPE: eTYPE-CAMELLIA128-CTS-CMAC (25)
                    ENCTYPE: eTYPE-CAMELLIA256-CTS-CMAC (26)
    
    

    On Windows, it's:

    Frame 18: 1299 bytes on wire (10392 bits), 1299 bytes captured (10392 bits) on interface 0
    Ethernet II, Src: Cisco_3c:7a:00 (00:05:9a:3c:7a:00), Dst: Cimsys_33:44:55 (00:11:22:33:44:55)
    Internet Protocol Version 4, Src: 10.10.1.43, Dst: 10.10.7.5
    Transmission Control Protocol, Src Port: 50004, Dst Port: 88, Seq: 5465, Ack: 1, Len: 1245
    [5 Reassembled TCP Segments (6709 bytes): dotnet/corefx#14(1366), dotnet/corefx#15(1366), dotnet/corefx#16(1366), dotnet/runtime#13850(1366), dotnet/runtime#13851(1245)]
    Kerberos
        Record Mark: 6705 bytes
        tgs-req
            pvno: 5
            msg-type: krb-tgs-req (12)
            padata: 2 items
            req-body
                Padding: 0
                kdc-options: 40810000 (forwardable, renewable, canonicalize)
                realm: CORP.TEST.LCL
                sname
                    name-type: kRB5-NT-PRINCIPAL (1)
                    sname-string: 1 item
                        SNameString: svcAXBCPDV
                till: 2037-09-13 02:48:05 (UTC)
                nonce: 544141559
                etype: 5 items
                enc-authorization-data
    

    Could it be the extra sname string for the realm? I'm using the same UPN in both (svcAXBCPDV@corp.test.lcl).

  9. SteveSyfuhs commented on Oct 3, 2019

    @SteveSyfuhs
  10. jonwingfield commented on Oct 3, 2019

    @jonwingfield
    Author

    @SteveSyfuhs but why is it being sent this way? Are there details in GSSAPI that are causing it to be handled differently?

  11. SteveSyfuhs commented on Oct 3, 2019

    @SteveSyfuhs
  12. mconnew commented on Oct 3, 2019

    @mconnew
    Member

    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).

  13. davidsh commented on Oct 3, 2019

    @davidsh
    Contributor

    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.

    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.

  14. jonwingfield commented on Oct 4, 2019

    @jonwingfield
    Author

    @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.

  15. davidsh commented on Oct 4, 2019

    @davidsh
    Contributor

    @davidsh Is this known to work with UPNs though?

    Probably not. See related issue #16576

  16. 11 remaining items

  17. modified the milestones: 5.0, Future on Feb 20, 2020
  18. removed their assignment
    on Jun 26, 2020
  19. joakimobstfelder commented on Aug 27, 2020

    @joakimobstfelder

    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

  20. SteveSyfuhs commented on Aug 27, 2020

    @SteveSyfuhs

    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.

  21. mconnew commented on Sep 1, 2020

    @mconnew
    Member

    @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.

  22. dotnet-policy-service commented on Mar 4, 2025

    @dotnet-policy-service
    Contributor

    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.

  23. dotnet-policy-service commented on Mar 18, 2025

    @dotnet-policy-service
    Contributor

    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.

  24. removed this from the Future milestone on Mar 18, 2025
  25. locked and limited conversation to collaborators on Apr 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions