GSSException:修改了消息流(41)

GSSException:修改了消息流(41)

问题描述:

我在林架构中使用LDAP(所有服务器和我的服务器都是windows)。我使用NTLM身份验证绑定到AD。GSSException:修改了消息流(41)

我有一个JAVA代码执行对LDAP服务器的操作。

代码被封装为一个tomcat servlet。

当直接运行JAVA代码(仅执行LDAP身份验证代码作为应用程序)时,该绑定对本地域(本地域=我登录到Windows,并与此域的用户一起运行此过程)和国外领域。

将JAVA代码作为servlet运行时,该绑定工作并验证来自一个域的用户,但不起作用,如果我试图从其他域验证用户,则不起作用(只有当我将重新启动tomcat)。

我得到一个异常:

GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Message stream modified (41))]] 

我会提到,这是相同的代码,具有相同的配置和相同的krb5文件。

编辑: 更多信息:

这是我的代码:

public void func(String realm, String kdc) { 
    try { 
     URL configURL = getClass().getResource("jaas_ntlm_configuration.txt"); 
     System.setProperty("java.security.auth.login.config", configURL.toString()); 

      System.setProperty("java.security.krb5.realm", realm); 
      System.setProperty("java.security.krb5.kdc",kdc); 

     // If the application is run on NT rather than Unix, use this name 
     String loginAppName = "MyConfig"; 

     // Create login context 
     LoginContext lc = new LoginContext(loginAppName, new SampleCallbackHandler()); 

     // Retrieve the information on the logged-in user 
     lc.login(); 

     // Get the authenticated subject 
     Subject subject = lc.getSubject(); 

     System.out.println(subject.toString()); 

     Subject.doAs(subject, new JndiAction(new String[] { "" })); 
    } 
    catch (LoginException e) { 
     e.printStackTrace(); 
    } 
} 

class JndiAction implements java.security.PrivilegedAction { 
    private String[] args; 

    public JndiAction(String[] origArgs) { 
     this.args = (String[])origArgs.clone(); 
    } 

    public Object run() { 
     performJndiOperation(args); 
     return null; 
    } 

    private static void performJndiOperation(String[] args) { 

     // Set up environment for creating initial context 
     Hashtable env = new Hashtable(11); 

     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 

     // Must use fully qualified hostname 
     env.put(Context.PROVIDER_URL, "ldap://server:389"); 

     // Request the use of the "GSSAPI" SASL mechanism 
     // Authenticate by using already established Kerberos credentials 
     env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI"); 

     try { 
      // Create the initial context 
      DirContext ctx = new InitialLdapContext(env, null); 


      // Close the context when we're done 
      ctx.close(); 
     } catch (NamingException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

而且我jaas_ntlm_configuration.txt文件包含:

MyConfig { com.sun.security.auth.module.Krb5LoginModule required 
useTicketCache=true 
doNotPrompt=false; 
}; 

我krb5.conf文件是:

# 
# All rights reserved. 
# 
#pragma ident @(#)krb5.conf 1.1 00/12/08 

[libdefaults] 
    default_tkt_enctypes = des3-cbc-sha1 des-cbc-md5 des-cbc-crc 
    default_tgs_enctypes = des3-cbc-sha1 des-cbc-md5 des-cbc-crc 
    forwardable = true 
    renewable = true 
    noaddresses = true 
    clockskew = 300 

[realms] 
     SUB1.DOMAIN.COM = { 
       kdc = DDC.SUB1.DOMAIN.COM 
     default_domain=DOMAIN.COM 
     } 
    SUB2.DOMAIN.COM = { 
       kdc = DDC.SUB.DOMAIN.COM 
     default_domain=DOMAIN.COM 
     } 
    SUB3.DOMAIN.COM = { 
       kdc = DDC.SUB3.DOMAIN.COM 
     default_domain=DOMAIN.COM 
     } 

[domain_realm] 
    .DOMAIN.COM = SUB1.DOMAIN.COM 
    .DOMAIN.COM = SUB2.DOMAIN.COM 
    .DOMAIN.COM = SUB3.DOMAIN.COM 

[logging] 
     default = FILE:/var/krb5/kdc.log 
     kdc = FILE:/var/krb5/kdc.log 
    kdc_rotate = { 

# How often to rotate kdc.log. Logs will get rotated no more 
# often than the period, and less often if the KDC is not used 
# frequently. 

     period = 1d 

# how many versions of kdc.log to keep around (kdc.log.0, kdc.log.1, ...) 

     versions = 10 
    } 

[appdefaults] 
    kinit = { 
     renewable = true 
     forwardable= true 
    } 
    rlogin = { 
     forwardable= true 
    } 
    rsh = { 
     forwardable= true 
    } 
    telnet = { 
      autologin = true 
     forwardable= true 
    } 

添加以下如Java参数:

-Djavax.security.auth.useSubjectCredsOnly=false -Djava.security.krb5.conf="krb5.conf" -Dsun.security.krb5.debug=true 

如果我叫FUNC( “SUB * .DOMAIN.COM”, “DDC.SUB * .DOMAIN.COM”)总是以相同的子域 - 它将工作,但如果我打电话与一个子域,然后与另一个,第二个将失败。

更多信息:

这里是krb5.debug输出=真:

java -Xmx100m -cp gssapi_test.jar -Djavax.security.auth.useSubjectCredsOnly=false -Djava.security.krb5.conf="krb5.conf" -Dsun.security.krb5.debug=true gssapitest.myTest my_config.txt 
2 users provided. Performing authentication #1 
Reading configuration file my_config.txt 
kdc: DDC.SUB1.DOMAIN.COM, realm: SUB1.DOMAIN.COM 
>>>KinitOptions cache name is C:\Users\user1\krb5cc_user1 
>> Acquire default native Credentials 
>>> Obtained TGT from LSA: Credentials: 
[email protected] 
server=krbtgt/[email protected] 
authTime=20130422075139Z 
startTime=20130422075139Z 
endTime=20130422175139Z 
renewTill=20130429075139Z 
flags: FORWARDABLE;RENEWABLE;INITIAL;PRE-AUTHENT 
EType (int): 23 
Subject: 
    Principal: [email protected] 
    Private Credential: Ticket (hex) = 
..... 

Client Principal = [email protected] 
Server Principal = krbtgt/[email protected] 
Session Key = EncryptionKey: keyType=23 keyBytes (hex dump)= 
0000: 2B 8C 97 3C 8E 83 66 F1 6D 58 6C 37 20 0E 1F 53 +..<..f.mXl7 ..S 


Forwardable Ticket true 
Forwarded Ticket false 
Proxiable Ticket false 
Proxy Ticket false 
Postdated Ticket false 
Renewable Ticket true 
Initial Ticket true 
Auth Time = Mon Apr 22 15:51:39 2013 
Start Time = Mon Apr 22 15:51:39 2013 
End Time = Tue Apr 23 01:51:39 2013 
Renew Till = Mon Apr 29 15:51:39 2013 
Client Addresses Null 

Connecting to LDAP 
Config name: krb5.conf 
Found ticket for [email protected] to go to krbtgt/[email protected] expiring on Tue Apr 23 01:51:39 2013 
Entered Krb5Context.initSecContext with state=STATE_NEW 
Service ticket not found in the subject 
>>> Credentials acquireServiceCreds: same realm 
default etypes for default_tgs_enctypes: 16 3 1. 
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
>>> KdcAccessibility: reset 
>>> KrbKdcReq send: kdc=DDC.SUB1.DOMAIN.COM UDP:88, timeout=30000, number of retries =3, #bytes=1554 
>>> KDCCommunication: kdc=DDC.SUB1.DOMAIN.COM UDP:88, timeout=30000,Attempt =1, #bytes=1554 
>>> KrbKdcReq send: #bytes read=107 
>>> KrbKdcReq send: kdc=DDC.SUB1.DOMAIN.COM TCP:88, timeout=30000, number of retries =3, #bytes=1554 
>>> KDCCommunication: kdc=DDC.SUB1.DOMAIN.COM TCP:88, timeout=30000,Attempt =1, #bytes=1554 
>>>DEBUG: TCPClient reading 1497 bytes 
>>> KrbKdcReq send: #bytes read=1497 
>>> KdcAccessibility: remove DDC.SUB1.DOMAIN.COM 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
>>> KrbApReq: APOptions are 00000000 00000000 00000000 00000000 
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType 
Krb5Context setting mySeqNumber to: 1005735013 
Krb5Context setting peerSeqNumber to: 0 
Created InitSecContextToken: 
..... 

Krb5Context.unwrap: token=[60 33 06 09 2a 86 48 86 f7 12 01 02 02 02 01 00 00 ff ff ff ff 94 52 14 5b f6 02 28 1c a4 3c c5 8f 03 9c a2 d6 e5 f6 f1 18 ed 6f 16 ab 07 a0 00 00 04 04 04 04 ] 
Krb5Context.unwrap: data=[07 a0 00 00 ] 
Krb5Context.wrap: data=[01 01 00 00 ] 
Krb5Context.wrap: token=[60 33 06 09 2a 86 48 86 f7 12 01 02 02 02 01 00 00 ff ff ff ff 2d b6 92 0d d9 51 da aa ef 41 67 33 5c de b3 e6 ce 9a 46 31 a0 a8 0e 27 01 01 00 00 04 04 04 04 ] 
Connected 
Disconnected 
#1: Done 
Performing authentication #2 
Reading configuration file my_config.txt 
kdc: DDC.SUB2.DOMAIN.COM, realm: SUB2.DOMAIN.COM 
>>>KinitOptions cache name is C:\Users\user1\krb5cc_user1 
>> Acquire default native Credentials 
>>> Obtained TGT from LSA: Credentials: 
[email protected] 
server=krbtgt/[email protected] 
authTime=20130422075139Z 
startTime=20130422075139Z 
endTime=20130422175139Z 
renewTill=20130429075139Z 
flags: FORWARDABLE;RENEWABLE;INITIAL;PRE-AUTHENT 
EType (int): 23 
Subject: 
    Principal: [email protected] 
    Private Credential: Ticket (hex) = 
..... 

Client Principal = [email protected] 
Server Principal = krbtgt/[email protected] 
Session Key = EncryptionKey: keyType=23 keyBytes (hex dump)= 
0000: 2B 8C 97 3C 8E 83 66 F1 6D 58 6C 37 20 0E 1F 53 +..<..f.mXl7 ..S 


Forwardable Ticket true 
Forwarded Ticket false 
Proxiable Ticket false 
Proxy Ticket false 
Postdated Ticket false 
Renewable Ticket true 
Initial Ticket true 
Auth Time = Mon Apr 22 15:51:39 2013 
Start Time = Mon Apr 22 15:51:39 2013 
End Time = Tue Apr 23 01:51:39 2013 
Renew Till = Mon Apr 29 15:51:39 2013 
Client Addresses Null 

Connecting to LDAP 
Found ticket for [email protected] to go to krbtgt/[email protected] expiring on Tue Apr 23 01:51:39 2013 
Entered Krb5Context.initSecContext with state=STATE_NEW 
Service ticket not found in the subject 
>>> Credentials acquireServiceCreds: same realm 
default etypes for default_tgs_enctypes: 16 3 1. 
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
>>> KrbKdcReq send: kdc=DDC.SUB1.DOMAIN.COM UDP:88, timeout=30000, number of retries =3, #bytes=1554 
>>> KDCCommunication: kdc=DDC.SUB1.DOMAIN.COM UDP:88, timeout=30000,Attempt =1, #bytes=1554 
>>> KrbKdcReq send: #bytes read=107 
>>> KrbKdcReq send: kdc=DDC.SUB1.DOMAIN.COM TCP:88, timeout=30000, number of retries =3, #bytes=1554 
>>> KDCCommunication: kdc=DDC.SUB1.DOMAIN.COM TCP:88, timeout=30000,Attempt =1, #bytes=1554 
>>>DEBUG: TCPClient reading 1482 bytes 
>>> KrbKdcReq send: #bytes read=1482 
>>> KdcAccessibility: remove DDC.SUB1.DOMAIN.COM 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
KrbException: Message stream modified (41) 
    at sun.security.krb5.KrbKdcRep.check(Unknown Source) 
    at sun.security.krb5.KrbTgsRep.<init>(Unknown Source) 
    at sun.security.krb5.KrbTgsReq.getReply(Unknown Source) 
    at sun.security.krb5.KrbTgsReq.sendAndGetCreds(Unknown Source) 
    at sun.security.krb5.internal.CredentialsUtil.serviceCreds(Unknown Source) 
    at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(Unknown Source) 
    at sun.security.krb5.Credentials.acquireServiceCreds(Unknown Source) 
    at sun.security.jgss.krb5.Krb5Context.initSecContext(Unknown Source) 
    at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source) 
    at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source) 
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(Unknown Source) 
    at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(Unknown Source) 
    at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source) 
    at javax.naming.spi.NamingManager.getInitialContext(Unknown Source) 
    at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source) 
    at javax.naming.InitialContext.init(Unknown Source) 
    at javax.naming.ldap.InitialLdapContext.<init>(Unknown Source) 
    at gssapitest.JndiAction.performJndiOperation(myTest.java:603) 
    at gssapitest.JndiAction.run(myTest.java:577) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Unknown Source) 
    at gssapitest.myTest.Do(myTest.java:59) 
    at gssapitest.myTest.main(myTest.java:513) 
javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Message stream modified (41))]] 
    at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(Unknown Source) 
    at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source) 
    at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source) 
    at javax.naming.spi.NamingManager.getInitialContext(Unknown Source) 
    at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source) 
    at javax.naming.InitialContext.init(Unknown Source) 
    at javax.naming.ldap.InitialLdapContext.<init>(Unknown Source) 
    at gssapitest.JndiAction.performJndiOperation(myTest.java:603) 
    at gssapitest.JndiAction.run(myTest.java:577) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Unknown Source) 
    at gssapitest.myTest.Do(myTest.java:59) 
    at gssapitest.myTest.main(myTest.java:513) 
Caused by: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Message stream modified (41))] 
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(Unknown Source) 
    ... 18 more 
Caused by: GSSException: No valid credentials provided (Mechanism level: Message stream modified (41)) 
    at sun.security.jgss.krb5.Krb5Context.initSecContext(Unknown Source) 
    at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source) 
    at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source) 
    ... 19 more 
Caused by: KrbException: Message stream modified (41) 
    at sun.security.krb5.KrbKdcRep.check(Unknown Source) 
    at sun.security.krb5.KrbTgsRep.<init>(Unknown Source) 
    at sun.security.krb5.KrbTgsReq.getReply(Unknown Source) 
    at sun.security.krb5.KrbTgsReq.sendAndGetCreds(Unknown Source) 
    at sun.security.krb5.internal.CredentialsUtil.serviceCreds(Unknown Source) 
    at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(Unknown Source) 
    at sun.security.krb5.Credentials.acquireServiceCreds(Unknown Source) 
    ... 22 more 
FAILED 

我能做些什么?我做错了什么?

谢谢。

NTLM!= Kerberos。 Java SASL不支持NTLM。正确配置Kerberos,它会工作。

+0

我想我配置得当。我发布了我的代码和配置,如果你能帮助你理解错误,我会很高兴。谢谢。 – Matan 2013-04-17 11:30:22

+0

你期望用什么? NTLM还是Kerberos? – 2013-04-17 21:09:43

+0

1.从您的应用程序中删除所有'System.setProperty',并在开始时为它们提供'-D'。 2.提供您尝试连接的示例主机名(SPN)和UPN。我们需要检查整个路径。森林中的跨领域对于JGSS来说不是问题。这在这里有魅力。你可能想通过使用这个[library]来减轻锅炉的痛苦(http://dirctxsrc.sourceforge.net/)。 – 2013-04-18 09:09:14

感谢您的支持!仅供参考,区域大写(即区域应该100%正确并且大写)对于避免“例外:krb_error 41消息流修改(41)”非常重要。

这里是正确的符号的一个例子:

[libdefaults] 
default_realm = EXAMPLE.COM 

[realms] 
EXAMPLE.COM = { 
kdc = domaincontroller.example.com 
admin_server = domaincontroller.example.com 
default_domain = EXAMPLE.COM 
} 

[domain_realm] 
.example.com = EXAMPLE.COM 
example.com = EXAMPLE.COM 

问候,

尼卡。

+0

及时修复 - 这正是我的配置错误。根本不是一个直观的错误,但将域名置于大写字母可以解决我的问题。 – Justin 2013-09-23 20:53:56