Acceptor names

ghudson@MIT.EDU ghudson at MIT.EDU
Fri Jan 28 16:39:28 EST 2011

I'd like to make some improvements to the way we match acceptor names
in krb5 1.10.  This will become a project proposal, but first I have a
few design questions.

There are five basic ways to be a krb5 acceptor.  You can:

1. Call gss_accept_sec_context with a null cred, or a cred acquired
with GSS_C_NO_NAME.  In this case, as of 1.7 we will scan the keytab
for a key matching the client's ticket, and will record what we found
as the acceptor name.

2. Import a host-based name like "HTTP" (with no hostname), acquire
creds, and call gss_accept_sec_context.  In this case, we require the
acceptor principal to be HTTP/localhostname at realm, where localhostname
is the canonicalized gethostname() return value and realm is
determined through profile domain_realm mapping, falling back to the
default realm.

3. As in case 2, import a host-based name like "HTTP at hostname".  In
this case, we canonicalize hostname (instead of the gethostname()
return value) and otherwise behave as in case 2.

4. Non-GSS: call krb5_sname_to_principal with a hostname (null
defaults to local hostname) and a service name (null defaults to
"host") and call krb5_rd_req with the result.  This behaves similarly
to cases 2 or 3, since our gss-krb5 code uses krb5_sname_to_principal
when canonicalizing a name.

5. Non-GSS: call krb5_rd_req with a caller-constructed principal name.
In this case, the acceptor principal must be the specified principal
name, except that an empty realm is translated to the local realm

I'd like the following changes, going case by case:

1. No behavior change.

2. Match any principal HTTP/*@* in the keytab, and record what we
found as the acceptor name.

3. If a new libdefault "ignore_acceptor_hostname" is set, behave as in
case 2.  Otherwise, match any principal HTTP/hostname@* in the keytab,
and record what we found.

4. Probably still similar to case 2 or 3, but this is up in the air.

5. A service principal with an empty realm would match any realm
present in the keytab, instead of looking for the default realm.

Before I get into implementation design, I want to resolve these

* The above changes have the effect of disregarding the profile
  domain_realm map and the default realm in the acceptor.  Is that
  okay?  Can people imagine cases where a keytab contains
  service/hostname at REALM for multiple realms and it's important to
  accept only a particular realm based on the domain_realm map?

* The new ignore_acceptor_hostname profile setting is a bludgeon to
  make apps work even if they import service at gethostname() (like
  unpatched SSH).  Unfortunately, admins will have to know about the
  krb5 setting in order to avoid the usual canonicalization-related
  failures setting up sshd.  Should we go further, at the risk of
  damaging the security of (for example) hypothetical virtual hosting
  apps?  Is it worth implementing the bludgeon at all if it has to be
  off by default?

I'm also keeping an eye on gss_canonicalize_name and gss_export_name.
RFC 2744 section 5.5 says that gss_canonicalize_name should produce:

   The mechanism name is the name that would be returned to a context
   acceptor on successful authentication of a context where the
   initiator used the input_name in a successful call to
   gss_acquire_cred, specifying an OID set containing <mech_type> as
   its only member, followed by a call to gss_init_sec_context,
   specifying <mech_type> as the authentication mechanism.

So, we want to be on the lookout for cases where import ->
canonicalize -> export doesn't match the result of import -> acquire
-> init -> accept -> {export src_name}.  This is all about initiator
names, not acceptor names, but we may already have some bugs related
to the referral realm (when a host-based service name is used as an
initiator name) and could have additional bugs if we start creating
partial principals like HTTP/@ to pass to rd_req.

More information about the krbdev mailing list