2009-12-10

歪打正着

上周末接到一个bug,大致内容是用户上传了新 Apache SSL 证书后会导致 WebUI 挂掉。吾大恐,虽然证书有备份可以恢复,可是这绝对是个容易让support phone愤怒的吼叫的bug -- 如果UI的一部分功能失常,用户还可以鼓捣鼓捣,现在连 webUI 都起不来了,这又如何忍得?

几经折腾后,发现是证书有问题,而这有问题的证书正是我的脚本生成出来的。之所以以前没有出现问题,是因为旧的证书是可用的。因为过期了,所以需要重新生成,而且恰好我心情好,毛遂自荐了自己的脚本(以前学openssl编程的时候自己用的),遂导致了这个bug的出现。

另外还有一个不可思议的歪打正着。那是今天早上遇到的一个bug,我们的API日志中错记了shutdown system这些信息,而导致该bug被发现的原因是被测机器恰好有过重启 -- 为了 cost-saving,某些服务器会在晚上自动关掉,然后上班前自动上电。因为QA不知道为何测试过程中机器被重启,于是仔细检查了日志,看到了它们。

好记性不如烂笔头,验证一个证书是否可以作为SSL Server证书:
# openssl verify -purpose sslserver -CAfile ca.pem server.pem


ca.pem是签名server.pem的CA证书,server.pem则是被测SSL Server证书。感慨一番:firefox遇到错误证书会提供详细信息,并让用户决定是否继续;而IE在证书签名错误的时候则直接挂断连接,显示页面无法显示,且无任何详细信息 -- 让人看起来觉得WebUI挂了。最后,再次抱怨一把:openssl的文档实在是有待丰富!

附上:Open Source Documentation Doesn't Have to Suck.

标签:

2009-08-21

两个补丁

今天提交了两个补丁,一个给libxr,一个给openssl。嗯,这样的生活才叫programming!

  1. [Patch] Enable IPv6 Server (Linux/Unix)

  2. [Patch] Fix IPv6 address handling

标签: ,

2009-06-19

BIO_copy_next_retry

这个礼拜还是比较充实的,至少很久没有这么充实了。终于弄出一个补丁,使得我们的服务器可以支持IPv6。基本的PoC已经在上周完成。因为没法等OpenSSL 1.0.0的正式release,于是只能自己改代码。手工创建 socket然后把accept()之后的connfd包装在一个BIO里面,所谓“曲线救国”了。本周只是把那些已经验证过的逻辑加到库中。本以为没啥问题的小事,却折腾了整整五天。

第一个问题出在Buffered IO上。代码里面原来用的是BIO_gets()来读数据,而这个函数只在Buffered IO中才有效。一开始我自己写了个BIO_readline(),想想不太好,于是在自己的BIO上又chain了一个BIO_f_buffer(),这样不改变原来的逻辑。
sbio = BIO_new_ssl(server->ctx, 0);
bbio = BIO_new(BIO_f_buffer());
sbio = BIO_push(bbio, sbio);


有了这一层bbio后,HTTP连接开始正常工作,而HTTPS的时候却一直SIGSEGV,无论32/64位机器,无论OpenSSL 0.9.7/0.9.8,屡试不爽。GDB、valgrind一起祭上,确信了不是自己代码中内存管理的问题,而gdb的backtrace显示,出问题的函数乃是:BIO_copy_next_retry()。它的代码很简单:
void BIO_copy_next_retry(BIO *b)
{
BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
b->retry_reason=b->next_bio->retry_reason;
}


问题是,它没有判断b->next_bio是否为NULL!稍微搜索一下,发现03年底就有人问过类似问题,只是无人解答。折腾了很久,这个SIGSEGV如同幽灵一般如影随形。晚上躺在床上梳理建立连接的流程,百思不得其解为何它的next_bio是NULL,而PoC中写的代码几乎如出一辙,却没有这个问题,无论数据量的大小如何。几于绝望的时候却是灵光乍现的时候。当再次瞄了一眼BIO_copy_next_retry()的时候,我突然想到:虽然俺不能改这段代码,我可以在我的BIO chain中再append一个BIO嘛!这样它的bio_next就一定不是NULL啦!于是这个礼拜最出彩的一行诞生了:
sbio = BIO_push(sbio, BIO_new(BIO_f_null()));


在BIO_push(bbio, sbio)之前,我在sbio后添加了一个啥事都不做的BIO filter,于是这个BIO chain看起来是这样:
bbio -> sbio -> null


由于null这个BIO啥事都不做,对结果没什么影响。而正如我一直希望的那样,这次SIGSEGV终于消失了。

标签:

2009-06-11

IPv6 in OpenSSL

最近的任务是让我们的XML-RPC Server能够在IPv6网络下远程访问。我们的底层数据是用OpenSSL的BIO来处理的,这意味着如果BIO_new_accept()之类直接支持了IPv6,那我的工作就容易许多。可惜的是,目前还不支持。综合搜索的结果来看,我只能手工创建socket,绑定一个IPv6地址,然后将accept之后的socket绑定到某个BIO。试了一下,确实可行。

说实话,openssl的代码不算好读,文档也有所欠缺,很多时候也只能去看源代码。网上抓了OpenSSL-1.0.0-beta2的代码看了一下,确信它在BIO层已经支持IPv6,而目前最新的版本0.9.8k则尚不支持。至于1.0.0何时发布,"The release date is to be set." 没有一个明确的schedule,这让人很郁闷。

下面是个故事:曾有一位RedHat的程序员在06年提交了让BIO支持IPv6的补丁,但被一位OpenSSL开发者拒绝了。摘录一段OpenSSL开发者的回复如下:
OK, to be absolutely sincere. It's not about what Microsoft [or RedHat] supports for the moment, but about exercising above mentioned discipline. It's not about looking for excuses, but exploring maximum possible extent of portability. Is it possible to write code which adapts itself to run-time environment? Regardless whether run-time is supported by vendor or not? How complicated is it? Forget that you're RedHat employee, become programmer instead:-) But this is getting off-topic. DSO_global_lookup was not the point I wanted to emphasize! DSO_global_lookup is mentioned only because you'll have to cope with it in HEAD branch. The main point is that changes of this haracter should be *conditional* for backward compatibility and you have to play by this rules.

现场:

  1. http://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest

  2. https://bugzilla.redhat.com/show_bug.cgi?id=198737

  3. https://www.redhat.com/archives/fedora-list/2009-March/msg00362.html


[1]里面记录了OpenSSL maintainer和提交补丁的RedHat Programmer之间的“交锋”; [2]里面记录了RedHat Programmer开发那个补丁的过程;[3]里面则是3年之后对这件事情的回顾。

仔细看了一下1.0.0-beta2的代码,现在的实现还是遵循了OpenSSL自己的discipline。我的疑问:

  1. 各个OpenSource项目有自己的discipline,但很多时候它的文档和discipline并不为成员之外的其他所熟知。出现冲突(实现的细节,风格的审美,可移植性/性能/安全因素等)的时候,patch的提供者和源代码的maintainer各自最理想的行为又是什么?

  2. 事实上,三年前如果OpenSSL的开发者在RedHat程序员的补丁只上稍加改进就能使得BIO直接支持IPv6,但直到三年之后,我们才看见它的存在,况且还是beta2。这真让人沮丧。

标签: