`
tetsu.soh
  • 浏览: 77325 次
  • 性别: Icon_minigender_1
  • 来自: 东京
社区版块
存档分类
最新评论

JAVA的bug?

阅读更多
在把向CDC1.1 prot kerberos的时候,遇到了一个问题。
在CDC1.0.1上运行良好的程序,产生了“server not found in kerberos database(7)” 错误。

找来找去,结果发现是在构造PrincipalName Object的时候,有如下一段代码:(Kerberos V5的SUN实现,源码对外不开放)
if (nameParts.length >= 2) {
    try {
        String hostName = (InetAddress.getByName(nameParts[1])).getCanonicalHostName();
    } catch (UnknownHostException e) {
        // no canonicalization, just convert to lowercase
        nameParts[1] = nameParts[1].toLowerCase();
    }
}
注意其中resolve hostname的方法,是通过调用InetAddress.getCanonicalHostName()来实现的。
在CDC1.0.1的kerberos中,因为没有这个方法,所以用getHostname来代替的。

Canonicalize是指“最简化”,就是数学中将一个表达式化为其最简形式的意思。

好了,回头再来看我们的kerberos。
RFC 1510和1964,对principalName的命名方法作了规定。简单来说,就是principal name由两部分组成:
service@hostname

RFC 1964的描述如下:
"When a reference to a name of this type is resolved, the "hostname" is canonicalized by attempting a DNS lookup and using the fully-qualified domain name which is returned, or by using the "hostname" as provided if the DNS lookup fails.  The canonicalization operation also maps the host's name into lower-case characters."

可是参看InetAddress.getCanonicalHostName()的API doc我们就发现问题了。该方法在解析失败后,返回的是IP地址,而不是“the 'hostname' as provided” -- 也就是InetAddress构造是所用的hostname。

这就导致了开始所说的错误。用户输入的是FQDN,而因某种原因,DNS解析失败后,principal name中的hostname却变成了IP address,这样的principal name当然在kerberos database中找不到了。

那么这是谁的bug?
InetAddress中getCanonocialHostName()的方法实现有问题?
RFC 1964要求canonicalize hostname,并说明了如何做,不过getCanonocialHostName()方法明显是不满足要求的,虽然挂了个canonical的名。当然了,这个方法不是仅在Kerberos的实现中使用,所以也不能说这个实现就不合规矩。

那么是Kerberos实现的错咯?
找了SUN的bugs database,没有找到相关的bugs报告。

我手头有的SUN实现的Kerberos,版本只到JDK1.5.0,不知道以后的版本中是不是修复了这个问题?
分享到:
评论
2 楼 tetsu.soh 2007-04-17  
今天在1G的一个同事的提示下,测试了如下一个程序. 改变Windows的“%system%drivers\etc\host”文件中对测试IP地址(133.139.22.35)的解析,结果也随之改变。
这是当然的。
try {
        InetAddress add = InetAddress.getByName("133.139.22.35");
        System.out.println("Canonical HostName: " + add.getCanonicalHostName());
} catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
}

但是如果做如下设定:
133.139.22.35   noah.spf.ricoh.co.jp   #domain name
133.139.22.35   noah-server.noah.spf.ricoh.co.jp    #host name

然后测试用hostname来测试,也就是
InetAddress.getByName("noah-server.noah.spf.ricoh.co.jp ");

返回的结果却是noah.spf.ricoh.co.jp (domain name!!!)

可见,getCanonicalHostName其实就是从本地的解析文件中顺序寻找IP地址的解析,如果找到了,就返回值(而不管这个值是什么)
如果找不到,就返回IP address。

这个实现是不是正确呢?
Java doc对这个方法的说明是“Gets the fully qualified domain name for this IP address. ”
对这个方法有两个疑问:
1。 这个FQDN是否应该经过确认?SUN的实现,是用SecurityManage.checkConnect方法,但是如果没有指定SecurityManager的话,就不测试。
其结果是,如果在host文件中,做如下修改:
133.139.22.35   xxxx.xxxx.xxxx   #whatever you like
133.139.22.35   noah.spf.ricoh.co.jp   #domain name
133.139.22.35   noah-server.noah.spf.ricoh.co.jp    #host name

那么上面的测试返回的结果就是“xxxx.xxxx.xxxx”了!

2。 Kerberos 的 principalname = service@hostname
但是在解析hostname的时候,JDK1.4后,使用了getCanonicalHostName()方法,按照API docs,这个方法返回的是FQDN,也就是Domain Name, 而不是Host Name。
这明显是不合理的。

Kerberos的这个实现问题已经通过公司提交给SUN了,目前还没有回复。等待中....
1 楼 tetsu.soh 2007-04-12  
没有朋友在做Kerberos的项目么?谁有1.5.0以后的SUN实现的kerberos源码?帮忙check以下吧

相关推荐

Global site tag (gtag.js) - Google Analytics