Skip to content

Deterministic KDC order #428

Open
Open

Description

@nhart12

I have a use-case with an edge deployed RODC and also some edge deployed containers running that'd I'd like to use this library in. The containers are chiseled images that don't contain ping (and I'm hoping to remove MIT GSS libraries).

One thing Im noticing - I'm attempting to configure a KDC precedence in my config. Similar to listing out multiple kdc values in a krb5.conf where the gss libraries will retry on a subsequent KDC if the first one fails. I'd like to prioritize the edge RODC/KDC and fallback on the network otherwise. I'm disabling PrioritizeKdcByPing (since the underlying OS doesn't even have ping)- the trouble is that even when disabling the ping check this line of code then randomizes the ping result leaving the KDC priority non-deterministic (instead of falling back to file or pinned kdc order)

Activity

  1. SteveSyfuhs commented on Jun 4, 2026

    @SteveSyfuhs
    Collaborator

    Interesting. So is the behavior you're trying to get "try explicit list (RODC first, then non-RODC out of site, etc.), if that that fails, try locator next"? Is the right?

  2. nhart12 commented on Jun 4, 2026

    @nhart12
    Author

    yes, is that possible with existing configuration options? Even falling back to locator / DNS Srv records is optional in my use case. Just wanted to deterministically go in order of

    1. local RODC
    2. Hardcoded DC -> Round robin DNS entry (with multiple out of site IPs)

    I want to test Pinning the local RODC first then clearing the pinned KDC on failure. That might work in the interim

  3. SteveSyfuhs commented on Jun 4, 2026

    @SteveSyfuhs
    Collaborator

    Sort of. You can implement your own derived ClientDomainService and override LocateKdc but that's a bit overkill:

    public virtual async Task<IEnumerable<DnsRecord>> LocateKdc(string domain, string servicePrefix)

  4. nhart12 commented on Jun 5, 2026

    @nhart12
    Author

    Thanks for the suggestion, going to try that now as pinning KDCs in order has the same randomization effect as configuring them in order.

    Side note:
    When running from develop branch I'm getting the following ASN parsing error when parsing a NegTokenResp object. I'm assuming it's related to the recent refactors around ASN generations.
    NegState is supposed to be an enumeration but it errors because the generated code tries to read as an Int

      NegTokenResp ::= SEQUENCE {
        negState       [0] ENUMERATED {
            accept-completed    (0),
            accept-incomplete   (1),
            reject              (2),
            request-mic         (3)
        } OPTIONAL,
       ...
       }
    

    NegotiationToken negoToken = NegotiationToken.Decode(incomingBlob.ToArray());

    Exception thrown: 'System.Security.Cryptography.CryptographicException' in Kerberos.NET.dll
    An exception of type 'System.Security.Cryptography.CryptographicException' occurred in Kerberos.NET.dll but was not handled in user code: 'ASN1 corrupted data. Expected Integer; Actual: Enumerated'
    Stack trace:
     >   at System.Security.Cryptography.Asn1.AsnReader.CheckExpectedTag(Asn1Tag tag, Asn1Tag expectedTag, UniversalTagNumber tagNumber) in \Kerberos.NET\Kerberos.NET\Asn1\Experimental\AsnReader.cs:line 489
     >   at System.Security.Cryptography.Asn1.AsnReader.GetIntegerContents(Asn1Tag expectedTag, UniversalTagNumber tagNumber, Int32& headerLength) in \Kerberos.NET\Kerberos.NET\Asn1\Experimental\AsnReader.Integer.cs:line 604
     >   at System.Security.Cryptography.Asn1.AsnReader.TryReadSignedInteger(Int32 sizeLimit, Asn1Tag expectedTag, UniversalTagNumber tagNumber, Int64& value) in \Kerberos.NET\Kerberos.NET\Asn1\Experimental\AsnReader.Integer.cs:line 641
     >   at System.Security.Cryptography.Asn1.AsnReader.TryReadInt32(Asn1Tag expectedTag, Int32& value) in \Kerberos.NET\Kerberos.NET\Asn1\Experimental\AsnReader.Integer.cs:line 170
     >   at System.Security.Cryptography.Asn1.AsnReader.TryReadInt32(Int32& value) in \Kerberos.NET\Kerberos.NET\Asn1\Experimental\AsnReader.Integer.cs:line 139
     >   at Kerberos.NET.Entities.NegTokenResp.Decode[T](AsnReader reader, Asn1Tag expectedTag, T& decoded) in \Kerberos.NET\Kerberos.NET\obj\Debug\netstandard2.0\Kerberos.NET.Asn1SourceGenerator\Kerberos.NET.Asn1SourceGenerator.Asn1IncrementalGenerator\NegTokenResp.g.cs:line 164
     >   at Kerberos.NET.Entities.NegTokenResp.Decode[T](AsnReader reader, T& decoded) in \Kerberos.NET\Kerberos.NET\obj\Debug\netstandard2.0\Kerberos.NET.Asn1SourceGenerator\Kerberos.NET.Asn1SourceGenerator.Asn1IncrementalGenerator\NegTokenResp.g.cs:line 144
     >   at Kerberos.NET.Entities.NegotiationToken.Decode[T](AsnReader reader, T& decoded) in \Kerberos.NET\Kerberos.NET\obj\Debug\netstandard2.0\Kerberos.NET.Asn1SourceGenerator\Kerberos.NET.Asn1SourceGenerator.Asn1IncrementalGenerator\NegotiationToken.g.cs:line 144
     >   at Kerberos.NET.Entities.NegotiationToken.Decode(ReadOnlyMemory`1 encoded, AsnEncodingRules ruleSet) in \Kerberos.NET\Kerberos.NET\obj\Debug\netstandard2.0\Kerberos.NET.Asn1SourceGenerator\Kerberos.NET.Asn1SourceGenerator.Asn1IncrementalGenerator\NegotiationToken.g.cs:line 116
     >   at Kerberos.NET.Entities.NegotiationToken.Decode(ReadOnlyMemory`1 data) in \Kerberos.NET\Kerberos.NET\obj\Debug\netstandard2.0\Kerberos.NET.Asn1SourceGenerator\Kerberos.NET.Asn1SourceGenerator.Asn1IncrementalGenerator\NegotiationToken.g.cs:line 109
    
  5. nhart12 commented on Jun 5, 2026

    @nhart12
    Author

    Something like this seems to fix the ASN parsing issue, although I'm naive as to what else that will impact
    #429

  6. nhart12 commented on Jun 5, 2026

    @nhart12
    Author

    Here's a proof of concept to making things more deterministic. I'm not a fan of the new config fields, but just wanted to throw the idea up
    #430

  7. nhart12 commented on Jun 5, 2026

    @nhart12
    Author

    Sort of. You can implement your own derived ClientDomainService and override LocateKdc but that's a bit overkill:

    Kerberos.NET/Kerberos.NET/Client/Transport/ClientDomainService.cs

    Line 69 in df3faec

    public virtual async Task<IEnumerable> LocateKdc(string domain, string servicePrefix)

    This works for me in the interim, thank you for the suggestion

  8. nhart12 commented on Aug 11, 2026

    @nhart12
    Author

    @SteveSyfuhs would you be open to config changes like above for more deterministic behavior?

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