校验和失败:的Kerberos /春/活动目录(2008年) [英] checksum failed: Kerberos / Spring / Active Directory (2008)

查看:5474
本文介绍了校验和失败:的Kerberos /春/活动目录(2008年)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有麻烦的Kerberos / AD身份验证与Web应用程序春的工作,我相信这个问题已经做了Kerberos票据和Active Directory域功能级别的加密类型。

We are having trouble getting Kerberos/AD authentication to work with a Spring webapp, and I believe the problem has to do with encryption types for the Kerberos tickets and the Active Directory domain functional level.

基本设置是:

  • Tomcat 7
  • Java 1.6 (29)
  • Windows Server 2008 R2
  • Spring 3.0
  • Spring Security Kerberos/Spnego extension M2 detailed here: http://blog.springsource.com/2009/09/28/spring-security-kerberos/

我有一个环境下,Active Directory域功能级别为Windows Server 2003和一切工作正常,与客户,如果他们登录到域作为预期验证。使用的Kerbtray检查门票在这种环境下,我可以看到,他们都同时具有门票加密类型和密钥加密类型RSADSI RC4-HMAC。

I have one environment where the Active Directory domain functional level is Windows Server 2003 and everything works fine, with clients authenticating as expected if they are logged on to the domain. Using kerbtray to examine the tickets in this environment I can see that they all have both ticket encryption type and key encryption type "RSADSI RC4-HMAC".

我有一个功能级别的Windows Server 2008的一个新的领域,而这正是验证不起作用。该应用程序返回错误试图验证该票的时候是:

I have a new domain with functional level Windows Server 2008, and this is where the authentication does not work. The application error returned when attempting to validate the ticket is:

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所以presumably是治疗Kerberos票据作为RC4-HMAC。使用的Kerbtray又到了这个时候检查门票有2张客户端域上:KRBTGT / .COM。这两种门票都有密钥加密类型RSADS1 RC4-HMAC,我们也有这个票证加密类型,但对方的Kerberos AES256-CTS-HMAC-SHA1-96。

The stack trace shows "ArcfourCrypto.decrypt" so presumably is treating the Kerberos ticket as RC4-HMAC. Using kerbtray again to examine the tickets this time there are 2 tickets on the client for the domain: krbtgt/.COM. Both of tickets have key encryption type RSADS1 RC4-HMAC, one also has this for ticket encryption type, but the other has "Kerberos AES256-CTS-HMAC-SHA1-96".

我不知道是肯定的,这是问题的原因,但它是我能找到的两个环境可能解释认证例外,唯一的区别。我试着更改AD加密策略,尝试了IE和Firefox,和pretty的很多其他一切我能想到的,但没有奏效。

I don't know for sure that this is the cause of the problem, but it is the only difference I've been able to find in the two environments that might explain the authentication exception. I've tried changing the AD encryption policy, tried IE and Firefox, and pretty much everything else I could think of, but nothing has worked.

任何帮助解决这将是非常美联社preciated。我想preFER修复它在Java端,因为我可能不能支配太多生产AD设置。

Any help addressing this would be much appreciated. I'd prefer to fix it on the java end as I probably can't dictate too much about the production AD setup.

推荐答案

这个问题似乎是在密钥表。有导致一些特定的密钥表文件指出了一些动作场面: (一)密钥表与​​Java的作品,但不与k5start /使用kinit工作; (二)密钥表不与Java的工作,但可以与k5start / kinit命令; (三)密钥表与​​他们两人的作品。

The problem seems to be in the keytab. There are some action sequences leading to some specific keytab file states: (A) keytab works with Java but does not work with k5start/kinit; (B) keytab does not work with Java, but works with k5start/kinit; (C) keytab works with both them.

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

The short Java code that allows to check if Java can authenticate using the keytab file:

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

,而属性文件中使用:

, and the property file to use:

#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创建的每个指令序列的起始状态是:删除密钥表文件,令牌缓存被删除,用户富是从被删除数据库。)

(Below we assume that krb/kdc is correctly installed and configured, the database is created with kdb5_util. The starting state of each command sequence is: the keytab file deleted, token cache is deleted, user "foo" is deleted from the database.)

下面的动作顺序导致密钥表状态(A):

The following action sequence leads to the keytab state (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 foo@EXAMPLE.COM
Password for foo@EXAMPLE.COM: 
k5start: error getting credentials: Decrypt integrity check failed
$


下面的动作顺序导致密钥表状态(B):


The following action sequence leads to the keytab state (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 foo@EXAMPLE.COM
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的。

But the "k5start foo" is okay in this state, as well as "kinit foo".

和下面的动作顺序导致状态(C):

And the following action sequence leads to state (C):

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

之后,这两个k5start / kinit命令和Java认证给予积极的结果。

after that both k5start/kinit and the java verification give positive result.

环境:

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上precise(12.04.1 LTS)与麻省理工学院的Kerberos 5-1.10.3从源代码进行编译。

Also the same behavior observed with Java 7. Also the same behavior was observed on Ubuntu precise (12.04.1 LTS) with MIT's kerberos 5-1.10.3 compiled from the source distribution.

这篇关于校验和失败:的Kerberos /春/活动目录(2008年)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆