SSL_library_init对于实际目的而言是不可重入的?

时间:2013-03-28 16:28:27

标签: c thread-safety openssl reentrancy

我正在使用openssl库打开某个服务器的TLS连接。阅读图书馆文档(是的,有些人还在阅读文档和手册页)我偶然发现了句子“SSL_libary_init()不是reentrant”。

我一般都明白什么是非重入函数:即一些函数以这样的方式保持内部状态:同时调用它两次或在执行时中断它可能会导致混乱(函数不执行调用者)期待着。)

但是在SSL_library_init()的特定情况下,我想知道它实际意味着什么。

  • 是否意味着如果在调用SSL_library_init()时发生某些中断,它将无法正确初始化SSL库?因此,我应该在调用它之前禁用所有可访问的中断并重新启用所需的中断吗?

  • 这是否意味着它的线程不安全,我应该确保两个线程不能同时调用它? (看起来很可能,即使线程安全与重入不完全相同)。

  • 这是否意味着我不应该在程序生命周期中调用它两次,或者在SSL连接打开时调用它会造成严重破坏?

我正在研究代理,一端是客户端而另一端是服务器,两端都可能正在使用TLS服务,(但我也可能只是一端,或者没有端)。我应该将SSL库作为系统范围的单例管理吗?如果是这种情况,它很容易管理,但它并不完全是一个重入问题,因为我理解这个词。

我不知道应该只调用一次的函数的简短词......

我对SSL_CTX_new()也有类似的问题。该文档声明它应该只在每个程序生命周期中调用一次。这很烦人,因为它似乎限制服务器和客户端(或在同一进程中运行的几个独立服务器或客户端实例)使用相同的SSL_METHOD并且感觉不对,但我仍然希望在这种情况下它只是一些文档不准确

有没有人有足够的openSSL经验来解释我应该或不应该使用OpenSSL初始化代码来保持安全?

1 个答案:

答案 0 :(得分:1)

我可以根据我所看到的内容给你一个提示。我有一个CentOS 7 / Django 1.9.3 / Apache 2.4 / mod_ssl / Python 3.4 Web服务器,它接收来自用户的https:连接。在处理请求时,服务器需要查询后端以获取满足请求所需的信息。后端查询在独立运行时工作正常,但它会生成:

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服务器上的命令行(在用户apache的WSGI目录中)运行时,该代码运行良好,但在Apache自己调用时会爆炸。