]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/ssl/impl/context.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / asio / ssl / impl / context.ipp
1 //
2 // ssl/impl/context.ipp
3 // ~~~~~~~~~~~~~~~~~~~~
4 //
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)
7 //
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)
10 //
11
12 #ifndef BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
13 #define BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
14
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
19 #include <boost/asio/detail/config.hpp>
20
21 #include <cstring>
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>
26
27 #include <boost/asio/detail/push_options.hpp>
28
29 namespace boost {
30 namespace asio {
31 namespace ssl {
32
33 struct context::bio_cleanup
34 {
35 BIO* p;
36 ~bio_cleanup() { if (p) ::BIO_free(p); }
37 };
38
39 struct context::x509_cleanup
40 {
41 X509* p;
42 ~x509_cleanup() { if (p) ::X509_free(p); }
43 };
44
45 struct context::evp_pkey_cleanup
46 {
47 EVP_PKEY* p;
48 ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }
49 };
50
51 struct context::rsa_cleanup
52 {
53 RSA* p;
54 ~rsa_cleanup() { if (p) ::RSA_free(p); }
55 };
56
57 struct context::dh_cleanup
58 {
59 DH* p;
60 ~dh_cleanup() { if (p) ::DH_free(p); }
61 };
62
63 context::context(context::method m)
64 : handle_(0)
65 {
66 ::ERR_clear_error();
67
68 switch (m)
69 {
70 // SSL v2.
71 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
72 case context::sslv2:
73 case context::sslv2_client:
74 case context::sslv2_server:
75 boost::asio::detail::throw_error(
76 boost::asio::error::invalid_argument, "context");
77 break;
78 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
79 case context::sslv2:
80 handle_ = ::SSL_CTX_new(::SSLv2_method());
81 break;
82 case context::sslv2_client:
83 handle_ = ::SSL_CTX_new(::SSLv2_client_method());
84 break;
85 case context::sslv2_server:
86 handle_ = ::SSL_CTX_new(::SSLv2_server_method());
87 break;
88 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
89
90 // SSL v3.
91 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
92 case context::sslv3:
93 handle_ = ::SSL_CTX_new(::TLS_method());
94 if (handle_)
95 {
96 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
97 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
98 }
99 break;
100 case context::sslv3_client:
101 handle_ = ::SSL_CTX_new(::TLS_client_method());
102 if (handle_)
103 {
104 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
105 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
106 }
107 break;
108 case context::sslv3_server:
109 handle_ = ::SSL_CTX_new(::TLS_server_method());
110 if (handle_)
111 {
112 SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
113 SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
114 }
115 break;
116 #elif defined(OPENSSL_NO_SSL3)
117 case context::sslv3:
118 case context::sslv3_client:
119 case context::sslv3_server:
120 boost::asio::detail::throw_error(
121 boost::asio::error::invalid_argument, "context");
122 break;
123 #else // defined(OPENSSL_NO_SSL3)
124 case context::sslv3:
125 handle_ = ::SSL_CTX_new(::SSLv3_method());
126 break;
127 case context::sslv3_client:
128 handle_ = ::SSL_CTX_new(::SSLv3_client_method());
129 break;
130 case context::sslv3_server:
131 handle_ = ::SSL_CTX_new(::SSLv3_server_method());
132 break;
133 #endif // defined(OPENSSL_NO_SSL3)
134
135 // TLS v1.0.
136 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
137 case context::tlsv1:
138 handle_ = ::SSL_CTX_new(::TLS_method());
139 if (handle_)
140 {
141 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
142 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
143 }
144 break;
145 case context::tlsv1_client:
146 handle_ = ::SSL_CTX_new(::TLS_client_method());
147 if (handle_)
148 {
149 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
150 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
151 }
152 break;
153 case context::tlsv1_server:
154 handle_ = ::SSL_CTX_new(::TLS_server_method());
155 if (handle_)
156 {
157 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
158 SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
159 }
160 break;
161 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
162 case context::tlsv1:
163 handle_ = ::SSL_CTX_new(::TLSv1_method());
164 break;
165 case context::tlsv1_client:
166 handle_ = ::SSL_CTX_new(::TLSv1_client_method());
167 break;
168 case context::tlsv1_server:
169 handle_ = ::SSL_CTX_new(::TLSv1_server_method());
170 break;
171 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
172
173 // TLS v1.1.
174 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
175 case context::tlsv11:
176 handle_ = ::SSL_CTX_new(::TLS_method());
177 if (handle_)
178 {
179 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
180 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
181 }
182 break;
183 case context::tlsv11_client:
184 handle_ = ::SSL_CTX_new(::TLS_client_method());
185 if (handle_)
186 {
187 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
188 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
189 }
190 break;
191 case context::tlsv11_server:
192 handle_ = ::SSL_CTX_new(::TLS_server_method());
193 if (handle_)
194 {
195 SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
196 SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
197 }
198 break;
199 #elif defined(SSL_TXT_TLSV1_1)
200 case context::tlsv11:
201 handle_ = ::SSL_CTX_new(::TLSv1_1_method());
202 break;
203 case context::tlsv11_client:
204 handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());
205 break;
206 case context::tlsv11_server:
207 handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());
208 break;
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");
215 break;
216 #endif // defined(SSL_TXT_TLSV1_1)
217
218 // TLS v1.2.
219 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
220 case context::tlsv12:
221 handle_ = ::SSL_CTX_new(::TLS_method());
222 if (handle_)
223 {
224 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
225 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
226 }
227 break;
228 case context::tlsv12_client:
229 handle_ = ::SSL_CTX_new(::TLS_client_method());
230 if (handle_)
231 {
232 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
233 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
234 }
235 break;
236 case context::tlsv12_server:
237 handle_ = ::SSL_CTX_new(::TLS_server_method());
238 if (handle_)
239 {
240 SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
241 SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
242 }
243 break;
244 #elif defined(SSL_TXT_TLSV1_1)
245 case context::tlsv12:
246 handle_ = ::SSL_CTX_new(::TLSv1_2_method());
247 break;
248 case context::tlsv12_client:
249 handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());
250 break;
251 case context::tlsv12_server:
252 handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
253 break;
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");
260 break;
261 #endif // defined(SSL_TXT_TLSV1_1)
262
263 // Any supported SSL/TLS version.
264 case context::sslv23:
265 handle_ = ::SSL_CTX_new(::SSLv23_method());
266 break;
267 case context::sslv23_client:
268 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
269 break;
270 case context::sslv23_server:
271 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
272 break;
273
274 // Any supported TLS version.
275 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
276 case context::tls:
277 handle_ = ::SSL_CTX_new(::TLS_method());
278 if (handle_)
279 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
280 break;
281 case context::tls_client:
282 handle_ = ::SSL_CTX_new(::TLS_client_method());
283 if (handle_)
284 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
285 break;
286 case context::tls_server:
287 handle_ = ::SSL_CTX_new(::TLS_server_method());
288 if (handle_)
289 SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
290 break;
291 #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
292 case context::tls:
293 handle_ = ::SSL_CTX_new(::SSLv23_method());
294 if (handle_)
295 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
296 break;
297 case context::tls_client:
298 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
299 if (handle_)
300 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
301 break;
302 case context::tls_server:
303 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
304 if (handle_)
305 SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
306 break;
307 #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
308
309 default:
310 handle_ = ::SSL_CTX_new(0);
311 break;
312 }
313
314 if (handle_ == 0)
315 {
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");
320 }
321
322 set_options(no_compression);
323 }
324
325 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
326 context::context(context&& other)
327 {
328 handle_ = other.handle_;
329 other.handle_ = 0;
330 }
331
332 context& context::operator=(context&& other)
333 {
334 context tmp(BOOST_ASIO_MOVE_CAST(context)(*this));
335 handle_ = other.handle_;
336 other.handle_ = 0;
337 return *this;
338 }
339 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
340
341 context::~context()
342 {
343 if (handle_)
344 {
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)
350 if (cb_userdata)
351 {
352 detail::password_callback_base* callback =
353 static_cast<detail::password_callback_base*>(
354 cb_userdata);
355 delete callback;
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)
361 }
362
363 if (SSL_CTX_get_app_data(handle_))
364 {
365 detail::verify_callback_base* callback =
366 static_cast<detail::verify_callback_base*>(
367 SSL_CTX_get_app_data(handle_));
368 delete callback;
369 SSL_CTX_set_app_data(handle_, 0);
370 }
371
372 ::SSL_CTX_free(handle_);
373 }
374 }
375
376 context::native_handle_type context::native_handle()
377 {
378 return handle_;
379 }
380
381 void context::clear_options(context::options o)
382 {
383 boost::system::error_code ec;
384 clear_options(o, ec);
385 boost::asio::detail::throw_error(ec, "clear_options");
386 }
387
388 BOOST_ASIO_SYNC_OP_VOID context::clear_options(
389 context::options o, boost::system::error_code& ec)
390 {
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)
395 {
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;
400 }
401 # endif // !defined(SSL_OP_NO_COMPRESSION)
402
403 ::SSL_CTX_clear_options(handle_, o);
404
405 ec = boost::system::error_code();
406 #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
407 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
408 (void)o;
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);
413 }
414
415 void context::set_options(context::options o)
416 {
417 boost::system::error_code ec;
418 set_options(o, ec);
419 boost::asio::detail::throw_error(ec, "set_options");
420 }
421
422 BOOST_ASIO_SYNC_OP_VOID context::set_options(
423 context::options o, boost::system::error_code& ec)
424 {
425 #if !defined(SSL_OP_NO_COMPRESSION)
426 if ((o & context::no_compression) != 0)
427 {
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;
433 }
434 #endif // !defined(SSL_OP_NO_COMPRESSION)
435
436 ::SSL_CTX_set_options(handle_, o);
437
438 ec = boost::system::error_code();
439 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
440 }
441
442 void context::set_verify_mode(verify_mode v)
443 {
444 boost::system::error_code ec;
445 set_verify_mode(v, ec);
446 boost::asio::detail::throw_error(ec, "set_verify_mode");
447 }
448
449 BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
450 verify_mode v, boost::system::error_code& ec)
451 {
452 ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
453
454 ec = boost::system::error_code();
455 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
456 }
457
458 void context::set_verify_depth(int depth)
459 {
460 boost::system::error_code ec;
461 set_verify_depth(depth, ec);
462 boost::asio::detail::throw_error(ec, "set_verify_depth");
463 }
464
465 BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
466 int depth, boost::system::error_code& ec)
467 {
468 ::SSL_CTX_set_verify_depth(handle_, depth);
469
470 ec = boost::system::error_code();
471 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
472 }
473
474 void context::load_verify_file(const std::string& filename)
475 {
476 boost::system::error_code ec;
477 load_verify_file(filename, ec);
478 boost::asio::detail::throw_error(ec, "load_verify_file");
479 }
480
481 BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
482 const std::string& filename, boost::system::error_code& ec)
483 {
484 ::ERR_clear_error();
485
486 if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
487 {
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);
492 }
493
494 ec = boost::system::error_code();
495 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
496 }
497
498 void context::add_certificate_authority(const const_buffer& ca)
499 {
500 boost::system::error_code ec;
501 add_certificate_authority(ca, ec);
502 boost::asio::detail::throw_error(ec, "add_certificate_authority");
503 }
504
505 BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
506 const const_buffer& ca, boost::system::error_code& ec)
507 {
508 ::ERR_clear_error();
509
510 bio_cleanup bio = { make_buffer_bio(ca) };
511 if (bio.p)
512 {
513 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
514 if (cert.p)
515 {
516 if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
517 {
518 if (::X509_STORE_add_cert(store, cert.p) == 1)
519 {
520 ec = boost::system::error_code();
521 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
522 }
523 }
524 }
525 }
526
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);
531 }
532
533 void context::set_default_verify_paths()
534 {
535 boost::system::error_code ec;
536 set_default_verify_paths(ec);
537 boost::asio::detail::throw_error(ec, "set_default_verify_paths");
538 }
539
540 BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
541 boost::system::error_code& ec)
542 {
543 ::ERR_clear_error();
544
545 if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
546 {
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);
551 }
552
553 ec = boost::system::error_code();
554 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
555 }
556
557 void context::add_verify_path(const std::string& path)
558 {
559 boost::system::error_code ec;
560 add_verify_path(path, ec);
561 boost::asio::detail::throw_error(ec, "add_verify_path");
562 }
563
564 BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
565 const std::string& path, boost::system::error_code& ec)
566 {
567 ::ERR_clear_error();
568
569 if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
570 {
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);
575 }
576
577 ec = boost::system::error_code();
578 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
579 }
580
581 void context::use_certificate(
582 const const_buffer& certificate, file_format format)
583 {
584 boost::system::error_code ec;
585 use_certificate(certificate, format, ec);
586 boost::asio::detail::throw_error(ec, "use_certificate");
587 }
588
589 BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
590 const const_buffer& certificate, file_format format,
591 boost::system::error_code& ec)
592 {
593 ::ERR_clear_error();
594
595 if (format == context_base::asn1)
596 {
597 if (::SSL_CTX_use_certificate_ASN1(handle_,
598 static_cast<int>(certificate.size()),
599 static_cast<const unsigned char*>(certificate.data())) == 1)
600 {
601 ec = boost::system::error_code();
602 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
603 }
604 }
605 else if (format == context_base::pem)
606 {
607 bio_cleanup bio = { make_buffer_bio(certificate) };
608 if (bio.p)
609 {
610 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
611 if (cert.p)
612 {
613 if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
614 {
615 ec = boost::system::error_code();
616 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
617 }
618 }
619 }
620 }
621 else
622 {
623 ec = boost::asio::error::invalid_argument;
624 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
625 }
626
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);
631 }
632
633 void context::use_certificate_file(
634 const std::string& filename, file_format format)
635 {
636 boost::system::error_code ec;
637 use_certificate_file(filename, format, ec);
638 boost::asio::detail::throw_error(ec, "use_certificate_file");
639 }
640
641 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
642 const std::string& filename, file_format format,
643 boost::system::error_code& ec)
644 {
645 int file_type;
646 switch (format)
647 {
648 case context_base::asn1:
649 file_type = SSL_FILETYPE_ASN1;
650 break;
651 case context_base::pem:
652 file_type = SSL_FILETYPE_PEM;
653 break;
654 default:
655 {
656 ec = boost::asio::error::invalid_argument;
657 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
658 }
659 }
660
661 ::ERR_clear_error();
662
663 if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
664 {
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);
669 }
670
671 ec = boost::system::error_code();
672 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
673 }
674
675 void context::use_certificate_chain(const const_buffer& chain)
676 {
677 boost::system::error_code ec;
678 use_certificate_chain(chain, ec);
679 boost::asio::detail::throw_error(ec, "use_certificate_chain");
680 }
681
682 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
683 const const_buffer& chain, boost::system::error_code& ec)
684 {
685 ::ERR_clear_error();
686
687 bio_cleanup bio = { make_buffer_bio(chain) };
688 if (bio.p)
689 {
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,
699 callback,
700 cb_userdata) };
701 if (!cert.p)
702 {
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);
706 }
707
708 int result = ::SSL_CTX_use_certificate(handle_, cert.p);
709 if (result == 0 || ::ERR_peek_error() != 0)
710 {
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);
715 }
716
717 #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER)
718 ::SSL_CTX_clear_chain_certs(handle_);
719 #else
720 if (handle_->extra_certs)
721 {
722 ::sk_X509_pop_free(handle_->extra_certs, X509_free);
723 handle_->extra_certs = 0;
724 }
725 #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
726
727 while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
728 callback,
729 cb_userdata))
730 {
731 if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
732 {
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);
737 }
738 }
739
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))
743 {
744 ::ERR_clear_error();
745 ec = boost::system::error_code();
746 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
747 }
748 }
749
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);
754 }
755
756 void context::use_certificate_chain_file(const std::string& filename)
757 {
758 boost::system::error_code ec;
759 use_certificate_chain_file(filename, ec);
760 boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
761 }
762
763 BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
764 const std::string& filename, boost::system::error_code& ec)
765 {
766 ::ERR_clear_error();
767
768 if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
769 {
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);
774 }
775
776 ec = boost::system::error_code();
777 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
778 }
779
780 void context::use_private_key(
781 const const_buffer& private_key, context::file_format format)
782 {
783 boost::system::error_code ec;
784 use_private_key(private_key, format, ec);
785 boost::asio::detail::throw_error(ec, "use_private_key");
786 }
787
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)
791 {
792 ::ERR_clear_error();
793
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)
801
802 bio_cleanup bio = { make_buffer_bio(private_key) };
803 if (bio.p)
804 {
805 evp_pkey_cleanup evp_private_key = { 0 };
806 switch (format)
807 {
808 case context_base::asn1:
809 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
810 break;
811 case context_base::pem:
812 evp_private_key.p = ::PEM_read_bio_PrivateKey(
813 bio.p, 0, callback,
814 cb_userdata);
815 break;
816 default:
817 {
818 ec = boost::asio::error::invalid_argument;
819 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
820 }
821 }
822
823 if (evp_private_key.p)
824 {
825 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
826 {
827 ec = boost::system::error_code();
828 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
829 }
830 }
831 }
832
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);
837 }
838
839 void context::use_private_key_file(
840 const std::string& filename, context::file_format format)
841 {
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");
845 }
846
847 void context::use_rsa_private_key(
848 const const_buffer& private_key, context::file_format format)
849 {
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");
853 }
854
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)
858 {
859 ::ERR_clear_error();
860
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)
868
869 bio_cleanup bio = { make_buffer_bio(private_key) };
870 if (bio.p)
871 {
872 rsa_cleanup rsa_private_key = { 0 };
873 switch (format)
874 {
875 case context_base::asn1:
876 rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
877 break;
878 case context_base::pem:
879 rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
880 bio.p, 0, callback,
881 cb_userdata);
882 break;
883 default:
884 {
885 ec = boost::asio::error::invalid_argument;
886 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
887 }
888 }
889
890 if (rsa_private_key.p)
891 {
892 if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
893 {
894 ec = boost::system::error_code();
895 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
896 }
897 }
898 }
899
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);
904 }
905
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)
909 {
910 int file_type;
911 switch (format)
912 {
913 case context_base::asn1:
914 file_type = SSL_FILETYPE_ASN1;
915 break;
916 case context_base::pem:
917 file_type = SSL_FILETYPE_PEM;
918 break;
919 default:
920 {
921 ec = boost::asio::error::invalid_argument;
922 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
923 }
924 }
925
926 ::ERR_clear_error();
927
928 if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
929 {
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);
934 }
935
936 ec = boost::system::error_code();
937 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
938 }
939
940 void context::use_rsa_private_key_file(
941 const std::string& filename, context::file_format format)
942 {
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");
946 }
947
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)
951 {
952 int file_type;
953 switch (format)
954 {
955 case context_base::asn1:
956 file_type = SSL_FILETYPE_ASN1;
957 break;
958 case context_base::pem:
959 file_type = SSL_FILETYPE_PEM;
960 break;
961 default:
962 {
963 ec = boost::asio::error::invalid_argument;
964 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
965 }
966 }
967
968 ::ERR_clear_error();
969
970 if (::SSL_CTX_use_RSAPrivateKey_file(
971 handle_, filename.c_str(), file_type) != 1)
972 {
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);
977 }
978
979 ec = boost::system::error_code();
980 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
981 }
982
983 void context::use_tmp_dh(const const_buffer& dh)
984 {
985 boost::system::error_code ec;
986 use_tmp_dh(dh, ec);
987 boost::asio::detail::throw_error(ec, "use_tmp_dh");
988 }
989
990 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
991 const const_buffer& dh, boost::system::error_code& ec)
992 {
993 ::ERR_clear_error();
994
995 bio_cleanup bio = { make_buffer_bio(dh) };
996 if (bio.p)
997 {
998 return do_use_tmp_dh(bio.p, ec);
999 }
1000
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);
1005 }
1006
1007 void context::use_tmp_dh_file(const std::string& filename)
1008 {
1009 boost::system::error_code ec;
1010 use_tmp_dh_file(filename, ec);
1011 boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
1012 }
1013
1014 BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
1015 const std::string& filename, boost::system::error_code& ec)
1016 {
1017 ::ERR_clear_error();
1018
1019 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
1020 if (bio.p)
1021 {
1022 return do_use_tmp_dh(bio.p, ec);
1023 }
1024
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);
1029 }
1030
1031 BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
1032 BIO* bio, boost::system::error_code& ec)
1033 {
1034 ::ERR_clear_error();
1035
1036 dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
1037 if (dh.p)
1038 {
1039 if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
1040 {
1041 ec = boost::system::error_code();
1042 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1043 }
1044 }
1045
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);
1050 }
1051
1052 BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
1053 detail::verify_callback_base* callback, boost::system::error_code& ec)
1054 {
1055 if (SSL_CTX_get_app_data(handle_))
1056 {
1057 delete static_cast<detail::verify_callback_base*>(
1058 SSL_CTX_get_app_data(handle_));
1059 }
1060
1061 SSL_CTX_set_app_data(handle_, callback);
1062
1063 ::SSL_CTX_set_verify(handle_,
1064 ::SSL_CTX_get_verify_mode(handle_),
1065 &context::verify_callback_function);
1066
1067 ec = boost::system::error_code();
1068 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1069 }
1070
1071 int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
1072 {
1073 if (ctx)
1074 {
1075 if (SSL* ssl = static_cast<SSL*>(
1076 ::X509_STORE_CTX_get_ex_data(
1077 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
1078 {
1079 if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
1080 {
1081 if (SSL_CTX_get_app_data(handle))
1082 {
1083 detail::verify_callback_base* callback =
1084 static_cast<detail::verify_callback_base*>(
1085 SSL_CTX_get_app_data(handle));
1086
1087 verify_context verify_ctx(ctx);
1088 return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
1089 }
1090 }
1091 }
1092 }
1093
1094 return 0;
1095 }
1096
1097 BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
1098 detail::password_callback_base* callback, boost::system::error_code& ec)
1099 {
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)
1107
1108 if (old_callback)
1109 delete static_cast<detail::password_callback_base*>(
1110 old_callback);
1111
1112 SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
1113
1114 ec = boost::system::error_code();
1115 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1116 }
1117
1118 int context::password_callback_function(
1119 char* buf, int size, int purpose, void* data)
1120 {
1121 using namespace std; // For strncat and strlen.
1122
1123 if (data)
1124 {
1125 detail::password_callback_base* callback =
1126 static_cast<detail::password_callback_base*>(data);
1127
1128 std::string passwd = callback->call(static_cast<std::size_t>(size),
1129 purpose ? context_base::for_writing : context_base::for_reading);
1130
1131 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
1132 strcpy_s(buf, size, passwd.c_str());
1133 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
1134 *buf = '\0';
1135 if (size > 0)
1136 strncat(buf, passwd.c_str(), size - 1);
1137 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
1138
1139 return static_cast<int>(strlen(buf));
1140 }
1141
1142 return 0;
1143 }
1144
1145 BIO* context::make_buffer_bio(const const_buffer& b)
1146 {
1147 return ::BIO_new_mem_buf(
1148 const_cast<void*>(b.data()),
1149 static_cast<int>(b.size()));
1150 }
1151
1152 } // namespace ssl
1153 } // namespace asio
1154 } // namespace boost
1155
1156 #include <boost/asio/detail/pop_options.hpp>
1157
1158 #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP