{scrollbar} Work in progress

This site is in the process of being reviewed and updated.

SASL GSSAPI Authentication to ApacheDS


Apache Directory currently supports the SASL GSSAPI mechanism. SASL GSSAPI allows Kerberos authentication to be used during LDAP Binds. Additionally, the GSSAPI mechanism can provide message integrity (checksums) and, optionally, message privacy (encryption). When using SASL message privacy, connections do not need SSL to protect communications.

Getting Started

  1. Make sure you are using ApacheDS 1.5.1, which is currently (4-JUN-2007) only available from the HEAD of trunk in svn. (How to build the trunks)
  2. You can double-check your version of ApacheDS by interrogating the RootDSE for the supported SASL mechanisms. Note the use of the fully-qualified domain name (FQDN), 'ldap.example.com'. Regardless of the enabled authentication mechanisms, you will always be able to query the RootDSE. You must see 'GSSAPI' in this returned list. $ ldapsearch -H ldap://ldap.example.com:10389 -s base -LLL supportedSASLMechanisms -x dn: supportedSASLMechanisms: GSSAPI supportedSASLMechanisms: DIGEST-MD5 supportedSASLMechanisms: CRAM-MD5
  3. (OPTIONAL) Install GSSAPI support for LDAP tools on Linux. By default, some Linux variants do not have SASL GSSAPI support installed. If Cyrus SASL GSSAPI is not present, install it with an RPM maintenance tool such as 'yum'. Note that the SASL support in ApacheDS is unrelated to the SASL library implementation being installed here. $ rpm -qa | grep sasl cyrus-sasl-lib-2.1.22-4 cyrus-sasl-2.1.22-4 ... cyrus-sasl-gssapi-2.1.22-4 $ yum install cyrus-sasl-gssapi
  4. Open the server.xml for editing. $ cd <trunk>/server-main $ vi server.xml
  5. Enable GSSAPI as a mechanism. GSSAPI is disabled by default. <!-- The list of supported authentication mechanisms. --> <property name="supportedMechanisms"> <list> ... <value>GSSAPI</value> </list> </property>
  6. Set the FQDN of the host. The FQDN must resolve, by hosts file, or DNS. Elements of the SASL GSSAPI mechanism are extremely picky about the FQDN you use. The FQDN should be the top-most entry in your hosts file or matching A and PTR records in DNS. If you are running the client and the server on the same machine, you may need to set the FQDN to be your hostname. You will likely find a sniffer (like WireShark) very handy for figuring out what hostnames are being assumed and whether DNS is working properly. <!-- The FQDN of this SASL host, validated during SASL negotiation. --> <property name="saslHost" value="ldap.example.com" />
  7. Set the service principal name that the server-side of the LDAP protocol provider will use to "accept" a GSSAPI context initiated by the LDAP client. The SASL principal MUST follow the name-form ldap/<fqdn>@<realm>. The 'ldap' name component and the @<realm> will be automatically added to the FQDN by the LDAP client. The LDAP client will then use this as the service principal name when requesting a service ticket from a KDC. In our case, the KDC is ApacheDS, itself. <!-- The Kerberos principal name for this LDAP service, used by GSSAPI. --> <property name="saslPrincipal" value="ldap/ldap.example.com@EXAMPLE.COM" />
  8. (OPTIONAL) Enforce quality-of-protection (QoP). The QoP level directly maps to the JNDI levels. Listing all possible levels means any level will be accepted. Listing only 'auth-conf' will allow only 'auth-conf' connections. These SASL QoP levels are global; they affect all connections using DIGEST-MD5 or GSSAPI.




    Use SASL for authentication only (no integrity or confidentiality protection).


    Use SASL with integrity protection. Integrity basically means "with a checksum." For GSSAPI integrity is always enabled.


    Use SASL with confidentiality protection. Confidentiality means "with encryption." Confidentiality is sometimes called privacy. When Confidentiality is enabled, you do not need SSL/TLS to protect connections.

    <!-- The desired quality-of-protection, used by DIGEST-MD5 and GSSAPI. --> <property name="saslQop"> <list> <value>auth</value> <value>auth-int</value> <value>auth-conf</value> </list> </property>
  9. Configure SASL realms. If the realm is not enabled, the connection will be rejected. Note that if your realm does not appear here, you will see an error similar to "Nonexistent realm: dummy.com." <!-- The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI. --> <property name="saslRealms"> <list> <value>example.com</value> <value>apache.org</value> </list> </property>
  10. Set the search base DN. The search base DN is where a subtree-scoped DIT search will be performed. This is BOTH where the LDAP service principal must reside, as well as where user principals must reside. That all principals must reside in a single sub-tree is currently (4-JUN-2007) a limitation of the SASL implementation. Work is underway to enable "multi-realm" capability, as well as "split realm" capability. "Split realm" capability will allow you to split principals (users, admins, services, machines) into separate subtrees. <!-- The base DN containing users that can be SASL authenticated. --> <property name="searchBaseDn" value="ou=users,dc=example,dc=com" />
  11. Configure your host so that it knows where to get Kerberos tickets. On linux this is configured in '/etc/krb5.conf'. The minimum config file must list the default Kerberos realm and the location of at least one key distribution center (KDC). With ApacheDS, the KDC and LDAP server are the same, so we'll re-use our 'ldap.example.com' hostname here. [libdefaults] default_realm = EXAMPLE.COM [realms] EXAMPLE.COM = { kdc = ldap.example.com } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM
  12. Enable the Kerberos protocol provider. By default, the LDAP protocol is enabled, but the Kerberos protocol is not. You may also change the Kerberos port so that Kerberos can bind if you're logged-in as a non-root user. If you change the default port of '88', you must change the KDC port in the krb5.conf, as well. <bean id="kdcConfiguration" class="org.apache.directory.server.kerberos.kdc.KdcConfiguration"> <!-- Whether to enable the Kerberos protocol. --> <property name="enabled" value="true" /> <!-- The port to run the Kerberos protocol on. --> <property name="ipPort" value="88" /> </bean>
  13. Enable the KeyDerivationService. In contrast to the SIMPLE, CRAM-MD5, and DIGEST-MD5 SASL mechanisms, Kerberos authentication is based on symmetric keys. Since a user can't be expected to remember a symmetric key, there are "key derivation functions" that will produce symmetric key material based on the concatenation of the password, realm, and username. Any changes to the user's password must result in new keys being generated. Luckily, ApacheDS has the "KeyDerivationService" interceptor. This service will intercept any adds or modifications to the user's 'userPassword' attribute and generate keys. Service principals typically use random keys, so the interceptor will generate random keys when the special keyword 'randomKey' is used. Unlike other combinations of separate LDAP and Kerberos servers, we do not need to export the service principal keys to a keytab file from the KDC and use it to configure the LDAP server. Since ApacheDS' LDAP and Kerberos protocol both have access to the DIT, we simply need to enable the KeyDerivationService and add some principals. <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration"> <property name="name" value="keyDerivationService" /> <property name="interceptor"> <bean class="org.apache.directory.server.core.kerberos.KeyDerivationService" /> </property> </bean>
  14. Pre-load principals using an LDIF file. If the LDAP SASL GSSAPI mechanism is enabled but the service principal is not found then you may see a WARN'ing in the server logs. With the KeyDerivationService enabled, you should be able to use LDIFs or LDAP to configure principals on-the-fly. For this example, since the LDIF format is concise, we review some LDIF entries. You will find attached to this page an example LDIF. Download the LDIF and configure the 'ldifDirectory' in server.xml. <property name="ldifDirectory"> <value>/path/to/sasl-gssapi-example.ldif</value> </property>
  15. Review the LDIF entries. The metaphor for Kerberos comes from the fact that it is "three-headed"; there is always a KDC principal, service principal, and user principal. All of these principals use the same objectClass'es. The attributes are the minimum to satisfy their respective schema, with the exception of the Kerberos schema. Because we are using the KeyDerivationService, we don't need to specify the Kerberos key, key types, or key version number (kvno); they are automatically added by the interceptor, which will also increment the kvno when the password changes. Looking at the LDIF file you'll see the ASL license, an organizational unit (ou) for our 'users' subcontext, and the following entries:

    Entry RDN


    Principal Name



    userpassword: s3crEt

    krb5PrincipalName: hnelson@EXAMPLE.COM

    Our user principal. Note the user password.


    userpassword: randomKey

    krb5PrincipalName: krbtgt/EXAMPLE.COM@EXAMPLE.COM

    The KDC principal, with a random key.


    userpassword: randomKey

    krb5PrincipalName: ldap/ldap.example.com@EXAMPLE.COM

    The LDAP principal, with a random key.

  16. You are now ready to start the server. Upon startup, the server will load the entries from the LDIF. $ cd <trunk>/server-main $ ./apacheds.sh
  17. Request a ticket-granting ticket (TGT) using 'kinit'. If you have not already "logged in," you must request a fresh TGT. Without a TGT, 'ldapsearch', for example, will fail with error "No credentials cache found." Also, if you don't specify the user principal, kinit will guess the principal name based on the logged-in user and the realm configured in the krb5.conf. $ kinit hnelson@EXAMPLE.COM Password for hnelson@EXAMPLE.COM: <s3crEt>
  18. You should now be able to query the DIT using Kerberos credentials. GSSAPI will use the Kerberos credentials (TGT) of the current user. GSSAPI supports the concept of "realm," but the realm is part of the username, eg 'hnelson@EXAMPLE.COM'. This is in contrast to other SASL mechanisms where the realm is separately and explicitly specified. $ ldapsearch -H ldap://ldap.example.com:10389 -b "dc=example,dc=com" "(uid=hnelson)" -Y GSSAPI
  19. (OPTIONAL) List your Kerberos credentials. You'll see that in addition to a TGT, you also now have a service ticket for the LDAP server. $ klist -5fea Ticket cache: FILE:/tmp/krb5cc_0 Default principal: hnelson@EXAMPLE.COM Valid starting Expires Service principal 06/04/07 20:42:19 06/05/07 20:41:37 krbtgt/EXAMPLE.COM@EXAMPLE.COM Etype (skey, tkt): DES cbc mode with RSA-MD5, DES cbc mode with RSA-MD5 Addresses: (none) 06/04/07 20:42:22 06/05/07 20:41:37 ldap/ldap.example.com@EXAMPLE.COM Etype (skey, tkt): DES cbc mode with RSA-MD5, DES cbc mode with RSA-MD5 Addresses: (none)
  • No labels