0
votes

I am trying to perform kerberos constrained delegation through my java code. I've a keytab file, SPN attached to the user, and the delegation enabled for the SPN to that user. When I am trying to login with Keytab, I am getting the SPN's TGT. However, the "forwardable" flag is set to false on this ticket.

In order to impersonate the other user, I need this flag set to true.

Note: ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION flag is set on the SPN user.

Any help is highly appreciated.

private void tryKrb5Module() throws LoginException {
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("javax.security.auth.useSubjectCredsOnly","true");//has no impact

        final Subject subject = new Subject();
        final Krb5LoginModule krb5LoginModule = new Krb5LoginModule();
        final Map<String,String> optionMap = new HashMap<String,String>();

        optionMap.put("keyTab", "c:\\ticket\\delegationUser.keytab");
        optionMap.put("principal", "TEST/TEST"); // default realm
        optionMap.put("doNotPrompt", "true");
        optionMap.put("refreshKrb5Config", "true");
        optionMap.put("useTicketCache", "true");
        optionMap.put("renewTGT", "true");
        optionMap.put("useKeyTab", "true");
        optionMap.put("storeKey", "true");
        optionMap.put("isInitiator", "true");


        krb5LoginModule.initialize(subject, null, new HashMap<String,String>(), optionMap);

        boolean loginOk = krb5LoginModule.login();
        System.out.println("======= login:  " + loginOk);

        boolean commitOk = krb5LoginModule.commit();
        System.out.println("======= commit: " + commitOk);

        System.out.println("======= Principal from subject: " + subject.getPrincipals());

    }
2
Please provide more details: which Java version are you running? what is your code to call "impersonate"? what are error messages you get?Yves Martin
According to other responses, you do not expect to do impersonation but only delegation "second-hop". You may find interesting code at github.com/tellisnz/collared-kerberosYves Martin
As "S4U2self" method is only useful for impersonation, your code is probably not designed as you expect. For KCD delegation, only "S4U2Proxy" method is needed.Yves Martin

2 Answers

0
votes

The service account "TEST" and its keytab are only there to establish a "trust" with KDC and grant service code to invoke method S4U2Self and S4U2Proxy. So the service account TGT is not expected to be forwardable.

There is no need for a krb5.conf file in addition to JAAS Login configuration you created as Map for Krb5LoginModule. An alternate option is to simply add optionMap.put("forwardable", "true"); and your service account "TEST" TGT will be forwardable.

By the way for kerberos constraint delegation, it is only required that the impersonated user ticket TGT generated with S4U2Self is forwardable which only depends on ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION flag on "TEST" service account. Code for S4U2Self generation is: https://github.com/ymartin59/java-kerberos-sfudemo/blob/master/src/main/java/sfudemo/KerberosDemo.java#L120

References:

0
votes

I figured out the solution. You need to set the krb config file in the system path. Then only the ticket obtained from the keytab is "forwardaable". Surprisingly, this is not mentioned anywhere clearly.

System.setProperty("java.security.krb5.conf", "path_to_krb_config");

Also make sure you have mentioned "forwardable = true" in your krb config file. Pasting example krb config file below:

[libdefaults]
default_realm = DOMAIN.COM
default_tkt_enctypes = aes128-cts aes128-cts-hmac-sha1-96 aes256-cts aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5
default_tgs_enctypes = aes128-cts aes128-cts-hmac-sha1-96 aes256-cts aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5
permitted_enctypes = aes128-cts aes128-cts-hmac-sha1-96 aes256-cts aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5
dns_lookup_kdc = true
dns_lookup_realm = false
forwardable = true

[realms]
    DOMAIN.COM = {
        kdc = KDC_HOST.DOMAIN.COM
        admin_server = KDC_HOST.DOMAIN.COM
        default_domain = DOMAIN.COM
    }

[domain_realms]
    domain.com = DOMAIN.COM
    .domain.com = DOMAIN.COM