Exception – Client not found in Kerberos database (6) with spnego-Kerberos IWA

kerberosspnego

I am getting following error for SPNEGO/Kerberos Authentication

I get this error when I run HelloKeyTab.java file.

***Exception in thread "main" javax.security.auth.login.LoginException: Client not
found in Kerberos database (6)**
        at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(K
b5LoginModule.java:763)
        at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.j
va:584)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl
java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcce
sorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at javax.security.auth.login.LoginContext.invoke(LoginContext.java:762)
        at javax.security.auth.login.LoginContext.access$000(LoginContext.java:
03)
        at javax.security.auth.login.LoginContext$4.run(LoginContext.java:690)
        at javax.security.auth.login.LoginContext$4.run(LoginContext.java:688)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:
87)
        at javax.security.auth.login.LoginContext.login(LoginContext.java:595)
        at net.sourceforge.spnego.SpnegoHttpURLConnection.<init>(SpnegoHttpURLC
nnection.java:207)
        at HelloKeytab.main(HelloKeytab.java:17)
Caused by: KrbException: Client not found in Kerberos database (6)
        at sun.security.krb5.KrbAsRep.<init>(KrbAsRep.java:76)
        at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319)
        at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364)
        at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(K
b5LoginModule.java:735)
        ... 14 more
Caused by: KrbException: Identifier doesn't match expected value (906)
        at sun.security.krb5.internal.KDCRep.init(KDCRep.java:143)
        at sun.security.krb5.internal.ASRep.init(ASRep.java:65)
        at sun.security.krb5.internal.ASRep.<init>(ASRep.java:60)
        at sun.security.krb5.KrbAsRep.<init>(KrbAsRep.java:60)
        ... 17 more*

Setup,link and files I have used for SPNEGO/Kerberos Authentication.
link- http://spnego.sourceforge.net/
Domain account for tomcat server
user – xyztest
password – ****
principal – princ HTTP/APPSERVER1@corp.xyz.com

1)HelloKeyTab.java – Test keytab generated for apache tomcat server

    public class HelloKeytab {

    public static void main(final String[] args) throws Exception {
        System.setProperty("java.security.krb5.conf", "krb5.conf");
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("java.security.auth.login.config", "login.conf");

        SpnegoHttpURLConnection spnego = null;

        try {
           System.out.println("11111111");
            spnego = new SpnegoHttpURLConnection("custom-client");
            spnego.connect(new URL("http://localhost:8080/DemoAuth/hello_spnego.jsp"));
            System.out.println("2222222");   
            System.out.println("HTTP Status Code: " 
                    + spnego.getResponseCode());

            System.out.println("HTTP Status Message: "
                    + spnego.getResponseMessage());

        } finally {
            if (null != spnego) {
                spnego.disconnect();
            }
        }
    }
}

2)krb5.conf – Kerberos Configuration File

 [libdefaults]
        default_tkt_enctypes = aes256-cts aes256-cts-hmac-sha1-96 aes128-cts-    hmac-sha1-96 aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc arcfour-hmac arcfour-hmac-md5 
        default_tgt_enctypes = aes256-cts aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc arcfour-hmac arcfour-hmac-md5 
       permitted_enctypes = aes256-cts aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc arcfour-hmac arcfour-hmac-md5
       default_domain = CORP.XYZ.COM

    [realms]
         CORP.XYZ.COM  = {
               kdc = CORP.XYZ.COM
               default_domain = CORP.XYZ.COM 
    }

    [domain_realm]
         CORP.XYZ.COM = CORP.XYZ.COM

3)login.conf -Login configuration file

    custom-client {
    com.sun.security.auth.module.Krb5LoginModule required
    storeKey=true
    useKeyTab=true
    keyTab="C:/apache-tomcat-7.0.40-windows-x64/apache-tomcat-7.0.40/bin/xyztest.keytab"
    principal="HTTP/APPSERVER1@corp.xyz.com";
};
spnego-client {
     com.sun.security.auth.module.Krb5LoginModule required;
};
spnego-server {
    com.sun.security.auth.module.Krb5LoginModule required
    storeKey=true
    useKeyTab=true
    keyTab="C:/apache-tomcat-7.0.40-windows-x64/apache-tomcat-7.0.40/bin/xyztest.keytab"
    principal="HTTP/APPSERVER1@corp.xyz.com";
};

4)setspn command -to register principal

setspn -s HTTP/APPSERVER1 xyztest
Checking domain DC=corp,DC=xyz,DC=com

Registering ServicePrincipalNames for CN=xyztest,CN=Users,DC=corp,DC=xyz,DC=com
       HTTP/APPSERVER1
Updated object

PS C:\Windows\system32> setspn -s HTTP/APPSERVER1.corp.xyz.com xyztest
Checking domain DC=corp,DC=xyz,DC=com

Registering ServicePrincipalNames for CN=xyztest,CN=Users,DC=corp,DC=xyz,DC=com
       HTTP/APPSERVER1.corp.xyz.com
Updated object

5)ktpass command : to generate keytab file

    ktpass /princ HTTP/APPSERVER1@corp.xyz.com /mapuser xyztest /pass ***** /out xyztest.keytab /crypto AES256-SHA1 /ptype KRB5_NT_PRINCIPAL
Targeting domain controller: xyzDC1.corp.xyz.com
Using legacy password setting method
ktpass : Successfully mapped HTTP/APPSERVER1 to xyztest.
At line:1 char:1
+ ktpass /princ HTTP/APPSERVER1@corp.xyz.com /mapuser xyztest /pass *****
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Successfully ma...o xyztest.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

Key created.
Output keytab to xyztest.keytab:
Keytab version: 0x502
keysize 84 HTTP/APPSERVER1@corp.xyz.com ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32 
(0x6e6afbbefc78946121bd7ed6657524c7409917cae1708223ce938449113d9805)

6)Apache tomcat server
7)JDK 7
8)Domain Controller – Windows Active directory
9)If I try to run kinit command to authenticate principal with keytab I get the same error Client not found in Kerberos database (6)

    Command - kinit -k -t xyztest.keytab HTTP/APPSERVER1@corp.xyz.com
Result - Exception krb_error 6 client not found in kerberos database (6)

10)HelloKDC.java : Link http://spnego.sourceforge.net/ provides HelloKDC.java to test connection to KDC. I can successfully connect to the KDC with HelloKDC.java

    public final class HelloKDC {

    private HelloKDC() {
        // default private
    }

    public static void main(final String[] args) throws Exception {

        // Domain (pre-authentication) account
        final String username = "xyztest";

        // Password for the pre-auth acct.
        final String password = "!Dragonfly1!";

        // Name of our krb5 config file
        final String krbfile = "krb5.conf";

        // Name of our login config file
        final String loginfile = "login.conf";

        // Name of our login module
        final String module = "spnego-client";

        // set some system properties
        System.setProperty("java.security.krb5.conf", krbfile);
        System.setProperty("java.security.auth.login.config", loginfile);
        //System.setProperty("sun.security.krb5.debug", true);

        // assert 
        HelloKDC.validate(username, password, krbfile, loginfile, module);

        final CallbackHandler handler = 
            HelloKDC.getUsernamePasswordHandler(username, password);

        final LoginContext loginContext = new LoginContext(module, handler);

        // attempt to login
        loginContext.login();

        // output some info
        System.out.println("Subject=" + loginContext.getSubject());

        // logout
        loginContext.logout();

        System.out.println("Connection test successful.");
    }

    private static void validate(final String username, final String password
        , final String krbfile, final String loginfile, final String moduleName) 
        throws FileNotFoundException, NoSuchAlgorithmException {

        // confirm username was provided
        if (null == username || username.isEmpty()) {
            throw new IllegalArgumentException("Must provide a username");
        }

        // confirm password was provided
        if (null == password || password.isEmpty()) {
            throw new IllegalArgumentException("Must provide a password");
        }

        // confirm krb5.conf file exists
        if (null == krbfile || krbfile.isEmpty()) {
            throw new IllegalArgumentException("Must provide a krb5 file");
        } else {
            final File file = new File(krbfile);
            if (!file.exists()) {
                throw new FileNotFoundException(krbfile);
            }
        }

        // confirm loginfile
        if (null == loginfile || loginfile.isEmpty()) {
            throw new IllegalArgumentException("Must provide a login file");
        } else {
            final File file = new File(loginfile);
            if (!file.exists()) {
                throw new FileNotFoundException(loginfile);
            }
        }

        // confirm that runtime loaded the login file
        final Configuration config = Configuration.getConfiguration();

        // confirm that the module name exists in the file
        if (null == config.getAppConfigurationEntry(moduleName)) {
            throw new IllegalArgumentException("The module name " 
                    + moduleName + " was not found in the login file");
        }        
    }

    private static CallbackHandler getUsernamePasswordHandler(
        final String username, final String password) {

        final CallbackHandler handler = new CallbackHandler() {
            public void handle(final Callback[] callback) {
                for (int i=0; i<callback.length; i++) {
                    if (callback[i] instanceof NameCallback) {
                        final NameCallback nameCallback = (NameCallback) callback[i];
                        nameCallback.setName(username);
                    } else if (callback[i] instanceof PasswordCallback) {
                        final PasswordCallback passCallback = (PasswordCallback) callback[i];
                        passCallback.setPassword(password.toCharArray());
                    } else {
                        System.err.println("Unsupported Callback: " 
                                + callback[i].getClass().getName());
                    }
                }
            }
        };

        return handler;
    }
}

Please provide me solution to resolve the error
Client not found in Kerberos database (6)

klist output

    #0>     Client: xyztest @ CORP.XYZ.COM
        Server: krbtgt/CORP.XYZ.COM @ CORP.XYZ.COM
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x60a10000 -> forwardable forwarded renewable pre_authent n
ame_canonicalize
        Start Time: 3/8/2017 10:01:14 (local)
        End Time:   3/8/2017 20:01:14 (local)
        Renew Time: 3/15/2017 10:01:14 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0x2 -> DELEGATION
        Kdc Called: xyzDC1.corp.xyz.com

#1>     Client: xyztest @ CORP.XYZ.COM
        Server: krbtgt/CORP.XYZ.COM @ CORP.XYZ.COM
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent nam
e_canonicalize
       Start Time: 3/8/2017 10:01:14 (local)
        End Time:   3/8/2017 20:01:14 (local)
        Renew Time: 3/15/2017 10:01:14 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0x1 -> PRIMARY
        Kdc Called: xyzDC1.corp.xyz.com

#2>     Client: xyztest @ CORP.XYZ.COM
        Server: ldap/xyzDC1.corp.xyz.com @ CORP.XYZ.COM
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_deleg
ate name_canonicalize
        Start Time: 3/8/2017 10:01:16 (local)
        End Time:   3/8/2017 20:01:14 (local)
        Renew Time: 3/15/2017 10:01:14 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called: xyzDC1.corp.xyz.com

#3>     Client: xyztest @ CORP.XYZ.COM
        Server: LDAP/xyzDC1.corp.xyz.com/corp.xyz.com @ CORP.ADAP
TIVE.COM
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_deleg
ate name_canonicalize
        Start Time: 3/8/2017 10:01:15 (local)
        End Time:   3/8/2017 20:01:14 (local)
        Renew Time: 3/15/2017 10:01:14 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called: xyzDC1.corp.xyz.com

#4>     Client: xyztest @ CORP.XYZ.COM
        Server: cifs/xyzDC1.corp.xyz.com @ CORP.XYZ.COM
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_deleg
ate name_canonicalize
        Start Time: 3/8/2017 10:01:14 (local)
        End Time:   3/8/2017 20:01:14 (local)
        Renew Time: 3/15/2017 10:01:14 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called: xyzDC1.corp.xyz.com

Best Answer

Keep the below things in mind when working on Kerberos Environment

  1. Realm (Domain Name) should be in UPPER CASE when creating keytab file as well as wherever you are using Realm
  2. For SPNEGO authentication, each server host should be mapped as HTTP/hostname for the web authentication user. For example,

    setspn -s HTTP/hostname xyztest

  3. Kerberos ticket should be available in the environment krb5ccname for each operation

To get Kerberos ticket using username and password

kinit principal password

To get Kerberos ticket using keytab

kinit -k -t keytab principal

You can set ticket location using environment variable krb5ccname

set krb5ccname=newticketfilelocation

To list the ticket details, change directory to java\bin and run klist. This is because klist command is available in windows and it shows only logged in user tickets. To list the ticket got from kinit command, you should run from java\bin location

klist
Related Topic