Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java/SPNEGO:不需要的SPN规范化?_Java_Windows_Kerberos_Spnego_Spn - Fatal编程技术网

Java/SPNEGO:不需要的SPN规范化?

Java/SPNEGO:不需要的SPN规范化?,java,windows,kerberos,spnego,spn,Java,Windows,Kerberos,Spnego,Spn,我目前正在尝试使用来自SourceForge的实现一个Java客户端到一个受SPNEGO保护的web服务(服务器使用相同的库)。我无法让它成功地进行身份验证,我的请求总是以 HTTP/1.1 500 Failure unspecified at GSS-API level (Mechanism level: Checksum failed) 这与我使用不合适的主机名从浏览器访问web服务时出现的症状类似,事实上,Wireshark中的一些调试显示,客户端在请求中发送了错误的SPN-我发送到se

我目前正在尝试使用来自SourceForge的实现一个Java客户端到一个受SPNEGO保护的web服务(服务器使用相同的库)。我无法让它成功地进行身份验证,我的请求总是以

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
(请参阅匹配的
主机
标题),Java请求票证的SPN是“内部”Windows名称:

从Chrome或IE发送的相同内容具有匹配的
主机
标题和SPN:

由于在我的代码或SPNEGO库中没有发生这种转换,我推测它一定发生在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();

上述评论的摘要:


重新检查你的DNS。进行反向查找。大多数问题都是由不正确的反向DNS条目引起的

中的第85页可能会帮助您检查和搜索“佳能”

当使用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
中的源代码,有一种方法实际上可以做到这一点:

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

因此,我想我们必须询问邮件列表。

重新检查您的DNS。进行反向查找。大多数问题都是由不正确的反向DNS条目引起的。你的领域名称是什么?这本书的第85页可能会对你有所帮助。Windows使用SSPI,它实际上与GSS-API做相同的事情,但方式不同。还有一个提示:您需要提供有关服务于
CLIENT.COM
领域的KDC的信息,否则Java将无法获得票证。我们有一个类似的星座在工作。这被认为是失败的,因为Kerberos不知道域
CLIENT.COM
。您也可以使用Wireshark嗅探KDC流量。过滤kerberos@Michael-O:谢谢,很好的评论。如果我读对了RFC,它不应该做任何反向查找的恶作剧,尽管。。。我将在周一验证DNS/Kerberos通信发生了什么…实际上不是,它说“当解析对此类名称的引用时,可以通过尝试DNS查找并使用返回的完全限定域名或使用“主机名”来规范化“主机名”(作为示例实现策略)“如果DNS查找失败,则按规定执行。“这要看情况了。进行反向查找是非常自然的。这就是Kerberos验证主机名的方式。如果您正在运行DNS循环,这实际上是至关重要的。否则,它将永远无法构建真正的SPN。星期一告诉我你的成绩。我很兴奋。谢谢——这很有道理,但我不明白为什么IE在这里的行为会与Java不同。我总是假设循环赛