2015-03-06 11 views
9

Sto provando a modificare un'applicazione dall'utilizzo di java7u51 a java8u40 ma l'autenticazione SSO non riesce. Il client non è cambiato, utilizza le chiamate Windows JNA (Secur32.INSTANCE.InitializeSecurityContext) ma il server non accetta più il ticket. Il codice del server non è cambiato, ma sta utilizzando le librerie java standard che sembrano essere cambiate. Il server funziona sotto linux.Cambiamento autenticazione lato server Kerberos/SPNEGO in Java8

Il codice server è di seguito. Sul mio computer Windows scrivo un file contenente il ticket in modo da poter eseguire il codice sottostante per il test. Ho un altissimo clockskew impostato in modo da poter testare contro il biglietto. Ho scritto il ticket del cliente usando java7u51 per ogni evenienza, ma questo non ha aiutato. Lo stesso ticket funziona bene quando eseguo il codice del server sottostante in java7.

Il bit che non riesce è che isEstablished restituisce falso. Non ci sono informazioni utili per il debug. isEstablished restituendo false implica che sono necessari più cicli, ma quello non è il caso, e non penso che dovrebbe essere.

Qualcuno sa di un motivo che ora non funzionerebbe in java8? Non è solo un problema di aggiornamento 40, non funziona con le versioni precedenti di java 8.

grazie

Properties.setProp("sun.security.krb5.debug", "true") 
Properties.setProp("java.security.krb5.realm", "xxxx") 
Properties.setProp("java.security.krb5.kdc", "xxxx") 
Properties.setProp("java.security.krb5.conf", url(getClass, "/krb5.conf.auth").toExternalForm) 
Properties.setProp("java.security.auth.login.config", url(getClass, "/jaas.conf.auth").toExternalForm) 
Properties.setProp("javax.security.auth.useSubjectCredsOnly", "true") 

val loginCtx: LoginContext = new LoginContext("Server", new LoginCallbackHandler(password)) 
loginCtx.login() 
val subject = loginCtx.getSubject 
val ticket = StringIO.readStringFromFile(new File("/tmp/ticket")) 
val decoder: BASE64Decoder = new BASE64Decoder 
val serviceTicket = decoder.decodeBuffer(ticket) 

val user = Subject.doAs(subject, new PrivilegedAction[Option[String]]() { 
    def run = { 
    try { 
     val manager = GSSManager.getInstance 
     val context: GSSContext = manager.createContext(null: GSSCredential) 
     val arrayOfBytes = context.acceptSecContext(serviceTicket, 0, serviceTicket.length) 
     // we ignore arrayOfBytes 
     assert(context.isEstablished, "Failed to establish context: " + context) 
     val username = context.getSrcName.toString 
     Some(username) 
    } catch { 
     case e: Exception => 
     println("failed: " + e.getMessage) 
     None 
    } 
    } 
}) 

krb5.conf.auth 
[libdefaults] 
default_realm = XXX 
allow_weak_crypto=true 
default_tkt_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
default_tgs_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
permitted_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
default_checksum = rsa-md5 
kdc_timesync = 0 
kdc_default_options = 0x40000010 
clockskew = 30000 
check_delegate = 0 
ccache_type = 3 
kdc_timeout = 60000 
forwardable = true 
dns_lookup_realm = true 
dns_lookup_kdc = true 
ticket_lifetime = 24h 

#excluding realms and domain_realm 

jaas.conf.auth (server section) 

Server { 
    com.sun.security.auth.module.Krb5LoginModule required 
    useKeyTab=false 
    debug=true 
    isInitiator=false 
    storeKey=true 
    useTicketCache=false 
    principal="XXX"; 
}; 

Aggiornamento: Nel caso in cui questo aiuta. Penso che il client stia inviando un ticket SPNEGO, perché se provo a forzare il contesto ad accettare solo Kerberos (1.2.840.113554.1.2.2) ottengo l'errore failed: No credential found for: 1.3.6.1.5.5.2 usage: Accept

Update 2: Questa non è proprio la risposta , ma se cambio il modo in cui il client Windows crea il ticket funziona. Quindi se invece di creare un ticket incapsulato SPNEGO si crea un ticket solo Kerberos, esso viene accettato da Java8. Quindi modificare "Negozia" in "Kerberos" in basso risolve il problema.

Secur32.INSTANCE.AcquireCredentialsHandle(
     servicePrincipalName, 
     "Negotiate", // Change to "Kerberos" 
     new NativeLong(Sspi.SECPKG_CRED_OUTBOUND), 
     null, 
     authIdentity.getPointer, 
     null, 
     null, 
     phClientCredential, 
     ptsClientExpiry) 
+0

Provare a utilizzare "NTLM" invece di "Negoziare" e dirmi se funziona. Ho avuto un problema simile. – kukis

+0

java8 forse ha abbandonato il supporto per 'allow_weak_crypto = true'? –

+0

Java 8 ha cambiato il valore predefinito di allow_weak_crypto in false, quindi non è possibile utilizzare DES a meno che non sia specificato esplicitamente come true: https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8 .html –

risposta

1

Kerberos/SPNEGO è un dominio dei rifiuti ..

Da quello che viene in mente, qui di seguito una lista di controllo rapido che si spera essere di alcun aiuto.

  1. Hai rigenerato il tuo keytab? con lo stesso JDK che si sta utilizzando sul lato server?
  2. Il server è in esecuzione con l'utente corretto (come definito nella scheda chiave)?
  3. Li hai generati selezionando l'opzione "non scadere mai"?
  4. Richiede la codifica a 256 bit? Può essere visto digitando (tipo di chiave 18 = AES-256):

    % JAVA_HOME% \ bin \ klist -e -f -a -k XX.keytab

    %JAVA_HOME%\bin\klist -e -f -a -k XX.keytab]

    Se è così, hanno si aggiunge il unrestricted policy fileslocal_policy.jar US_export_policy.jar sotto% JAVA_HOME% \ jre \ lib \ security? Assicurati che il valore KVNO sia lo stesso nella lista che ottieni. Idealmente, dovresti vedere solo una uscita.

  5. Il tuo SPN è pingable?

  6. L'elenco dei server KDC è corretto?
  7. Prestare attenzione al krb5.conf. Hai problemi con. Sembra essere case sensitive anche in ambiente Windows.

Kerberos può essere difficile da configurare. Perciò buona fortuna.