c++ - boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) undefined symbol

标签 c++ macos ssl boost

我正在运行 OSX Yosemite 10.10.5,带有 clang-700.0.72 和安装了 boost 1.56 的brew。

我正在将 boost::asio 用于非 ssl 和 tls 套接字。 这些有问题的行不在我的项目中,但似乎源自 boost 1.56 本身。

我使用 cmake,并且使用 find_package(需要 OpenSSL) 与 openssl 链接,并且我确实有 openssl 1.0.2g

该项目使用 C++11,有问题的行似乎是:

体系结构 x86_64 的 undefined symbol : “_SSLv2_client_method”,引用自: asio_tls.cpp.o 中的 boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) “_SSLv2_method”,引用自: asio_tls.cpp.o 中的 boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) “_SSLv2_server_method”,引用自: asio_tls.cpp.o 中的 boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) ld:未找到架构 x86_64 的符号

我根本不使用 SSLv2,事实上代码只专注于使用 TLS v2:

class asio_socket_https
{
public:
    asio_socket_https(const std::string token)
    : ctx_(boost::asio::ssl::context::tlsv12_client), token_(token)
    {}

稍后,在初始化套接字和上下文时,我会:

ctx_.set_options(boost::asio::ssl::context::default_workarounds
                |boost::asio::ssl::context::no_sslv2
                |boost::asio::ssl::context::no_sslv3
                |boost::asio::ssl::context::no_tlsv1
                |boost::asio::ssl::context::single_dh_use);

我没有编译错误,应用程序链接到 libssl/libcrypto,并且我没有在 Linux 下测试它(仅限 OSX)。

我看到了一个具有相同主题但没有答案的问题 here .

实际链接标志:

/usr/bin/g++ -std=c++11 -Wall -g -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/asio_tls.dir/examples/asio_tls.cpp.o -o asio_tls librapp.0.2.dylib/usr/local/lib/libboost_system-mt.dylib/usr/local/lib/libboost_thread-mt.dylib/usr/local/lib/libboost_random-mt.dylib/usr/local/lib/libboost_unit_test_framework-mt.dylib/usr/local/lib/libboost_program_options-mt.dylib/usr/local/Cellar/openssl/1.0.2g/lib/libssl.dylib/usr/local/Cellar/openssl/1.0.2g/lib/libcrypto.dylib

编辑

我今天在 Ubuntu 14.04 下测试了相同的代码,在检测 openssl 1.0.1f 时它构建得很好(完全没有问题)。 这开始看起来像是 OSX 特有的问题。

@rhashimoto 似乎是正确的,而链接器在 /usr/local/Cellar/openssl/ 中使用 Cellar 版本的 openssl,所使用的 header 位于 /usr/local/下openssl 我认为它与brew 管理的不一样。

解决方案

问题出在我的 CMakeLists.txt 中,我以为 find_package(OpenSSL REQUIRED) 就足够了,不幸的是,这破坏了链接库的版本导入的库头文件。

默认库是 OSX 的 openssl,而我使用 ${OPENSSL_LIBRARIES} 显式链接。

只需添加以下内容即可解决问题(现在它使用从 brew 安装的 openssl):

find_package(OpenSSL REQUIRED)
if (OPENSSL_FOUND)
    include_directories(${OPENSSL_INCLUDE_DIR})
endif()

然后执行target_link_libraries(... ${OPENSSL_LIBRARIES})

最佳答案

Boost Asio 确实在 boost/asio/ssl/impl/context.ipp 中使用了 SSLv2_client_method()SSLv2_server_method() ,条件是缺少预处理器符号OPENSSL_NO_SSL2:

#if defined(OPENSSL_NO_SSL2)
  case context::sslv2:
  case context::sslv2_client:
  case context::sslv2_server:
    boost::asio::detail::throw_error(
        boost::asio::error::invalid_argument, "context");
    break;
#else // defined(OPENSSL_NO_SSL2)
  case context::sslv2:
    handle_ = ::SSL_CTX_new(::SSLv2_method());
    break;
  case context::sslv2_client:
    handle_ = ::SSL_CTX_new(::SSLv2_client_method());
    break;
  case context::sslv2_server:
    handle_ = ::SSL_CTX_new(::SSLv2_server_method());
    break;
#endif // defined(OPENSSL_NO_SSL2)

OPENSSL_NO_SSL2 如果您的 OpenSSL 库 header 不包含对 SSLv2 的支持,则应在该 header 中进行定义,但显然您的构建并未采用它。

对这种行为的一种常见解释是,您正在使用仍然支持 SSLv2 的 OpenSSL 库中的 header 进行编译,并链接到另一个不支持 SSLv2 的 OpenSSL 库中的二进制文件。将 -H 标志插入到编译器选项中可能会有所帮助,该选项将在处理时记录 header 路径,以便您可以验证正在使用哪些 header 。

关于c++ - boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36626031/

相关文章:

c++ - 根据与相机的距离调整点 Sprite 的大小

c++ - 使用正则表达式匹配函数定义

ssl - Github 如何在允许通过 Markdown 显示图片的情况下维护 https?

apache - 如何在代理后面隐藏弱 SSL?

c++ - clang AST : extern LinkageSpec issue

c++ - 如何将 unique_ptr 与 c 库中分配的数据一起使用?

ios - 在设备上的应用程序上运行泄漏命令行工具

macos - 如何监听系统范围的打开和保存面板事件?

macos - 请求用户访问 `root` 以更新 `/etc/paths.d`

c# - 比较 bouncycaSTLe x509 与 x509certificate2