2011-12-14 24 views
8

Mamy problem z uzyskaniem uwierzytelniania Kerberos/AD do pracy z webappą Spring i uważam, że problem dotyczy szyfrowania dla biletów Kerberos i Active Directory poziom funkcjonalny domeny.Nie powiodła się kontrola kontrolna: Kerberos/Spring/Active Directory (2008)

Podstawowa konfiguracja jest:

Mam jeden en vironment, w którym poziom funkcjonalny domeny Active Directory to Windows Server 2003, a wszystko działa poprawnie, a klienci uwierzytelniają się zgodnie z oczekiwaniami, jeśli są zalogowani do domeny. Używając kerbtray do sprawdzenia biletów w tym środowisku widzę, że wszystkie mają zarówno typ szyfrowania biletu, jak i kluczowy typ szyfrowania "RSADSI RC4-HMAC".

Mam nową domenę z poziomem funkcjonalnym Windows Server 2008, i to tam uwierzytelnianie nie działa. Błąd aplikacji zwracany, gdy próbuje skasować bilet jest:

Kerberos validation not successful... 

Caused by: 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 sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(Unknown Source) 
    at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(Unknown Source) 
    at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) 
    at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) 
    at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:146) 
    at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136) 
    ... 34 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.<init>(Unknown Source) 
    at sun.security.jgss.krb5.InitSecContextToken.<init>(Unknown Source) 
    ... 43 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) 

Ślad stosu pokazuje „ArcfourCrypto.decrypt”, więc prawdopodobnie jest traktowanie bilet Kerberos jako RC4-HMAC. Za pomocą kerbtray ponownie, aby sprawdzić bilety tym razem są 2 bilety na klienta dla domeny: krbtgt/.COM. Oba bilety mają kluczowy typ szyfrowania RSADS1 RC4-HMAC, jeden również ma to dla typu szyfrowania biletu, ale drugi ma "Kerberos AES256-CTS-HMAC-SHA1-96".

Nie wiem na pewno, że to jest przyczyna problemu, ale jest to jedyna różnica, którą udało mi się znaleźć w dwóch środowiskach, które mogłyby wyjaśnić wyjątek uwierzytelniania. Próbowałem zmienić zasady szyfrowania AD, wypróbowałem IE i Firefox i prawie wszystko, co mogłem wymyślić, ale nic nie zadziałało.

Każda pomoc dotycząca tego problemu byłaby bardzo doceniana. Wolałbym naprawić to na końcu javy, ponieważ prawdopodobnie nie mogę dyktować zbyt wiele na temat konfiguracji AD.

+0

Czy sprawdziłeś komunikację w Wireshark i sprawdziłeś bilety? –

+0

Dzięki @ Michael-O - Używałem Wiresharka podczas pracy nad tym wcześniej, ale nie mam już dostępnych danych wyjściowych. Nie mogłem tego w ogóle uruchomić - przywróciłem domenę testową do poziomu funkcjonalnego Windows Server 2003 a potem działało normalnie. Teraz muszę skonfigurować nową domenę testową z 2008 roku, aby spróbować znaleźć sensowne rozwiązanie ... – slt

Odpowiedz

0

Problem polega na tym, jak generowany jest token i jak jest sprawdzany po stronie serwera. Ze śledzenia wyjątku wynika, że ​​problem polega na tym, że strona klienta nie ustawia sumy kontrolnej, a strona serwer chce sprawdzić poprawność sumy kontrolnej. Suma kontrolna jest jedną z wartości paramerów ustawionych w tokenie, co ma oczywiste znaczenie.

W 2008 musi być sposób na wyłączenie tej funkcji, aby zignorować sprawdzanie sum kontrolnych. Ale otwiera kolejne drzwi i konieczne może być oszacowanie ryzyka rezydualnego.

16

Problem pojawia się w pliku keytab. Istnieje kilka sekwencji działań prowadzących do określonych stanów plików listy kluczy: (A) keytab działa z Javą, ale nie działa z k5start/kinit; (B) keytab nie działa z Javą, ale działa z k5start/kinit; (C) keytab współpracuje z obydwoma.

Krótki kod Java, który pozwala sprawdzić, czy Java może uwierzytelnić przy użyciu pliku tablicy kluczy:

import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStream; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Properties; 

import javax.security.auth.Subject; 

import com.sun.security.auth.module.Krb5LoginModule; 

/** 
* This is simple Java program that tests ability to authenticate 
* with Kerberos using the JDK implementation. 
* 
* The program uses no libraries but JDK itself. 
*/ 
public class Krb { 

    private void loginImpl(final String propertiesFileName) throws Exception { 
    System.out.println("NB: system property to specify the krb5 config: [java.security.krb5.conf]"); 
    //System.setProperty("java.security.krb5.conf", "/etc/krb5.conf"); 

    System.out.println(System.getProperty("java.version")); 

    System.setProperty("sun.security.krb5.debug", "true"); 

    final Subject subject = new Subject(); 

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

    if (propertiesFileName == null) { 
     //optionMap.put("ticketCache", "/tmp/krb5cc_1000"); 
     optionMap.put("keyTab", "/etc/krb5.keytab"); 
     optionMap.put("principal", "foo"); // 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"); 
    } else { 
     File f = new File(propertiesFileName); 
     System.out.println("======= loading property file ["+f.getAbsolutePath()+"]"); 
     Properties p = new Properties(); 
     InputStream is = new FileInputStream(f); 
     try { 
     p.load(is); 
     } finally { 
     is.close(); 
     } 
     optionMap.putAll((Map)p); 
    } 
    optionMap.put("debug", "true"); // switch on debug of the Java implementation 

    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("======= Subject: " + subject); 
    } 

    public static void main(String[] args) throws Exception { 
    System.out.println("A property file with the login context can be specified as the 1st and the only paramater."); 
    final Krb krb = new Krb(); 
    krb.loginImpl(args.length == 0 ? null : args[0]); 
    } 
} 

, a plik nieruchomość używać:

#ticketCache=/tmp/krb5cc_1000 
keyTab=/etc/krb5.keytab 
principal=foo 

doNotPrompt=true 
refreshKrb5Config=true 
useTicketCache=true 
renewTGT=true 
useKeyTab=true 
storeKey=true 
isInitiator=true 

(Poniżej zakładamy, że KRB/kdc jest poprawnie zainstalowany i skonfigurowany, baza danych jest tworzona za pomocą kdb5_util .Stan wyjściowy każdej sekwencji poleceń jest: usunięty plik keytab, pamięć podręczna tokenów jest usuwana, użytkownik "foo" jest usuwany z bazy danych.)


następującą kolejność działania prowadzi do stanu keytab (A):

$ echo -e "foo\nfoo" | kadmin.local -q "addprinc foo" 
$ echo -e "foo\nfoo" | kadmin.local -q "ktadd foo" 
$ java -cp . Krb ./krb5.properties 
# Now java auth okay, but the following command fails: 
$ k5start foo 
Kerberos initialization for [email protected] 
Password for [email protected]: 
k5start: error getting credentials: Decrypt integrity check failed 
$ 

następującą kolejność działania prowadzi do stanu keytab (B):

$ echo -e "foo\nfoo" | kadmin.local -q "addprinc foo" 
$ echo -e "foo\nfoo" | kadmin.local -q "ktadd foo" 
$ echo -e "foo\nfoo" | kadmin.local -q "cpw foo" 
$ java -cp . Krb ./krb5.properties 
A property file with the login context can be specified as the 1st and the only paramater. 
NB: system property to specify the krb5 config: [java.security.krb5.conf] 
1.6.0_33 
======= loading property file [/tmp/krb-test/yhadoop-common/./krb5.properties] 
Debug is true storeKey true useTicketCache true useKeyTab true doNotPrompt true ticketCache is null isInitiator true KeyTab is /etc/krb5.keytab refreshKrb5Config is true principal is foo tryFirstPass is false useFirstPass is false storePass is false clearPass is false 
Refreshing Kerberos configuration 
Config name: /etc/krb5.conf 
>>> KdcAccessibility: reset 
>>> KdcAccessibility: reset 
Acquire TGT from Cache 
>>>KinitOptions cache name is /tmp/krb5cc_0 
Principal is [email protected] 
null credentials from Ticket Cache 
>>> KeyTabInputStream, readName(): EXAMPLE.COM 
>>> KeyTabInputStream, readName(): foo 
>>> KeyTab: load() entry length: 49; type: 23 
Added key: 23version: 3 
Ordering keys wrt default_tkt_enctypes list 
default etypes for default_tkt_enctypes: 23. 
0: EncryptionKey: keyType=23 kvno=3 keyValue (hex dump)= 
0000: 5F 7F 9B 42 BB 02 51 81 32 05 1D 7B C0 9F 19 C0 _..B..Q.2....... 


principal's key obtained from the keytab 
Acquire TGT using AS Exchange 
default etypes for default_tkt_enctypes: 23. 
>>> KrbAsReq calling createMessage 
>>> KrbAsReq in createMessage 
>>> KrbKdcReq send: kdc=localhost UDP:88, timeout=30000, number of retries =3, #bytes=128 
>>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =1, #bytes=128 
>>> KrbKdcReq send: #bytes read=611 
>>> KrbKdcReq send: #bytes read=611 
>>> KdcAccessibility: remove localhost:88 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
Checksum failed ! 
       [Krb5LoginModule] authentication failed 
Checksum failed 
Exception in thread "main" javax.security.auth.login.LoginException: Checksum failed 
     at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:696) 
     at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:542) 
     at Krb.loginImpl(Krb.java:65) 
     at Krb.main(Krb.java:77) 
Caused by: KrbException: Checksum failed 
     at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(ArcFourHmacEType.java:85) 
     at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(ArcFourHmacEType.java:77) 
     at sun.security.krb5.EncryptedData.decrypt(EncryptedData.java:168) 
     at sun.security.krb5.KrbAsRep.<init>(KrbAsRep.java:87) 
     at sun.security.krb5.KrbAsReq.getReply(KrbAsReq.java:446) 
     at sun.security.krb5.Credentials.sendASRequest(Credentials.java:401) 
     at sun.security.krb5.Credentials.acquireTGT(Credentials.java:350) 
     at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:672) 
     ... 3 more 
Caused by: java.security.GeneralSecurityException: Checksum failed 
     at sun.security.krb5.internal.crypto.dk.ArcFourCrypto.decrypt(ArcFourCrypto.java:388) 
     at sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(ArcFourHmac.java:74) 
     at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(ArcFourHmacEType.java:83) 
     ... 10 more 
$ 

Ale "k5start foo" jest w porządku w tym stanie, a także "kinit foo".


oraz następującą kolejność działania prowadzi do Stanu (C):

$ echo -e "foo\nfoo" | kadmin.local -q "addprinc foo" 
$ ktutil 
ktutil: addent -password -p foo -k 1 -e rc4-hmac 
Password for [email protected]: 
ktutil: wkt /etc/krb5.keytab 
ktutil: q 

po tym jak k5start/kinit Java i weryfikacja daje wynik pozytywny.


Środowisko:

yum list krb5-appl-servers krb5-libs krb5-server krb5-workstation kstart pam_krb5 
... 
Installed Packages 
krb5-libs.x86_64                   1.9-33.el6_3.3                  @updates 
krb5-server.x86_64                   1.9-33.el6_3.3                  @updates 
krb5-workstation.x86_64                  1.9-33.el6_3.3                  @updates 
kstart.x86_64                    4.1-2.el6                   @epel 
... 
$ cat /etc/redhat-release 
CentOS release 6.3 (Final) 
$ java -version 
java version "1.6.0_33" 
Java(TM) SE Runtime Environment (build 1.6.0_33-b03) 
Java HotSpot(TM) 64-Bit Server VM (build 20.8-b03, mixed mode) 

również takie samo zachowanie zaobserwowano Java 7. takie samo zachowanie zaobserwowano również na Ubuntu precyzyjnego (12.04.1 LTS) z Kerberos MIT 5-1.10.3 skompilowany z dystrybucji źródłowej.

+4

Niezła dokładna odpowiedź! – Hbcdev

+0

@Ivan - Jestem w stanie odzyskać bilet z keytab. Jednak w przypadku kodu Java 7 nie powiodło się to nagle z błędem Checksum. Czy odtworzenie keytab jest jedyną opcją? –

Powiązane problemy