2

我正在使用 openssl 库打开与某个服务器的 TLS 连接。阅读库文档(是的,有些人仍然阅读文档和手册页)我偶然发现了“SSL_libary_init() 不是可重入的”这句话。

我一般理解什么是不可重入函数:即某些函数以这样的方式保持内部状态,即同时调用它两次或在执行时中断它可能会导致混乱(该函数没有按照调用者的期望执行) .

但在 SSL_library_init() 的特定情况下,我想知道它的实际含义。

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

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

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

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

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

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

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

4

1 回答 1

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 服务器上的命令行运行时(在 WSGI 目录中以用户 apache 身份运行)完美运行,但在被 Apache 本身调用时会崩溃。

于 2016-04-05T18:13:47.477 回答