Sit amet felis. Mauris semper,

Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque sed felis. Aliquam sit amet felis. Mauris semper, velit semper laoreet dictum, quam diam dictum urna, nec placerat elit nisl in quam. Etiam augue pede, molestie eget, ...

Category name clash

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque sed felis. Aliquam sit amet felis. Mauris semper, velit semper laoreet dictum, quam diam dictum urna, nec placerat elit nisl in quam. Etiam augue pede, molestie eget, rhoncus at, convallis ut, eros. Aliquam pharetra. Nulla in tellus eget odio sagittis blandit. ...

Test with enclosures

Here's an mp3 file that was uploaded as an attachment: Juan Manuel Fangio by Yue And here's a link to an external mp3 file: Acclimate by General Fuzz Both are CC licensed. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque sed felis. Aliquam sit amet felis. Mauris semper, velit semper laoreet dictum, ...

Block quotes

Some block quote tests: Here's a one line quote. This part isn't quoted. Here's a much longer quote: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In dapibus. In pretium pede. Donec molestie facilisis ante. Ut a turpis ut ipsum pellentesque tincidunt. Morbi blandit sapien in mauris. Nulla lectus lorem, varius aliquet, ...

Contributor post, approved

I'm just a lowly contributor. My posts must be approved by the editor.Mauris semper, velit semper laoreet dictum, quam diam dictum urna, nec placerat elit nisl in quam. Etiam augue pede, molestie eget, rhoncus at, convallis ut, eros. Aliquam pharetra. Nulla in tellus eget odio sagittis blandit. Maecenas at ...

Posted by The Java Monkey - - 39 comments




Note: This blog relates to version 1.5.1 of Apache Directory Server - since then they have radically changed the configuration format. That is, version 1.5.3 cannot be configured as a KDC using the steps in this blog.

All the Kerberos authentication development I have done has been in a Windows environment. All of this development has required single-sign-on (SSO) between interoperable .NET WSE3 and Java applications. Therefore, Active Directory has been the KDC.

I really like having a full development environment on my laptop, so that if necessary, I can try things out at home or on my daily commute to work (an hour on the train). Without having a VPN to my work environment, the next best thing is to have my own KDC installed on my laptop.

As seems to be the case with nearly every type of Java enterprise component or solution that one needs, the Apache Software Foundation have a great Java-based solution that fits like a hand into a glove - the Apache Directory Project.

Out of the box, Apache Directory isn't configured as a KDC, and their site is kind of hard to use to locate and understand this configuration. This blog details how I setup my Apache Directory install as a working KDC for Kerberos authentication and authorisation through Java.

The Software
Download both Apache Directory Server and its front end, Apache Directory Studio. Studio is a pretty impressive front end, and looks *really* nice. A great example of how nice an application developed on the Eclipse platform can look and feel. Anyway, go to those links and download the server and the studio and install them.

Apache Directory is Java based and runs as a Windows service. It is configured using Spring, so some familiarity with Spring would be useful, but is not essential. Once it has installed, pull up a file browser and we'll dive in and Kerberos-alize it.

Configuring the Beast (Kerberos)
Under your Apache Directory Server install (C:\Program Files\Apache Directory Server), navigate to the folder instances\default\conf. This folder contains the config files for your server instance. server.xml is the Spring context configuration for your server, and contains the Kerberos config settings. Open this file up in a text editor.

Firstly, make sure that the kdcConfiguration bean is enabled (not commented out). You may also need to set the enabled flag to true (see the part highlighted in blue):



<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" />
<!--<property name="searchBaseDn" value="ou=Users" />-->
</bean>
Secondly, ensure that the Key Derivation Service is enabled:



<bean class="org.apache.directory.server.core.configuration.
MutableInterceptorConfiguration">
<property name="name" value="keyDerivationService" />
<property name="interceptorClassName"
value="org.apache.directory.server.core.kerberos.KeyDerivationService" />
</bean>
Thirdly, ensure that the kdcConfiguration bean is injected onto the configuration bean (as a property ref). That is, the following line must appear and not be commented out on the configuration bean:



<property name="kdcConfiguration" ref="kdcConfiguration" />
Finally, I always configure my Kerberos principals/identities via an .ldif file, as opposed to trying to do it through the front end. Make sure that on the configuration bean, the ldifDirectory property is enabled and points to a location on your machine where it can find an .ldif file that we are about to prepare.

Apache Directory comes with a domain, EXAMPLE.COM already setup. This is fine for the purposes we need it for. Create the following .ldif file, modifying the names where appropriate (i.e. client and server names) and point the server.xml Spring context to this, as mentioned above. Note that the service principal has my laptop machine name "BULLY" in its krb5 principal - this should be changed to the name of the server that your service is going to be running on.

Stop and start the Apache Directory service (on Windows this can be done through the Services administrative tool). This causes the .ldif file to load, as long as it has never been loaded before.



# Web server identity/service principal.
dn: uid=webserver,ou=users,dc=example,dc=com
objectclass: top
objectclass: person
objectclass: inetOrgPerson
objectclass: krb5Principal
objectclass: krb5KDCEntry
cn: Web Server
sn: Web Server
uid: webserver
userpassword: Password99
krb5PrincipalName: webserver/bully@EXAMPLE.COM

# User / client principal.
dn: uid=monkey,ou=users,dc=example,dc=com
objectclass: top
objectclass: person
objectclass: inetOrgPerson
objectclass: krb5Principal
objectclass: krb5KDCEntry
cn: Monkey
sn: Monkey
uid: monkey
userpassword: Password99
krb5PrincipalName: monkey@EXAMPLE.COM

# Ticket Granting Service.
dn: uid=krbtgt,ou=users,dc=example,dc=com
objectclass: top
objectclass: person
objectclass: inetOrgPerson
objectclass: krb5Principal
objectclass: krb5KDCEntry
cn: KDC Service
sn: KDC Service
uid: krbtgt
userpassword: randomKey
krb5PrincipalName: krbtgt/EXAMPLE.COM@EXAMPLE.COM

Apache Directory Studio



Studio itself, can be used to connect to any LDAP server. To connect it to Apache Directory Server, in the connections panel (see screenshot), click the "New Connection..." button, and fill out the details as follows:

Hostname: localhost
Port: 10389
Encryption Method: No encryption

Authentication Method: Simple Authentication
Bind DN or user: uid=admin,ou=system
Bind password: secret

These will connect you to the server as the admin user.

The .ldif file that was loaded above, will have setup the client principal, the server principal, and the krbtgt service. That is, you now have a fully functioning KDC! You can now try running your Kerberos programs against the KDC. Your Kerberos settings should be similar to the following:

java.security.krb5.realm=EXAMPLE.COM
java.security.krb5.kdc=localhost

Apache Directory Server uses a rolling log file for its logging, which is an invaluable source for tracking down error messages and authentication failures. Under the install of the server, go to the instances\default\log folder and use a tailing program to view the log.

As you attempt to authenticate against the KDC, you will get exception stack traces and error messages printed here, which make it pretty obvious what the problem with your request was. Also note that you may have to set the rootCategory in the log4j.properties config file under instances\default\conf to DEBUG to get all the information you need (and of course, restart the Apache Directory Server).

Most likely, you will get some error messages from the KDC when initially trying to talk to it, so post them here and we can work through them!

Ciao.

39 Responses so far.

  1. Anonymous says:

    Thanks a lot!

    This works with ApacheDS 1.5.1.
    But it fails with ApacheDS 1.5.3. The server.xml has changed. So be warned ;-)

  2. Thanks for spotting that - the new format is completely different!

    I'll try and get a blog around the new format once I've worked it out - however, at the moment 1.5.3 doesn't even run for me - keeps on crashing on startup when trying to resolve a schema!

  3. cmilono says:

    After struggling with 1.5.4, I found your blog (excellent, BTW), and I went back to 1.5.1.

    I am getting KRBError code 9 - The client or server has a null key - during the JAAS login.

    I checked server.xml and uncommented GSSAPI from the supportedMechanisms and checked on the saslPrincipal and saslHost, and I am still getting this error.

    The logs don't seem to help.

    Hints?

    TIA

  4. Hi,

    I haven't seen that problem before.

    Did your Apache DS server log acknowledge when your request came in?

    It seems to be Kerberos specific error as opposed to an error from within a Java library somewhere. There are loads of Kerberos general search results about this problem, all of them suggesting to reset the password for the account you are logging in as:

    http://support.microsoft.com/kb/230476
    0x9 (KDC_ERR_NULL_KEY) "The client or server has a null key"
    Keys should never be null (blank). Even null passwords generate keys because the password is concatenated with other elements to form the key. If a client sees this error, the administrator should reset the password on the account.

    In a copy of the Apache DS source code I can see where the error is defined:

    http://svn.apache.org/repos/asf/directory/deceased/pre-m2/kerberos-common-0.6/common/src/java/org/apache/kerberos/exceptions/ErrorType.java

    And it is thrown using the following code:

    EncryptionType encryptionType = authContext.getEncryptionType();
    clientKey = clientEntry.getKeyMap().get( encryptionType );
    if ( clientKey == null ) {
    throw new KerberosException( ErrorType.KDC_ERR_NULL_KEY );
    }

    Apart from resetting the password and restarting your Apache DS service, I'd also make sure you are using a very recent JVM for client and Apache DS, as new encryption type support was adding in the late 1.5's (e.g. 12+). The code above is trying to get a key by encryption type, so maybe the encryption type isn't supported by the JVM that your Apache DS is running from.

  5. cmilono says:

    I put it into debug and it looks like there might be a bind issue between KRB and LDAP. I'm on J1.6.

    Other areas I considered and will investigate include a subtle configuration mistake in their interceptor function which appears responsible for setting the "krb5keyversionnumber" (among other things). The key/password is dynamic as "randomKey".

    I'm also getting "init() encoding tag is 126 req type is 11".

    I'll keep you posted - I've been interrupted with multiple balls-in-the-air distractions.

    One goal is to have an Open Source apache-style licensed KDC that can sit as a replacement for ActiveDirectory in a testing environment until we can provision another set of AD instances.

  6. cmilono says:

    Very interesting investigation - the log said:

    WARN [org.apache.directory.server.core.DefaultDirectoryService] - You didn't change the admin password of directory service instance 'default'. Please update the admin password as soon as possible to prevent a possible security breach.

    Followed by:
    WARN [org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler] - The client or server has a null key (9)

    Followed by:
    ERROR [org.apache.directory.server.ldap.support.UnbindHandler] - failed to unbind session properly
    org.apache.directory.shared.ldap.exception.LdapNameNotFoundException: uid=admin,ou=system

    ---------------------
    ...so I changed the passphrases for admin (and the client) and I was told the new password violated its policy (where is that configured?). So, I gave them stronger passphrases and now I get a completely different error in the log:

    WARN [org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler] - Additional pre-authentication required (25)
    WARN [org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler] - Integrity check on decrypted field failed (31)
    ERROR [org.apache.directory.server.Service] - SynchWorker failed to synch directory.
    org.apache.directory.shared.ldap.exception.LdapAuthenticationException

  7. cmilono says:

    I checked the validity of the Unlimited Strength Jurisdiction Policy, and found I had applied it to a JDK whilst I was actually pointing to a JRE in ApacheDS and the Client/Server code (I'm now trying your Client/Server Hello World example [bless you for all of this].

    I got past the decrypted field failed and now have yet-another issue:

    Using builtin default etypes for default_tkt_enctypes
    default etypes for default_tkt_enctypes: 3 1 23 16 17 18.
    Acquire TGT using AS Exchange
    Using builtin default etypes for default_tkt_enctypes
    default etypes for default_tkt_enctypes: 3 1 23 16 17 18.
    >>> KrbAsReq calling createMessage
    >>> KrbAsReq in createMessage
    >>> KrbKdcReq send: kdc=CMILONO-WK.NA.BARFOO.COM UDP:88, timeout=30000, number of
    retries =3, #bytes=178
    >>> KDCCommunication: kdc=CMILONO-WK.NA.BARFOO.COM UDP:88, timeout=30000,Attempt
    =1, #bytes=178
    SocketTimeOutException with attempt: 1
    >>> KDCCommunication: kdc=CMILONO-WK.NA.BARFOO.COM UDP:88, timeout=30000,Attempt
    =2, #bytes=178
    SocketTimeOutException with attempt: 2
    >>> KDCCommunication: kdc=CMILONO-WK.NA.BARFOO.COM UDP:88, timeout=30000,Attempt
    =3, #bytes=178
    SocketTimeOutException with attempt: 3
    [Krb5LoginModule] authentication failed
    Receive timed out
    javax.security.auth.login.LoginException: Receive timed out
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Un
    known Source)
    at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)

    This is the Server starting, and it appears it is getting the TGT and failing on a Session Ticket?

  8. It is using the AS-REQ to get a TGT from the KDC. It basically looks like it can't see the KDC/Apache DS domain/machine that you have specified. I'd try by IP address and see if that works to get it going.

    An "AS" request is the "Authentication Service" request is what grabs a TGT from the KDC. Its not really needed from the server's point of view anyway, but it must be being forced through as part of the JAAS login.

  9. I found some decent descriptions on MSDN about the requests:

    # TGT. The TGT is created by the KDC and sent to the client if authentication to the KDC succeeds.

    # Service ticket. A service ticket is the data created by the KDC, which is provided to the client and then sent by the client to the server to establish authentication of the client.

    # AS-REQ/REP. The authentication service request/response (AS-REQ/REP) exchange is the Kerberos TGT request and reply messages sent to the KDC from the client. If the exchange is successful, the client is provided with a TGT.

    # TGS-REQ/REP. The ticket-granting service request/response (TGS-REQ/REP) exchange is the Kerberos service ticket request and reply messages that are sent to the KDC from the client when it is instructed to obtain a service ticket for a server.

    # GSS. The Generic Security Service application programming interface (GSS-API) and the Generic Security Service Negotiate Support Provider (GSS-SPNEGO) mechanisms negotiate a secure context for sending and receiving messages between the client and server by using key material derived from the previous ticket exchanges.

  10. cmilono says:

    The AS Request is going through KDC to LDAP as part of the Authentication exchnage, correct?
    If I use a bogus uid, it will tell me that it isn't found in LDAP, so KDC must be accepting a connection and passing the credentials on to LDAP.

    I changed the java.security.krb5.kdc property to an IP address, but to no avail.

  11. The connect error, CMILONO-WK.NA.BARFOO.COM UDP:88 - the KDC is meant to be running on port 88 - your spring context config for the kdc should be set to port 88, so I'm assuming its actually the call to the KDC that is the issue.

  12. cmilono says:

    I got it all working now - it was an over-zealous uncommenting around the keyDerivationService which permitted passwordPolicyService and others to become active, though I'm surprised at it.

    One behavior was if I changed the passwords to a policy, then if I restarted ApacheDS, it would fail. I'll need to look into the password policy configuration aspects.

  13. Awesome, it took me a while to get it set up too, but it is worth the hassle, as I can run Kerberos SOAP stuff entirely off my laptop when I'm not on my work domain.

    Hopefully they sort out their docs for the new versions so we can use them.

  14. Pattabi says:
    This comment has been removed by the author.
  15. Pattabi says:
    This comment has been removed by the author.
  16. chandra says:

    I am getting error "SocketTimeOutException with attempt: 3
    javax.security.auth.login.LoginException: Receive timed out" when I try to connect to server using client bat file.

    as per one of comment I have also tried ip &hostname as below but i am getting same exception.
    krb5PrincipalName: webserver/192.168.2.52@EXAMPLE.COM
    krb5PrincipalName: webserver/hosname@EXAMPLE.COM

    please help me , i am stuck at this point.

    complete console output.

    D:\kerberos-gss-getting-started>java -classpath build/classes javamonkey.app.gss.Client
    Using builtin default etypes for default_tkt_enctypes
    default etypes for default_tkt_enctypes: 3 1 23 16 17.
    Using builtin default etypes for default_tkt_enctypes
    default etypes for default_tkt_enctypes: 3 1 23 16 17.
    >>> KrbAsReq calling createMessage
    >>> KrbAsReq in createMessage
    >>> KrbKdcReq send: kdc=127.0.0.1 UDP:88, timeout=30000, number of retries =3, #bytes=145
    >>> KDCCommunication: kdc=127.0.0.1 UDP:88, timeout=30000,Attempt =1, #bytes=145
    SocketTimeOutException with attempt: 1
    >>> KDCCommunication: kdc=127.0.0.1 UDP:88, timeout=30000,Attempt =2, #bytes=145
    SocketTimeOutException with attempt: 2
    >>> KDCCommunication: kdc=127.0.0.1 UDP:88, timeout=30000,Attempt =3, #bytes=145
    SocketTimeOutException with attempt: 3
    javax.security.auth.login.LoginException: Receive timed out
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
    at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at javax.security.auth.login.LoginContext.invoke(Unknown Source)
    at javax.security.auth.login.LoginContext.access$000(Unknown Source)
    at javax.security.auth.login.LoginContext$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
    at javax.security.auth.login.LoginContext.login(Unknown Source)
    at javamonkey.app.gss.Client.login(Client.java:89)
    at javamonkey.app.gss.Client.main(Client.java:50)
    Caused by: java.net.SocketTimeoutException: Receive timed out
    at java.net.PlainDatagramSocketImpl.receive0(Native Method)
    at java.net.PlainDatagramSocketImpl.receive(Unknown Source)
    at java.net.DatagramSocket.receive(Unknown Source)
    at sun.security.krb5.internal.UDPClient.receive(Unknown Source)
    at sun.security.krb5.KrbKdcReq$KdcCommunication.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.krb5.KrbKdcReq.send(Unknown Source)
    at sun.security.krb5.KrbKdcReq.send(Unknown Source)
    at sun.security.krb5.KrbKdcReq.send(Unknown Source)
    at sun.security.krb5.KrbAsReq.send(Unknown Source)
    at sun.security.krb5.Credentials.sendASRequest(Unknown Source)
    at sun.security.krb5.Credentials.acquireTGT(Unknown Source)
    ... 14 more
    There was an error during the JAAS login

  17. Anonymous says:

    Almost worked as you said for me - the page at http://cwiki.apache.org/DIRxINTEROP/kerberos-authentication-to-openldap-using-apacheds.html also helped. I was running into an error at the start of authentication "Failed to get initial context ou=users,dc=example,dc=com". I had to add the following to my LDIF file:

    # Define organizational unit for 'users' context
    dn: ou=users,dc=example,dc=com
    objectclass: top
    objectclass: organizationalunit
    ou: users

  18. satyajeet says:

    Hi,

    I am getting the following error, please suggest some solution

    Exception in thread "main" GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7) - Server not found in Kerberos database)

  19. Krassimir Koychev says:

    Very helpful. Thank you!
    When I start the server I receive this:
    default etypes for default_tkt_enctypes: 3 1 23 16 17.
    D:\java\Kerberos\security.token
    Found key for webserver/krasi@EXAMPLE.COM(3)
    Found key for webserver/krasi@EXAMPLE.COM(17)
    Found key for webserver/krasi@EXAMPLE.COM(23)
    Found key for webserver/krasi@EXAMPLE.COM(16)
    Found key for webserver/krasi@EXAMPLE.COM(1)
    Entered Krb5Context.acceptSecContext with state=STATE_NEW
    >>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
    GSSException: Failure unspecified at GSS-API level (Mechanism level: Integrity check on decrypted field failed (31))

  20. Gaga says:

    hey man, thanks for the help, it's a really great job.
    I wanted to ask you about which configuration u have to get this thing work I mean:
    - OS
    - apache directory server version
    - apache directory studio version
    - java version
    I'm really going crazy to get this thing work... :(

  21. Hi, no problems. I haven't actually used Apache Directory Server for a couple of years, as I no longer work at the company that I had to do this LDAP kerberos type stuff for, but the details are:

    OS = Windows XP - media center edition and professional editions - it worked on both fine. Haven't ever tried it on Vista or Win 7, or Win XP Home edition though.

    Apache Directory Server version was 1.5.1. I discovered that as of version 1.5.3 they changed how they configured it, and didn't put up any documentation on this. It will probably take different steps to configure it these days - hopefully the Apache Directory Server site has better docs now.

    Apache Directory Studio - was whatever version was out when 1.5.1 of the server was out - not too sure on what that was sorry.

    Java version - I used Java 5, jdk 1.5.0.7, but I think I tried it on other Java 1.5 versions and it was fine too.

  22. Anonymous says:

    how to create the .ldif file and how to make it be pointed in spring context of server.xml?

  23. Thanks a lot for sharing such an informative blog about Using Apache Directory Server as a Key Distribution Centre (KDC).It helped me as I am a beginer so was not knowing how to do this.The way it is written is also impressive.

  24. DEVEN !!! says:

    Hey !! The step where we restart the apache directory service after modyfying the server.xml file , I am getting an " Error:1067 Windows could not start the apache Directory Server - default service on Local Computer.
    Error 1067: The process terminated unexpectedly. "

    Please Help, I'm stuck on this for 3 days now :'(

  25. Anonymous says:

    But how to do it with, for instance, mytest.org, instead of an example.com domain?

  26. Shelly says:

    I am trying to implement SSO using JAAS and GSS API with Apache DS and Kerberos. I did the following steps-

    1. Setup the KDC using Apache DS 1.5.1 and Apache Directory Studio 1.5.3
    2. Created a JAAS config file with below details-
    GSSClient{
    com.sun.security.auth.module.Krb5LoginModule required
    useTicketCache=false;
    };
    GSSServer{
    com.sun.security.auth.module.Krb5LoginModule required
    storeKey=true;
    };
    3. Created Server and Client classes
    4. Ran server using the main method
    5. When I try to run the server code I get a timeout exception-
    >>> KrbAsReq in createMessage
    >>> KrbKdcReq send: kdc=localhost UDP:88, timeout=30000, number of retries =3, #bytes=238
    >>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =1, #bytes=238
    SocketTimeOutException with attempt: 1
    >>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =2, #bytes=238
    SocketTimeOutException with attempt: 2
    >>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =3, #bytes=238
    I checked the server.xml settings and tried replacing hostname with IP address but no use. I am completely stuck and need advise. Please help!!!

    Thanks.

  27. Anonymous says:

    Hello,

    I have installed Apache DS in 2003 server. I tried loading the new LDIF file in DS, but the studio still reflects the sample LDIF file. I changed the LDIF path in the server.xml in default instance and at root directory.

    Please support.

    Thanks.

  28. Anonymous says:

    You are the Best! Thanks so much for putting this article together. Though this may not work out, but lists the things that we need to look for and configure. I'm going to give it a shot with latest Apache DS.

Leave a Reply

Recent Posts