Thread-safety in Kerberos libs

Xiaoshan Zuo Xiaoshan.Zuo at datadomain.com
Sat Dec 29 14:21:53 EST 2007


Ken,

Thanks for quick reply. Please see my comments inline.

> -----Original Message-----
> From: Ken Raeburn [mailto:raeburn at MIT.EDU]
> Sent: Saturday, December 29, 2007 2:09 AM
> To: Xiaoshan Zuo
> Cc: krbdev at MIT.EDU
> Subject: Re: Thread-safety in Kerberos libs
> 
> On Dec 28, 2007, at 21:55, Xiaoshan Zuo wrote:
> > I am working on adding Kerberos authentication to a multi-threaded
> > application. The libraries I am going to use are libkrb4.s0.2 and
> > libgssapi_krb5.so.2. The exact functions I am going to use in a
> > multi-threaded context are:
> >
> > gss_verify_mic
> > gss_get_mic
> > gss_release_buffer
> > gss_wrap
> > gss_unwrap
> >
> > I am trying to figure out whether those functions are thread-safe.
In
> > the doc/threads.txt file, it says that:
> >
> > "Any use of krb5_context must be confined to one thread at a time by
> > the application code."
> 
> It should say something along the lines of, "Any use of a given
> krb5_context object...."  Using distinct krb5_context objects
> simultaneously in different threads should be fine.
> 
In our application there will be multiple RPC sessions, each with their
krb5_context. The context creation and destroy are handled by one thread
(I think the context creation and destroy are sequential in nature). In
data exchange phase, those sessions can be serviced by multiple threads.
I think Linux kernel has some modified gssapi/Kerberos modules which is
similar to what we need.

Our requirement comes down to the thread-safety of the code in
xdr_rpc_gss_wrap_data() function:

        if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
                if (!xdr_rpc_gss_buf(xdrs, &databuf, (unsigned int)-1))
                        goto errout;

                /* Checksum rpc_gss_data_t. */
                maj_stat = gss_get_mic(&min_stat, ctx, qop,
                                       &databuf, &wrapbuf);
                if (maj_stat != GSS_S_COMPLETE) {
                        log_debug("gss_get_mic failed");
                        goto errout;
                }
                /* Marshal checksum. */
                xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned
int)-1);
                gss_release_buffer(&min_stat, &wrapbuf);
        }
        else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
                /* Encrypt rpc_gss_data_t. */
                maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
                                    &conf_state, &wrapbuf);
                if (maj_stat != GSS_S_COMPLETE) {
                        log_status("gss_wrap", maj_stat, min_stat);
                        goto errout;
                }
                /* Marshal databody_priv. */
                xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned
int)-1);
                gss_release_buffer(&min_stat, &wrapbuf);
        }

And similar function xdr_rpc_gss_wrap_data(). gss_get_mic() and
gss_wrap() can be called at the same time, and any one of them can be
called by more than one threads simultaneously.

> Also, that doesn't quite apply to the GSS library; any uses in there
> of a global krb5_context should be protected by locks.  Generally,
> any simple read-only object like an input buffer or OID can be shared
> across threads; GSS credentials can be shared; GSS security contexts
> cannot.  I'd have to go digging around to figure out the rest.
> 

Is a global krb5_context used in the libraries? I guess you mean the
krb5_context created by calling program.

> Note that thread safety is not part of the GSSAPI specification.  In
> another implementation, it may not be safe to perform any GSSAPI
> operations simultaneously in two threads, even simple ones on
> seemingly unrelated objects.
> 
> You also mention libkrb4, but not what functions might be used in
> multithreaded operation.  Be aware that not only are many of the
> libkrb4 functions not thread-safe (and unlikely to ever be made
> safe), but the library also maintains internal state across calls in
> one or two places, such that a sequence of calls in two threads,
> fully serialized but relating to two different authentication
> contexts, could give incorrect results.  Like too many things, this
> isn't well documented. :-(  Since our eventual plan is to eliminate
> krb4, I doubt this will get fixed.
>

I apologize, it should be libkrb5, that was a copy/paste error.

 
> > I also searched the email archive, there are multiple threads on
this
> > subject. In those threads, people blamed some functions in C
> > library for
> > causing thread-safe problem, there was no mention of krb5_context.
> > Do we
> > know whether it is just C library or Kerberos library is not thread-
> > safe
> > by itself?
> 
> We've tried to make accesses to certain types of objects (like ccache
> and keytab objects) thread-safe by adding locking.  Simple data
> structures included in krb5.h, like krb5_data and principal names,
> can't have mutexes added without changing the API that we've
> committed to maintaining for now, so uses of them can't be made
> thread-safe, though read-only uses (if we actually documented which
> those are) can be done simultaneously.  Any global state in the krb5
> library (except for a couple of exported global variables that are
> part of that API) should be protected by mutexes.  Anything dealing
> with global state like signals and terminal I/O are going to get
> messy in multithreaded code.
> 
> Because of some of these things, it's never going to be the case that
> two threads can do absolutely anything they want in the krb5 library
> without interfering with each other.  If both try to prompt for
> passwords, for example, things will probably get confused.  But I
> believe we've done a fairly good job of making thread-safe everything
> we intended to; any remaining issues (including the glaring lack of
> current, clear, specific documentation on this issue) are bugs.  (I
> see the latest release of valgrind has the helgrind tool enabled
> again; we should use that and run some tests, it may well find
> problems we've overlooked.)
> 

The thing we care about is: can two threads call krb5 library to do
integrity check and encryption/decryption on input buffers at the same
time with the same krb5 context. Since those operations don't change any
security context which is established at context creation, they should
be thread-safe.

Do you see there are any thread-safety issues on those operations? In
gss_krb5int_make_seal_token_v3() from file k5sealv3.c, ctx->seq_send is
modified and used without locking, is this a problem?

If there are other issues and can be fixed relatively easily, I think I
can help to provide a patch.

Thanks,

- Xiaoshan

> We do rely on stuff in other libraries that may or may not be thread-
> safe.  Some implementations of getaddrinfo, for example, are not
> thread-safe, and that's not something you can really test for in a
> configure script.  Some systems are missing thread-safe "_r" versions
> of various C library routines (e.g., getpwnam, gmtime) and thus wind
> up using shared static storage; that, we check for at configure time
> and issue warning messages.
> 
> Please do let us know if you encounter any problems relating to
> thread safety in the GSSAPI or krb5 libraries.
> 
> Ken




More information about the krbdev mailing list