5

I built a Java application, which runs a command via ssh. In the first attempt I authenticated via username and password, and everything worked fine.

Now I want to use a Kerberos keytab file to make the authentication, but this makes problems!

Here a few words to my configuration:

  • KDC server: my-server.de
  • Realm name: MYREALM.DE
  • Keytab username: keytabuser
  • KDC = server: runs on CentOS 7
  • my client: Windows 8.1 (x64) with all default configurations, Kerberos for Windows installed
  • my username on client: Daniel
  • kinit -kt ... seems to work fine, so the keytab file should also be ok

What I have so far is this code snippet:

public static void main(String[] args) {
        String host = "my-server.de";
        String user = "keytabuser";
        String  command = "ls -l";

        JSch jsch = new JSch();
        jsch.setLogger(new MyLogger());

        System.setProperty("java.security.krb5.conf", "C:\\ProgramData\\MIT\\Kerberos5\\krb5.ini");
        System.setProperty("java.security.auth.login.config", "C:\\ProgramData\\MIT\\Kerberos5\\jaas.conf");
        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");

        //to enable kerberos debugging mode
        System.setProperty("sun.security.krb5.debug", "true");

        try {
            Session session = jsch.getSession(user, host, 22);
            Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("PreferredAuthentications", "gssapi-with-mic");

            session.setConfig(config);
            session.connect(20000);

            Channel channel = session.openChannel("exec");
            ... // Do the commands

            channel.disconnect();
            session.disconnect();
            System.out.println("DONE");

        } catch (JSchException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

This is my jaas.conf file:

com.sun.security.jgss.krb5.initiate {
  com.sun.security.auth.module.Krb5LoginModule required
  doNotPrompt=true
  principal="keytabuser@MYREALM.DE"
  useKeyTab=true
  keyTab="C:\ProgramData\MIT\Kerberos5\keytabuser.keytab"
  storeKey=true;
};

And here my krb5.ini file:

[libdefaults]
  default_realm = MYREALM.DE

[realms]
  MYREALM.DE = {
    admin_server = my-server.de
    kdc = my-server.de
  }

When I run this application I get the following output:

UPDATED: New console output after new jsch dependency 0.1.54

INFO: Connecting to my-server.de port 22
INFO: Connection established
INFO: Remote version string: SSH-2.0-OpenSSH_6.6.1
INFO: Local version string: SSH-2.0-JSCH-0.1.54
INFO: CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
INFO: aes256-ctr is not available.
INFO: aes192-ctr is not available.
INFO: aes256-cbc is not available.
INFO: aes192-cbc is not available.
INFO: CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
INFO: CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
INFO: SSH_MSG_KEXINIT sent
INFO: SSH_MSG_KEXINIT received
INFO: kex: server: curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
INFO: kex: server: ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519
INFO: kex: server: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
INFO: kex: server: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
INFO: kex: server: hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
INFO: kex: server: hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
INFO: kex: server: none,zlib@openssh.com
INFO: kex: server: none,zlib@openssh.com
INFO: kex: server: 
INFO: kex: server: 
INFO: kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
INFO: kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
INFO: kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc
INFO: kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc
INFO: kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
INFO: kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
INFO: kex: client: none
INFO: kex: client: none
INFO: kex: client: 
INFO: kex: client: 
INFO: kex: server->client aes128-ctr hmac-md5 none
INFO: kex: client->server aes128-ctr hmac-md5 none
INFO: SSH_MSG_KEX_ECDH_INIT sent
INFO: expecting SSH_MSG_KEX_ECDH_REPLY
INFO: ssh_rsa_verify: signature true
WARN: Permanently added 'my-server.de' (RSA) to the list of known hosts.
INFO: SSH_MSG_NEWKEYS sent
INFO: SSH_MSG_NEWKEYS received
INFO: SSH_MSG_SERVICE_REQUEST sent
INFO: SSH_MSG_SERVICE_ACCEPT received
INFO: Authentications that can continue: gssapi-with-mic
INFO: Next authentication method: gssapi-with-mic
INFO: Disconnecting from my-server.de port 22
com.jcraft.jsch.JSchException: Auth fail
    at com.jcraft.jsch.Session.connect(Session.java:519)
    at kerberos.JschKerberos.main(JschKerberos.java:49)

Is there something incorrect with my configuration? Are there some conditions between the local (user, domain, etc.) and the remote one?

D. Müller
  • 3,336
  • 4
  • 36
  • 84
  • My 2 cents: to get all debug traces, add `-Dsun.security.krb5.debug=true -Djava.security.debug=gssloginconfig,configfile,configparser‌​,logincontext` on the command line, to be sure that you don't miss any initialization setp – Samson Scharfrichter Jan 20 '17 at 20:16
  • Also set `useTicketCache=false` and `storeKey=false` to make sure that you don't suffer from side effects from the cache. Since you provide the keytab to JAAS, you can keep your ticket private to your Java process. – Samson Scharfrichter Jan 20 '17 at 20:19
  • Ok, I'll try later, thank you for the help so far. The jaas.conf and krb5.ini are ok or did I miss something? – D. Müller Jan 20 '17 at 20:21
  • The `java.security.debug` flags will show you *exactly* what Java thinks about your config... – Samson Scharfrichter Jan 20 '17 at 20:22
  • I added also the second flag to my java code by "System.setProperty("java.security.debug", "gssloginconfig,configfile,configparser‌​‌​,logincontext");" (the first one I already had in the code). Still the same console output like above... – D. Müller Jan 21 '17 at 11:17
  • Setting that property via `System.setProperty()` might be to late. Try passing that as a parameter to the `java` binary (using `-D....`) –  Jan 21 '17 at 14:19
  • Ok, added the flags to the "java" command, still exact the same output. – D. Müller Jan 23 '17 at 08:41
  • changed the jsch version to the newest (0.1.54), now getting a longer console output, see in the question section above. – D. Müller Jan 23 '17 at 10:16

1 Answers1

4

I finally found the solution! It was a missing service keytab for the sshd service! Some service principals aren't generated automatically by the Kerberos server. So this has to been done manually by the kadmin, as the sshd service also has to authenticate against Kerberos! This is done by the host/fqdn@REALM principal.

Important here: The "host" is a fixed String(!), I always replaced it by the hostname of my OpenSSH server machine... So, only "fqdn" and "REALM.COM" must be replaced by your data!

So these were the necessary steps for me to get the application work:

  1. Set GSSAPIAuthentication yes in the /etc/ssh/sshd_conf config file of the OpenSSH server
  2. Set Host * [...] GSSAPIAuthentication yes in the /etc/ssh/ssh_conf config file of the ssh client
  3. Check the jaas.conf and krb5.conf (or .ini) files on the client for correct settings (see the code blocks in the question section above)
  4. On the Kerberos server, open kadmin.local and type ktadd host/my-server.de
  5. optional: Add a user principal (if not exists yet): ktadd keytabuser
  6. Make a kinit keytabuser (with password) or kinit -kt /path/to/file.keytab keytabuser (normal Kerberos command)
  7. Check if the user is authenticated via klist
  8. Run the application or ssh directly via console ssh keytabuser@my-server.de
  9. You should be logged in by the cached ticket!

Of course, the user keytabuser must be a user on the ssh-server machine!

D. Müller
  • 3,336
  • 4
  • 36
  • 84
  • 2
    Duh. So you tried Kerberos auth in SSH, without first binding *globally* your Linux server auth to Kerberos (via `sssd` and the default `/etc/krb5.keytab`). And you did not know about Kerberos SPN (Service Principal Name) syntax. Looks like you got to a result against all odds, congratulations... – Samson Scharfrichter Jan 24 '17 at 22:10