2012-09-01 102 views
3

我正在尝试使用SourceForge中的SPNEGO library(服务器使用相同的库)来实现Java客户端到SPNEGO保护的Web服务。我不能让它成功地进行身份验证,我的要求总是最终的Java/SPNEGO:不需要的SPN规范化?

HTTP/1.1 500 Failure unspecified at GSS-API level (Mechanism level: Checksum failed) 

这类似于从浏览器的不适当的主机名访问Web服务的时候,我得到的症状,并在Wireshark的确实有些调试显示客户端发送错误的SPN与请求 - 我发送到service-test.client.com,它被注册为SPN并且在DNS中有A记录,但在Windows域中被注册为server-1234.client.corp。虽然我把我的请求http://service-test.client.com(查看匹配Host头),该SPN是Java的请求票是“内部” Windows名称:

Wireshark decode of the HTTP request

从Chrome或IE浏览器发出同样有配套Host头和结节:

enter image description here

因为无这个翻译在我的代码或SPNEGO库中出现,我相信它必须somehwere在JRE发生。我一直在寻找JGSS的来源,但这有点难以理解。任何人都可以告诉我如何跳过此翻译并获得正确SPN的门票?

客户端代码:从上面的意见

SpnegoHttpURLConnection con = new SpnegoHttpURLConnection("spnego-client", user, password); 
con.connect(new URL("http://service-test.client.com:8083/service")); 
int rc = con.getResponseCode(); 
String msg = con.getResponseMessage(); 
+0

重新检查您的DNS。做一个反向查找。大多数问题都来自不正确的反向DNS条目。你的领域的名字是什么?在[RFC](http://www.ietf.org/rfc/rfc2743.txt)中可能会帮助你。 Windows使用的SSPI实际上与GSS-API的功能完全相同,但以不同的方式。另一个提示:您需要提供有关服务于CLIENT.COM域的KDC的信息,否则Java将无法获得票证。 我们有一个类似的星座在工作。这被认为是失败的,因为Kerberos不知道领域CLIENT.COM。 –

+0

您也可以使用Wireshark嗅探KDC流量。过滤“kerberos”。 –

+0

@ Michael-O:谢谢,很棒的评论。如果我正确地阅读了RFC,它不应该做任何反向查找恶作剧,但是...我将在星期一验证什么DNS/Kerberos通信发生... – themel

回答

3

摘要:

重新检查你的DNS。做一个反向查找。大多数问题都来自不正确的反向DNS条目。

Page 85在RFC2713可能会帮助你并检查RFC4120并搜索“canon”。

当使用GSS-API构建基于主机的服务的SPN时,必须使用目标机制对该名称进行规范化。在RFC说

当这种类型的名称的引用解析中,“主机名”可以(作为例子的实施策略)可以通过尝试DNS查找和使用完全限定域名是规范化返回,或者如果DNS查询失败,则使用“主机名”提供。规范化操作还将主机名称映射为小写字符。

凡Kerberos 5的RFC说:

服务器和传输时。因此,例如,不应该依赖不受保护的DNS记录来将主机别名映射到服务器的主名称 ,因为攻击者可以修改映射并接受主要名称作为打算联系的一方的主名称冒充 这个派对。

基于Kerberos的Kerberos和协议的实现必须不使用不安全的DNS查询来规范服务主体名称的主机名组件 。,他们不得使用不安全的DNS 查询将一个名称映射到另一个名称以确定与其通信的主体名称的主机部分)。在没有安全名称服务的环境 中,应用程序作者可能会将 静态配置的域名添加到未限定的主机名,然后 会将该名称传递给安全机制,但它们不应该多于 。如果可用,安全名称服务设施可能会被信任主机名标准化,但客户端的这种规范化 不应该是KDC实现所必需的。

实现注意事项:许多当前的实现在某种程度上对所提供的服务名称进行了一定程度的规范化,但通常使用DNS,即使是 ,但它会产生安全问题。然而,关于服务名称是否为 大小写被折叠为小写或者是否使用了反向分辨率,各实现之间不存在任何 一致性。要使 最大限度地提高互操作性和安全性,应用程序应该提供安全机制的名称,这些名称可以通过将用户输入的名称折叠为小写,而不执行任何其他修改 或规范化。

似乎GSS-API impls可能规范化,但如果DNS不受信任,Kerberos不应这样做。 所以这取决于。反向查找完成是非常自然的。这就是Kerberos验证主机名的方式。如果您正在运行DNS循环,这实际上是至关重要的。没有它,它永远不会构建真正的SPN。

虽然我真的是这样的Kerberos邮件列表。这是一个非常有趣的观点。

我已经检查了MIT Kerberos实现和存在,实际上做到这一点,如果你在sn2princ.c查看源代码的方法krb5_sname_to_principal

if (type == KRB5_NT_SRV_HST) { 
     struct addrinfo *ai = NULL, hints; 
     int err; 
     char hnamebuf[NI_MAXHOST]; 

     /* Note that the old code would accept numeric addresses, 
      and if the gethostbyaddr step could convert them to 
      real hostnames, you could actually get reasonable 
      results. If the mapping failed, you'd get dotted 
      triples as realm names. *sigh* 

      The latter has been fixed in hst_realm.c, but we should 
      keep supporting numeric addresses if they do have 
      hostnames associated. */ 

     memset(&hints, 0, sizeof(hints)); 
     hints.ai_flags = AI_CANONNAME; 
     err = getaddrinfo(hostname, 0, &hints, &ai); 
     if (err) { 
#ifdef DEBUG_REFERRALS 
      printf("sname_to_princ: failed to canonicalize %s; using as-is", hostname); 
#endif 
     } 
     remote_host = strdup((ai && ai->ai_canonname) ? ai->ai_canonname : hostname); 
     if (!remote_host) { 
      if(ai) 
       freeaddrinfo(ai); 
      return ENOMEM; 
     } 

     if ((!err) && maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) { 
      /* 
      * Do a reverse resolution to get the full name, just in 
      * case there's some funny business going on. If there 
      * isn't an in-addr record, give up. 
      */ 
      /* XXX: This is *so* bogus. There are several cases where 
       this won't get us the canonical name of the host, but 
       this is what we've trained people to expect. We'll 
       probably fix it at some point, but let's try to 
       preserve the current behavior and only shake things up 
       once when it comes time to fix this lossage. */ 
      err = getnameinfo(ai->ai_addr, ai->ai_addrlen, 
           hnamebuf, sizeof(hnamebuf), 0, 0, NI_NAMEREQD); 
      freeaddrinfo(ai); 
      if (err == 0) { 
       free(remote_host); 
       remote_host = strdup(hnamebuf); 
       if (!remote_host) 
        return ENOMEM; 
      } 
     } else 
      freeaddrinfo(ai); 
    } 

所以,我想我们要问与邮件列表。

+0

我在MIT Kerberos邮件列表上创建了一个[thread](http://mailman.mit.edu/pipermail/kerberos/2012-September/018372.html)。 –