[krbdev.mit.edu #2652] Implementation notes

Sam Hartman via RT rt-comment at krbdev.mit.edu
Wed Sep 20 21:54:15 EDT 2006



I want these to be easier to find than a deleted development branch.

notes on krb5_get_cred_from_kdc_opt:
===================================
current behaviour:
  - start with known target realm
  - check if we have TGT for that realm
    - if not, traverse world to find TGTs
  - if that worked, request ticket from ultimate target realm

problems with this:
  - linear processing doesn't work, since ultimate target realm can change at any time
  - can't really check if we already have the remote TGT since required TGT can change
    - is checking for a cached TGT useful at all, or should we go
      straight to asking the KDC about it?
	answer: yes, if there's a proposed realm attached to the
	principal, search for a matching TGT and use that for the
	request, but this request should still be made with referrals
	requested.
	new answer: no, absent an actual service ticket for what you're
	after, start with the local KDC and see what it gives you.  you
	may get a TGT you already have (which is pointless), but you may
	also get a referral you need to make sense of it.  EXCEPT that if
	you start with a non-local realm it came from a domain_realm
	mapping (which we always trust), so start with that instead.
	problem: how do you tell if it's from a domain_realm mapping or
	something user-constructed?  the answer seems to be that if
	there's a non-local service realm name given for the initial
	credential that it should always be used no matter what.
	this might be broken behaviour, though.

notes:
  - if referred, it comes with a cross-realm TGT for the new realm,
    so we will always already have a TGT for the new realm, and
    checking isn't necessary.  we can also be assumed to already have a
    TGT for the start realm.
    - BUT, we may not have a TGT initially if we're subject to a
      domain_realm mapping

new logic:
1) the referrals case:
  - check for TGT for initial realm
    - if a remote realm was specified (which must have happened via a
      domain_realm mapping), obtain a TGT for it the standard way and
      start with that.
  - use client realm for server if not specified
  - iterate through this loop:
    - request ticket with referrals turned on
    - if that fails:
      - if this was the first request, punt to non-referrals case
      - otherwise, retry once without referrals turned on then terminate
        either way
    - if it works, either use the service ticket or follow the referral path
    - if loop count exceeded, hardfail
2) the nonreferrals case
  - this is mostly the old walk_realm_tree TGT-finding (which allows
    limited shortcut referrals per 4120) followed by a standard tgs-req.
  - originally requested principal is used for this, although if we were
    handed something without a realm, determine a fallback realm based on
    DNS TXT records or a truncation of the domain name.

notes on resolving hostnames
============================
krb5_get_host_realm does various sanity-checking on supplied hostnames
including folding them to lowercase and using the local hostname if
blank.  Currently krb5_get_fallback_host realm is set up to do the same
thing, with the common code moved to krb5_clean_hostname.  (Stupid
name...)  Should it really do that, or should it be much more limited?

problems
========
- draft and actual microsoft implementation are divergent enough that MS
  machines not usable for full testing

realm referrals, client side implementation:
===========================================
- new realm selection priority is:
  1) client-side locally configured domain_realm mapping
  2) referral request to kdc (always!)
  3) DNS TXT record lookup (if configured)
  4) default realm assumption (realm=DNS domain of server)
  (this is the same as exists now but with referrals added,
   though 3 and 4 are deferred to get_cred_from_kdc)
- whether to do referral or not is *not* configurable
- client-side realm of "" (empty but *not* null string) used in client
  libraries to indicate domain_realm mapping failure and fallback to
  referral.  not subject to configuration.
- krb5_sname_to_principal makes existing call to krb5_get_host_realm
  - krb5_get_host_realm returns domain_realm mapping if found, otherwise
    returns "".
    [this could fall back to TXT or default realm assumption instead]
    [but it isn't; this happens later if at all; the relevant fallbacks
    will happen as part of credential-obtaining process]
- code using alternatives to krb5_sname_to_principal (krb5_parse_name,
  krb5_build_principal) is on its own.
- actual referral request handled in krb5_get_cred_from_kdc
  - client will always request referrals from kdc
  - realm choice:
    - if realm supplied, start with that.
    - if no realm specified, request server referral; if that fails,
      fall back to TXT request/default realm assumption and try that instead
      (copy code from krb5_get_host_realm; make fallback a separate function
      if referrals are runtime-configurable and the same code will be
      needed in krb5_get_host_realm
- ccache considerations:
  - referrals may also have had name canonicalization done.  store the
    ultimate ticket under the requested service name under the
    assumption that it will continue to be requested the same way.
    service names for non-referral requests will never be
    canonicalized but we should handle that case anyway.
  - canonical service name still available within the ticket
  - will/should the library use or search on the canonical principal
      name as well?

- cross realm routing
  - if capath present *and* realm is known, attempt to follow to end,
    allowing shortcuts
  - recheck for capath entry if realm is rewritten on referral
    - requests still made with referrals turned on, so referrals along
      the path, and especially at the end of the path, still work
    - still need to understand full capth functionality here.
  - client currently tries to construct a trust path following the DNS
    hierarchy until it finds a server to ask; this is still useful
    (maybe?) as a fallback but should only be tried after server
    referrals have failed.
  - if referrals provide an initial referral TGT or two, but this path
    terminates at a server that provides neither a service ticket or a
    referral, what happens?
  - establish maximum referral traverse; more than microsoft's 5, but
    finite

 

realm referrals, server side implementation:
===========================================
- kdc should accept any sort of name, short or long
  (see below for detailed canonicalization notes)
- add code to process_tgs_req to handle tgs_req canonicalize flag
  - add second case for firstpass=1 within the "if (nprincs != 1)" block
- add new library function to fetch referral realm
  - Microsoft/umich patch uses static kdc.conf configuration along the
    same general lines as the domain_realm mapping; compatability with
    that (logically and probably syntactically) seems desirable and
    technically unobjectionable.
  - raeburn thinks it might be interesting to make this overridable
    with a kdc plugin.

hostname canonicalization, server side
======================================
- do not rewrite service names when not also returning a referral; this
  is a nonstated design requirement for clients that appears to violate
  the client requirements in the -06 draft, but currently deployed
  implementations apparently rely upon this not happening.  unclear now
  if it's the right thing, but we're stuck with it.
- canonicalization only done:
  1) if local db lookup of principal as presented fails
  2) only if uncanonicalized referral has already failed
  3) only for principals with exactly two parts
     (this will break NT-SRV-XHST; does anyone care?)
  4) only for principals with a specified name type,
     by default NT-SRV-HST and maybe NT-UNKNOWN
  5) only for principals with specified service names
- any rewriting action taken on presumed hostnames will end with case
  folding to lowercase.  there's some conflict on whether this is a
  "MUST" or "SHOULD" in 4120, but it's clearly appropriate once we're
  rewriting.
- strategy for service name canonicalization
  - if short name, try resolving it serially with a kdc-configured domain list
  - thus the client can send an unqualified name, but loses security
  - follow cnames, but don't do rdns lookup
  - can this break backward compatability?
  - is blocking on DNS here OK?
    - utilize a mapping, possibly something automatically generated from
      local DNS zone(s), to rewrite hostnames for referral.
- unanswered question: how do we handle servers known by multiple names?
  provide multiple db entries?  add these to keytab as well?

hostname canonicalization, client side
======================================
- our client will always send a fully-qualified name to the server
  for something that appears to be a hostname
  (basically the same cases where we do rdns now)
- idea: client code will not do rdns by default, but instead will resolve
  hostnames as far as fully qualifying them in the client name resolution
  environment and following CNAME records
  [this seems desirable but could be technically problematic]

namespace issues
================
- defined separate KDC option bit for RFC-style canonicalization since
  the microsoft implementation is so different
  - should key usage and padata types be different as well?
- keyusage defined in draft (26) collides with KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID

from 21 aug 2006 meeting, notable screw cases and notes on same:
===============================================================
- referrals which terminate at a non-referral-capable realm should retry
  the final request without referrals turned on (the "referrals to MIT" case)
- intermediate cross-realm TGTs should not be cached, only the final
  service ticket, anything from the local KDC, and anything that came up
  during the degenerate (walk_realm_tree) unreferred traversal case
- "too many hops" failure can be a hard failure
- TGT referrals per original 4120 spec should continue to Just Work
  - the code path for this is different and doesn't check much.
    is this a gaping hole waiting to be filled maliciously?
- bug: principal parsing fails with zero-length realm
- maybe bug: win->athena referrals don't work
  - hey, wait, there's no cross-realm TGT there.  wacky.
- the case where we make a default realm assumption is very important to
  maintain the current functionality with
- it's more important to minimize KDC round-trips and perform to
  minimally functional spec than to make all possible (and probably
  futile) fallbacks

from 25 august 2006 meeting, thoughts on fallbacks:
==================================================
Part of the current plan is to move configuration information from the
client to the server.  This, however, leaves us vulnerable in cases where
the home KDC ("A") knows that the service principal exists in C but that
the trust path traverses B, which is not referral capable.  Our
conclusion is that the server should not be configured to offer referrals
to C at all, but should of course continue to return a cross-realm TGT to
B if asked, and that the client fallback to the standard
non-referral-based traversal is the only functional path here.

But is that really the right thing?

misc questions answered:
=======================
- should do_traversal code for old-style lookups still be requesting referrals?
  If so, within what scope should they actually be used?
  - probably not.  the old traversal code is network-intensive and resilient enough as is.




More information about the krb5-bugs mailing list