我使用OpenSSL库打开一些服务器的TLS连接。阅读图书馆的文档(是的,有些人仍然在阅读文档和手册页)我偶然发现了一句话“SSL-libary-init()不是reentrant”。
一般来说,我理解什么是不可重入函数(non-reentrant function):即某个函数以这样的方式保持一个内部状态,即同时调用它两次或在执行时中断它,可能会导致混乱(该函数不执行调用方所期望的操作)。
但在SSL_library_in it()的特定情况下,我想知道它实际上是什么意思。
这是否意味着,如果在调用SSL_library_init()时发生中断,它将无法正确初始化SSL库因此,我是否应该在调用之前禁用所有可访问的中断,并在以后重新启用所需的中断?
这是否意味着它是线程不安全的,并且我应该确保两个线程不能同时调用它(看起来很可能,即使线程安全并不完全意味着可重入)。
这是否意味着我不应该在程序生命周期中调用它两次,或者在SSL连接打开时调用它会造成严重破坏?
当我在处理一个一端是客户端,另一端是服务器的代理时,两端可能都在使用TLS服务(但我也可能只是一端,或者没有)我应该将SSL库作为一个系统范围的单例来管理吗如果是这样的话,管理起来就很容易了,但据我所知,这并不完全是一个可重复的问题。
我不知道一个函数的缩写应该只调用一次。。。
我对SSL_CTX_new()也有类似的问题文档说明,每个程序生命周期只应调用一次这很烦人,因为它似乎限制了服务器和客户机(或在同一进程中运行的几个独立服务器或客户机实例)使用同一SSL_方法,而且感觉不对,但我仍然希望在这种情况下,这只是一些文档不准确。
有没有人有足够的openSSL经验来解释我应该或不应该对openSSL初始化代码做些什么来保持安全?
最佳答案
我可以根据我所看到的给你一个提示我有一个CentOS 7/Django 1.9.3/Apache 2.4/mod_ssl/Python 3.4web服务器,它接收来自用户的https:connections处理请求时,服务器需要查询后端以获取满足请求所需的信息独立运行时,后端查询工作正常,但它会生成:
OSError(0, 'Error')
Line 810, /lib64/python3.4/ssl.py
803 def do_handshake(self, block=False):
804 """Perform a TLS/SSL handshake."""
805 self._check_connected()
806 timeout = self.gettimeout()
807 try:
808 if timeout == 0.0 and block:
809 self.settimeout(None)
810 self._sslobj.do_handshake() # <<<-------
在Apache WSGI上下文中运行时。
如果事实上mod_ssl导致了我的错误,这意味着库是线程安全的(因为Apache当然可以同时服务多个web请求),但不可重入的(因为ssl不能在一个线程中使用两次,例如用于前端和后端连接)。
当然,两层web服务器是一种成熟的设计模式,因此必须有一个解决方案感谢你发布了关于不可重入的信息——这是我发现的第一条可能是我问题的原因的线索。
作为参考,我的代码调用一个RESTful服务,该服务获取从SSL_CLIENT_CERT提取的用户可分辨名称,并以JSON格式返回用户属性:
import requests, urllib
URL = 'https://example.com/rest/user_info/'
def get_user_info(dn)
query = URL + urllib.parse.quote(dn)
return requests.get(query, cert=('server.crt', 'server.key'), verify='ca_bundle.crt').json()
当从web服务器上的命令行运行时(在WSGI目录中,用户是apache),该代码工作得很好,但是当apache自己调用时,它就会崩溃。