File indexing completed on 2025-06-30 08:08:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
0013 #define BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
0014
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif
0018
0019 #include <boost/asio/detail/config.hpp>
0020
0021 #include <cstring>
0022 #include <boost/asio/detail/throw_error.hpp>
0023 #include <boost/asio/error.hpp>
0024 #include <boost/asio/ssl/context.hpp>
0025 #include <boost/asio/ssl/error.hpp>
0026
0027 #include <boost/asio/detail/push_options.hpp>
0028
0029 namespace boost {
0030 namespace asio {
0031 namespace ssl {
0032
0033 struct context::bio_cleanup
0034 {
0035 BIO* p;
0036 ~bio_cleanup() { if (p) ::BIO_free(p); }
0037 };
0038
0039 struct context::x509_cleanup
0040 {
0041 X509* p;
0042 ~x509_cleanup() { if (p) ::X509_free(p); }
0043 };
0044
0045 struct context::evp_pkey_cleanup
0046 {
0047 EVP_PKEY* p;
0048 ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }
0049 };
0050
0051 #if (OPENSSL_VERSION_NUMBER < 0x30000000L)
0052 struct context::rsa_cleanup
0053 {
0054 RSA* p;
0055 ~rsa_cleanup() { if (p) ::RSA_free(p); }
0056 };
0057
0058 struct context::dh_cleanup
0059 {
0060 DH* p;
0061 ~dh_cleanup() { if (p) ::DH_free(p); }
0062 };
0063 #endif
0064
0065 context::context(context::method m)
0066 : handle_(0)
0067 {
0068 ::ERR_clear_error();
0069
0070 switch (m)
0071 {
0072
0073 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
0074 case context::sslv2:
0075 case context::sslv2_client:
0076 case context::sslv2_server:
0077 boost::asio::detail::throw_error(
0078 boost::asio::error::invalid_argument, "context");
0079 break;
0080 #else
0081 case context::sslv2:
0082 handle_ = ::SSL_CTX_new(::SSLv2_method());
0083 break;
0084 case context::sslv2_client:
0085 handle_ = ::SSL_CTX_new(::SSLv2_client_method());
0086 break;
0087 case context::sslv2_server:
0088 handle_ = ::SSL_CTX_new(::SSLv2_server_method());
0089 break;
0090 #endif
0091
0092
0093 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
0094 case context::sslv3:
0095 handle_ = ::SSL_CTX_new(::TLS_method());
0096 if (handle_)
0097 {
0098 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
0099 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
0100 }
0101 break;
0102 case context::sslv3_client:
0103 handle_ = ::SSL_CTX_new(::TLS_client_method());
0104 if (handle_)
0105 {
0106 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
0107 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
0108 }
0109 break;
0110 case context::sslv3_server:
0111 handle_ = ::SSL_CTX_new(::TLS_server_method());
0112 if (handle_)
0113 {
0114 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
0115 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
0116 }
0117 break;
0118 #elif defined(OPENSSL_NO_SSL3)
0119 case context::sslv3:
0120 case context::sslv3_client:
0121 case context::sslv3_server:
0122 boost::asio::detail::throw_error(
0123 boost::asio::error::invalid_argument, "context");
0124 break;
0125 #else
0126 case context::sslv3:
0127 handle_ = ::SSL_CTX_new(::SSLv3_method());
0128 break;
0129 case context::sslv3_client:
0130 handle_ = ::SSL_CTX_new(::SSLv3_client_method());
0131 break;
0132 case context::sslv3_server:
0133 handle_ = ::SSL_CTX_new(::SSLv3_server_method());
0134 break;
0135 #endif
0136
0137
0138 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
0139 case context::tlsv1:
0140 handle_ = ::SSL_CTX_new(::TLS_method());
0141 if (handle_)
0142 {
0143 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0144 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
0145 }
0146 break;
0147 case context::tlsv1_client:
0148 handle_ = ::SSL_CTX_new(::TLS_client_method());
0149 if (handle_)
0150 {
0151 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0152 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
0153 }
0154 break;
0155 case context::tlsv1_server:
0156 handle_ = ::SSL_CTX_new(::TLS_server_method());
0157 if (handle_)
0158 {
0159 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0160 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
0161 }
0162 break;
0163 #elif defined(SSL_TXT_TLSV1)
0164 case context::tlsv1:
0165 handle_ = ::SSL_CTX_new(::TLSv1_method());
0166 break;
0167 case context::tlsv1_client:
0168 handle_ = ::SSL_CTX_new(::TLSv1_client_method());
0169 break;
0170 case context::tlsv1_server:
0171 handle_ = ::SSL_CTX_new(::TLSv1_server_method());
0172 break;
0173 #else
0174 case context::tlsv1:
0175 case context::tlsv1_client:
0176 case context::tlsv1_server:
0177 boost::asio::detail::throw_error(
0178 boost::asio::error::invalid_argument, "context");
0179 break;
0180 #endif
0181
0182
0183 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
0184 case context::tlsv11:
0185 handle_ = ::SSL_CTX_new(::TLS_method());
0186 if (handle_)
0187 {
0188 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
0189 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
0190 }
0191 break;
0192 case context::tlsv11_client:
0193 handle_ = ::SSL_CTX_new(::TLS_client_method());
0194 if (handle_)
0195 {
0196 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
0197 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
0198 }
0199 break;
0200 case context::tlsv11_server:
0201 handle_ = ::SSL_CTX_new(::TLS_server_method());
0202 if (handle_)
0203 {
0204 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
0205 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
0206 }
0207 break;
0208 #elif defined(SSL_TXT_TLSV1_1)
0209 case context::tlsv11:
0210 handle_ = ::SSL_CTX_new(::TLSv1_1_method());
0211 break;
0212 case context::tlsv11_client:
0213 handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());
0214 break;
0215 case context::tlsv11_server:
0216 handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());
0217 break;
0218 #else
0219 case context::tlsv11:
0220 case context::tlsv11_client:
0221 case context::tlsv11_server:
0222 boost::asio::detail::throw_error(
0223 boost::asio::error::invalid_argument, "context");
0224 break;
0225 #endif
0226
0227
0228 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
0229 case context::tlsv12:
0230 handle_ = ::SSL_CTX_new(::TLS_method());
0231 if (handle_)
0232 {
0233 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
0234 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
0235 }
0236 break;
0237 case context::tlsv12_client:
0238 handle_ = ::SSL_CTX_new(::TLS_client_method());
0239 if (handle_)
0240 {
0241 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
0242 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
0243 }
0244 break;
0245 case context::tlsv12_server:
0246 handle_ = ::SSL_CTX_new(::TLS_server_method());
0247 if (handle_)
0248 {
0249 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
0250 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
0251 }
0252 break;
0253 #elif defined(SSL_TXT_TLSV1_2)
0254 case context::tlsv12:
0255 handle_ = ::SSL_CTX_new(::TLSv1_2_method());
0256 break;
0257 case context::tlsv12_client:
0258 handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());
0259 break;
0260 case context::tlsv12_server:
0261 handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
0262 break;
0263 #else
0264 case context::tlsv12:
0265 case context::tlsv12_client:
0266 case context::tlsv12_server:
0267 boost::asio::detail::throw_error(
0268 boost::asio::error::invalid_argument, "context");
0269 break;
0270 #endif
0271
0272
0273 #if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) \
0274 && !defined(LIBRESSL_VERSION_NUMBER)) \
0275 || defined(BOOST_ASIO_USE_WOLFSSL)
0276 case context::tlsv13:
0277 handle_ = ::SSL_CTX_new(::TLS_method());
0278 if (handle_)
0279 {
0280 SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);
0281 SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);
0282 }
0283 break;
0284 case context::tlsv13_client:
0285 handle_ = ::SSL_CTX_new(::TLS_client_method());
0286 if (handle_)
0287 {
0288 SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);
0289 SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);
0290 }
0291 break;
0292 case context::tlsv13_server:
0293 handle_ = ::SSL_CTX_new(::TLS_server_method());
0294 if (handle_)
0295 {
0296 SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);
0297 SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);
0298 }
0299 break;
0300 #else
0301
0302
0303 case context::tlsv13:
0304 case context::tlsv13_client:
0305 case context::tlsv13_server:
0306 boost::asio::detail::throw_error(
0307 boost::asio::error::invalid_argument, "context");
0308 break;
0309 #endif
0310
0311
0312
0313
0314 case context::sslv23:
0315 handle_ = ::SSL_CTX_new(::SSLv23_method());
0316 break;
0317 case context::sslv23_client:
0318 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
0319 break;
0320 case context::sslv23_server:
0321 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
0322 break;
0323
0324
0325 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
0326 case context::tls:
0327 handle_ = ::SSL_CTX_new(::TLS_method());
0328 if (handle_)
0329 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0330 break;
0331 case context::tls_client:
0332 handle_ = ::SSL_CTX_new(::TLS_client_method());
0333 if (handle_)
0334 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0335 break;
0336 case context::tls_server:
0337 handle_ = ::SSL_CTX_new(::TLS_server_method());
0338 if (handle_)
0339 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0340 break;
0341 #else
0342 case context::tls:
0343 handle_ = ::SSL_CTX_new(::SSLv23_method());
0344 if (handle_)
0345 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
0346 break;
0347 case context::tls_client:
0348 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
0349 if (handle_)
0350 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
0351 break;
0352 case context::tls_server:
0353 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
0354 if (handle_)
0355 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
0356 break;
0357 #endif
0358
0359 default:
0360 handle_ = ::SSL_CTX_new(0);
0361 break;
0362 }
0363
0364 if (handle_ == 0)
0365 {
0366 boost::system::error_code ec = translate_error(::ERR_get_error());
0367 boost::asio::detail::throw_error(ec, "context");
0368 }
0369
0370 set_options(no_compression);
0371 }
0372
0373 context::context(context::native_handle_type native_handle)
0374 : handle_(native_handle)
0375 {
0376 if (!handle_)
0377 {
0378 boost::asio::detail::throw_error(
0379 boost::asio::error::invalid_argument, "context");
0380 }
0381 }
0382
0383 context::context(context&& other)
0384 {
0385 handle_ = other.handle_;
0386 other.handle_ = 0;
0387 }
0388
0389 context& context::operator=(context&& other)
0390 {
0391 context tmp(static_cast<context&&>(*this));
0392 handle_ = other.handle_;
0393 other.handle_ = 0;
0394 return *this;
0395 }
0396
0397 context::~context()
0398 {
0399 if (handle_)
0400 {
0401 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0402 && (!defined(LIBRESSL_VERSION_NUMBER) \
0403 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0404 || defined(BOOST_ASIO_USE_WOLFSSL)
0405 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0406 #else
0407 void* cb_userdata = handle_->default_passwd_callback_userdata;
0408 #endif
0409 if (cb_userdata)
0410 {
0411 detail::password_callback_base* callback =
0412 static_cast<detail::password_callback_base*>(
0413 cb_userdata);
0414 delete callback;
0415 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0416 && (!defined(LIBRESSL_VERSION_NUMBER) \
0417 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0418 || defined(BOOST_ASIO_USE_WOLFSSL)
0419 ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
0420 #else
0421 handle_->default_passwd_callback_userdata = 0;
0422 #endif
0423 }
0424
0425 if (SSL_CTX_get_app_data(handle_))
0426 {
0427 detail::verify_callback_base* callback =
0428 static_cast<detail::verify_callback_base*>(
0429 SSL_CTX_get_app_data(handle_));
0430 delete callback;
0431 SSL_CTX_set_app_data(handle_, 0);
0432 }
0433
0434 ::SSL_CTX_free(handle_);
0435 }
0436 }
0437
0438 context::native_handle_type context::native_handle()
0439 {
0440 return handle_;
0441 }
0442
0443 void context::clear_options(context::options o)
0444 {
0445 boost::system::error_code ec;
0446 clear_options(o, ec);
0447 boost::asio::detail::throw_error(ec, "clear_options");
0448 }
0449
0450 BOOST_ASIO_SYNC_OP_VOID context::clear_options(
0451 context::options o, boost::system::error_code& ec)
0452 {
0453 #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
0454 && (OPENSSL_VERSION_NUMBER != 0x00909000L)
0455 # if !defined(SSL_OP_NO_COMPRESSION)
0456 if ((o & context::no_compression) != 0)
0457 {
0458 # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
0459 handle_->comp_methods = SSL_COMP_get_compression_methods();
0460 # endif
0461 o ^= context::no_compression;
0462 }
0463 # endif
0464
0465 ::SSL_CTX_clear_options(handle_, o);
0466
0467 ec = boost::system::error_code();
0468 #else
0469
0470 (void)o;
0471 ec = boost::asio::error::operation_not_supported;
0472 #endif
0473
0474 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0475 }
0476
0477 void context::set_options(context::options o)
0478 {
0479 boost::system::error_code ec;
0480 set_options(o, ec);
0481 boost::asio::detail::throw_error(ec, "set_options");
0482 }
0483
0484 BOOST_ASIO_SYNC_OP_VOID context::set_options(
0485 context::options o, boost::system::error_code& ec)
0486 {
0487 #if !defined(SSL_OP_NO_COMPRESSION)
0488 if ((o & context::no_compression) != 0)
0489 {
0490 #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
0491 handle_->comp_methods =
0492 boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
0493 #endif
0494 o ^= context::no_compression;
0495 }
0496 #endif
0497
0498 ::SSL_CTX_set_options(handle_, o);
0499
0500 ec = boost::system::error_code();
0501 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0502 }
0503
0504 void context::set_verify_mode(verify_mode v)
0505 {
0506 boost::system::error_code ec;
0507 set_verify_mode(v, ec);
0508 boost::asio::detail::throw_error(ec, "set_verify_mode");
0509 }
0510
0511 BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
0512 verify_mode v, boost::system::error_code& ec)
0513 {
0514 ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
0515
0516 ec = boost::system::error_code();
0517 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0518 }
0519
0520 void context::set_verify_depth(int depth)
0521 {
0522 boost::system::error_code ec;
0523 set_verify_depth(depth, ec);
0524 boost::asio::detail::throw_error(ec, "set_verify_depth");
0525 }
0526
0527 BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
0528 int depth, boost::system::error_code& ec)
0529 {
0530 ::SSL_CTX_set_verify_depth(handle_, depth);
0531
0532 ec = boost::system::error_code();
0533 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0534 }
0535
0536 void context::load_verify_file(const std::string& filename)
0537 {
0538 boost::system::error_code ec;
0539 load_verify_file(filename, ec);
0540 boost::asio::detail::throw_error(ec, "load_verify_file");
0541 }
0542
0543 BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
0544 const std::string& filename, boost::system::error_code& ec)
0545 {
0546 ::ERR_clear_error();
0547
0548 if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
0549 {
0550 ec = translate_error(::ERR_get_error());
0551 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0552 }
0553
0554 ec = boost::system::error_code();
0555 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0556 }
0557
0558 void context::add_certificate_authority(const const_buffer& ca)
0559 {
0560 boost::system::error_code ec;
0561 add_certificate_authority(ca, ec);
0562 boost::asio::detail::throw_error(ec, "add_certificate_authority");
0563 }
0564
0565 BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
0566 const const_buffer& ca, boost::system::error_code& ec)
0567 {
0568 ::ERR_clear_error();
0569
0570 bio_cleanup bio = { make_buffer_bio(ca) };
0571 if (bio.p)
0572 {
0573 if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
0574 {
0575 for (bool added = false;; added = true)
0576 {
0577 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
0578 if (!cert.p)
0579 {
0580 unsigned long err = ::ERR_get_error();
0581 if (added && ERR_GET_LIB(err) == ERR_LIB_PEM
0582 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
0583 break;
0584
0585 ec = translate_error(err);
0586 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0587 }
0588
0589 if (::X509_STORE_add_cert(store, cert.p) != 1)
0590 {
0591 ec = translate_error(::ERR_get_error());
0592 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0593 }
0594 }
0595 }
0596 }
0597
0598 ec = boost::system::error_code();
0599 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0600 }
0601
0602 void context::set_default_verify_paths()
0603 {
0604 boost::system::error_code ec;
0605 set_default_verify_paths(ec);
0606 boost::asio::detail::throw_error(ec, "set_default_verify_paths");
0607 }
0608
0609 BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
0610 boost::system::error_code& ec)
0611 {
0612 ::ERR_clear_error();
0613
0614 if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
0615 {
0616 ec = translate_error(::ERR_get_error());
0617 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0618 }
0619
0620 ec = boost::system::error_code();
0621 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0622 }
0623
0624 void context::add_verify_path(const std::string& path)
0625 {
0626 boost::system::error_code ec;
0627 add_verify_path(path, ec);
0628 boost::asio::detail::throw_error(ec, "add_verify_path");
0629 }
0630
0631 BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
0632 const std::string& path, boost::system::error_code& ec)
0633 {
0634 ::ERR_clear_error();
0635
0636 if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
0637 {
0638 ec = translate_error(::ERR_get_error());
0639 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0640 }
0641
0642 ec = boost::system::error_code();
0643 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0644 }
0645
0646 void context::use_certificate(
0647 const const_buffer& certificate, file_format format)
0648 {
0649 boost::system::error_code ec;
0650 use_certificate(certificate, format, ec);
0651 boost::asio::detail::throw_error(ec, "use_certificate");
0652 }
0653
0654 BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
0655 const const_buffer& certificate, file_format format,
0656 boost::system::error_code& ec)
0657 {
0658 ::ERR_clear_error();
0659
0660 if (format == context_base::asn1)
0661 {
0662 if (::SSL_CTX_use_certificate_ASN1(handle_,
0663 static_cast<int>(certificate.size()),
0664 static_cast<const unsigned char*>(certificate.data())) == 1)
0665 {
0666 ec = boost::system::error_code();
0667 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0668 }
0669 }
0670 else if (format == context_base::pem)
0671 {
0672 bio_cleanup bio = { make_buffer_bio(certificate) };
0673 if (bio.p)
0674 {
0675 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
0676 if (cert.p)
0677 {
0678 if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
0679 {
0680 ec = boost::system::error_code();
0681 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0682 }
0683 }
0684 }
0685 }
0686 else
0687 {
0688 ec = boost::asio::error::invalid_argument;
0689 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0690 }
0691
0692 ec = translate_error(::ERR_get_error());
0693 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0694 }
0695
0696 void context::use_certificate_file(
0697 const std::string& filename, file_format format)
0698 {
0699 boost::system::error_code ec;
0700 use_certificate_file(filename, format, ec);
0701 boost::asio::detail::throw_error(ec, "use_certificate_file");
0702 }
0703
0704 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
0705 const std::string& filename, file_format format,
0706 boost::system::error_code& ec)
0707 {
0708 int file_type;
0709 switch (format)
0710 {
0711 case context_base::asn1:
0712 file_type = SSL_FILETYPE_ASN1;
0713 break;
0714 case context_base::pem:
0715 file_type = SSL_FILETYPE_PEM;
0716 break;
0717 default:
0718 {
0719 ec = boost::asio::error::invalid_argument;
0720 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0721 }
0722 }
0723
0724 ::ERR_clear_error();
0725
0726 if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
0727 {
0728 ec = translate_error(::ERR_get_error());
0729 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0730 }
0731
0732 ec = boost::system::error_code();
0733 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0734 }
0735
0736 void context::use_certificate_chain(const const_buffer& chain)
0737 {
0738 boost::system::error_code ec;
0739 use_certificate_chain(chain, ec);
0740 boost::asio::detail::throw_error(ec, "use_certificate_chain");
0741 }
0742
0743 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
0744 const const_buffer& chain, boost::system::error_code& ec)
0745 {
0746 ::ERR_clear_error();
0747
0748 bio_cleanup bio = { make_buffer_bio(chain) };
0749 if (bio.p)
0750 {
0751 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0752 && (!defined(LIBRESSL_VERSION_NUMBER) \
0753 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0754 || defined(BOOST_ASIO_USE_WOLFSSL)
0755 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
0756 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0757 #else
0758 pem_password_cb* callback = handle_->default_passwd_callback;
0759 void* cb_userdata = handle_->default_passwd_callback_userdata;
0760 #endif
0761 x509_cleanup cert = {
0762 ::PEM_read_bio_X509_AUX(bio.p, 0,
0763 callback,
0764 cb_userdata) };
0765 if (!cert.p)
0766 {
0767 ec = translate_error(ERR_R_PEM_LIB);
0768 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0769 }
0770
0771 int result = ::SSL_CTX_use_certificate(handle_, cert.p);
0772 if (result == 0 || ::ERR_peek_error() != 0)
0773 {
0774 ec = translate_error(::ERR_get_error());
0775 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0776 }
0777
0778 #if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \
0779 && (!defined(LIBRESSL_VERSION_NUMBER) \
0780 || LIBRESSL_VERSION_NUMBER >= 0x2090100fL)) \
0781 || defined(BOOST_ASIO_USE_WOLFSSL)
0782 ::SSL_CTX_clear_chain_certs(handle_);
0783 #else
0784 if (handle_->extra_certs)
0785 {
0786 ::sk_X509_pop_free(handle_->extra_certs, X509_free);
0787 handle_->extra_certs = 0;
0788 }
0789 #endif
0790
0791 while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
0792 callback,
0793 cb_userdata))
0794 {
0795 if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
0796 {
0797 ec = translate_error(::ERR_get_error());
0798 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0799 }
0800 }
0801
0802 result = ::ERR_peek_last_error();
0803 if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
0804 && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
0805 {
0806 ::ERR_clear_error();
0807 ec = boost::system::error_code();
0808 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0809 }
0810 }
0811
0812 ec = translate_error(::ERR_get_error());
0813 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0814 }
0815
0816 void context::use_certificate_chain_file(const std::string& filename)
0817 {
0818 boost::system::error_code ec;
0819 use_certificate_chain_file(filename, ec);
0820 boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
0821 }
0822
0823 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
0824 const std::string& filename, boost::system::error_code& ec)
0825 {
0826 ::ERR_clear_error();
0827
0828 if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
0829 {
0830 ec = translate_error(::ERR_get_error());
0831 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0832 }
0833
0834 ec = boost::system::error_code();
0835 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0836 }
0837
0838 void context::use_private_key(
0839 const const_buffer& private_key, context::file_format format)
0840 {
0841 boost::system::error_code ec;
0842 use_private_key(private_key, format, ec);
0843 boost::asio::detail::throw_error(ec, "use_private_key");
0844 }
0845
0846 BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
0847 const const_buffer& private_key, context::file_format format,
0848 boost::system::error_code& ec)
0849 {
0850 ::ERR_clear_error();
0851
0852 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0853 && (!defined(LIBRESSL_VERSION_NUMBER) \
0854 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0855 || defined(BOOST_ASIO_USE_WOLFSSL)
0856 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
0857 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0858 #else
0859 pem_password_cb* callback = handle_->default_passwd_callback;
0860 void* cb_userdata = handle_->default_passwd_callback_userdata;
0861 #endif
0862
0863 bio_cleanup bio = { make_buffer_bio(private_key) };
0864 if (bio.p)
0865 {
0866 evp_pkey_cleanup evp_private_key = { 0 };
0867 switch (format)
0868 {
0869 case context_base::asn1:
0870 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
0871 break;
0872 case context_base::pem:
0873 evp_private_key.p = ::PEM_read_bio_PrivateKey(
0874 bio.p, 0, callback,
0875 cb_userdata);
0876 break;
0877 default:
0878 {
0879 ec = boost::asio::error::invalid_argument;
0880 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0881 }
0882 }
0883
0884 if (evp_private_key.p)
0885 {
0886 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
0887 {
0888 ec = boost::system::error_code();
0889 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0890 }
0891 }
0892 }
0893
0894 ec = translate_error(::ERR_get_error());
0895 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0896 }
0897
0898 void context::use_private_key_file(
0899 const std::string& filename, context::file_format format)
0900 {
0901 boost::system::error_code ec;
0902 use_private_key_file(filename, format, ec);
0903 boost::asio::detail::throw_error(ec, "use_private_key_file");
0904 }
0905
0906 void context::use_rsa_private_key(
0907 const const_buffer& private_key, context::file_format format)
0908 {
0909 boost::system::error_code ec;
0910 use_rsa_private_key(private_key, format, ec);
0911 boost::asio::detail::throw_error(ec, "use_rsa_private_key");
0912 }
0913
0914 BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
0915 const const_buffer& private_key, context::file_format format,
0916 boost::system::error_code& ec)
0917 {
0918 ::ERR_clear_error();
0919
0920 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0921 && (!defined(LIBRESSL_VERSION_NUMBER) \
0922 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0923 || defined(BOOST_ASIO_USE_WOLFSSL)
0924 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
0925 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0926 #else
0927 pem_password_cb* callback = handle_->default_passwd_callback;
0928 void* cb_userdata = handle_->default_passwd_callback_userdata;
0929 #endif
0930
0931 bio_cleanup bio = { make_buffer_bio(private_key) };
0932 if (bio.p)
0933 {
0934 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
0935 evp_pkey_cleanup evp_private_key = { 0 };
0936 switch (format)
0937 {
0938 case context_base::asn1:
0939 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
0940 break;
0941 case context_base::pem:
0942 evp_private_key.p = ::PEM_read_bio_PrivateKey(
0943 bio.p, 0, callback,
0944 cb_userdata);
0945 break;
0946 default:
0947 {
0948 ec = boost::asio::error::invalid_argument;
0949 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0950 }
0951 }
0952
0953 if (evp_private_key.p)
0954 {
0955 if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)
0956 {
0957 ec = translate_error(
0958 ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));
0959 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0960 }
0961
0962 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
0963 {
0964 ec = boost::system::error_code();
0965 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0966 }
0967 }
0968 #else
0969 rsa_cleanup rsa_private_key = { 0 };
0970 switch (format)
0971 {
0972 case context_base::asn1:
0973 rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
0974 break;
0975 case context_base::pem:
0976 rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
0977 bio.p, 0, callback,
0978 cb_userdata);
0979 break;
0980 default:
0981 {
0982 ec = boost::asio::error::invalid_argument;
0983 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0984 }
0985 }
0986
0987 if (rsa_private_key.p)
0988 {
0989 if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
0990 {
0991 ec = boost::system::error_code();
0992 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0993 }
0994 }
0995 #endif
0996 }
0997
0998 ec = translate_error(::ERR_get_error());
0999 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1000 }
1001
1002 BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file(
1003 const std::string& filename, context::file_format format,
1004 boost::system::error_code& ec)
1005 {
1006 int file_type;
1007 switch (format)
1008 {
1009 case context_base::asn1:
1010 file_type = SSL_FILETYPE_ASN1;
1011 break;
1012 case context_base::pem:
1013 file_type = SSL_FILETYPE_PEM;
1014 break;
1015 default:
1016 {
1017 ec = boost::asio::error::invalid_argument;
1018 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1019 }
1020 }
1021
1022 ::ERR_clear_error();
1023
1024 if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
1025 {
1026 ec = translate_error(::ERR_get_error());
1027 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1028 }
1029
1030 ec = boost::system::error_code();
1031 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1032 }
1033
1034 void context::use_rsa_private_key_file(
1035 const std::string& filename, context::file_format format)
1036 {
1037 boost::system::error_code ec;
1038 use_rsa_private_key_file(filename, format, ec);
1039 boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
1040 }
1041
1042 BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(
1043 const std::string& filename, context::file_format format,
1044 boost::system::error_code& ec)
1045 {
1046 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1047 ::ERR_clear_error();
1048
1049 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
1050 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
1051
1052 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
1053 if (bio.p)
1054 {
1055 evp_pkey_cleanup evp_private_key = { 0 };
1056 switch (format)
1057 {
1058 case context_base::asn1:
1059 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
1060 break;
1061 case context_base::pem:
1062 evp_private_key.p = ::PEM_read_bio_PrivateKey(
1063 bio.p, 0, callback,
1064 cb_userdata);
1065 break;
1066 default:
1067 {
1068 ec = boost::asio::error::invalid_argument;
1069 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1070 }
1071 }
1072
1073 if (evp_private_key.p)
1074 {
1075 if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)
1076 {
1077 ec = translate_error(
1078 ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));
1079 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1080 }
1081
1082 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
1083 {
1084 ec = boost::system::error_code();
1085 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1086 }
1087 }
1088 }
1089
1090 ec = translate_error(::ERR_get_error());
1091 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1092 #else
1093 int file_type;
1094 switch (format)
1095 {
1096 case context_base::asn1:
1097 file_type = SSL_FILETYPE_ASN1;
1098 break;
1099 case context_base::pem:
1100 file_type = SSL_FILETYPE_PEM;
1101 break;
1102 default:
1103 {
1104 ec = boost::asio::error::invalid_argument;
1105 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1106 }
1107 }
1108
1109 ::ERR_clear_error();
1110
1111 if (::SSL_CTX_use_RSAPrivateKey_file(
1112 handle_, filename.c_str(), file_type) != 1)
1113 {
1114 ec = translate_error(::ERR_get_error());
1115 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1116 }
1117
1118 ec = boost::system::error_code();
1119 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1120 #endif
1121 }
1122
1123 void context::use_tmp_dh(const const_buffer& dh)
1124 {
1125 boost::system::error_code ec;
1126 use_tmp_dh(dh, ec);
1127 boost::asio::detail::throw_error(ec, "use_tmp_dh");
1128 }
1129
1130 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
1131 const const_buffer& dh, boost::system::error_code& ec)
1132 {
1133 ::ERR_clear_error();
1134
1135 bio_cleanup bio = { make_buffer_bio(dh) };
1136 if (bio.p)
1137 {
1138 return do_use_tmp_dh(bio.p, ec);
1139 }
1140
1141 ec = translate_error(::ERR_get_error());
1142 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1143 }
1144
1145 void context::use_tmp_dh_file(const std::string& filename)
1146 {
1147 boost::system::error_code ec;
1148 use_tmp_dh_file(filename, ec);
1149 boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
1150 }
1151
1152 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
1153 const std::string& filename, boost::system::error_code& ec)
1154 {
1155 ::ERR_clear_error();
1156
1157 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
1158 if (bio.p)
1159 {
1160 return do_use_tmp_dh(bio.p, ec);
1161 }
1162
1163 ec = translate_error(::ERR_get_error());
1164 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1165 }
1166
1167 BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
1168 BIO* bio, boost::system::error_code& ec)
1169 {
1170 ::ERR_clear_error();
1171
1172 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1173 EVP_PKEY* p = ::PEM_read_bio_Parameters(bio, 0);
1174 if (p)
1175 {
1176 if (::SSL_CTX_set0_tmp_dh_pkey(handle_, p) == 1)
1177 {
1178 ec = boost::system::error_code();
1179 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1180 }
1181 else
1182 ::EVP_PKEY_free(p);
1183 }
1184 #else
1185 dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
1186 if (dh.p)
1187 {
1188 if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
1189 {
1190 ec = boost::system::error_code();
1191 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1192 }
1193 }
1194 #endif
1195
1196 ec = translate_error(::ERR_get_error());
1197 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1198 }
1199
1200 BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
1201 detail::verify_callback_base* callback, boost::system::error_code& ec)
1202 {
1203 if (SSL_CTX_get_app_data(handle_))
1204 {
1205 delete static_cast<detail::verify_callback_base*>(
1206 SSL_CTX_get_app_data(handle_));
1207 }
1208
1209 SSL_CTX_set_app_data(handle_, callback);
1210
1211 ::SSL_CTX_set_verify(handle_,
1212 ::SSL_CTX_get_verify_mode(handle_),
1213 &context::verify_callback_function);
1214
1215 ec = boost::system::error_code();
1216 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1217 }
1218
1219 int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
1220 {
1221 if (ctx)
1222 {
1223 if (SSL* ssl = static_cast<SSL*>(
1224 ::X509_STORE_CTX_get_ex_data(
1225 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
1226 {
1227 if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
1228 {
1229 if (SSL_CTX_get_app_data(handle))
1230 {
1231 detail::verify_callback_base* callback =
1232 static_cast<detail::verify_callback_base*>(
1233 SSL_CTX_get_app_data(handle));
1234
1235 verify_context verify_ctx(ctx);
1236 return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
1237 }
1238 }
1239 }
1240 }
1241
1242 return 0;
1243 }
1244
1245 BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
1246 detail::password_callback_base* callback, boost::system::error_code& ec)
1247 {
1248 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
1249 && (!defined(LIBRESSL_VERSION_NUMBER) \
1250 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
1251 || defined(BOOST_ASIO_USE_WOLFSSL)
1252 void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
1253 ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
1254 #else
1255 void* old_callback = handle_->default_passwd_callback_userdata;
1256 handle_->default_passwd_callback_userdata = callback;
1257 #endif
1258
1259 if (old_callback)
1260 delete static_cast<detail::password_callback_base*>(
1261 old_callback);
1262
1263 SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
1264
1265 ec = boost::system::error_code();
1266 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1267 }
1268
1269 int context::password_callback_function(
1270 char* buf, int size, int purpose, void* data)
1271 {
1272 using namespace std;
1273
1274 if (data)
1275 {
1276 detail::password_callback_base* callback =
1277 static_cast<detail::password_callback_base*>(data);
1278
1279 std::string passwd = callback->call(static_cast<std::size_t>(size),
1280 purpose ? context_base::for_writing : context_base::for_reading);
1281
1282 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
1283 strcpy_s(buf, size, passwd.c_str());
1284 #else
1285 *buf = '\0';
1286 if (size > 0)
1287 strncat(buf, passwd.c_str(), size - 1);
1288 #endif
1289
1290 return static_cast<int>(strlen(buf));
1291 }
1292
1293 return 0;
1294 }
1295
1296 BIO* context::make_buffer_bio(const const_buffer& b)
1297 {
1298 return ::BIO_new_mem_buf(
1299 const_cast<void*>(b.data()),
1300 static_cast<int>(b.size()));
1301 }
1302
1303 boost::system::error_code context::translate_error(long error)
1304 {
1305 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1306 if (ERR_SYSTEM_ERROR(error))
1307 {
1308 return boost::system::error_code(
1309 static_cast<int>(ERR_GET_REASON(error)),
1310 boost::asio::error::get_system_category());
1311 }
1312 #endif
1313
1314 return boost::system::error_code(static_cast<int>(error),
1315 boost::asio::error::get_ssl_category());
1316 }
1317
1318 }
1319 }
1320 }
1321
1322 #include <boost/asio/detail/pop_options.hpp>
1323
1324 #endif