LoginSignup
3
2

More than 5 years have passed since last update.

LibreSSL と Boost.ASIO.SSL を組み合わせて使う事になった場合に ::SSL_CTX_get_default_passwd_cb_userdata 等複数箇所で翻訳時エラーが生じてしまう場合の応急対処法

Last updated at Posted at 2017-01-05

問題

LibreSSL と Boost.ASIO.SSL を組み合わせて使う事になった場合に ::SSL_CTX_get_default_passwd_cb_userdata 等複数箇所で翻訳時エラーが生じてしまう。

発生条件

以下の組み合わせにより発生する。

  1. LibreSSL を使用したい
    • 執筆時点の最新版は 2.5.0, 2.4.4 、あるいはそれ以降も対応されない可能性あり。
  2. Boost.ASIO.SSL を使用したい。
    • Boost-1.61以降執筆現在最新1.63まで、あるいはそれ以降も対応されない可能性あり。

現象

翻訳時エラーが発生する。Boost.ASIO.SSL

...include/boost/asio/ssl/impl/context.ipp: In destructor 'boost::asio::ssl::context::~context()':
.../include/boost/asio/ssl/impl/context.ipp:232:25: error: '::SSL_CTX_get_default_passwd_cb_userdata' has not been declared
     void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
                         ^~

類似のエラーが大量に発生する。

原因

Boost.ASIO.SSL の以下のコミットから asio/ssl/impl/context.hpp などのソースコード複数について OPENSSL_VERSION_NUMBER によるプリプロセッサーレベルの分岐処理が導入され、 OpenSSL-1.1 系の API への対応が追加された。

#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
    void* cb_userdata = handle_->default_passwd_callback_userdata;
#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) \
    && (OPENSSL_VERSION_NUMBER < 0x10100000L)
    ::SSL_COMP_free_compression_methods();
#endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)

OpenSSL では OPENSSL_VERSION_NUMBER0x10100000L 未満か否かによって OpenSSL-1.1 系の API を使用可能か判別できる。

# define OPENSSL_VERSION_NUMBER  0x10100040L
# ifdef OPENSSL_FIPS
#  define OPENSSL_VERSION_TEXT    "OpenSSL 1.1.0d-fips-dev  xx XXX xxxx"
# else
#  define OPENSSL_VERSION_TEXT    "OpenSSL 1.1.0d-dev  xx XXX xxxx"
# endif

一方、 LibreSSL-2.4/2.5 系では openssl/opensslv.hOPENSSL_VERSION_NUMBER0x20000000L と LibreSSL または互換の OpenSSL の API とは連動せず固定値で定義している。

/* These will never change */
#define OPENSSL_VERSION_NUMBER  0x20000000L
#define OPENSSL_VERSION_TEXT    LIBRESSL_VERSION_TEXT
#define OPENSSL_VERSION_PTEXT   " part of " OPENSSL_VERSION_TEXT

また、 LibreSSL-2.4/2.5 は OpenSSL-1.1 系の API に対応していない。

よって、 LibreSSL-2.4/2.5 と Boost-1.61/1.62/1.63.ASIO.SSL を組み合わせると、 Boost.ASIO.SSL のソースコード中から OpenSSL-1.1 系の API を使用するコードがプリプロセッサーレベルで有効となり、 OpenSSL-1.1 系の API に未対応の LibreSSL-2.4/2.5 ではその API が未定義で使用できないため、翻訳時エラーとなる。

余談: LibreSSL のバージョン情報

原因と直接は関係しないが、 LibreSSL のバージョン情報をプリプロセッサーで取得したい場合は、 openssl/opensslv.h に次の LibreSSL 独自の定義が追加されているのでこちらを使用できる。

#define LIBRESSL_VERSION_NUMBER       0x2030200fL
#define LIBRESSL_VERSION_TEXT "LibreSSL 2.3.2"

応急対処法

Boost.ASIO.SSL のヘッダーインクルード前後で OPENSSL_VERSION_NUMBER を偽装する事で比較的簡単に応急対処できる。

/// @brief LibreSSL と Boost.ASIO.SSL の OpenSSL-1.1 API 対応判定の偽装処理
/// @ref http://qiita.com/usagi/items/acee410849ca8f4f9c11
/// @{
#if LIBRESSL_VERSION_NUMBER <= 0x2050100fL
  #include <openssl/opensslv.h>
  #undef OPENSSL_VERSION_NUMBER
  #define OPENSSL_VERSION_NUMBER 0x10001fffL
#endif
/// @}

#include <boost/asio/ssl.hpp>

注意

  • この記事で紹介する対処方法は「応急」である事を理解して施し、適切な保守を行う必要がある。
3
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2