2 // ssl/impl/context.ipp
3 // ~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
6 // Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 #ifndef BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
13 #define BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
19 #include <boost/asio/detail/config.hpp>
22 #include <boost/asio/detail/throw_error.hpp>
23 #include <boost/asio/error.hpp>
24 #include <boost/asio/ssl/context.hpp>
25 #include <boost/asio/ssl/error.hpp>
27 #include <boost/asio/detail/push_options.hpp>
33 struct context::bio_cleanup
36 ~bio_cleanup() { if (p) ::BIO_free(p); }
39 struct context::x509_cleanup
42 ~x509_cleanup() { if (p) ::X509_free(p); }
45 struct context::evp_pkey_cleanup
48 ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }
51 struct context::rsa_cleanup
54 ~rsa_cleanup() { if (p) ::RSA_free(p); }
57 struct context::dh_cleanup
60 ~dh_cleanup() { if (p) ::DH_free(p); }
63 context::context(context::method m)
71 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
73 case context::sslv2_client:
74 case context::sslv2_server:
75 boost::asio::detail::throw_error(
76 boost::asio::error::invalid_argument, "context");
78 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
80 handle_ = ::SSL_CTX_new(::SSLv2_method());
82 case context::sslv2_client:
83 handle_ = ::SSL_CTX_new(::SSLv2_client_method());
85 case context::sslv2_server:
86 handle_ = ::SSL_CTX_new(::SSLv2_server_method());
88 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
91 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
93 handle_ = ::SSL_CTX_new(::TLS_method());
96 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
97 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
100 case context::sslv3_client:
101 handle_ = ::SSL_CTX_new(::TLS_client_method());
104 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
105 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
108 case context::sslv3_server:
109 handle_ = ::SSL_CTX_new(::TLS_server_method());
112 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
113 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
116 #elif defined(OPENSSL_NO_SSL3)
118 case context::sslv3_client:
119 case context::sslv3_server:
120 boost::asio::detail::throw_error(
121 boost::asio::error::invalid_argument, "context");
123 #else // defined(OPENSSL_NO_SSL3)
125 handle_ = ::SSL_CTX_new(::SSLv3_method());
127 case context::sslv3_client:
128 handle_ = ::SSL_CTX_new(::SSLv3_client_method());
130 case context::sslv3_server:
131 handle_ = ::SSL_CTX_new(::SSLv3_server_method());
133 #endif // defined(OPENSSL_NO_SSL3)
136 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
138 handle_ = ::SSL_CTX_new(::TLS_method());
141 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
142 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
145 case context::tlsv1_client:
146 handle_ = ::SSL_CTX_new(::TLS_client_method());
149 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
150 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
153 case context::tlsv1_server:
154 handle_ = ::SSL_CTX_new(::TLS_server_method());
157 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
158 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
161 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
163 handle_ = ::SSL_CTX_new(::TLSv1_method());
165 case context::tlsv1_client:
166 handle_ = ::SSL_CTX_new(::TLSv1_client_method());
168 case context::tlsv1_server:
169 handle_ = ::SSL_CTX_new(::TLSv1_server_method());
171 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
174 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
175 case context::tlsv11:
176 handle_ = ::SSL_CTX_new(::TLS_method());
179 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
180 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
183 case context::tlsv11_client:
184 handle_ = ::SSL_CTX_new(::TLS_client_method());
187 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
188 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
191 case context::tlsv11_server:
192 handle_ = ::SSL_CTX_new(::TLS_server_method());
195 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
196 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
199 #elif defined(SSL_TXT_TLSV1_1)
200 case context::tlsv11:
201 handle_ = ::SSL_CTX_new(::TLSv1_1_method());
203 case context::tlsv11_client:
204 handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());
206 case context::tlsv11_server:
207 handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());
209 #else // defined(SSL_TXT_TLSV1_1)
210 case context::tlsv11:
211 case context::tlsv11_client:
212 case context::tlsv11_server:
213 boost::asio::detail::throw_error(
214 boost::asio::error::invalid_argument, "context");
216 #endif // defined(SSL_TXT_TLSV1_1)
219 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
220 case context::tlsv12:
221 handle_ = ::SSL_CTX_new(::TLS_method());
224 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
225 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
228 case context::tlsv12_client:
229 handle_ = ::SSL_CTX_new(::TLS_client_method());
232 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
233 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
236 case context::tlsv12_server:
237 handle_ = ::SSL_CTX_new(::TLS_server_method());
240 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
241 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
244 #elif defined(SSL_TXT_TLSV1_1)
245 case context::tlsv12:
246 handle_ = ::SSL_CTX_new(::TLSv1_2_method());
248 case context::tlsv12_client:
249 handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());
251 case context::tlsv12_server:
252 handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
254 #else // defined(SSL_TXT_TLSV1_1)
255 case context::tlsv12:
256 case context::tlsv12_client:
257 case context::tlsv12_server:
258 boost::asio::detail::throw_error(
259 boost::asio::error::invalid_argument, "context");
261 #endif // defined(SSL_TXT_TLSV1_1)
263 // Any supported SSL/TLS version.
264 case context::sslv23:
265 handle_ = ::SSL_CTX_new(::SSLv23_method());
267 case context::sslv23_client:
268 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
270 case context::sslv23_server:
271 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
274 // Any supported TLS version.
275 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
277 handle_ = ::SSL_CTX_new(::TLS_method());
279 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
281 case context::tls_client:
282 handle_ = ::SSL_CTX_new(::TLS_client_method());
284 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
286 case context::tls_server:
287 handle_ = ::SSL_CTX_new(::TLS_server_method());
289 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
291 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
293 handle_ = ::SSL_CTX_new(::SSLv23_method());
295 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
297 case context::tls_client:
298 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
300 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
302 case context::tls_server:
303 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
305 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
307 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
310 handle_ = ::SSL_CTX_new(0);
316 boost::system::error_code ec(
317 static_cast<int>(::ERR_get_error()),
318 boost::asio::error::get_ssl_category());
319 boost::asio::detail::throw_error(ec, "context");
322 set_options(no_compression);
325 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
326 context::context(context&& other)
328 handle_ = other.handle_;
332 context& context::operator=(context&& other)
334 context tmp(BOOST_ASIO_MOVE_CAST(context)(*this));
335 handle_ = other.handle_;
339 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
345 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
346 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
347 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
348 void* cb_userdata = handle_->default_passwd_callback_userdata;
349 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
352 detail::password_callback_base* callback =
353 static_cast<detail::password_callback_base*>(
356 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
357 ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
358 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
359 handle_->default_passwd_callback_userdata = 0;
360 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
363 if (SSL_CTX_get_app_data(handle_))
365 detail::verify_callback_base* callback =
366 static_cast<detail::verify_callback_base*>(
367 SSL_CTX_get_app_data(handle_));
369 SSL_CTX_set_app_data(handle_, 0);
372 ::SSL_CTX_free(handle_);
376 context::native_handle_type context::native_handle()
381 void context::clear_options(context::options o)
383 boost::system::error_code ec;
384 clear_options(o, ec);
385 boost::asio::detail::throw_error(ec, "clear_options");
388 BOOST_ASIO_SYNC_OP_VOID context::clear_options(
389 context::options o, boost::system::error_code& ec)
391 #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
392 && (OPENSSL_VERSION_NUMBER != 0x00909000L)
393 # if !defined(SSL_OP_NO_COMPRESSION)
394 if ((o & context::no_compression) != 0)
396 # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
397 handle_->comp_methods = SSL_COMP_get_compression_methods();
398 # endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
399 o ^= context::no_compression;
401 # endif // !defined(SSL_OP_NO_COMPRESSION)
403 ::SSL_CTX_clear_options(handle_, o);
405 ec = boost::system::error_code();
406 #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
407 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
409 ec = boost::asio::error::operation_not_supported;
410 #endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
411 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
412 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
415 void context::set_options(context::options o)
417 boost::system::error_code ec;
419 boost::asio::detail::throw_error(ec, "set_options");
422 BOOST_ASIO_SYNC_OP_VOID context::set_options(
423 context::options o, boost::system::error_code& ec)
425 #if !defined(SSL_OP_NO_COMPRESSION)
426 if ((o & context::no_compression) != 0)
428 #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
429 handle_->comp_methods =
430 boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
431 #endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
432 o ^= context::no_compression;
434 #endif // !defined(SSL_OP_NO_COMPRESSION)
436 ::SSL_CTX_set_options(handle_, o);
438 ec = boost::system::error_code();
439 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
442 void context::set_verify_mode(verify_mode v)
444 boost::system::error_code ec;
445 set_verify_mode(v, ec);
446 boost::asio::detail::throw_error(ec, "set_verify_mode");
449 BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
450 verify_mode v, boost::system::error_code& ec)
452 ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
454 ec = boost::system::error_code();
455 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
458 void context::set_verify_depth(int depth)
460 boost::system::error_code ec;
461 set_verify_depth(depth, ec);
462 boost::asio::detail::throw_error(ec, "set_verify_depth");
465 BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
466 int depth, boost::system::error_code& ec)
468 ::SSL_CTX_set_verify_depth(handle_, depth);
470 ec = boost::system::error_code();
471 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
474 void context::load_verify_file(const std::string& filename)
476 boost::system::error_code ec;
477 load_verify_file(filename, ec);
478 boost::asio::detail::throw_error(ec, "load_verify_file");
481 BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
482 const std::string& filename, boost::system::error_code& ec)
486 if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
488 ec = boost::system::error_code(
489 static_cast<int>(::ERR_get_error()),
490 boost::asio::error::get_ssl_category());
491 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
494 ec = boost::system::error_code();
495 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
498 void context::add_certificate_authority(const const_buffer& ca)
500 boost::system::error_code ec;
501 add_certificate_authority(ca, ec);
502 boost::asio::detail::throw_error(ec, "add_certificate_authority");
505 BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
506 const const_buffer& ca, boost::system::error_code& ec)
510 bio_cleanup bio = { make_buffer_bio(ca) };
513 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
516 if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
518 if (::X509_STORE_add_cert(store, cert.p) == 1)
520 ec = boost::system::error_code();
521 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
527 ec = boost::system::error_code(
528 static_cast<int>(::ERR_get_error()),
529 boost::asio::error::get_ssl_category());
530 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
533 void context::set_default_verify_paths()
535 boost::system::error_code ec;
536 set_default_verify_paths(ec);
537 boost::asio::detail::throw_error(ec, "set_default_verify_paths");
540 BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
541 boost::system::error_code& ec)
545 if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
547 ec = boost::system::error_code(
548 static_cast<int>(::ERR_get_error()),
549 boost::asio::error::get_ssl_category());
550 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
553 ec = boost::system::error_code();
554 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
557 void context::add_verify_path(const std::string& path)
559 boost::system::error_code ec;
560 add_verify_path(path, ec);
561 boost::asio::detail::throw_error(ec, "add_verify_path");
564 BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
565 const std::string& path, boost::system::error_code& ec)
569 if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
571 ec = boost::system::error_code(
572 static_cast<int>(::ERR_get_error()),
573 boost::asio::error::get_ssl_category());
574 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
577 ec = boost::system::error_code();
578 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
581 void context::use_certificate(
582 const const_buffer& certificate, file_format format)
584 boost::system::error_code ec;
585 use_certificate(certificate, format, ec);
586 boost::asio::detail::throw_error(ec, "use_certificate");
589 BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
590 const const_buffer& certificate, file_format format,
591 boost::system::error_code& ec)
595 if (format == context_base::asn1)
597 if (::SSL_CTX_use_certificate_ASN1(handle_,
598 static_cast<int>(certificate.size()),
599 static_cast<const unsigned char*>(certificate.data())) == 1)
601 ec = boost::system::error_code();
602 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
605 else if (format == context_base::pem)
607 bio_cleanup bio = { make_buffer_bio(certificate) };
610 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
613 if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
615 ec = boost::system::error_code();
616 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
623 ec = boost::asio::error::invalid_argument;
624 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
627 ec = boost::system::error_code(
628 static_cast<int>(::ERR_get_error()),
629 boost::asio::error::get_ssl_category());
630 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
633 void context::use_certificate_file(
634 const std::string& filename, file_format format)
636 boost::system::error_code ec;
637 use_certificate_file(filename, format, ec);
638 boost::asio::detail::throw_error(ec, "use_certificate_file");
641 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
642 const std::string& filename, file_format format,
643 boost::system::error_code& ec)
648 case context_base::asn1:
649 file_type = SSL_FILETYPE_ASN1;
651 case context_base::pem:
652 file_type = SSL_FILETYPE_PEM;
656 ec = boost::asio::error::invalid_argument;
657 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
663 if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
665 ec = boost::system::error_code(
666 static_cast<int>(::ERR_get_error()),
667 boost::asio::error::get_ssl_category());
668 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
671 ec = boost::system::error_code();
672 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
675 void context::use_certificate_chain(const const_buffer& chain)
677 boost::system::error_code ec;
678 use_certificate_chain(chain, ec);
679 boost::asio::detail::throw_error(ec, "use_certificate_chain");
682 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
683 const const_buffer& chain, boost::system::error_code& ec)
687 bio_cleanup bio = { make_buffer_bio(chain) };
690 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
691 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
692 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
693 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
694 pem_password_cb* callback = handle_->default_passwd_callback;
695 void* cb_userdata = handle_->default_passwd_callback_userdata;
696 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
697 x509_cleanup cert = {
698 ::PEM_read_bio_X509_AUX(bio.p, 0,
703 ec = boost::system::error_code(ERR_R_PEM_LIB,
704 boost::asio::error::get_ssl_category());
705 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
708 int result = ::SSL_CTX_use_certificate(handle_, cert.p);
709 if (result == 0 || ::ERR_peek_error() != 0)
711 ec = boost::system::error_code(
712 static_cast<int>(::ERR_get_error()),
713 boost::asio::error::get_ssl_category());
714 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
717 #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER)
718 ::SSL_CTX_clear_chain_certs(handle_);
720 if (handle_->extra_certs)
722 ::sk_X509_pop_free(handle_->extra_certs, X509_free);
723 handle_->extra_certs = 0;
725 #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
727 while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
731 if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
733 ec = boost::system::error_code(
734 static_cast<int>(::ERR_get_error()),
735 boost::asio::error::get_ssl_category());
736 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
740 result = ::ERR_peek_last_error();
741 if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
742 && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
745 ec = boost::system::error_code();
746 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
750 ec = boost::system::error_code(
751 static_cast<int>(::ERR_get_error()),
752 boost::asio::error::get_ssl_category());
753 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
756 void context::use_certificate_chain_file(const std::string& filename)
758 boost::system::error_code ec;
759 use_certificate_chain_file(filename, ec);
760 boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
763 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
764 const std::string& filename, boost::system::error_code& ec)
768 if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
770 ec = boost::system::error_code(
771 static_cast<int>(::ERR_get_error()),
772 boost::asio::error::get_ssl_category());
773 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
776 ec = boost::system::error_code();
777 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
780 void context::use_private_key(
781 const const_buffer& private_key, context::file_format format)
783 boost::system::error_code ec;
784 use_private_key(private_key, format, ec);
785 boost::asio::detail::throw_error(ec, "use_private_key");
788 BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
789 const const_buffer& private_key, context::file_format format,
790 boost::system::error_code& ec)
794 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
795 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
796 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
797 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
798 pem_password_cb* callback = handle_->default_passwd_callback;
799 void* cb_userdata = handle_->default_passwd_callback_userdata;
800 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
802 bio_cleanup bio = { make_buffer_bio(private_key) };
805 evp_pkey_cleanup evp_private_key = { 0 };
808 case context_base::asn1:
809 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
811 case context_base::pem:
812 evp_private_key.p = ::PEM_read_bio_PrivateKey(
818 ec = boost::asio::error::invalid_argument;
819 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
823 if (evp_private_key.p)
825 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
827 ec = boost::system::error_code();
828 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
833 ec = boost::system::error_code(
834 static_cast<int>(::ERR_get_error()),
835 boost::asio::error::get_ssl_category());
836 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
839 void context::use_private_key_file(
840 const std::string& filename, context::file_format format)
842 boost::system::error_code ec;
843 use_private_key_file(filename, format, ec);
844 boost::asio::detail::throw_error(ec, "use_private_key_file");
847 void context::use_rsa_private_key(
848 const const_buffer& private_key, context::file_format format)
850 boost::system::error_code ec;
851 use_rsa_private_key(private_key, format, ec);
852 boost::asio::detail::throw_error(ec, "use_rsa_private_key");
855 BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
856 const const_buffer& private_key, context::file_format format,
857 boost::system::error_code& ec)
861 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
862 pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
863 void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
864 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
865 pem_password_cb* callback = handle_->default_passwd_callback;
866 void* cb_userdata = handle_->default_passwd_callback_userdata;
867 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
869 bio_cleanup bio = { make_buffer_bio(private_key) };
872 rsa_cleanup rsa_private_key = { 0 };
875 case context_base::asn1:
876 rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
878 case context_base::pem:
879 rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
885 ec = boost::asio::error::invalid_argument;
886 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
890 if (rsa_private_key.p)
892 if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
894 ec = boost::system::error_code();
895 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
900 ec = boost::system::error_code(
901 static_cast<int>(::ERR_get_error()),
902 boost::asio::error::get_ssl_category());
903 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
906 BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file(
907 const std::string& filename, context::file_format format,
908 boost::system::error_code& ec)
913 case context_base::asn1:
914 file_type = SSL_FILETYPE_ASN1;
916 case context_base::pem:
917 file_type = SSL_FILETYPE_PEM;
921 ec = boost::asio::error::invalid_argument;
922 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
928 if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
930 ec = boost::system::error_code(
931 static_cast<int>(::ERR_get_error()),
932 boost::asio::error::get_ssl_category());
933 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
936 ec = boost::system::error_code();
937 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
940 void context::use_rsa_private_key_file(
941 const std::string& filename, context::file_format format)
943 boost::system::error_code ec;
944 use_rsa_private_key_file(filename, format, ec);
945 boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
948 BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(
949 const std::string& filename, context::file_format format,
950 boost::system::error_code& ec)
955 case context_base::asn1:
956 file_type = SSL_FILETYPE_ASN1;
958 case context_base::pem:
959 file_type = SSL_FILETYPE_PEM;
963 ec = boost::asio::error::invalid_argument;
964 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
970 if (::SSL_CTX_use_RSAPrivateKey_file(
971 handle_, filename.c_str(), file_type) != 1)
973 ec = boost::system::error_code(
974 static_cast<int>(::ERR_get_error()),
975 boost::asio::error::get_ssl_category());
976 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
979 ec = boost::system::error_code();
980 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
983 void context::use_tmp_dh(const const_buffer& dh)
985 boost::system::error_code ec;
987 boost::asio::detail::throw_error(ec, "use_tmp_dh");
990 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
991 const const_buffer& dh, boost::system::error_code& ec)
995 bio_cleanup bio = { make_buffer_bio(dh) };
998 return do_use_tmp_dh(bio.p, ec);
1001 ec = boost::system::error_code(
1002 static_cast<int>(::ERR_get_error()),
1003 boost::asio::error::get_ssl_category());
1004 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1007 void context::use_tmp_dh_file(const std::string& filename)
1009 boost::system::error_code ec;
1010 use_tmp_dh_file(filename, ec);
1011 boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
1014 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
1015 const std::string& filename, boost::system::error_code& ec)
1017 ::ERR_clear_error();
1019 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
1022 return do_use_tmp_dh(bio.p, ec);
1025 ec = boost::system::error_code(
1026 static_cast<int>(::ERR_get_error()),
1027 boost::asio::error::get_ssl_category());
1028 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1031 BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
1032 BIO* bio, boost::system::error_code& ec)
1034 ::ERR_clear_error();
1036 dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
1039 if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
1041 ec = boost::system::error_code();
1042 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1046 ec = boost::system::error_code(
1047 static_cast<int>(::ERR_get_error()),
1048 boost::asio::error::get_ssl_category());
1049 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1052 BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
1053 detail::verify_callback_base* callback, boost::system::error_code& ec)
1055 if (SSL_CTX_get_app_data(handle_))
1057 delete static_cast<detail::verify_callback_base*>(
1058 SSL_CTX_get_app_data(handle_));
1061 SSL_CTX_set_app_data(handle_, callback);
1063 ::SSL_CTX_set_verify(handle_,
1064 ::SSL_CTX_get_verify_mode(handle_),
1065 &context::verify_callback_function);
1067 ec = boost::system::error_code();
1068 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1071 int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
1075 if (SSL* ssl = static_cast<SSL*>(
1076 ::X509_STORE_CTX_get_ex_data(
1077 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
1079 if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
1081 if (SSL_CTX_get_app_data(handle))
1083 detail::verify_callback_base* callback =
1084 static_cast<detail::verify_callback_base*>(
1085 SSL_CTX_get_app_data(handle));
1087 verify_context verify_ctx(ctx);
1088 return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
1097 BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
1098 detail::password_callback_base* callback, boost::system::error_code& ec)
1100 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
1101 void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
1102 ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
1103 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1104 void* old_callback = handle_->default_passwd_callback_userdata;
1105 handle_->default_passwd_callback_userdata = callback;
1106 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1109 delete static_cast<detail::password_callback_base*>(
1112 SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
1114 ec = boost::system::error_code();
1115 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1118 int context::password_callback_function(
1119 char* buf, int size, int purpose, void* data)
1121 using namespace std; // For strncat and strlen.
1125 detail::password_callback_base* callback =
1126 static_cast<detail::password_callback_base*>(data);
1128 std::string passwd = callback->call(static_cast<std::size_t>(size),
1129 purpose ? context_base::for_writing : context_base::for_reading);
1131 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
1132 strcpy_s(buf, size, passwd.c_str());
1133 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
1136 strncat(buf, passwd.c_str(), size - 1);
1137 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
1139 return static_cast<int>(strlen(buf));
1145 BIO* context::make_buffer_bio(const const_buffer& b)
1147 return ::BIO_new_mem_buf(
1148 const_cast<void*>(b.data()),
1149 static_cast<int>(b.size()));
1154 } // namespace boost
1156 #include <boost/asio/detail/pop_options.hpp>
1158 #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP