Kerberos, GSSAPI and SASL Authentication using LDAP

There seems to be plenty of HOWTO's on getting Kerberos working with LDAP, with step by step instructions through the process. I found http://aput.net/~jheiss/krbldap/howto.html very good. I have documented here, not a step by step guide, but a list of the issues I have faced configuring Kerberos to work with LDAP when things don't go the way the HOWTO's say it should. Hopefully each issue will be accompanied by a solution.

ktadd hangs

When using kerberos with various server/service principals it is inevitable that you will need to add some of these to /etc/krb5.keytab or some other keytab file. At times I found that after logging in to kadmin.local and typing ktadd host/myserver.example.com that nothing happened. The command just hung.

I solved this by:

[root]# cp /etc/krb5.keytab /etc/krb5.keytab.old
[root]# rm /etc/krb5.keytab
[root]# mv /etc/krb5.keytab.old /etc/krb5.keytab
[root]# kadmin.local
Authenticating as principal root/admin@EXAMPLE.COM with password.
kadmin.local:  ktadd host/myserver.example.com
Entry for principal host/myserver.example.com with kvno 11, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal host/myserver.example.com with kvno 11, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal host/myserver.example.com with kvno 11, encryption type DES with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal host/myserver.example.com with kvno 11, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/etc/krb5.keytab.

Maybe some file locking issue?

ldap_sasl_interactive_bind_s: Unknown authentication method (-6)

Doing an LDAP search with a SASL bind e.g.

[lance]% ldapsearch  -LLL -b 'dc=example,dc=com' '(givenname=lance)' cn
ldap_sasl_interactive_bind_s: Unknown authentication method (-6)
	additional info: SASL(-4): no mechanism available: No worthy mechs found

In this instance the cyrus-sasl-gssapi package was not installed.

[root]# yum install cyrus-sasl-gssapi
[lance]% ldapsearch  -LLL -b 'dc=example,dc=com'   '(givenname=lance)' cn
SASL/GSSAPI authentication started
SASL username: l.rathbone@EXAMPLE.COM
SASL SSF: 56
SASL installing layers
dn: uid=l.rathbone,cn=users,dc=example,dc=com
cn: Lance Rathbone

ldap_sasl_interactive_bind_s: No such object (16)

Doing an LDAP search with a SASL bind e.g.

[lance]% ldapsearch -LLL -s base -b '' '(objectClass=*)' +
ldap_sasl_interactive_bind_s: No such object (16)

In this instance the sasl libraries were not installed. Install the libraries and restart the LDAP server.

[root]# yum install cyrus-sasl 
[root]# yum install cyrus-sasl-devel 
[root]# yum install cyrus-sasl-gssapi 
[root]# service ldap restart 
Stopping slapd:                                         [ OK ] 
Checking config files for slapd: config file testing succeeded 
                                                        [ OK ] 
Starting slapd:                                         [ OK ] 
[root]# exit 
[lance]% ldapsearch -LLL  -s base  -b ’’ -x supportedSASLMechanisms 
dn: 
supportedSASLMechanisms: GSSAPI 

ldap_sasl_interactive_bind_s: No such object (32)

Doing an LDAP search with a SASL bind e.g.

[lance]% ldapsearch -LLL -s base -b '' '(objectClass=*)' +
ldap_sasl_interactive_bind_s: No such object (32)

instead of:

[lance]% ldapsearch -LLL -s base -b '' '(objectClass=*)' +
SASL/GSSAPI authentication started
SASL username: lance@EXAMPLE.COM
SASL SSF: 56
SASL installing layers
dn:
namingContexts: dc=example,dc=com
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
subschemaSubentry: cn=Subschema

This error will occur when the LDAP server doesn't provide a root DSE1. This may be due to access controls. In your slapd.conf file you will need something like:

access to dn.base="" attrs=supportedSASLMechanisms,namingContexts,subschemaSubentry,objectClass,entry
        by domain.subtree="example.com" read
        by peername.ip="127.0.0.1" read
        by peername.ip="112.123.123.12" read
        by peername.ip="112.123.123.13" read
        by * none

Subnet masks can be used with this syntax: peername.ip=112.123.123.0%255.255.255.0.

After you make the changes you will need to restart the LDAP service.

Comments in slapd.conf

On a side point. Be careful with the use of comments within slapd.conf. Lines beginning with '#' are ignored and assumed to be comments. However, if a line begins with white space, it is considered a continuation of the previous line. Continuation lines are unwrapped before comment processing is applied.

Thus sometimes unexpected results occur. e.g.

access to dn.base="" attrs=supportedSASLMechanisms,namingContexts,subschemaSubentry,objectClass,entry
        by domain.subtree="example.com" read
        by peername.ip="127.0.0.1" read
#        by peername.ip="112.123.123.12" read
        by peername.ip="112.123.123.13" read
        by * none

You might think this only removes 112.123.123.12. However, because the following lines all begin with whitespace, this comments out all entries to the end of the stanza, until there is a blank line. Problem! So, if you want to remove an item you have three options:

  1. delete the unwanted line completely.
  2. don't indent the following line. Use no whitespace at all at the start of the line.
  3. follow the commented line with a blank line (one that contains no whitespace).
access to dn.base="" attrs=supportedSASLMechanisms,namingContexts,subschemaSubentry,objectClass,entry
        by domain.subtree="example.com" read
        by peername.ip="127.0.0.1" read
#        by peername.ip="112.123.123.12" read

        by peername.ip="112.123.123.13" read
        by peername.ip="112.123.123.14" read
        by * none

ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)

[lance]% ldapsearch -LLL -s base  -b '' '(objectClass=*)' +
ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)
        additional info: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

You are using the TLS_CACERT configuration option in your ldap.conf file on the client machine, however the file you have designated does not contain the CA certificate matching the one that was used to sign the LDAP server's certificate. Keep in mind that the TLS_CACERT file can contain multiple CA certificates - just concatenate them together. This can be useful if you are phasing in a new CA certificate and/or LDAP server certificate.

ldap_sasl_interactive_bind_s: Local error (-2)

 
[lance]% ldapwhoami
ldap_sasl_interactive_bind_s: Local error (-2)
	additional info: SASL(-1): generic failure: GSSAPI Error: Miscellaneous failure (No credentials cache found)

You have not done a kinit i.e. you have not authenticated against your kerberos server so there is no kerberos ticket available.

[lance]% klist
klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_0)


Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached
[lance]% kinit lance
Password for lance@EXAMPLE.COM
[lance]% klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: lance@EXAMPLE.COM

Valid starting     Expires            Service principal
02/02/07 13:33:46  02/02/07 21:33:46  krbtgt/EXAMPLE.COM@EXAMPLE.COM


Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached
[lance]% ldapwhoami
SASL/GSSAPI authentication started
SASL username: lance@EXAMPLE.COM
SASL SSF: 56
SASL installing layers
dn:uid=lance,cn=users,dc=example,dc=com
[lance]% 

ldap_sasl_interactive_bind_s: Local error (-2)

[lance]% ldapsearch -LLL -s base  -b '' '(objectClass=*)' +
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
        additional info: SASL(-1): generic failure: GSSAPI Error: Miscellaneous failure (Ticket expired)

Very similar to the previous error. This time your Kerberos ticket has expired. Again, you need to do a kinit.

ldap_sasl_interactive_bind_s: Internal (implementation specific) error (80)

[lance]# ldapsearch  -LLL -s base  -b '' '(objectClass=*)' +
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Internal (implementation specific) error (80)
        additional info: SASL(-1): generic failure: GSSAPI Error: Miscellaneous failure (No principal in keytab matches desired name)

This error would be much easier to debug if the error message would include the principal that it is looking for. Basically, your LDAP server needs to provide a Kerberos service principal e.g. ldap/ldap.example.com which you will need to place in a keytab file. The name of the principal will be the name of the process owner (ldap) followed by a "/" followed by the canonical name of the server (ldap.example.com). Also the LDAP server needs to know where this keytab file is.

The LDAP server may not be able to find the keytab file. You will need to tell slapd where to find the keytab in your startup script. You can do this directly on your init script (but see note below for Redhat systems).

[root]# vi /etc/init.d/slapd
#!/sbin/sh
# /etc/init.d/slapd -- Start slapd.
#

KRB5_KTNAME="FILE:/etc/openldap/ldap.keytab"
export KRB5_KTNAME

Using Redhat you can simply edit /etc/sysconfig/ldap

[root]# vi /etc/sysconfig/ldap
export KRB5_KTNAME="FILE:/etc/openldap/ldap.keytab"
[root]# service ldap start

The other possibility is that there really is a problem with the naming of the principal. The kerberos principal has to match the FQDN of the LDAP server. Make sure the DNS CNAME matches your hostname and that there is no ambiguity in your /etc/hosts file. If your server is ldap.example.com and the user running slapd is ldap then your principal will be ldap/ldap.example.com. Also, keep in mind the curiously named sasl-host line in your slapd.conf. This refers to the LDAP server not your KDC server. (I would have called it sasl-client.)

[root]# vi /etc/openldap/slapd.conf
sasl-realm     EXAMPLE.COM 
sasl-host      ldap.com.au

ldap_sasl_interactive_bind_s: Internal (implementation specific) error (80)

[lance]# ldapsearch -LLL -s base  -b '' '(objectClass=*)' +
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Internal (implementation specific) error (80)
        additional info: SASL(-1): generic failure: GSSAPI Error: Miscellaneous failure (Permission denied)

The LDAP server cannot read the keytab file. /etc/krb5.keytab is readable only by root and should NOT be made available to the LDAP server. The keytab file that the LDAP server uses must be readable by the owner of the slapd service (in this case ldap).

[root]# chgrp ldap /etc/openldap/ldap.keytab
[root]# chmod 640 /etc/openldap/ldap.keytab
[root]# ls -l /etc/openldap/ldap.keytab
-rw-r-----  1 root ldap 1826 Oct 25 13:28 /etc/openldap/ldap.keytab
[lance]# ldapsearch -LLL -s base  -b '' '(objectClass=*)'
SASL/GSSAPI authentication started
SASL username: lance/admin@EXAMPLE.COM
SASL SSF: 56
SASL installing layers
dn:
objectClass: top
objectClass: OpenLDAProotDSE
[lance]#
[lance]# ldapsearch -LLL -s base -b '' '(objectClass=*)' +
SASL/GSSAPI authentication started
SASL username: lance/admin@EXAMPLE.COM
SASL SSF: 56
SASL installing layers
dn:
namingContexts: dc=example,dc=com
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
subschemaSubentry: cn=Subschema

GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Unknown code krb5 194)

Error code 194 refers to "Credentials cache file permissions incorrect". In this situation you are probably using a cron job to create a ticket but the LDAP user cannot read the ticket cache file. Make sure the cache file is owned by the user trying to make the client connection. This is most probably the owner of the slapd process. (In my case this is ldap.)

[root]# ls -l /tmp/ldap.tkt
-rw------- 1 root root 519 Nov  1 09:14 /tmp/ldap.tkt
[root]# chown ldap:ldap /tmp/ldap.tkt
[root]# ls -l /tmp/ldap.tkt
-rw------- 1 ldap ldap 519 Nov  1 09:14 /tmp/ldap.tkt

GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Unknown code krb5 195)

This can happen if you simply have not done a kinit if you are working from the command line. However, in the case of a service such as slapd it may mean that client process (slapd) cannot find the ticket cache file. You will need to let the LDAP server know where the cache file is.

Using Redhat you can edit /etc/sysconfig/ldap

[root]# vi /etc/sysconfig/ldap
export KRB5CCNAME=/tmp/ldap.tkt
[root]# service ldap start

If you are not using Redhat you will need to make changes to your slapd startup file.

[root]# vi /etc/init.d/slapd
#!/sbin/sh
# /etc/init.d/slapd -- Start slapd.
#

KRB5CCNAME="/tmp/ldap.tkt"
export KRB5CCNAME
[root]# service ldap start

1 DSE DSA Specific Entry. DSA in turn stands for Directory System Agent (any directory enabled service providing DAP or LDAP access)


Author: Lance Rathbone
Last modified: Monday November 01, 2010

Home