Automatic Prompting for Tickets on Windows

Alexandra Ellwood lxs at MIT.EDU
Wed Dec 3 15:11:30 EST 2003


Oops, I think I've horribly confused you.  This probably has to do 
with KfM's terminology, which is CCAPI v3-based.  I keep forgetting 
that KfW doesn't really use CCAPI v3.  I'll attempt to clarify my 
terminology

There are two different "default ccache" names running around on the 
Mac.  There is the system default ccache and the context default 
ccache.

The system default ccache is stored on the CCacheServer and is the 
same for all applications.   People familiar with UNIX Kerberos can 
think of the system default ccache as being similar to the 
environment variable KRB5CCNAME, except that it is login session 
global rather than being inherited from process to process.  Changing 
the system default ccache from one application changes it for all 
applications in that user's login session.

The name of the system default ccache can be obtained 
programmatically by calling the CCAPI v3 function 
cc_context_get_default_ccache_name().  Users can see the name of the 
system default ccache by looking at the underlined principal in 
Kerberos.app or running klist.  They can change the system default 
ccache by selecting a new principal and clicking the "Make User 
Active" button in Kerberos.app or by running the command line program 
kswitch.

The context default ccache is per krb5_context, KClient session. 
When an application creates a new krb5_context or KClient session, 
the context default ccache will be set to the current value of the 
system default ccache.  Once set, the context default ccache is never 
re-synced with the system default ccache unless the application 
manually sets it to that value.  This behavior is critical for 
KClient because v4 has no concept of an auth context.

Arguably it is less critical for v5 and GSSAPI because existing 
connections have an auth context and do not need to remember the name 
of the ccache which was used to establish the connection.  So for v5 
it's basically used to make sure that if you establish a connection 
and then forward credentials over it that you end up getting 
credentials from the same ccache you established the connection with.

The context default ccache is never visible to the user unless the 
application chooses to display it (such as a status bar that says 
something like "authenticated as lxs at ATHENA.MIT.EDU").  It can be 
obtained programmatically with  krb5_cc_default_name (context) or 
KClientGetCCacheReference (session, &ccache).

Look at get_from_os() in ccdefname.c to see the place in the krb5 
sources where the system default ccache gets propagated to the 
context default ccache.


>>There is a deficiency in the GSSAPI implementation (RT 1579 "GSS 
>>not noticing changes in active principal?") which is exposed when 
>>automatic prompting is turned on.  The krb5_context used by GSSAPI 
>>has a cached copy of the current ccache name and current ccache 
>>principal.  Because the krb5_context is global, the name and 
>>principal get cached when the library initializes.  This means that 
>>the library always uses whatever the default ccache was as the time 
>>the application launched.  Changing the system default ccache 
>>(whether by CCAPI v3+ or by the Windows registry stuff -- see 
>>get_from_os() in ccdefname.c) has no impact on the ccache the 
>>application uses.
>
>One could make a very strong argument that changing the default 
>ccache after an application launches SHOULD NOT alter the ccache 
>used by an application.  If an application creates its own ccache 
>that should not be altered by the user changing the default ccache 
>in another application such as the ticket manager.

This makes sense for short-running command line applications like 
ssh, where the user sets KRB5CCNAME (either on the command line or 
with the ticket manager) and then runs the program.  In a long 
running application like Fetch or Mail.app which makes multiple 
connections during its lifetime, the user needs a way to switch 
tickets which does not require manual intervention on the part of the 
application.  This capability is critical for sites where the users 
typically have tickets for 2-3 different principals and need to 
switch between them to connect to different servers.

Applications should not have to display their own UI to allow the 
user to select which tickets new connections should use.  They also 
shouldn't be encouraged to do this because they will each implement 
the ticket selection process slightly differently, resulting in 
inconsistent behavior between applications.

Note that behavior I am talking about does not prevent an application 
from manually insisting on using a specific ccache.  Most krb5 
functions allow the application to specify a specific ccache, and I 
believe that you can specify specific credentials to use with 
gss_acquire_cred().  What I'm talking about is the behavior when the 
caller passes NULL for the ccache.  If we make this behavior make 
sense, then applications won't have to do any extra work.

And yes, interrealm trust would solve this problem without the need 
for multiple ticket caches.  Unfortunately many of the sites with 
this problem are still doing a lot of v4.

>Of course, for the Logon Library neither the context nor the desired 
>credential cache name is passed to the 
>__KLInternalAcquireInitialTicketsForCache.  Therefore, there is no 
>way for the Logon Library to know the preference of the application 
>other than by using the current default ccache or examining the 
>environment variable.

The krb5_context is not passed into 
__KLInternalAcquireInitialTicketsForCache because it doesn't need the 
entire context.  What is passed in is:

KLStatus __KLAcquireInitialTicketsForCache (
   const KLPrincipal    inPrincipal,     // the principal in the context
   KLLoginOptions       inLoginOptions,  // init creds options (eg: 
forwardable?)
   const char          *inCacheName,     // the ccache name in the context
   KLKerberosVersion    inKerberosVersion, // ticket version (v4 or v5?)
   KLPrincipal         *outPrincipal,    // principal we got tix for
   char               **outCacheName)    // ccache those tix when into

Arguments 1 and 3 are the context default principal and the context 
default ccache respectively.  The __KLAcquireInitialTicketsForCache() 
will hunt around the ccache collection looking for this principal and 
ccache name if either argument is non-NULL.  It will *only* use the 
system default cache (and the client principal of the tickets inside 
it) if inPrincipal and inCacheName are both NULL.

This is what causes the GSSAPI problem.  GSSAPI provides no way for 
the application to set the context default ccache and principal in 
the library's global krb5_context.  So the application either gets 
stuck on one ccache/principal or it calls the private API 
gss_krb5_ccache_name() to manually reset it.

>In the Leash calls, a krb5_context can be optionally provided.  If 
>it is provided, it indicates which ccache should be used for the 
>application.
>
>>As you might have noticed, Fetch and some other GSSAPI applications 
>>on the Mac don't actually have this behavior.  The reason for this 
>>is that they can work around the problem by using the private API 
>>gss_krb5_ccache_name() to manually reset the ccache name in 
>>GSSAPI's krb5_context.  The problem is, gss_krb5_ccache_name() is a 
>>private API -- not even part of the GSSAPI C Bindings -- and really 
>>should be avoided.
>
>There does need to be a mechanism which allows a GSSAPI application 
>to specify which ccache it wants to use.  If that is not performed 
>by a private function, then it must be done via the environment 
>variable:  KRB5_ENV_CCNAME.

The problem isn't that the application can't do it programmatically, 
but that it shouldn't have to (or be encouraged to).  There should be 
a general, consistent way for the user to set the default credentials 
used by new connections which works for all applications, similar to 
the way KRB5CCNAME works for short running command line applications. 
If we don't provide a way for the library to automatically do this by 
default, then every application will end up needing to write the same 
code.

>>So after talking to the rest of the team, we agreed that we should 
>>fix this problem for 1.3.2 so that Windows doesn't end up with the 
>>same private API usage that we have on the Mac.
>
>Unlike on the Mac, Windows does not yet have support for managing 
>multiple ccache's in the Leash Ticket Manager.  This functionality 
>will not be added until the KfW 3.0 release.  I am not sure that we 
>have to push a fix through for the KfW 2.5.1 (Krb5 1.3.2) release.

How do sites with multiple realms use KfW now?  From looking at 
get_from_os() it seems that there is some registry entry that 
determines the default ccache name.  Is there a command line way to 
change this entry?

>>Since we already have automatic popup implemented on the Mac -- 
>>making it easy to test -- I will offer to do the work to fix it. 
>>Sam suggested syncing with the system default (ie: calling 
>>krb5_cc_set_default_name(context, NULL)) inside 
>>krb5int_cc_default(), but I may be forced to do it inside 
>>gss_acquire_cred() or kg_get_defcred() because krb5_fwd_tgt_creds() 
>>calls krb5int_cc_default(), but shouldn't be picking up the system 
>>default ccache -- it would be arguably a bug to connect with one 
>>set of creds and end up forwarding another set...
>
>This code already exists within krb5int_cc_default() for USE_LOGON_LIBRARY:
>
>    /* Try to make sure a krb5 tgt is in the cache */
>    err = __KLInternalAcquireInitialTicketsForCache (desiredPrincipal, NULL,
>                                        krb5_cc_default_name (context),
>
>    if (err == klNoErr) {
>            /* This function tries to get tickets and put them in the
>    specified
>               cache, however, if the cache does not exist, it may
>    choose to put
>               them elsewhere (ie: the system default) so we set that
>    here */
>            if (strcmp (krb5_cc_default_name (context), outCacheName) !=
>    0) {
>                    krb5_cc_set_default_name (context, outCacheName);
>            }
>            KLDisposeString (outCacheName);
>    }
>
>Therefore, if the cache name was altered the synchronization is 
>already performed.  This is true for 1.3.1.

The code above changes the context default ccache name if 
__KLInternalAcquireInitialTicketsForCache() was forced to put the 
tickets in a different place than the context default ccache name. 
This can happen if the tickets in the context default ccache do not 
have the same client principal as the context default principal. 
Note that unless both inCacheName and inPrincipal are NULL, 
__KLInternalAcquireInitialTicketsForCache() will never even look at 
the value of the system default ccache, so the context default ccache 
will not get synchronized with the system default ccache.



Hope this makes more sense than the last message...

--lxs
-- 
-----------------------------------------------------------------------------
Alexandra Ellwood                                               <lxs at mit.edu>
MIT Information Systems                               http://mit.edu/lxs/www/
-----------------------------------------------------------------------------
--


More information about the krbdev mailing list