Saturday, May 31, 2014

NoSuchMethodError SpnegoAuthenticationProcessingFilter AbstractAuthenticationToken

In a nutshell, the solution to this problem involved cloning the git project, building the sources and deploying the newly created artifact (jar) to my local maven repository; see below for me details.

As part of an attempt to kerberize an web application (see here for details), which uses Spring Security's LDAP, I added in the necessary dependencies shown here:
<dependency>
    <groupId>org.springframework.security.extensions</groupId>
    <artifactId>spring-security-kerberos-core</artifactId>
    <version>1.0.0.M1</version>
</dependency>
and which I found here:
https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension

Next I configured the Spring Security XML configuration file as follows (description can be found at the link above too)

<beans ... >

<sec:http entry-point-ref="spnegoEntryPoint">
    <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
    <sec:custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
</sec:http>
    
    
<bean id="spnegoEntryPoint" class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />

<bean id="spnegoAuthenticationProcessingFilter" class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="kerberosServiceAuthenticationProvider" />
</sec:authentication-manager>

<bean id="kerberosServiceAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
    <property name="ticketValidator">
        <bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
            <property name="servicePrincipal" value="HTTP/tomcat@EXAMPLE.COM" />
            <property name="keyTabLocation" value="classpath:krb5.keytab" />
            <property name="debug" value="true"/>
        </bean>
    </property>
    <property name="userDetailsService" ref="dummyUserDetailsService" />
</bean>

<bean id="dummyUserDetailsService" class="org.wmmnpr.mykrb.config.Krb5DumyUserService"/>



</beans>

And started the Maven based project using the maven-tomcat-plugin as follows:
>mvn tomcat7:run

When I tried to access a protected URL, I got the following error:

org.apache.catalina.core.StandardWrapperValve invoke
Schwerwiegend: Servlet.service() for servlet [jsp] in context with path [/mykrb5webapp] threw exception [Filter execution threw an exception] with root cause
java.lang.NoSuchMethodError: org.springframework.security.authentication.AbstractAuthenticationToken.<init>(Ljava/util/List;)V
at org.springframework.security.extensions.kerberos.KerberosServiceRequestToken.<init>

Obviously, the SpnegoAuthenticationProcessingFilter was incompatible with the spring-security-core library. I had no option but to clone the spring-security-security repository and see if I could fix the problem.

Using the eclipse git plugin, I cloned the remote repository (https://github.com/spring-projects/spring-security-kerberos.git) and then ran the gradle buiild. To import the code into eclipse I added "apply plugin: 'eclipse'" to the sources build.gradle file and run the "eclipse" target. This generated the proper eclipse project files, which allowed me to import the project into eclipse (see below)



To build and deploy the library, I ran the gradle.gui by calling:

gradlew.bat --gui




This made it very easy to install the jar into my local maven repository. All I had to do was click on the install target shown above.

Next, I updated the eclipse project of my web application to reflect the new version and ran the project again in the debugger. 

The problem was that the source code was the changed but the executable code seemed to be different. When I tried to step through my changed code, the debugger didn't seem to know about the changes. 

I spent lots of time trying to clean and rebuild the gradle project, I even deleted the artifacts in my maven repository, but it didn't help either. 

Then started I started the jvisualvm using the same user, tomcat, under which the web application as running (see here)



I could not see which jar file the class was being loaded from. To do that, I needed to start the server using the -verbose:class JVM option, which I passed to maven by setting in the environment the MAVEN_OPTS variable.

This showed the source jar of the class very nicely.


[Loaded org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter from file:/C:/Users/wnpr/.m2/repository/org/springframework/security/extensions/spring-security-kerberos-core/1.0.0.CI-SNAPSHOT/spring-security-kerberos-core-1.0.0.CI-SNAPSHOT.jar]

Despite all my efforts, I was still getting the NoSuchMethodError. Eventually, I had the idea to look into the publish-maven.gradle file. There I found references to some external resources.

scm {
     url = 'https://github.com/SpringSource/spring-security-kerberos'
     connection = 'scm:git:git://github.com/SpringSource/spring-security-kerberos'
     developerConnection = 'scm:git:git://github.com/SpringSource/spring-security-kerberos'

}

which I changed to something meaningless:

scm {
     url = 'https://githubxxx.com/SpringSource/spring-security-kerberos'
    connection = 'scm:git:git://githubxxx.com/SpringSource/spring-security-kerberos'
     developerConnection = 'scm:git:git://githubxxx.com/SpringSource/spring-security-kerberos'



I ran the gradle clean, the maven install and started the web application. This time java code shown in the debugger agreed what was being executed and the NoSuchMethodError was gone. Obviously, the jars which I had picked up from the recommended setting (shown below) were wrong; however, now it didn't matter as I was building my own using gradle and deploying to my local maven repository.


<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>http://repo.spring.io/snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>

   <repository>
<id>spring-milestone</id>
<name>Spring Portfolio Milestone Repository</name>
<url>http://maven.springframework.org/milestone</url>
   </repository>
</repositories>


All that was left to do, was to comment out the above in my pom.xml file and change my dependency declaration of the kerberos artifact.

<dependency>
   <groupId>org.springframework.security.kerberos</groupId>
   <artifactId>spring-security-kerberos-core</artifactId>
   <version>1.0.0.CI-SNAPSHOT</version>
</dependency>



Windows 7 home directory Administrator runas

While trying to start various applications on Windows 7 using a local account, I kept getting:

"Could not create directory" ...

In the case below, I tried to start jvisualvm as a user called tomcat, whom I created as a local user with admin rights; however,  instead of using tomcat's own home directory, the application kept trying to use the one from the Administrator user.




The application was being started with runas:

>runas /user:tomcat /profile jvisualvm

Fixing this required opening a cmd window as tomcat

>runas /user:tomcat cmd
Geben Sie das Kennwort für "tomcat" ein:

Es wird versucht, cmd als Benutzer "GFT6841\tomcat" zu starten...

then starting regedit and changing all references to "Administrator" to appropriate user, in my case tomcat, in the the following keys:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\
Desktop
LocalAppData
AppData

There might be more but changing the above was sufficient for my purposes.


jvisualvm runas windows

On Windows 7, it may be necessary to profile a java application which is running under a user other than the one you're presently logged on as. 

To be able to see the process, it will also be necessary to run jvisualvm as that user. This can be done as follows:

>runas /user:tomcat jvisualm 

Where tomcat is the user name under which the program was running, namely Apache Tomcat, that I wanted to profile.

Make sure that the jvisualvm is in the path. 

If you encounter problems with the runas user not being able to access or create certain folders, like this:

"Could not create directory" ...

then see here.

Windows Maven runas

Rather than passing user.home to the JVM as shown below, a better fix, which requires a registry change, can be found here.

I created a new Windows' account called tomcat and wanted to start my web application using Maven's maven-tomcat-plugin for debugging purposes . 

From my "normal" Windows' account, I started a new command prompt window for the:
tomcat user as follows:

C:\Users\wnpr>runas /user:tomcat cmd
Geben Sie das Kennwort für "tomcat" ein:
Es wird versucht, cmd als Benutzer "GFT6841\tomcat" zu starten...

C:\Users\wnpr>

In the newly opened window, I tried to clean the project using Maven.

>mvn clean
Could not create local repository at C:\Users\Administrator\.m2\repository -> [Help 1]



My first attempt to solve this issue was taken from stackoverflow and involved creating a .m2 folder in the tomcat user's home directory and to copying a settings.xml file into the folder and, in the settings.xml file, setting the "localRepository" XML element to point to the actual repository's location, which existed in my normal user's directory; namely: "C:\Users\wnpr\.m2\repository"; however, this still didn't help.  

Then I tried to hard code it in the MAVEN_HOME\bin\m2.conf file, see below, but this didn't change anything either.

set maven.home default ${user.home}/.m2

Next, I tried to pass it to Maven as a run time parameter
>mvn  clean -Duser.home=c:\Users\wnpr 

This helped for clean and compiling but not exactly for running the application.

:Error creating bean with name org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator defined in class path resource [applicationContext-security.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cannot locate default realm

Which is a Kerberos error and not a tomcat one. For the solution see here.

  
  

Thursday, May 29, 2014

spring kerberos spnego Cannot locate default realm

While trying to start my kerberized application using the maven-tomcat-plugin as a different user under Windows 7, I got the following error : Cannot locate default realm.

Looking at the krb5.conf file, I realized that various things in the file were wrong so I changed them and the file look as follows:

[libdefaults]
default_realm = EXAMPLE.COM
# default_tgs_enctypes = des-cbc-md5,des3-cbc-sha1-kd
# defaualt_tkt_enctypes = des-cbc-md5,des3-cbc-sha1-kd
kdc_timeout = 5000
dns_lookup_realm = false
dns_lookup_kdc = false
allow_weak_crypto = yes
forwardable = true

[realms]
EXAMPLE.COM = {
kdc = 127.0.0.1:60088
}

[login]
krb4_convert = true
krb4_get_tickets = false


This didn't do much so I looked in the ApacheDS log file for more clues and noticed that the service principal's name (servicePrincipal) of the KerberosServiceAuthenticationProvider bean was incorrect. I corrected it and the server started properly. Below is the complete Spring Security configuration file, less the namespace related attributes, and below that the corresponding LDAP structure.

<beans ...>
    
<sec:http entry-point-ref="spnegoEntryPoint">
    <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
    <sec:custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
</sec:http>
    
    
<bean id="spnegoEntryPoint" class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />

<bean id="spnegoAuthenticationProcessingFilter" class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="kerberosServiceAuthenticationProvider" />
</sec:authentication-manager>

<bean id="kerberosServiceAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
    <property name="ticketValidator">
        <bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
            <property name="servicePrincipal" value="HTTP/tomcat@EXAMPLE.COM" />
            <property name="keyTabLocation" value="classpath:krb5.keytab" />
            <property name="debug" value="true"/>
        </bean>
    </property>
    <property name="userDetailsService" ref="dummyUserDetailsService" />
</bean>

<!-- Just returns the User authenticated by Kerberos and gives him the ROLE_USER -->
<!--  
<bean id="dummyUserDetailsService1" class="org.springframework.security.extensions.kerberos.sample.DummyUserDetailsService"/>
-->

<bean id="dummyUserDetailsService" class="org.wmmnpr.mykrb.config.Krb5DumyUserService"/>



</beans>




The server produced the following output during its start.




keytab add principal access denied

While trying to add a new principal, I got an access denied error. The error is mostly likely related to the fact that I'm  trying to generate a keytab with a session, which was created using "runas". That is the cmd console is running as a user, which is different from the one I logged on as.

>ktab.exe" -a tomcat@EXAMPLE.COM secret
Failed to save new entry.
java.io.FileNotFoundException: C:\Users\Administrator\krb5.keytab (Zugriff verweigert)at java.io.FileOutputStream.open(Native Method)

Or "Access denied"

Because I was suspicious that the problem was somehow related to the tomcat user's environment, I decided to explicitly specified the keytab file with the "-k" parameter,

>ktab.exe" -a tomcat@EXAMPLE.COM secret -k c:\Users\tomcat\krb5.keytab
Done!
Service key for tomcat@EXAMPLE.COM is saved in c:\Users\tomcat\krb5.keytab

This wasn't that obvious because the program's help of the documentation are vague about the usage of the flag.

Wednesday, May 28, 2014

Spring Security XML Configuration maven project


As a starting point for my application, I used the maven-archetype-webapp project template. I created an instance of the archetype with help from eclipse's (kepler's) maven plugin (if you have troubles, then go here). Shown here is a walk-through of the wizard's steps:








With the web application in place, I then changed the default web.xml to the following:

<web-app>
<display-name>Archetype Created Web Application</display-name>

<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext 
instead of the default XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>

<!-- Configuration locations must consist of one or more comma- or space-delimited 
fully-qualified @Configuration classes. Fully-qualified packages may also 
be specified for component-scanning -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.wmmnpr.mykrb.config</param-value>
</context-param>


<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>

I used the AnnotationConfigWebApplicationContext configurator because I'm only interested in configuring the security via XML and not the rest. 

In the org.wmmnpr.mykrb.config package(because the archetype doesn't include such a package it  had to be created as part of a new "src" folder), I created the following @Configuration class that will be scanned by the AnnotationConfigWebApplicationContext  configurator. 

@Configuration
@ImportResource("classpath:applicationContext-security.xml")
public class BootConfiguration {

}

As one can see, this class contains a reference the XML file, which configures the application's security. 

Before the project can be run, the maven-tomcat-plugin must be added to the project's pom and then started using the maven7:run goal. My first start produced the following error:

You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema with Spring Security 3.2. Please update your schema declarations to the 3.2 schema.
Offending resource: class path resource [applicationContext-security.xml]

From the message, it's clear that the "schemaLocation" attribute's map entry for the XML namespace ("s") had to be changed: 
http://www.springframework.org/schema/security/spring-security-3.2.xsd

My complete security configuration is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:s="http://www.springframework.org/schema/security"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans                         
                 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/util 
                 http://www.springframework.org/schema/util/spring-util-3.2.xsd 
          http://www.springframework.org/schema/security                 
                 http://www.springframework.org/schema/security/spring-security-3.2.xsd" >

            
    <s:http use-expressions="true" auto-config="true"  > 
        <s:intercept-url pattern="/**" access="isFullyAuthenticated()"/>                
    </s:http>
    
    <s:authentication-manager>
        <s:authentication-provider ref="ldapAuthenticationProvider"/>
    </s:authentication-manager>

    <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
        <constructor-arg value="ldap://192.168.48.30/dc=gft,dc=com" />
    </bean>

    <bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">

        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <constructor-arg ref="contextSource" />
                <property name="userSearch">
                    <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
                      <constructor-arg index="0" value="ou=users,ou=frankfurt,ou=gftobjects"/>
                      <constructor-arg index="1" value="cn={0}"/>
                      <constructor-arg index="2" ref="contextSource" />
                    </bean>
                </property>
            </bean>
        </constructor-arg>
        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator"/>
        </constructor-arg>

    </bean>

</beans>


The application now starts and the index.jsp is protected. When I log in, I get:

[ERROR] An internal error occurred while trying to authenticate the user.
org.springframework.security.authentication.InternalAuthenticationServiceException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1 ]; remaining name 'ou=users,ou=frankfurt,ou=gftobjects'
        at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:191)

I modified the XML configuration file because various things were wrong and now it works. The attributes of the parent element are the same as those above.

<beans ... >
           
    <s:http use-expressions="true" auto-config="true"  > 
        <s:intercept-url pattern="/**" access="isFullyAuthenticated()"/>                
    </s:http>
    
    <s:authentication-manager>
        <s:authentication-provider ref="ldapAuthenticationProvider"/>
    </s:authentication-manager>

    <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
        <constructor-arg value="ldap://192.168.48.30/dc=gft,dc=com" />
    </bean>

    <bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">

        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <constructor-arg ref="contextSource" />
                <property name="userDnPatterns">
                <array>
                <value>cn={0},ou=users,ou=frankfurt,ou=gftobjects</value>                            
                </array>                
                </property>
            </bean>
        </constructor-arg>
        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator"/>
        </constructor-arg>

    </bean>
</beans>

If you still have problem, then you might want to look here.
















Monday, May 26, 2014

new local account in Windows 7


In a previous blog, I got kinit to work with ApacheDS. Now, I'm going to try to use the setup to kerberize a small Spring web application; however, before doing so I thought it might be wise to create a new local account for my web application. The account is called tomcat and to do this on Windows 7, the following was done:

Right click on the Start ->Computer item to invoke the context menu from which you should choose the Manage item (here Verwalten)



This will start the Computer Management application (here Computerverwaltung), which can be use to add local accounts and groups.



The home directory, which was create for the new user, tomcat.




>runas /user:tomcat cmd
Geben Sie das Kennwort für "tomcat" ein:

Es wird versucht, cmd als Benutzer "GFT6841\tomcat" zu starten...





To run kinit:

%JDK_HOME%\bin\kinit.exe" tomcat@EXAMPLE.COM secret

C:\Users\tomcat>"c:\Program Files\Java\jdk1.7.0_25\bin\klist" -c c:\Users\tomcat
\krb5_tomcat

Credentials cache: c:\Users\tomcat\krb5_tomcat

Default principal: tomcat@EXAMPLE.COM, 1 entry found.

[1]  Service Principal:  krbtgt/EXAMPLE.COM@EXAMPLE.COM
     Valid starting:  May 26,  2014 16:35

     Expires:         May 27,  2014 16:35






kinit apacheds kerberos

I've installed ApacheDS and am trying to configure it to run as a kerberos server on my localhost.  When I run kinit (the one from the installed jre7) to get a ticket granting ticket (TGT), I get the following error:

C:\Users\wnpr>kinit.exe hnelson@EXAMPLE.COM
Password for hnelson@EXAMPLE.COM:secret
Exception: krb_error 6 Client not found in Kerberos database (6) - Client not found in Kerberos database Client not found in Kerberos database
KrbException: Client not found in Kerberos database (6) - Client not found in Kerberos 

The configuration, which is being used by kinit, is in the %JRE_HOME%/lib/security/krb5.conf
file.

The LDAP/Kerberos configuration is in the "instances\default\conf" of my ApachDS installation and is called config.ldif. If one opens the configuration file with Apache Directory Studio,  one should see the following:



Notice that the Kerberos Server has been activated on the default port, which agrees with the one configured in the krb5.conf. 

Below one can see the DIT structure, which is the default one plus a new partition called sevenSeas and a new user.




The problem is why cannot Kerberos find the hnelson user. Notice that the search basis is set to "ou=users,ou=system".

To further investigate the issue, I increased the servers log level to debug by changing the log4j.properties file found in the $APACHEDS_HOME directory as shown here:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${apacheds.log.dir}/apacheds.log

log4j.appender.R.MaxFileSize=10240KB
# Keep some backup files
log4j.appender.R.MaxBackupIndex=5

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n

log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n

# with these we'll not get innundated when switching to DEBUG
log4j.logger.jdbm.recman.BaseRecordManager=DEBUG
log4j.logger.org.apache.directory.server.OPERATION_LOG=DEBUG
log4j.logger.org.apache.directory.server.OPERATION_TIME=FATAL
log4j.logger.org.apache.directory.api.CODEC_LOG=DEBUG
log4j.logger.org.apache.directory.server.ACI_LOG=DEBUG
log4j.logger.org.apache.directory.server.PROVIDER_LOG=DEBUG
log4j.logger.org.apache.directory.server.CONSUMER_LOG=DEBUG
log4j.logger.org.apache.directory.CURSOR_LOG=DEBUG
log4j.logger.org.apache.directory.api=DEBUG
log4j.logger.org.apache.directory.server=DEBUG
log4j.logger.net.sf.ehcache=FATAL

log4j.logger.org.apache.mina=FATAL

The output looked like this:

[14:46:57] DEBUG [org.apache.directory.server.PROVIDER_LOG] - syncrepl provider initialized successfully
[14:46:57] INFO [org.apache.directory.server.ldap.LdapServer] - Successful bind of an LDAP Service (10636) is completed.
[14:46:57] INFO [org.apache.directory.server.ldap.LdapServer] - Successful bind of an LDAP Service (10389) is completed.
[14:46:57] INFO [org.apache.directory.server.ldap.LdapServer] - Ldap service started.
[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - LDAP server: started in 481 milliseconds
[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Starting the NTP server
[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Cannot find any reference to the NTP Server in the configuration : the server won't be started
[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Starting the Kerberos server
[14:46:57] DEBUG [org.apache.directory.server.protocol.shared.transport.UdpTransport] - UDP Transport created : <0.0.0.0:60088,>
[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Starting the Kerberos server
[14:46:57] DEBUG [org.apache.directory.server.kerberos.kdc.KdcServer] - initializing the kerberos replay cache
[14:46:57] INFO [org.apache.directory.server.core.api.CacheService] - fetching the cache named kdcReplayCache
[14:46:57] INFO [org.apache.directory.server.kerberos.kdc.KdcServer] - Kerberos service started.

[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Kerberos server: started in 39 milliseconds

The following entries were written to the log upon executing kinit hnelson@EXAMPLE.COM 

[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Kerberos server: started in 39 milliseconds
[14:46:57] INFO [org.apache.directory.server.ApacheDsService] - Cannot find any reference to the HTTP Server in the configuration : the server won't be started
[14:51:10] DEBUG [org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler] - /127.0.0.1:55596 CREATED:  datagram
[14:51:10] DEBUG [org.apache.directory.server.KERBEROS_LOG] - /127.0.0.1:55596 CREATED:  datagram

[14:51:10] DEBUG [org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler] - /127.0.0.1:55596 OPENED

I re-executed kinit.

[14:51:11] DEBUG [org.apache.directory.server.kerberos.protocol.codec.KerberosDecoder] - Decoded KerberosMessage : 
>-------------------------------------------------------------------------------
AS-REQ
pvno : 5
msg-type : AS_REQ
kdc-req-body : 
    KDCOptions : 
    cname : { name-type: KRB_NT_UNKNOWN, name-string : <'hnelson'> }
    realm : EXAMPLE.COM
    sname : { name-type: KRB_NT_SRV_INST, name-string : <'krbtgt', 'EXAMPLE.COM'> }
    till : 19700101000000Z
    nonce : 508742362
    etype : des-cbc-md5 (3) des3-cbc-sha1-kd (16)
    addresses : 192.168.178.42 fe80:0:0:0:45a9:39dc:cf90:bdc2 fe80:0:0:0:287f:3fbf:3f57:4dd5 2001:0:5ef5:79fd:287f:3fbf:3f57:4dd5

-------------------------------------------------------------------------------<



[14:51:11] DEBUG [org.apache.directory.api.ldap.model.schema.syntaxCheckers.Ia5StringSyntaxChecker] - Syntax valid for 'hnelson@EXAMPLE.COM'
[14:51:11] DEBUG [org.apache.directory.server.OPERATION_LOG] - >> SearchOperation : SearchContext for Dn 'ou=users,ou=system', filter :'(krb5PrincipalName=hnelson@EXAMPLE.COM)'

.
.
[14:51:11] DEBUG [org.apache.directory.api.ldap.model.schema.syntaxCheckers.DnSyntaxChecker] - Syntax valid for 'cn=hnelson,ou=users,ou=system'


I then added some kerberos related elements to the user's entry.




The log file now showed something else.

[15:42:24] DEBUG [org.apache.directory.server.core.authn.AuthenticationInterceptor] - Operation Context: SearchContext for Dn 'ou=users,ou=system', filter :'(krb5PrincipalName=hnelson@EXAMPLE.COM)'
[15:42:24] DEBUG [org.apache.directory.server.xdbm.search.impl.DefaultSearchEngine] - Nb results : 2 for filter : (&:[2](krb5PrincipalName=hnelson@EXAMPLE.COM:[?])(#{SUBTREE_SCOPE (Estimated), 'ou=users,ou=system', DEREF_ALWAYS}:[2]))
[15:42:24] DEBUG [org.apache.directory.server.protocol.shared.kerberos.StoreUtils] - Found entry cn=hnelson,ou=users,ou=system for kerberos principal name hnelson@EXAMPLE.COM
[15:42:24] DEBUG [org.apache.directory.server.KERBEROS_LOG] - Found entry cn=hnelson,ou=users,ou=system for kerberos principal name hnelson@EXAMPLE.COM
[15:42:24] ERROR [org.apache.directory.server.KERBEROS_LOG] - Error while searching for client hnelson@EXAMPLE.COM : Client not found in Kerberos database


Which didn't quiet make sense because I still got the "Client not found" error message.

I've added a kbrtgt and a ldap to the users node and placed the user node with in the dc=example,dc=com partition and am now getting a password decryption error.

INFO   | jvm 1    | 2014/05/25 00:15:55 | [00:15:55] DEBUG [org.apache.directory.server.KERBEROS_LOG] - --> Verifying the policy
INFO   | jvm 1    | 2014/05/25 00:15:55 | [00:15:55] DEBUG [org.apache.directory.server.KERBEROS_LOG] - --> Verifying using SAM subsystem.
INFO   | jvm 1    | 2014/05/25 00:15:55 | [00:15:55] DEBUG [org.apache.directory.server.KERBEROS_LOG] - --> Verifying using encrypted timestamp.
INFO   | jvm 1    | 2014/05/25 00:15:55 | [00:15:55] DEBUG [org.apache.directory.server.KERBEROS_LOG] - Entry for client principal hnelson@EXAMPLE.COM has no SAM type.  Proceeding with standard pre-authentication.
INFO   | jvm 1    | 2014/05/25 00:15:55 | [00:15:55] DEBUG [org.apache.directory.server.KERBEROS_LOG] - Decrypting data using key des3-cbc-sha1-kd (16) and usage ERR_603 AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the client key (1)
INFO   | jvm 1    | 2014/05/25 00:15:55 | javax.crypto.IllegalBlockSizeException: Input length not multiple of 8 bytes

INFO   | jvm 1    | 2014/05/25 00:15:55 | at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:854)

My LDAP configuration now looks like this:



At first I  thought it must having something to do with the user password but then I remembered that the special thing about kerberos is that the user never sends his or her password accross the network so the error must be referring to the krb5key.

Time to dig a little deeper into the DIT (Data Information Tree) and the Object Tree Structure.

From zytrax:

"LDAP Data Interchange Files (LDIF) which are fully described in a later chapter. LDIFs are textual files that describe the tree hierarchy - the Directory Information Tree (DIT)"

 Important Note: The lines in the above LDIF file beginning with 'dn:' essentially tell the LDAP server how to structure or place the entry within the DIT. In general, it does not matter what attribute value is used for this purpose as long as the 'dn:' is unique. ..........However, if the entry is going to be used for user authentication, say, a logon or Single Sign-On type use, the 'dn:' value becomes extremely important and defines the logon (or Bind DN in the jargon) identifier. It is sometimes (especially in the context of LDAP used within Microsoft's AD) referred to as a Principal DN though this term is not used within the LDAP standards definitions. For more on this topic.

More about DN and binding.

LDAP: DNs for Authentication

the Bind DN CAN ONLY be the DN used when the entry was added or created.

References:

http://www.zytrax.com/books/ldap/ch2/index.html#basic

http://www.zytrax.com/books/ldap/apa/binddn.html


I restructured the DIT so that it looked like this:



and added example.com to the host file in C:\Windows\System32\drivers\etc

# localhost name resolution is handled within DNS itself.
# 127.0.0.1       localhost
# ::1             localhost
127.0.0.1 EXAMPLE.COM

Now, kinit gives:

kinit.exe hnelson@EXAMPLE.COM
Password for hnelson@EXAMPLE.COM:
Exception: krb_error 6 Client not found in Kerberos database (6) - Client not found in Kerberos database Client not found in Kerberos database
KrbException: Client not found in Kerberos database (6) - Client not found in Kerberos database


The IllegalBlockSizeException disappeared because the search basis, due to the changes in the DIT structure, was wrong. Once corrected so that the target DN was found, the error reoccurred again.

I found some useful information about the krb5.conf file and the TGT Request here:
http://docs.oracle.com/cd/E19253-01/816-4557/egric/index.html. Here I read that it is recommendable not to set default_tkt_enctypes (See below).

Note, that the encryption types specified in default_tkt_enctypes must match at least one of the principal key encryption types in the principal database stored on the KDC. Otherwise, the TGT request will fail. In most situations, it is best not to set default_tkt_enctypes because this parameter can be a source of interoperability problems.

I commented out the setting in my krb5.conf, which now looks like this:

[libdefaults]
default_realm = EXAMPLE.COM
# default_tgs_enctypes = des-cbc-md5,des3-cbc-sha1-kd
# default_tkt_enctypes = des-cbc-md5,des3-cbc-sha1-kd
kdc_timeout = 5000
dns_lookup_realm = false
dns_lookup_kdc = false
allow_weak_crypto = yes
forwardable = true

[realms]
EXAMPLE.COM = {
kdc = example.com:60088
}

[login]
krb4_convert = true
krb4_get_tickets = false



This solved the issue with the illegal block side and produced a new error.

kinit.exe  wmmnpr@EXAMPLE.COM
Password for wmmnpr@EXAMPLE.COM:
Exception: krb_error 7 Server not found in Kerberos database (7) - Server not found in Kerberos database Server not found in Kerberos database

KrbException: Server not found in Kerberos database (7) - Server not found in Kerberos database

I put the IP Address (127.0.0.1) back in place of the hostname (example.com) but that still didn't help. 

During testing, I typed in the wrong password, which produce a new error:

kinit.exe hnelson@EXAMPLE.COM
Password for hnelson@EXAMPLE.COM:
Exception: krb_error 31 Integrity check on decrypted field failed (31) - Integrity check on decrypted field failed Integrity check on decrypted field failed



I could see in the log, that ApacheDS was looking for the krbtgt service in the same sub-tree as the user.

[org.apache.directory.server.KERBEROS_LOG] - --> Getting the server entry for {}{ name-type: KRB_NT_SRV_INST, name-string : <'krbtgt', 'EXAMPLE.COM'> }

 [org.apache.directory.server.core.authn.AuthenticationInterceptor] - Operation Context: SearchContext for Dn 'ou=users,dc=security,dc=example,dc=com', filter :'(krb5PrincipalName=krbtgt/EXAMPLE.COM@EXAMPLE.COM)'

So I copied the krbtgt entry back to the users entry.




And now bingo!

kinit.exe wmmnpr@EXAMPLE.COM
Password for wmmnpr@EXAMPLE.COM:
New ticket is stored in cache file C:\Users\wnpr\krb5cc_wnpr


What confuses me is that I seem to be getting a service ticket and not a ticket granting ticket. See log entries:

INFO   | jvm 1    | 2014/05/26 09:39:27 | [09:39:27] DEBUG [org.apache.directory.server.KERBEROS_LOG] - --> Generating ticket for { name-type: KRB_NT_SRV_INST, name-string : <'krbtgt', 'EXAMPLE.COM'> }

INFO   | jvm 1    | 2014/05/26 09:39:27 | [09:39:27] DEBUG [org.apache.directory.server.KERBEROS_LOG] - Ticket will be issued for access to { name-type: KRB_NT_SRV_INST, name-string : <'krbtgt', 'EXAMPLE.COM'> }.