Skip to content
dumischbaenger edited this page Nov 6, 2018 · 16 revisions

JavaKerberosAuthenticationMSSQL is a sample app that demonstrates how to connect to an MSSQL Server with Kerberos authentication with Java.

Prerequisites

MS SQLServer

The first thing you have to ensure is that your MSSQL server is proper configured. In my case our data centre service missed to add the "validated write to service principal name" entitlement. So the server was not able to authenticate via Kerberos at all. See this wiki for some common mistakes.

Java

Install the JCE Unlimited Strength Jurisdiction Policy Files in your Java directory. This is necessary to use stronger Kerberos encryption types. In my case AD offered me aes256-cts-hmac-sha1-96 that was not compatible with Java 8 without this Java add-on.

If you just want to test something you can perhaps use a historical encryption type like RC4-HMAC.

Driver versions

With MS JDBC driver version 6.2 there comes a different behaviour regarding JAAS. See here:

Authenticate completely via Java

MS JDBC 6

The authentication procedure uses JAAS. That said you need a module configuration file and a CallbackHandler.

In my case I replaced the module configuration by the class KerberosConfig. The configuration name is fix "SQLJDBCDriver".

To inform JAAS about my classes I set two system properties:

Security.setProperty("auth.login.defaultCallbackHandler", "de.dumischbaenger.kerberos.KerberosCallBackHandler");
Security.setProperty("login.configuration.provider", "de.dumischbaenger.kerberos.KerberosConfig");

Now run the gradle task runJavaKerberos.

As you can see in the log files JAAS uses both KerberosCallBackHandler and KerberosConfig. The configuration name is "SQLJDBCDriver".

2018-10-08 12:59:54:720 +0200 [main] INFO KerberosConfig - AppConfigurationEntry with name SQLJDBCDriver gets used
2018-10-08 12:59:54:723 +0200 [main] INFO KerberosConfig - AppConfigurationEntry with name SQLJDBCDriver gets used
2018-10-08 12:59:54:727 +0200 [main] INFO KerberosCallBackHandler - NameCallback
2018-10-08 12:59:54:729 +0200 [main] INFO KerberosCallBackHandler - PasswordCallback

MS JDBC 7

MS JDBC driver version 7 behaves slightly different. You can add the user name and password and JaasConfigurationName to the connect string directly so the KerberosCallBackHandler class is not used any more. If you check the logs there is no message of KerberosCallBackHandler.

Now run the gradle task runJavaKerberos.

2018-10-09 07:10:59:736 +0200 [main] INFO KerberosConfig - AppConfigurationEntry with name JavaKerberos gets used

As you can see in the logs the JDBC driver uses the configuration name JavaKerberos from the connect string.

Acquire a TGT in Linux and start Java application afterwards

Prerequisites

Add your realm to krb5.conf

# Other applications require this directory to perform krb5 configuration.
includedir /etc/krb5.conf.d/

includedir /var/lib/sss/pubconf/krb5.include.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 dns_lookup_realm = false
 dns_lookup_kdc=false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 default_ccache_name = KEYRING:persistent:%{uid}

 default_realm = MYDOMAIN.LOCAL
[realms]


 MYDOMAIN.LOCAL = {
  dc.mydomain.local
 }

[domain_realm]
 mydomain.local = MYDOMAIN.LOCAL
 .mydomain.local = MYDOMAIN.LOCAL

Configure ticket cache

Normally I use the kernels key ring. Unfortunately Java does not support this type of cache so you have to tell Kerberos to use a different type of cache in this case. I do it with the KRB5CCNAME environment variable.

export KRB5CCNAME="FILE:/tmp/myticket"

Get a ticket

Now - given everything is correctly configured - you can get your ticket with kinit:

List your ticket with klist -e:

Ticket cache: FILE:/tmp/myticket
Default principal: [email protected]

Valid starting       Expires              Service principal
17.10.2018 09:17:18  17.10.2018 19:17:18  krbtgt/[email protected]
        renew until 24.10.2018 09:17:13, Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 

Keytab

If you don't want to get a ticket manually by kinit you can use a keytab.

Create keytab

Start the tool ktutil and enter the following commands:

addent -password -p [email protected] -k 1 -e aes256-cts-hmac-sha1-96
wkt mylogon.keytab
q

List the content of your keytab with klist -k mylogon.keytab -e:

Keytab name: FILE:mylogon.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   1 [email protected] (aes256-cts-hmac-sha1-96) 

Now you can use kinit to get the ticket without password but a keytab file:

kinit [email protected] -k -t mylogon.keytab

You can see the ticket details with klist -e again:

Ticket cache: FILE:/tmp/ktticket
Default principal: [email protected]

Valid starting       Expires              Service principal
17.10.2018 09:37:32  17.10.2018 19:37:32  krbtgt/[email protected]
        renew until 24.10.2018 09:37:32, Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 

Start program

Now start your IDE from this shell and run the gradle task runOsKerberos. The program uses now your existing ticket to authenticate against MS SQL server.