Configuring GSSAPI and Cyrus SASL

This document was contributed by Ken Hornstein and updated by Alexey Melnikov.

A couple of people have asked me privately, "Hey, how did you get the GSSAPI mechanism to work? I tried, but the sample apps kept failing". (The short answer: I'm a tenacious bastard).

I figured that it couldn't hurt to give a quick explanation as to how you get GSSAPI working with the sample apps, since it wasn't obvious to me, and I consider myself not completely ignorant of GSSAPI and Kerberos.

  1. Compile the Cyrus-SASL distribution with the GSSAPI plugin for your favorite GSS-API mechanism. I personally use the GSSAPI libraries included with the MIT Kerberos 5 distribution; Heimdal and CyberSafe work as well.
  2. Start up the sample-server. The command-line used for sample-server needs to specify the GSSAPI service name and the location of the plug-ins; your sample command line might look something like this:
      ./sample-server -s host -p ../plugins/.libs
    
    on UNIX and like
      sample-server -s host -p ..\plugins
    
    on Windows.

    In this example, I am using "host", which already exists on my machine, but only root can read it, so I an running this as root. If you want to use an alternate service name, you will need to create that service in Kerberos, place it in a keytab readable by you, _and_ point your Kerberos library at it. Unix: both MIT Kerberos and Heimdal, use /etc/krb5.keytab on Unix by default, but this can be changed by setting the KRB5_KTNAME environment variable; the default for CyberSafe Kerberos is /krb5/v5srvtab for UNIX systems and can be changed by setting the CSFC5KTNAME environment variable. Windows: the default service key table location for CyberSafe is C:\Program Files\CyberSafe\v5srvtab, unless the CyberSafe registry setting for the KeyTab key is set to an alternate path. MIT Kerberos on Windows uses the keytab filename krb5kt.

    You should get a response similar to:

      Generating client mechanism list...
      Sending list of 3 mechanism(s)
      S: R1NTQVBJIFBMQUlOIEFOT05ZTU9VUw==
    

    Note that later on (assuming everything works) you might need to paste in lines that are longer than canonical input processing buffer on your system. You can get around that by messing around with stty; while the details vary from system to system, on Solaris you can do something like:

      ( stty -icanon min 1 time 0 ; ./sample-server -s host -p ../plugins/.libs )
    
  3. Obtain a Kerberos ticket for the user you want to authenticate as.
      kinit kenh
    
  4. Start up the sample client. You need to specify the service name, the hostname, and the userid. An example might be
      ./sample-client -s host -n your.fqdn.here -u kenh -p ../plugins/.libs
    

    You should get a response similar to this:

      Waiting for mechanism list from server...
    
  5. Cut-and-paste the initial mechanism line from the server process (this includes the "S: ") into the client process. You should get something similar to:
      S: R1NTQVBJIFBMQUlOIEFOT05ZTU9VUw==
      Choosing best mechanism from: GSSAPI PLAIN ANONYMOUS
      Using mechanism GSSAPI
      Preparing initial.
      Sending initial response...
      C: <.... lots of base 64 data ...>
      Waiting for server reply...
    

    If GSSAPI isn't selected as the mechanism, there is a few things that might have gone wrong:

    You can turn on a healthy amount of debugging information by changing the definition in config.h of the VL macro to (and recompiling libsasl):

      #define VL(foo) printf foo;
    

    There is a possibility you might get an error that looks like this:

      sample-client: Starting SASL negotiation: generic failure
    

    This can mean that you didn't provide all of the required information to the sample-client (did you provide a service name with -s, the hostname of the service with -n, and a username with -u ?), or that GSSAPI has failed (unfortunately, on the client you cannot find out the internal GSSAPI error; you will need to break out the debugger for that).

  6. Cut and paste the client response (The _entire_ line that begins with C:, including the initial "C: ") to the server process. You should get a response back that starts with "S: ". Cut and paste that to the client, and continue this exchange until you either get "Negotiation complete", or an error. If you get an error on the server you should get a complete error message (including the GSSAPI error string); on the client you unfortunately will only probably get "generic failure", which will again require the use of a debugger (but the VL macro should help with this).

    One common thing that happens is that on your server you might see the error:

      sample-server: Performing SASL negotiation: authentication failure
    	(Requested identity not authenticated identity)
    

    This comes from not having a requested identity (the -u option) that matches the identity that you were authenticated to via the GSSAPI. This is of course mechanism specific, but if for example you're using Kerberos, the Cyrus SASL library strips out the @REALM from your identity if you are in the same realm as the server. So if your Kerberos identity is user@SOME.REALM and the server is in SOME.REALM, you need to specify "user" to the -u flag of the client. If you're accessing a server in a foreign realm, you need to pass the full principal name via the -u option to make this work correctly.

    If you complete the negotiation successfully, you should see something that looks like (on both the client and server):

      Negotiation complete
      Username: kenh
      sample-server: realm: can't request info until later in exchange
      SSF: 56
    

    If you get to that, then you've done it, and GSSAPI works successfully! If you have questions about any of this, feel free to drop me a line.


    Back to the index