File indexing completed on 2025-01-18 09:29:02
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 case context::tlsv13:
0276 handle_ = ::SSL_CTX_new(::TLS_method());
0277 if (handle_)
0278 {
0279 SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);
0280 SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);
0281 }
0282 break;
0283 case context::tlsv13_client:
0284 handle_ = ::SSL_CTX_new(::TLS_client_method());
0285 if (handle_)
0286 {
0287 SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);
0288 SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);
0289 }
0290 break;
0291 case context::tlsv13_server:
0292 handle_ = ::SSL_CTX_new(::TLS_server_method());
0293 if (handle_)
0294 {
0295 SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);
0296 SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);
0297 }
0298 break;
0299 #else
0300
0301 case context::tlsv13:
0302 case context::tlsv13_client:
0303 case context::tlsv13_server:
0304 boost::asio::detail::throw_error(
0305 boost::asio::error::invalid_argument, "context");
0306 break;
0307 #endif
0308
0309
0310
0311 case context::sslv23:
0312 handle_ = ::SSL_CTX_new(::SSLv23_method());
0313 break;
0314 case context::sslv23_client:
0315 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
0316 break;
0317 case context::sslv23_server:
0318 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
0319 break;
0320
0321
0322 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
0323 case context::tls:
0324 handle_ = ::SSL_CTX_new(::TLS_method());
0325 if (handle_)
0326 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0327 break;
0328 case context::tls_client:
0329 handle_ = ::SSL_CTX_new(::TLS_client_method());
0330 if (handle_)
0331 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0332 break;
0333 case context::tls_server:
0334 handle_ = ::SSL_CTX_new(::TLS_server_method());
0335 if (handle_)
0336 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
0337 break;
0338 #else
0339 case context::tls:
0340 handle_ = ::SSL_CTX_new(::SSLv23_method());
0341 if (handle_)
0342 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
0343 break;
0344 case context::tls_client:
0345 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
0346 if (handle_)
0347 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
0348 break;
0349 case context::tls_server:
0350 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
0351 if (handle_)
0352 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
0353 break;
0354 #endif
0355
0356 default:
0357 handle_ = ::SSL_CTX_new(0);
0358 break;
0359 }
0360
0361 if (handle_ == 0)
0362 {
0363 boost::system::error_code ec = translate_error(::ERR_get_error());
0364 boost::asio::detail::throw_error(ec, "context");
0365 }
0366
0367 set_options(no_compression);
0368 }
0369
0370 context::context(context::native_handle_type native_handle)
0371 : handle_(native_handle)
0372 {
0373 if (!handle_)
0374 {
0375 boost::asio::detail::throw_error(
0376 boost::asio::error::invalid_argument, "context");
0377 }
0378 }
0379
0380 context::context(context&& other)
0381 {
0382 handle_ = other.handle_;
0383 other.handle_ = 0;
0384 }
0385
0386 context& context::operator=(context&& other)
0387 {
0388 context tmp(static_cast<context&&>(*this));
0389 handle_ = other.handle_;
0390 other.handle_ = 0;
0391 return *this;
0392 }
0393
0394 context::~context()
0395 {
0396 if (handle_)
0397 {
0398 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0399 && (!defined(LIBRESSL_VERSION_NUMBER) \
0400 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0401 || defined(BOOST_ASIO_USE_WOLFSSL)
0402 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0403 #else
0404 void* cb_userdata = handle_->default_passwd_callback_userdata;
0405 #endif
0406 if (cb_userdata)
0407 {
0408 detail::password_callback_base* callback =
0409 static_cast<detail::password_callback_base*>(
0410 cb_userdata);
0411 delete callback;
0412 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0413 && (!defined(LIBRESSL_VERSION_NUMBER) \
0414 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0415 || defined(BOOST_ASIO_USE_WOLFSSL)
0416 ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
0417 #else
0418 handle_->default_passwd_callback_userdata = 0;
0419 #endif
0420 }
0421
0422 if (SSL_CTX_get_app_data(handle_))
0423 {
0424 detail::verify_callback_base* callback =
0425 static_cast<detail::verify_callback_base*>(
0426 SSL_CTX_get_app_data(handle_));
0427 delete callback;
0428 SSL_CTX_set_app_data(handle_, 0);
0429 }
0430
0431 ::SSL_CTX_free(handle_);
0432 }
0433 }
0434
0435 context::native_handle_type context::native_handle()
0436 {
0437 return handle_;
0438 }
0439
0440 void context::clear_options(context::options o)
0441 {
0442 boost::system::error_code ec;
0443 clear_options(o, ec);
0444 boost::asio::detail::throw_error(ec, "clear_options");
0445 }
0446
0447 BOOST_ASIO_SYNC_OP_VOID context::clear_options(
0448 context::options o, boost::system::error_code& ec)
0449 {
0450 #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
0451 && (OPENSSL_VERSION_NUMBER != 0x00909000L)
0452 # if !defined(SSL_OP_NO_COMPRESSION)
0453 if ((o & context::no_compression) != 0)
0454 {
0455 # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
0456 handle_->comp_methods = SSL_COMP_get_compression_methods();
0457 # endif
0458 o ^= context::no_compression;
0459 }
0460 # endif
0461
0462 ::SSL_CTX_clear_options(handle_, o);
0463
0464 ec = boost::system::error_code();
0465 #else
0466
0467 (void)o;
0468 ec = boost::asio::error::operation_not_supported;
0469 #endif
0470
0471 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0472 }
0473
0474 void context::set_options(context::options o)
0475 {
0476 boost::system::error_code ec;
0477 set_options(o, ec);
0478 boost::asio::detail::throw_error(ec, "set_options");
0479 }
0480
0481 BOOST_ASIO_SYNC_OP_VOID context::set_options(
0482 context::options o, boost::system::error_code& ec)
0483 {
0484 #if !defined(SSL_OP_NO_COMPRESSION)
0485 if ((o & context::no_compression) != 0)
0486 {
0487 #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
0488 handle_->comp_methods =
0489 boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
0490 #endif
0491 o ^= context::no_compression;
0492 }
0493 #endif
0494
0495 ::SSL_CTX_set_options(handle_, o);
0496
0497 ec = boost::system::error_code();
0498 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0499 }
0500
0501 void context::set_verify_mode(verify_mode v)
0502 {
0503 boost::system::error_code ec;
0504 set_verify_mode(v, ec);
0505 boost::asio::detail::throw_error(ec, "set_verify_mode");
0506 }
0507
0508 BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
0509 verify_mode v, boost::system::error_code& ec)
0510 {
0511 ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
0512
0513 ec = boost::system::error_code();
0514 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0515 }
0516
0517 void context::set_verify_depth(int depth)
0518 {
0519 boost::system::error_code ec;
0520 set_verify_depth(depth, ec);
0521 boost::asio::detail::throw_error(ec, "set_verify_depth");
0522 }
0523
0524 BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
0525 int depth, boost::system::error_code& ec)
0526 {
0527 ::SSL_CTX_set_verify_depth(handle_, depth);
0528
0529 ec = boost::system::error_code();
0530 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0531 }
0532
0533 void context::load_verify_file(const std::string& filename)
0534 {
0535 boost::system::error_code ec;
0536 load_verify_file(filename, ec);
0537 boost::asio::detail::throw_error(ec, "load_verify_file");
0538 }
0539
0540 BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
0541 const std::string& filename, boost::system::error_code& ec)
0542 {
0543 ::ERR_clear_error();
0544
0545 if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
0546 {
0547 ec = translate_error(::ERR_get_error());
0548 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0549 }
0550
0551 ec = boost::system::error_code();
0552 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0553 }
0554
0555 void context::add_certificate_authority(const const_buffer& ca)
0556 {
0557 boost::system::error_code ec;
0558 add_certificate_authority(ca, ec);
0559 boost::asio::detail::throw_error(ec, "add_certificate_authority");
0560 }
0561
0562 BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
0563 const const_buffer& ca, boost::system::error_code& ec)
0564 {
0565 ::ERR_clear_error();
0566
0567 bio_cleanup bio = { make_buffer_bio(ca) };
0568 if (bio.p)
0569 {
0570 if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
0571 {
0572 for (bool added = false;; added = true)
0573 {
0574 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
0575 if (!cert.p)
0576 {
0577 unsigned long err = ::ERR_get_error();
0578 if (added && ERR_GET_LIB(err) == ERR_LIB_PEM
0579 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
0580 break;
0581
0582 ec = translate_error(err);
0583 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0584 }
0585
0586 if (::X509_STORE_add_cert(store, cert.p) != 1)
0587 {
0588 ec = translate_error(::ERR_get_error());
0589 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0590 }
0591 }
0592 }
0593 }
0594
0595 ec = boost::system::error_code();
0596 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0597 }
0598
0599 void context::set_default_verify_paths()
0600 {
0601 boost::system::error_code ec;
0602 set_default_verify_paths(ec);
0603 boost::asio::detail::throw_error(ec, "set_default_verify_paths");
0604 }
0605
0606 BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
0607 boost::system::error_code& ec)
0608 {
0609 ::ERR_clear_error();
0610
0611 if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
0612 {
0613 ec = translate_error(::ERR_get_error());
0614 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0615 }
0616
0617 ec = boost::system::error_code();
0618 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0619 }
0620
0621 void context::add_verify_path(const std::string& path)
0622 {
0623 boost::system::error_code ec;
0624 add_verify_path(path, ec);
0625 boost::asio::detail::throw_error(ec, "add_verify_path");
0626 }
0627
0628 BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
0629 const std::string& path, boost::system::error_code& ec)
0630 {
0631 ::ERR_clear_error();
0632
0633 if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
0634 {
0635 ec = translate_error(::ERR_get_error());
0636 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0637 }
0638
0639 ec = boost::system::error_code();
0640 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0641 }
0642
0643 void context::use_certificate(
0644 const const_buffer& certificate, file_format format)
0645 {
0646 boost::system::error_code ec;
0647 use_certificate(certificate, format, ec);
0648 boost::asio::detail::throw_error(ec, "use_certificate");
0649 }
0650
0651 BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
0652 const const_buffer& certificate, file_format format,
0653 boost::system::error_code& ec)
0654 {
0655 ::ERR_clear_error();
0656
0657 if (format == context_base::asn1)
0658 {
0659 if (::SSL_CTX_use_certificate_ASN1(handle_,
0660 static_cast<int>(certificate.size()),
0661 static_cast<const unsigned char*>(certificate.data())) == 1)
0662 {
0663 ec = boost::system::error_code();
0664 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0665 }
0666 }
0667 else if (format == context_base::pem)
0668 {
0669 bio_cleanup bio = { make_buffer_bio(certificate) };
0670 if (bio.p)
0671 {
0672 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
0673 if (cert.p)
0674 {
0675 if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
0676 {
0677 ec = boost::system::error_code();
0678 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0679 }
0680 }
0681 }
0682 }
0683 else
0684 {
0685 ec = boost::asio::error::invalid_argument;
0686 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0687 }
0688
0689 ec = translate_error(::ERR_get_error());
0690 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0691 }
0692
0693 void context::use_certificate_file(
0694 const std::string& filename, file_format format)
0695 {
0696 boost::system::error_code ec;
0697 use_certificate_file(filename, format, ec);
0698 boost::asio::detail::throw_error(ec, "use_certificate_file");
0699 }
0700
0701 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
0702 const std::string& filename, file_format format,
0703 boost::system::error_code& ec)
0704 {
0705 int file_type;
0706 switch (format)
0707 {
0708 case context_base::asn1:
0709 file_type = SSL_FILETYPE_ASN1;
0710 break;
0711 case context_base::pem:
0712 file_type = SSL_FILETYPE_PEM;
0713 break;
0714 default:
0715 {
0716 ec = boost::asio::error::invalid_argument;
0717 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0718 }
0719 }
0720
0721 ::ERR_clear_error();
0722
0723 if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
0724 {
0725 ec = translate_error(::ERR_get_error());
0726 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0727 }
0728
0729 ec = boost::system::error_code();
0730 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0731 }
0732
0733 void context::use_certificate_chain(const const_buffer& chain)
0734 {
0735 boost::system::error_code ec;
0736 use_certificate_chain(chain, ec);
0737 boost::asio::detail::throw_error(ec, "use_certificate_chain");
0738 }
0739
0740 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
0741 const const_buffer& chain, boost::system::error_code& ec)
0742 {
0743 ::ERR_clear_error();
0744
0745 bio_cleanup bio = { make_buffer_bio(chain) };
0746 if (bio.p)
0747 {
0748 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0749 && (!defined(LIBRESSL_VERSION_NUMBER) \
0750 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0751 || defined(BOOST_ASIO_USE_WOLFSSL)
0752 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
0753 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0754 #else
0755 pem_password_cb* callback = handle_->default_passwd_callback;
0756 void* cb_userdata = handle_->default_passwd_callback_userdata;
0757 #endif
0758 x509_cleanup cert = {
0759 ::PEM_read_bio_X509_AUX(bio.p, 0,
0760 callback,
0761 cb_userdata) };
0762 if (!cert.p)
0763 {
0764 ec = translate_error(ERR_R_PEM_LIB);
0765 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0766 }
0767
0768 int result = ::SSL_CTX_use_certificate(handle_, cert.p);
0769 if (result == 0 || ::ERR_peek_error() != 0)
0770 {
0771 ec = translate_error(::ERR_get_error());
0772 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0773 }
0774
0775 #if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \
0776 && (!defined(LIBRESSL_VERSION_NUMBER) \
0777 || LIBRESSL_VERSION_NUMBER >= 0x2090100fL)) \
0778 || defined(BOOST_ASIO_USE_WOLFSSL)
0779 ::SSL_CTX_clear_chain_certs(handle_);
0780 #else
0781 if (handle_->extra_certs)
0782 {
0783 ::sk_X509_pop_free(handle_->extra_certs, X509_free);
0784 handle_->extra_certs = 0;
0785 }
0786 #endif
0787
0788 while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
0789 callback,
0790 cb_userdata))
0791 {
0792 if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
0793 {
0794 ec = translate_error(::ERR_get_error());
0795 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0796 }
0797 }
0798
0799 result = ::ERR_peek_last_error();
0800 if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
0801 && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
0802 {
0803 ::ERR_clear_error();
0804 ec = boost::system::error_code();
0805 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0806 }
0807 }
0808
0809 ec = translate_error(::ERR_get_error());
0810 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0811 }
0812
0813 void context::use_certificate_chain_file(const std::string& filename)
0814 {
0815 boost::system::error_code ec;
0816 use_certificate_chain_file(filename, ec);
0817 boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
0818 }
0819
0820 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
0821 const std::string& filename, boost::system::error_code& ec)
0822 {
0823 ::ERR_clear_error();
0824
0825 if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
0826 {
0827 ec = translate_error(::ERR_get_error());
0828 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0829 }
0830
0831 ec = boost::system::error_code();
0832 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0833 }
0834
0835 void context::use_private_key(
0836 const const_buffer& private_key, context::file_format format)
0837 {
0838 boost::system::error_code ec;
0839 use_private_key(private_key, format, ec);
0840 boost::asio::detail::throw_error(ec, "use_private_key");
0841 }
0842
0843 BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
0844 const const_buffer& private_key, context::file_format format,
0845 boost::system::error_code& ec)
0846 {
0847 ::ERR_clear_error();
0848
0849 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0850 && (!defined(LIBRESSL_VERSION_NUMBER) \
0851 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0852 || defined(BOOST_ASIO_USE_WOLFSSL)
0853 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
0854 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0855 #else
0856 pem_password_cb* callback = handle_->default_passwd_callback;
0857 void* cb_userdata = handle_->default_passwd_callback_userdata;
0858 #endif
0859
0860 bio_cleanup bio = { make_buffer_bio(private_key) };
0861 if (bio.p)
0862 {
0863 evp_pkey_cleanup evp_private_key = { 0 };
0864 switch (format)
0865 {
0866 case context_base::asn1:
0867 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
0868 break;
0869 case context_base::pem:
0870 evp_private_key.p = ::PEM_read_bio_PrivateKey(
0871 bio.p, 0, callback,
0872 cb_userdata);
0873 break;
0874 default:
0875 {
0876 ec = boost::asio::error::invalid_argument;
0877 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0878 }
0879 }
0880
0881 if (evp_private_key.p)
0882 {
0883 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
0884 {
0885 ec = boost::system::error_code();
0886 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0887 }
0888 }
0889 }
0890
0891 ec = translate_error(::ERR_get_error());
0892 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0893 }
0894
0895 void context::use_private_key_file(
0896 const std::string& filename, context::file_format format)
0897 {
0898 boost::system::error_code ec;
0899 use_private_key_file(filename, format, ec);
0900 boost::asio::detail::throw_error(ec, "use_private_key_file");
0901 }
0902
0903 void context::use_rsa_private_key(
0904 const const_buffer& private_key, context::file_format format)
0905 {
0906 boost::system::error_code ec;
0907 use_rsa_private_key(private_key, format, ec);
0908 boost::asio::detail::throw_error(ec, "use_rsa_private_key");
0909 }
0910
0911 BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
0912 const const_buffer& private_key, context::file_format format,
0913 boost::system::error_code& ec)
0914 {
0915 ::ERR_clear_error();
0916
0917 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
0918 && (!defined(LIBRESSL_VERSION_NUMBER) \
0919 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
0920 || defined(BOOST_ASIO_USE_WOLFSSL)
0921 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
0922 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
0923 #else
0924 pem_password_cb* callback = handle_->default_passwd_callback;
0925 void* cb_userdata = handle_->default_passwd_callback_userdata;
0926 #endif
0927
0928 bio_cleanup bio = { make_buffer_bio(private_key) };
0929 if (bio.p)
0930 {
0931 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
0932 evp_pkey_cleanup evp_private_key = { 0 };
0933 switch (format)
0934 {
0935 case context_base::asn1:
0936 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
0937 break;
0938 case context_base::pem:
0939 evp_private_key.p = ::PEM_read_bio_PrivateKey(
0940 bio.p, 0, callback,
0941 cb_userdata);
0942 break;
0943 default:
0944 {
0945 ec = boost::asio::error::invalid_argument;
0946 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0947 }
0948 }
0949
0950 if (evp_private_key.p)
0951 {
0952 if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)
0953 {
0954 ec = translate_error(
0955 ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));
0956 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0957 }
0958
0959 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
0960 {
0961 ec = boost::system::error_code();
0962 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0963 }
0964 }
0965 #else
0966 rsa_cleanup rsa_private_key = { 0 };
0967 switch (format)
0968 {
0969 case context_base::asn1:
0970 rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
0971 break;
0972 case context_base::pem:
0973 rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
0974 bio.p, 0, callback,
0975 cb_userdata);
0976 break;
0977 default:
0978 {
0979 ec = boost::asio::error::invalid_argument;
0980 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0981 }
0982 }
0983
0984 if (rsa_private_key.p)
0985 {
0986 if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
0987 {
0988 ec = boost::system::error_code();
0989 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0990 }
0991 }
0992 #endif
0993 }
0994
0995 ec = translate_error(::ERR_get_error());
0996 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0997 }
0998
0999 BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file(
1000 const std::string& filename, context::file_format format,
1001 boost::system::error_code& ec)
1002 {
1003 int file_type;
1004 switch (format)
1005 {
1006 case context_base::asn1:
1007 file_type = SSL_FILETYPE_ASN1;
1008 break;
1009 case context_base::pem:
1010 file_type = SSL_FILETYPE_PEM;
1011 break;
1012 default:
1013 {
1014 ec = boost::asio::error::invalid_argument;
1015 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1016 }
1017 }
1018
1019 ::ERR_clear_error();
1020
1021 if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
1022 {
1023 ec = translate_error(::ERR_get_error());
1024 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1025 }
1026
1027 ec = boost::system::error_code();
1028 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1029 }
1030
1031 void context::use_rsa_private_key_file(
1032 const std::string& filename, context::file_format format)
1033 {
1034 boost::system::error_code ec;
1035 use_rsa_private_key_file(filename, format, ec);
1036 boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
1037 }
1038
1039 BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(
1040 const std::string& filename, context::file_format format,
1041 boost::system::error_code& ec)
1042 {
1043 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1044 ::ERR_clear_error();
1045
1046 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
1047 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
1048
1049 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
1050 if (bio.p)
1051 {
1052 evp_pkey_cleanup evp_private_key = { 0 };
1053 switch (format)
1054 {
1055 case context_base::asn1:
1056 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
1057 break;
1058 case context_base::pem:
1059 evp_private_key.p = ::PEM_read_bio_PrivateKey(
1060 bio.p, 0, callback,
1061 cb_userdata);
1062 break;
1063 default:
1064 {
1065 ec = boost::asio::error::invalid_argument;
1066 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1067 }
1068 }
1069
1070 if (evp_private_key.p)
1071 {
1072 if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)
1073 {
1074 ec = translate_error(
1075 ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));
1076 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1077 }
1078
1079 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
1080 {
1081 ec = boost::system::error_code();
1082 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1083 }
1084 }
1085 }
1086
1087 ec = translate_error(::ERR_get_error());
1088 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1089 #else
1090 int file_type;
1091 switch (format)
1092 {
1093 case context_base::asn1:
1094 file_type = SSL_FILETYPE_ASN1;
1095 break;
1096 case context_base::pem:
1097 file_type = SSL_FILETYPE_PEM;
1098 break;
1099 default:
1100 {
1101 ec = boost::asio::error::invalid_argument;
1102 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1103 }
1104 }
1105
1106 ::ERR_clear_error();
1107
1108 if (::SSL_CTX_use_RSAPrivateKey_file(
1109 handle_, filename.c_str(), file_type) != 1)
1110 {
1111 ec = translate_error(::ERR_get_error());
1112 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1113 }
1114
1115 ec = boost::system::error_code();
1116 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1117 #endif
1118 }
1119
1120 void context::use_tmp_dh(const const_buffer& dh)
1121 {
1122 boost::system::error_code ec;
1123 use_tmp_dh(dh, ec);
1124 boost::asio::detail::throw_error(ec, "use_tmp_dh");
1125 }
1126
1127 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
1128 const const_buffer& dh, boost::system::error_code& ec)
1129 {
1130 ::ERR_clear_error();
1131
1132 bio_cleanup bio = { make_buffer_bio(dh) };
1133 if (bio.p)
1134 {
1135 return do_use_tmp_dh(bio.p, ec);
1136 }
1137
1138 ec = translate_error(::ERR_get_error());
1139 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1140 }
1141
1142 void context::use_tmp_dh_file(const std::string& filename)
1143 {
1144 boost::system::error_code ec;
1145 use_tmp_dh_file(filename, ec);
1146 boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
1147 }
1148
1149 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
1150 const std::string& filename, boost::system::error_code& ec)
1151 {
1152 ::ERR_clear_error();
1153
1154 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
1155 if (bio.p)
1156 {
1157 return do_use_tmp_dh(bio.p, ec);
1158 }
1159
1160 ec = translate_error(::ERR_get_error());
1161 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1162 }
1163
1164 BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
1165 BIO* bio, boost::system::error_code& ec)
1166 {
1167 ::ERR_clear_error();
1168
1169 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1170 EVP_PKEY* p = ::PEM_read_bio_Parameters(bio, 0);
1171 if (p)
1172 {
1173 if (::SSL_CTX_set0_tmp_dh_pkey(handle_, p) == 1)
1174 {
1175 ec = boost::system::error_code();
1176 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1177 }
1178 else
1179 ::EVP_PKEY_free(p);
1180 }
1181 #else
1182 dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
1183 if (dh.p)
1184 {
1185 if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
1186 {
1187 ec = boost::system::error_code();
1188 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1189 }
1190 }
1191 #endif
1192
1193 ec = translate_error(::ERR_get_error());
1194 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1195 }
1196
1197 BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
1198 detail::verify_callback_base* callback, boost::system::error_code& ec)
1199 {
1200 if (SSL_CTX_get_app_data(handle_))
1201 {
1202 delete static_cast<detail::verify_callback_base*>(
1203 SSL_CTX_get_app_data(handle_));
1204 }
1205
1206 SSL_CTX_set_app_data(handle_, callback);
1207
1208 ::SSL_CTX_set_verify(handle_,
1209 ::SSL_CTX_get_verify_mode(handle_),
1210 &context::verify_callback_function);
1211
1212 ec = boost::system::error_code();
1213 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1214 }
1215
1216 int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
1217 {
1218 if (ctx)
1219 {
1220 if (SSL* ssl = static_cast<SSL*>(
1221 ::X509_STORE_CTX_get_ex_data(
1222 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
1223 {
1224 if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
1225 {
1226 if (SSL_CTX_get_app_data(handle))
1227 {
1228 detail::verify_callback_base* callback =
1229 static_cast<detail::verify_callback_base*>(
1230 SSL_CTX_get_app_data(handle));
1231
1232 verify_context verify_ctx(ctx);
1233 return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
1234 }
1235 }
1236 }
1237 }
1238
1239 return 0;
1240 }
1241
1242 BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
1243 detail::password_callback_base* callback, boost::system::error_code& ec)
1244 {
1245 #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
1246 && (!defined(LIBRESSL_VERSION_NUMBER) \
1247 || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \
1248 || defined(BOOST_ASIO_USE_WOLFSSL)
1249 void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
1250 ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
1251 #else
1252 void* old_callback = handle_->default_passwd_callback_userdata;
1253 handle_->default_passwd_callback_userdata = callback;
1254 #endif
1255
1256 if (old_callback)
1257 delete static_cast<detail::password_callback_base*>(
1258 old_callback);
1259
1260 SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
1261
1262 ec = boost::system::error_code();
1263 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1264 }
1265
1266 int context::password_callback_function(
1267 char* buf, int size, int purpose, void* data)
1268 {
1269 using namespace std;
1270
1271 if (data)
1272 {
1273 detail::password_callback_base* callback =
1274 static_cast<detail::password_callback_base*>(data);
1275
1276 std::string passwd = callback->call(static_cast<std::size_t>(size),
1277 purpose ? context_base::for_writing : context_base::for_reading);
1278
1279 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
1280 strcpy_s(buf, size, passwd.c_str());
1281 #else
1282 *buf = '\0';
1283 if (size > 0)
1284 strncat(buf, passwd.c_str(), size - 1);
1285 #endif
1286
1287 return static_cast<int>(strlen(buf));
1288 }
1289
1290 return 0;
1291 }
1292
1293 BIO* context::make_buffer_bio(const const_buffer& b)
1294 {
1295 return ::BIO_new_mem_buf(
1296 const_cast<void*>(b.data()),
1297 static_cast<int>(b.size()));
1298 }
1299
1300 boost::system::error_code context::translate_error(long error)
1301 {
1302 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1303 if (ERR_SYSTEM_ERROR(error))
1304 {
1305 return boost::system::error_code(
1306 static_cast<int>(ERR_GET_REASON(error)),
1307 boost::asio::error::get_system_category());
1308 }
1309 #endif
1310
1311 return boost::system::error_code(static_cast<int>(error),
1312 boost::asio::error::get_ssl_category());
1313 }
1314
1315 }
1316 }
1317 }
1318
1319 #include <boost/asio/detail/pop_options.hpp>
1320
1321 #endif