浏览 3655 次
锁定老帖子 主题:JAVA的bug?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-12
在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,不知道以后的版本中是不是修复了这个问题? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-04-12
没有朋友在做Kerberos的项目么?谁有1.5.0以后的SUN实现的kerberos源码?帮忙check以下吧
|
|
返回顶楼 | |
发表时间: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了,目前还没有回复。等待中.... |
|
返回顶楼 | |