rpcsec_gss and Kerberos 5

Kevin Coffman kwc at citi.umich.edu
Thu May 23 13:25:01 EDT 2002


Hi Ken,

I noticed in the referenced message below that you said "after we get 
rpcsec_gss support".

Here at CITI, we are doing the Linux platform reference kernel 
implementation of NFSv4 which requires userland rpcsec_gss for the 
GSSD.  The work was started by taking the rpc code from the MIT K5 
distribution.  Changes have been made to that code to bring it "almost" 
up to spec.  (rfc 2203)  It currently interoperates with the Sun 
implementation and passes their rpc test suite, as well as 
interoperates with the Linux kernel rpcsec_gss.  There is a bit more 
work to be completed.

We are hoping that the Kerberos team might be willing to take these 
changes back into the distribution as an alternative rpc, or to replace 
the current rpc.  Would our work be considered to be folded back into 
the K5 distribution?

I realize this would make an incompatible change for the kadmin 
interface, but hopefully we can discuss ways around that.

Thanks,
Kevin
 
> Emily Ratliff <ratliff at austin.ibm.com> writes:
> > Now that you've forgotten what you said:
> > http://diswww.mit.edu:8008/menelaus.mit.edu/krb5dev/6761
> > 
> > and I've played with it for a while, I have a few questions and comments.
> 
> Oh, I haven't forgotten.  In fact, just a few days ago I was saying to
> Tom that I should email you and find out how it was going....
> 
> > > The callback functions may only be registered while no locks are held
> > > (which presumably means before any threads are created and while in
> > > the main application).  Locks are not held across library calls; they
> > > are always released.
> > I agree with both of these items, but the first is the goal of the 
> > application. I don't see how to enforce this in the library.
> 
> Yes, we would just assert that it's the application writer's
> responsiblity.  If an application dynamically loads the library after
> spawning multiple threads, we may have a problem.  I don't know if
> there's anything we can do about that.
> 
> > > (Question: Should the callback functions be registered through
> > > separate functions, or one call with extra arguments or a structure
> > > pointer?)
> > OpenSSL registers the callback functions individually, but I still prefer 
> > a structure pointer.
> 
> Okay.  I don't think it makes a lot of difference.  Both approaches
> are extensible in different ways, and we probably don't want much in
> the way of extensions happening anyways.
> 
> > > Each library (each that has data needing protecting, that is) provides
> > > a set of functions for manipulating these callbacks, based in part on
> > > the OpenSSL API.
> > Why allow the capability to have different callbacks for different 
> > libraries loaded by the same application? In other words, if a single 
> > application uses more than one library, the app has to register the same 
> > callbacks with each libary that it uses. OpenSSL only has the thread 
> > support in one libary, so this issue hasn't shown up for them.
> 
> Actually, I was thinking that every library would have to be using the
> same thread interface through callbacks.  But if an application only
> directly refers to one of the APIs we provide (GSS, krb5, RPC after we
> get rpcsec_gss support), they shouldn't need to use the callback
> registration function from a different API.  E.g., a "pure" GSS
> application shouldn't call or even know about
> krb5_register_thread_callback_thingamabob, it should only call
> gss_register_thread_callback_thingamabob.
> 
> But at the same time, the GSS and krb5 thread hooks shouldn't have
> compiled-in knowledge of, for example, how many locks are needed by
> the other library or what thread package support was compiled in.  So
> I'd expect the GSS library to act like any other krb5 application,
> registering thread callback functions if it's told to use something
> other than the default (or perhaps always registering?), reporting
> that GSS is not thread-safe if krb5 isn't, etc.
> 
> This sort of layering requires a few tricks, for example gss_num_locks
> would need to ask krb5_num_locks how many locks the krb5 library
> needs, and add them to the count of locks that the GSS library itself
> needs.
> 
> 
> > > (Question: Should we consider gssapi thread-safe if it uses locks
> > > around krb5 calls that can call DNS or C library routines that are not
> > > known to be thread-safe, or worse, are known not to be thread-safe?)
> > Sure, but hopefully we will do better.
> 
> I'm not so sure.  Okay, so we put a lock around GSS calls to
> gethostbyname.  And we put another lock around krb5 calls to
> gethostbyname.  If the problem isn't already obvious, even combining
> those locks into one won't prevent another application thread from
> calling gethostbyname.
> 
> I guess it comes down to, what does "the krb5 library is thread-safe"
> mean?  Can it be used in one thread while another thread is doing
> random C library calls?  Or must C library calls be excluded while the
> krb5 library is being used (in however many threads)?
> 
> To put a different spin on it, if some other package maintainer uses
> the same definition for "thread-safe" that we do, can their library
> and ours be used simultaneously in different threads?  Or do two
> supposedly thread-safe libraries add up to an unsafe application?
> 
> Note that I'm assuming we get stuck with some C library or resolver
> functions not known to be thread-safe, or known not to be; if we get
> rid of all such calls on a system, obviously we win big.  But I'm
> fairly confident that on some systems we just won't be able to.
> 
> > > Should locks be ref-counted?  
> > ...
> > > (What's OpenSSL do?)
> > OpenSSL does do ref-counting for locks. I'd like to postpone this one til 
> > later though.
> 
> Okay.
> 
> > > For each library's prefix "foo" (to be determined for libraries like
> > > com_err without consistent prefixes), we'd have the following
> > > functions and macros, with names adjusted accordingly:
> > 
> > > void foo_set_locking_callback (void (*lockfn)(int mode, int locknum,
> > >                                               const char *file,
> > >                                               int line));
> > Why per-library on this one? Why not a global that is shared? It will be 
> > set the same unless the application is doing something very strange. 
> 
> What name should we use for this, that would be appropriate for a pure
> krb5 application and for a pure gssapi application and for a pure
> sunrpc application and for a pure krb4 application (hopefully a dying
> breed, but still out there), and an application using com_err but none
> of the rest of Kerberos (as happens on Linux, for example)?
> 
> This routine could be global, but only if the lock numbers for
> everything are going to be coordinated.  Someday, I'd like to see us
> have a GSS library capable of dynamically loading multiple mechanisms
> from the filesystem.  It's hard to indicate the correct number of
> locks if the implementations of different mechanisms don't coordinate.
> 
> I sort of anticipated doing something like:
> 
>     #define gss_locks_needed  8
>     static void (*lockfn)() = ...;
>     int gss_num_locks () {
>         return gss_locks_needed + krb5_num_locks ();
>     }
>     static void k5lock (int mode, int locknum, const char *file, int line) {
>         (*lockfn) (mode, locknum + gss_locks_needed, file, line);
>     }
>     void gss_set_locking_callback (void (*fn)()) {
>         lockfn = fn;
>         krb5_set_locking_callback (k5lock);
>     }
> 
> This lets a GSS application register a callback and go about its
> business.  And if a GSS/krb5 application wants to manage the krb5
> locks directly, that'll work too, as long as the same thread package
> underlies all the registered callbacks.  It would just mean the GSS
> code reserves some lock numbers that don't get used.
> 
> This can be extended to deal with dynamically loaded objects, though
> they'd probably all have to be loaded just to give an answer for
> gss_num_locks if the info isn't cached in a config file or
> something....
> 
> 
> > >    Q: What about systems that might have multiple thread packages that
> > >    *are* known to play nicely together?  If some FooThreads package is
> > >    provided by the kernel and the pthreads implementation uses
> > >    FooThreads primitives in a compatible way, the application should
> > >    be okay even if it doesn't use the same interface as the gss/krb5
> > >    libraries.  Should that knowledge be in the library or the
> > >    application?  Should we not bother?  */
> > > /* Should these be macros or enumerators?  */
> > > #define FOO_THREADS_PTHREAD   1
> > > #define FOO_THREADS_WIN32     2
> > > #define FOO_THREADS_MACOS9    3
> > > #define FOO_THREADS_MACH      4
> > The library won't know which thread library and hopefully won't need to 
> > know, right? It just needs to know whether it has callbacks registered and 
> > is thread-safe, or it has the threading API compiled in with no callbacks 
> > registered or doesn't have the threading API compiled in and is unsafe.
> 
> It won't know which version of the thread library, but it'll know at
> compile time which API (if any) is compiled in as the default.
> 
> If an application doesn't want to register a lock function, it can
> still do a safety check that the library wasn't built against a
> different thread system.  If we assume that same API means same
> implementation (which may not be true in some systems?), that should
> be enough to let the application run safely.
> 
> (If it's not enough, maybe we should always make the application
> register the callbacks, and always default to no locking?)
> 
> > > #define LOCKMODE_LOCK   1
> > > #define LOCKMODE_UNLOCK 2
> > > /* Acquire the lock.
> > > 
> > >    Q: Support ref-counted locks at this layer?  */
> > > void fooint_lock (int mode, int locknum, const char *file, int line);
> > > #define LOCK(N)    fooint_lock(LOCKMODE_LOCK,(N),__FILE__,__LINE__)
> > > #define UNLOCK(N)  fooint_lock(LOCKMODE_UNLOCK,(N),__FILE__,__LINE__)
> > LOCKMODE_LOCK and LOCKMODE_UNLOCK can't be private to the library, since 
> > the library won't know what to pass to the locking callback to get lock 
> > and unlock capability - this will be defined by the application that 
> > sets the locking function.
> 
> Good point.  The macro names should perhaps be per-library too, but
> the values should be consistent across all the libraries.
> 
> > I wrote a proof of concept that is rather different than what is described 
> > here. I need to rework it to meet in the middle. My proof of concept has 
> > the library registering the API (it knows the system that it runs on), but 
> > that makes no sense because you want to avoid the overhead unless the 
> > application is threaded.
> 
> Would weak references help?  Checking a function address shouldn't be
> too expensive.  Or are pthread_create and friends always available
> even if you don't ask for them at link time?
> 
> My hunch is that having one version of the library just do something
> reasonable, as much as possible, for both threaded and non-threaded
> applications, without the application having to do the registration at
> all, would be ideal.  Whether it's an attainable ideal, I don't
> know. :-)
> 
> > So, I just wanted to double check the advisibility of defining all of this 
> > per library since that will duplicate the code per library and cause any 
> > application that links to more than one library to have to set up the 
> > callbacks per library (more duplicated code). (Do most apps link to only 
> > one or more than one library?)
> 
> There are applications that are linking to SASL and GSS and krb5 and
> krb4 and openssl and....  In theory, we can also have apps directly
> using only GSS, or only SASL, and using other libraries under the
> covers when using the krb5-based implementations; it certainly should
> be possible.  (In the Kerberos tree itself, of course, we never have
> anything quite so simple.)
> 
> I'm hoping the API is sufficient that the application only needs to
> register callbacks with the libraries it uses directly; libraries
> picked up indirectly should be "informed" by the directly-used library
> that pulls them in.  Yes, there would be some duplicated code, but I
> don't think there would be all that much.
> 
> Ken
> _______________________________________________
> krbdev mailing list             krbdev at mit.edu
> http://mailman.mit.edu/mailman/listinfo/krbdev
> 





More information about the krbdev mailing list