2015-12-16 14 views
5

Sto lavorando a un'applicazione Web con SSO basata sull'accesso al dominio di Windows, per questo motivo ho scelto di convalidare i ticket Kerberos. Ma ora sto affrontando un problema per il quale non riesco a trovare una soluzione. Riesco a convalidare un ticket senza eccezioni, ma quando sto cercando di ottenere l'userName, viene generato NullPointerException, perché il nome utente è null e non so dove sia il problema.GSSContext con null SrcName

Perché il nome utente è nullo se non ottengo alcuna eccezione durante la convalida?

Come ottengo Nome utente: String clientName = gssContext.getSrcName().toString();

Creo il mio cliente sulla base di questo:

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

Aggiornamento 1:

Come contenuti di installazione, basta copiare e incollare modulo qui 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(); 

Aggiornamento 2:

Se ho la sicurezza di primavera di installazione basato su questo https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension ho anche avuto la stessa errore:

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; 
    } 

} 
.515.053.691,36321 milioni

Update 3:

provato anche il cambiamento versione Java 1,8-1,7 come suggerito qui Domain authentication with Kerberos fails. Nessun risultato.

Update 4:

Prima di tutto. Non utilizzare Java 1.8 b40 e b45, entrambi sono danneggiati. E non testarlo sul PC locale, non funziona (non so perché).

Dopo aver modificato la versione più recente (b65) di Java, ho ottenuto un'eccezione sulla codifica (Impossibile trovare la chiave del tipo appropriato per decrittografare AP REP - AES256 ...). Questo ho fissato da Java Cryptography Extension (JCE) per Java 1.8 e ri-creare keytab con /crypto AES256-SHA1 dopo tutto questo ho ottenuto eccezione:

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

ho provato this tutorial e l'altro modo per creare keytabfile, ma ho ancora don' Ho una soluzione.

+0

prega, mostrano il codice che si utilizza per stabilire il contesto –

+1

So che questo è un vecchio thread, ma di recente ho avuto lo stesso problema esatto e nel mio caso è stato un problema con lo spn. Ho chiamato il mio servizio e poi ho digitato 'klist' in cmd per cercare il mio servizio. dopo averlo trovato ho visto qualcosa di simile a questo: HTTP/[email protected] Quello che devi fare è verificare che venga creato un SPN per questo. Crea un account di servizio e crea lo spn con 'setspn -un dominio HTTP/service.domain.com \ serviceAccout' e successivamente crea un keytab con' ktab -k FILE: your_filename.ktab -un dominio HTTP/service.domain.com \ password_of_service_account'. – Nico

risposta

1

Sembra che il contesto non sia completamente stabilito quando si sta cercando di ottenere SrcName. Sembra che la ragione per ScrName sia nullo. Secondo https://www-01.ibm.com/support/knowledgecenter/SSYKE2_7.0.0/com.ibm.java.security.api.doc/jgss/org/ietf/jgss/GSSContext.html, acceptSecContext() genera un token e se non è null, questo token deve essere inviato al peer. Dopo la chiamata acceptSecContext() dovresti controllare se isEstablished() restituisce false.Se è così,

If this method returns false it indicates that a token is needed from its peer in order to continue the context establishment phase. A return value of true signals that the local end of the context is established. This may still require that a token be sent to the peer, if one is produced by GSS-API. During the context establishment phase, the isProtReady() method may be called to determine if the context can be used for the per-message operations. This allows applications to use per-message operations on contexts which aren't fully established.

Lo stesso è spiegato più in dettaglio nel tutorial http://www.cs.mun.ca/java-api-1.5/guide/security/jgss/tutorials/BasicClientServer.html:

The acceptSecContext method may in turn return a token. If it does, the acceptor should send that token to the initiator, which should then call initSecContext again and pass it this token. Each time initSecContext or acceptSecContext returns a token, the application that called the method should send the token to its peer and that peer should pass the token to its appropriate method (acceptSecContext or initSecContext). This continues until the context is fully established (which is the case when the context's isEstablished method returns true).

+1

Sfortunatamente, non aiuta. – Vartlok

1

Ho affrontato lo stesso errore Checksum failed in sede di attuazione il mio GSSAPI presa demo che è una modifica della Oracle GSSAPI Codice tutorial. Ho eseguito il mio codice su una macchina Linux iscritta in un regno Kerberos FreeIPA. Ho usato il file vanilla krb5.conf del mio sistema Linux. Non ci sono vincoli sul biglietto etype sono lì:

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

Il regno di default FreeIPA è quello di utilizzare il tipo 18 biglietti (AES-256).

Circa la mia domanda, è questo file criterio configurato:

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"; 
}; 

Quando si esegue l'applicazione che ho ottenuto questo errore sul lato accettatore:

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

Nel mio caso l'errore nasce nel Accettatore GSS. Nella mia applicazione creo la configurazione Jaas a livello di codice (mi riferirò a questo come DConfig) e non uso un file di configurazione. La prima soluzione, ho trovato, è usare i file di configurazione invece di DConfig e il problema è scomparso, ha funzionato bene. La soluzione temporanea, file di JAAS Config:

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

Con questa configurazione, nessun problema si pone sul lato accettore e l'applicazione sono stati in grado di verificare la validità ticket di servizio e accettare la connessione.

Mi sono chiesto .. PERCHÉ?

Ho controllato le differenze nell'oggetto (s) acquisito con le due configurazioni. Nel caso di lavoro, con il file di configurazione, l'oggetto contiene, nelle credenziali private, le credenziali di hash della password e il ticket TGT principale. Con DConfig, ottengo un oggetto con solo hash di password ma non esiste un ticket TGT principale in credenziali private.

mio fix

DConfig contiene le stesse impostazioni del file di configurazione e le altre opzioni sono la replica di Krb5LoginModule default, in un primo momento non vedo una ragione per il comportamento scorretto.

L'impostazione isInitiator = true, nel lato Accettatore DConfig, ha risolto il problema. `isInitiator = true ha forzato la persistenza del ticket TGT nell'oggetto.

Con questa soluzione alternativa l'errore è scomparso senza modifiche nel sistema krb5.conf.

Il mio centesimo è ... dopo l'accesso di Jaas, controlliamo le credenziali del soggetto personale per mancanza di credenziali (è necessario il TGT del servizio principale nel soggetto accettore) e nel caso provi a impostare isInitiator = true anche sul lato dell'accettore.

saluti