2011-12-14 99 views
8

我们在获得Kerberos/AD身份验证以使用Spring Web应用程序时遇到问题,并且我认为问题与Kerberos票证和Active Directory的加密类型有关域功能级别。校验和失败:Kerberos/Spring/Active Directory(2008)

基本设置是:

我有一个en其中Active Directory域功能级别为Windows Server 2003的环境,并且一切正常,客户端在登录到域时按预期进行身份验证。使用kerbtray检查此环境中的故障​​单,我可以看到它们都具有故障单加密类型和密钥加密类型“RSADSI RC4-HMAC”。

我有一个功能级Windows Server 2008的新域,这是验证不起作用的地方。返回应用程序错误试图验证检票时是:

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) 

堆栈跟踪显示“ArcfourCrypto.decrypt”,所以推测是治疗Kerberos票据作为RC4-HMAC。此次再次使用kerbtray检查票据时,客户端上有两张票:krbtgt/.COM。两张票都具有密钥加密类型RSADS1 RC4-HMAC,其中一个也具有此票据加密类型,但另一个具有“Kerberos AES256-CTS-HMAC-SHA1-96”。

我不确定这是问题的原因,但它是我在两种可能解释认证异常的环境中找到的唯一区别。我尝试过更改AD加密策略,尝试过IE和Firefox,以及几乎所有我能想到的东西,但都没有成功。

任何帮助解决这个问题将不胜感激。我宁愿修复它在java端,因为我可能不能指定太多关于生产AD设置。

+0

您是否检查了Wireshark中的通信并检查了门票? – 2011-12-20 17:01:35

+0

谢谢@ Michael-O - 我之前在使用Wireshark时曾使用过Wireshark,但没有可用的输出。我无法完成此任务 - 我将测试域恢复到Windows Server 2003的功能级别然后它正常工作。现在我需要设置一个新的2008测试域名,以尝试找到一个可行的解决方案.... – slt 2012-01-03 11:08:54

回答

0

问题是如何生成令牌,以及如何在服务器端对其进行验证。从异常跟踪中,它显示问题是,客户端不设置校验和,服务器端正在验证校验和。校验和是令牌中设置的参数值之一,它具有明显的含义。

2008年必须有一种方法来禁用此功能来忽略校验和检查。但打开另一扇门,你可能需要评估剩余风险。

16

该问题似乎在keytab中。有一些动作序列导致某些特定的密钥表文件状态: (A)keytab与Java协同工作,但不适用于k5start/kinit; (B)keytab不适用于Java,但适用于k5start/kinit; (C)keytab同时适用于它们。

短的Java代码,允许检查,如果Java可以使用keytab文件验证:

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

,以及属性文件中使用:

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

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

(下面我们假设KRB/kdc已正确安装和配置,数据库使用kdb5_util创建,每个命令序列的起始状态为:删除keytab文件,删除令牌缓存,删除用户“foo”。)


下列动作顺序导致了密钥表状态(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 
$ 

下列动作顺序导致了密钥表状态(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 
$ 

但“k5start foo”在这种状态下是可以的,还有“kinit foo”。


而下面的动作序列导致状态(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 

之后,这两个k5start /的kinit和Java验证得到阳性结果。


环境:

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) 

还与Java观察到相同的行为7. 也观察到在Ubuntu精确(12.04.1 LTS)与麻省理工学院的Kerberos 5-1.10.3相同的行为编译来自源代码分发。