Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GSSContext with null SrcName

I'm working a web appliaction with SSO based on the Windows domain login, for this purpose I have chosen to validate Kerberos tickets. But now I'm facing a problem for which I can't find a solution. I manage to validate a ticket without exceptions, but when I'm trying to get the userName, NullPointerException is thrown, because the username is null and I don't know where is problem.

Why is user name null if I don't get any exception during the validation?

How I get userName: String clientName = gssContext.getSrcName().toString();

I create my client based on this:

Using GSSManager to validate a Kerberos ticket

How to obtain a kerberos service ticket via GSS-API?

http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/single-signon.html

Update 1:

How I setup content, just copy-paste form here https://stackoverflow.com/a/25450862/1646082:

final Oid spnegoOid = new Oid("1.3.6.1.5.5.2");

GSSManager gssmgr = GSSManager.getInstance();

// tell the GSSManager the Kerberos name of the service
GSSName serviceName = gssmgr.createName(this.servicePrincipal, GSSName.NT_USER_NAME);

// get the service's credentials. note that this run() method was called by Subject.doAs(),
// so the service's credentials (Service Principal Name and password) are already
// available in the Subject
GSSCredential serviceCredentials = gssmgr.createCredential(serviceName,
        GSSCredential.INDEFINITE_LIFETIME, spnegoOid, GSSCredential.ACCEPT_ONLY);

// create a security context for decrypting the service ticket
GSSContext gssContext = gssmgr.createContext(serviceCredentials);

// decrypt the service ticket
System.out.println("Entering accpetSecContext...");
System.out.println( new String (Base64.encodeBase64( gssContext.acceptSecContext(this.kerberosTicket, 0,
        this.kerberosTicket.length) ) ));

// get the client name from the decrypted service ticket
// note that Active Directory created the service ticket, so we can trust it
String clientName = gssContext.getSrcName().toString();

Update 2:

If I setup spring security based on this https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension i also got the same error:

java.lang.NullPointerException at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136) at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:125) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:422)

private static class KerberosValidateAction implements PrivilegedExceptionAction<String> {
    byte[] kerberosTicket;

    public KerberosValidateAction(byte[] kerberosTicket) {
        this.kerberosTicket = kerberosTicket;
    }

    @Override
    public String run() throws Exception {
        GSSContext context = GSSManager.getInstance().createContext((GSSCredential) null);
        context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length);
        String user = context.getSrcName().toString(); // ERROR!
        context.dispose();
        return user;
    }

}

Update 3:

Also tried change Java version from 1.8 to 1.7 as suggested here Domain authentication with Kerberos fails. No result.

Update 4:

First of all. Don't user Java 1.8 b40 and b45, both of them are broken. And don't test it on local PC, it doesn't work(I don't know why).

After changing on newest(b65) Java version, I got exception about encription(Cannot find key of appropriate type to decrypt AP REP - AES256 ...). This I have fixed by Java Cryptography Extension (JCE) for Java 1.8 and re-create keytab with /crypto AES256-SHA1 after all this i got exception:

GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed) at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Unknown Source) at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) at GssServer$GssServerAction.run(GssServer.java:159) ... 4 more Caused by: KrbException: Checksum failed at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(Unknown Source) at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(Unknown Source) at sun.security.krb5.EncryptedData.decrypt(Unknown Source) at sun.security.krb5.KrbApReq.authenticate(Unknown Source) at sun.security.krb5.KrbApReq.(Unknown Source) at sun.security.jgss.krb5.InitSecContextToken.(Unknown Source) ... 8 more Caused by: java.security.GeneralSecurityException: Checksum failed at sun.security.krb5.internal.crypto.dk.ArcFourCrypto.decrypt(Unknown Source) at sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(Unknown Source) ... 14 more

I tried this tutorial and other way to create keytabfile, but i still don't have solution.

like image 707
Vartlok Avatar asked Dec 16 '15 07:12

Vartlok


1 Answers

I faced the same Checksum failed error when implementing my GSSAPI socket demo that is a modification of the Oracle GSSAPI tutorial code. I executed my code on a Linux machine enrolled into a FreeIPA kerberos realm. I have used the vanilla krb5.conf file of my Linux system. No constraints on ticket etype are there:

...
[libdefaults]
  default_realm = AUTHDEMO.IT
  dns_lookup_realm = true
  dns_lookup_kdc = true
  rdns = false
  ticket_lifetime = 24h
  forwardable = true
  udp_preference_limit = 0 
...

The FreeIPA realm default is to use type 18 tickets (AES-256).

About my application, it has this policy file configured:

grant CodeBase "file:./app.jar" {
        permission java.security.AllPermission;
};

grant CodeBase "file:./app.jar" 
    Principal javax.security.auth.kerberos.KerberosPrincipal 
        "[email protected]" {

    permission java.net.SocketPermission "*", "accept";

    permission javax.security.auth.kerberos.ServicePermission
        "[email protected]", "accept";
};

When executing the application I got this error on the acceptor side:

GSSException: Failure unspecified at GSS-API level (Mechanism level: Encryption type AES256CTS mode with HMAC SHA1-96 is not supported/enabled)

In my case the error arises in the GSS acceptor side. In my application I generate the Jaas configuration programmatically (I'll refer at this as DConfig) and I don't use a config file. The first solution, I found, is to use config files instead of DConfig and the problem disappeared, it worked fine. The temporary solution, Jaas Config file:

DemoServer {
  com.sun.security.auth.module.Krb5LoginModule required
   principal="[email protected]"
   storeKey=true
   debug=true; #not mandatory
};

With this configuration, no problem arises on the acceptor side and the application were able to check the service ticket validity and accept the connection.

I asked myself.. WHY?

I checked differences in the Subject(s) acquired with the two configurations. In the working case, with the config file, the subject contains, into the private credentials, both the password hashes credentials and the principal TGT ticket. With DConfig, I obtain a Subject with only password hashes but there is no principal TGT ticket in private credentials.

My fix

DConfig contains the same settings of the configuration file and the other options are the replica of Krb5LoginModule defaults, at first I cannot see a reason for the misbehaviour.

Setting isInitiator = true, into the acceptor side DConfig, solved the issue. `isInitiator = true has forced the persistence of TGT ticket into the subject.

With this workaround the error has disappeared with no change into the system krb5.conf.

My cent is... after Jaas login, let's check your subject private credentials for lacking creds (You need the service principal TGT into your acceptor side subject!) and in case try to set isInitiator = true to the acceptor side too.

Regards

like image 128
Fabiano Tarlao Avatar answered Oct 04 '22 12:10

Fabiano Tarlao