Subject: Re: Single canonical names

From: Martin Rex <[email-masked]>
Date: Sat, 6 Nov 2004 00:19:35 +0100 (MET)

Nicolas Williams wrote:
> 
> > The purpose of MNs is for authentication (ACL checks).  Even
>                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Nit: authorization.

Nope, I really meant authentication.  The check whether we do recognize
the canonical name that we get as the result of one (out of many)
methods to authenticate a user.  In our application for example
this is the transformation of a name as known to the gssapi mechanism
into the legacy namespace of our application.

Authorization, including wether we allow this user to logon at all
is done later in the game.  I don't even want to talk about the
fine-grained authorization profiles that come into play once
the user passes our logon checks.

>
> For those who don't remember, we've argued as to the, shall we say,
> quality of gss_canonicalize_name()'s output.
> 
> The crux of the matter is this: all these names are really based on
> human-readable names (for example, the exported name token for the
> Kerberos V mechanism is really an encoding of a Kerberos V principal and
> realm name), but these can change and may require online infrastructure
> to validate.

The crux of the matter is that Kerberos 5 authentication is by definition
based on printable Kerberos principal names. Period.

I know that when Microsoft uses Kerberos for authentication, it entirely
ignores the Kerberos principal names that are involved when they
find a PAC inside the ticket.  However this only works in a homogeneous
Microsoft Windows environment.  As soon as you include non-Microsoft-W2K
machines in your infrastructure (or use a non-Microsoft KDC), you
can not use the canonical representation of a name which microsoft
uses in their proprietary ACLs, these fancy SIDs.

The only name that is guaranteed to be universally available across
a heterogeneous Kerberos 5 infrastructure is the Kerberos principal
name, because that is the lowest common denominator that every
implementation must understand and provide.

And frankly, if you look at the transformation calls that Microsoft
provides between SIDs and Kerberos principal names (in both directions)
an which names you need where (do SIDs work as target names with
Microsoft's Kerberos SSP?)

> 
> I don't have any intention to break GSS_Canonicalize_name(), but to
> provide for alternatives to name-based authorization, specifically
> authorization by "internal" IDs (e.g., POSIX UIDs, GIDs, Windows SIDs).

The problem with UUIDs, GUIDs or Windows SIDs is, that although
there may be less motivation to change or reuse them over time
than printable names, but

 - they're still inherently non-portable across heterogenous environments
 - they're not used natively for maintenance by (human) admins
   and therefore translation/lookup APIs are necessary for the transformations
 - the use of UUIDs, GUIDs or Windows SIDs vs. printable names is
   often quite inconsistent in those areas where they're used
 - the translation/conversion APIs between the printable and the
   binary canonical forms are often insufficient, plain broken or even
   missing/non-functional in existing implementations.
 - the translation/conversion usually requires access to a central
   name service / directory and therefore credentials, and that
   is a serious problem for some environments and some uses.

Funny that you mention POSIX uid_t.  They used to be 16-bit on Unix,
providing a *MUCH* smaller space than Kerberos principal names,
and they're only valid locally which makes them less useful.

>
> Yes, we intend to provide at least runtime feature detection facilities,
> as well as compile-time facilities for language bindings where that
> makes sense.  Runtime feature detection facilities can be used to build
> compile-time profiles, BTW (think of GNU autoconf); as Sam points out,
> this not ideal for cross-compilation, but in a pinch it will do.
> 
> (And note that link-time feature detection is also possible; think of
> weak symbolic references, shared object filters).

I consider unix system loader / runtimer linker behaviour with
the global symbol space, function overloading and other nuisances
among the worst of evil inventions in IT.

As soon as code from different sources that has never seen each
other before meets on a customers machine and causes problems,
you will realize that.

Just recently I had to deal with an AIX problem coming from the
crazy "-brtl -bnortllib" linker switches, and when you dig into
the underlying issues, you'll realize that the responsible
engineer were plain nuts.

>
> I want to keep this implementation specific, though most implementations
> allow for/default to finding a credential in the "credential store"
> corresponding to the calling thread's/process' current user context
> (note: I consider a PAG to be part of such a user context).  On such
> platforms the application must switch to the user context of the user
> for which it wants to acquire credentials; many applications don't have
> the privilege to do so.

A lot of code is not prepared for "impersonation" kind of techiques
or even breaks.  Usually this model makes abstraction much much harder,
because you need access to the lower level handle to switch around
at the application layer, which means you have to tunnel the access
through all layers.

Even Microsoft's Software breaks in various ways because it cannot
correctly cope with this architecture.

I.e. when doing an NTLM SSPI-authentication and impersonation.
After an authentication through the network with a failed logon
to a domain account and a fallback to the local guest account,
QueryContextAttributes(Names) will ALWAYS return an account name
that looks nice, but doesn't even exist (i.e. PC_NBNAME\DOM_USER
instead of PC_NBNAME\GUEST) and LookupAccountSID() will do
the exact same error when it's call while still impersonating.
So you have to Impersonate, QueryToken,Revert,LookupAccountSID
to reliably get the real name...
I reported this bug to Microsoft in 1997, but I think it never
got fixed in NT4 and I never felt like checking whether W2K
still has it.

The problem here is that with sufficiently modularized code and
sufficient abstraction, you don't know which API calls will
actually perform operations where OS-level access control is
involved so to play on the safe side you'll probably have
to switch between original and impersonated identity like
crazy and localize the impersonation code path as closely
as possible to exactly those operations that should be
performed under the impersonating user.

But as I said--with sufficiently modularized code you'll
get into troubles sooner or later, so that inside a
high-level abstracted function that is supposed to be
performed under impersonation, you'll suddenly have a
need to do a translation/lookup which ultimately
does a remote request through the network, and *Booom*
you have a problem.  Now you do not only have to tunnel
the handle for switching access tokens not only
backup to the application layer, but also downward
into abstract modularized service functions which may
eventually have a need for it.

That's a *lot* of work for being inherently non-portable.

And believe me, there are a lot of things that simply can not
be mapped to Posix style access control.  That model is ok
for a simple fileserver (or a web-server that is effectively
used in a fileserver manner), but not for a lot of real
world scenarious with magnitudes higher complexity.

If it were easy, then you could write down a mapping of
e.g. an X.509 cert basic constraints and (extended) key usage extensions
into a Posix style ACL...  ;-)

-Martin

_______________________________________________
Kitten mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/kitten

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 5 Nov 2004 17:33:33 -0600

> the user passes our logon checks.

Ah, ok, this is very specific to your app.

> based on printable Kerberos principal names. Period.

Yup.

> implementation must understand and provide.

We propose portable GSS-APIv3 interfaces to facilitate use of internal
identifiers.

>  - they're still inherently non-portable across heterogenous environments

This is less of an issue than you think (but I'm not prepared, today,
for lack of time, to back this up with a full treatment).

>    and therefore translation/lookup APIs are necessary for the transformations

That's ok, we all use them, at least on such platforms as Unix, Windows.

>    often quite inconsistent in those areas where they're used

I'm not sure what you mean here.

>    missing/non-functional in existing implementations.

See above.

>    is a serious problem for some environments and some uses.

Sort of.  Just as tickets can carry authorization data, so could certs
(the necessary hooks are already there).

> and they're only valid locally which makes them less useful.

But they're not 16-bit wide anymore.  Certainly not on Solaris.

> among the worst of evil inventions in IT.

I'll pass on this comment.

> other before meets on a customers machine and causes problems,

Users should not use LD_LIBRARY_PATH, if that's what you mean.  Yes,
abuse of LD_LIBRARY_PATH leads to Bad Things.

> That's a *lot* of work for being inherently non-portable.

Again, I lack the time to provide a full answer to this.  Suffice it to
say that I disagree and will come back to this later (probably much
later).

Nico
--