欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[疑难杂症]系统时间不对导致SSL连接失败

程序员文章站 2022-03-05 12:13:29
...

问题描述

我们某安卓盒子的客户端,每次开机第一次连接服务器大概率出现ssl错误导致连接失败,openssl返回的错误是:

SSL_connect error:00000001:lib(0):func(0):reason(1)

抓取网络pcap包,发现在ssl握手时,客户端收到服务器的证书认为证书无效,但是同样的证书过一会再连接,又可以建立连接。此问题仅发生在某特定型号的盒子

问题分析

分析了一下证书的认证过程,无外乎判断一下证书有效时间,双方支持的加密格式等等,最终发现是安卓端的时间有问题:系统是不保存时间的,每次开机从网络校时,经常出现校时延误甚至校时失败,拿一个2014年的初始时间去检查证书的时间,所以认定证书“过期”了。

这里一个坑的地方是,盒子上面显示的是桌面app获取的时间,不是底层系统的时间,底层系统的时间可以在shell里通过date命令查看。

另外一个坑,openssl的错误信息可能一次get不完,需要get多次才能把所有信息打印出来,修正了一下打印错误信息的代码

                char error_str[256];
                while (rc != 0) {
                    ERR_error_string_n(rc, error_str, sizeof(error_str));
                    g_warning("%s: SSL_connect %s", c->name, error_str);
                    rc = ERR_get_error();
                }

所以问题完整错误信息应该是:

SSL_connect error:00000001:lib(0):func(0):reason(1)
SSL_connect error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

问题解决

作为一个第三方应用开发人员,对android rom的bug无可奈何,普通应用连设置系统时间的权限都都没有。当然可以通过设置证书的有效期在2014年开始规避,这显然不是好办法。

比较合理的办法是通过我们app先获取一个正确时间,再拿这个时间去校准,而不是让openssl使用系统返回的时间。

修改openssl的库,让openssl提供一个可以设置校准时间的接口:

int SSL_connect_ptime(SSL *s, time_t ptime)
{
    if (ptime)
        X509_VERIFY_PARAM_set_time(s->param, ptime);

    return SSL_connect(s);
}

用过ssl的同学应该熟悉这个SSL_connect(),增加一个openssl的接口必须在util/libssl.num文件上加上你的函数名,注意后面的序号和版本号

 SSL_COMP_get_id                         412	1_1_0d	EXIST::FUNCTION:
 SSL_COMP_get0_name                      413	1_1_0d	EXIST::FUNCTION:
+SSL_connect_ptime                       414	1_1_0d	EXIST::FUNCTION:

FIXED & END

相关标签: openssl