comparison DEPENDENCIES/generic/include/boost/asio/ssl/impl/context.ipp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 //
2 // ssl/impl/context.ipp
3 // ~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
6 // Copyright (c) 2005-2013 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 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
22 # include <cstring>
23 # include <boost/asio/detail/throw_error.hpp>
24 # include <boost/asio/error.hpp>
25 # include <boost/asio/ssl/context.hpp>
26 # include <boost/asio/ssl/error.hpp>
27 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
28
29 #include <boost/asio/detail/push_options.hpp>
30
31 namespace boost {
32 namespace asio {
33 namespace ssl {
34
35 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
36
37 struct context::bio_cleanup
38 {
39 BIO* p;
40 ~bio_cleanup() { if (p) ::BIO_free(p); }
41 };
42
43 struct context::x509_cleanup
44 {
45 X509* p;
46 ~x509_cleanup() { if (p) ::X509_free(p); }
47 };
48
49 struct context::evp_pkey_cleanup
50 {
51 EVP_PKEY* p;
52 ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }
53 };
54
55 struct context::rsa_cleanup
56 {
57 RSA* p;
58 ~rsa_cleanup() { if (p) ::RSA_free(p); }
59 };
60
61 struct context::dh_cleanup
62 {
63 DH* p;
64 ~dh_cleanup() { if (p) ::DH_free(p); }
65 };
66
67 context::context(context::method m)
68 : handle_(0)
69 {
70 switch (m)
71 {
72 #if defined(OPENSSL_NO_SSL2)
73 case context::sslv2:
74 case context::sslv2_client:
75 case context::sslv2_server:
76 boost::asio::detail::throw_error(
77 boost::asio::error::invalid_argument, "context");
78 break;
79 #else // defined(OPENSSL_NO_SSL2)
80 case context::sslv2:
81 handle_ = ::SSL_CTX_new(::SSLv2_method());
82 break;
83 case context::sslv2_client:
84 handle_ = ::SSL_CTX_new(::SSLv2_client_method());
85 break;
86 case context::sslv2_server:
87 handle_ = ::SSL_CTX_new(::SSLv2_server_method());
88 break;
89 #endif // defined(OPENSSL_NO_SSL2)
90 case context::sslv3:
91 handle_ = ::SSL_CTX_new(::SSLv3_method());
92 break;
93 case context::sslv3_client:
94 handle_ = ::SSL_CTX_new(::SSLv3_client_method());
95 break;
96 case context::sslv3_server:
97 handle_ = ::SSL_CTX_new(::SSLv3_server_method());
98 break;
99 case context::tlsv1:
100 handle_ = ::SSL_CTX_new(::TLSv1_method());
101 break;
102 case context::tlsv1_client:
103 handle_ = ::SSL_CTX_new(::TLSv1_client_method());
104 break;
105 case context::tlsv1_server:
106 handle_ = ::SSL_CTX_new(::TLSv1_server_method());
107 break;
108 case context::sslv23:
109 handle_ = ::SSL_CTX_new(::SSLv23_method());
110 break;
111 case context::sslv23_client:
112 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
113 break;
114 case context::sslv23_server:
115 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
116 break;
117 #if defined(SSL_TXT_TLSV1_1)
118 case context::tlsv11:
119 handle_ = ::SSL_CTX_new(::TLSv1_1_method());
120 break;
121 case context::tlsv11_client:
122 handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());
123 break;
124 case context::tlsv11_server:
125 handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());
126 break;
127 #else // defined(SSL_TXT_TLSV1_1)
128 case context::tlsv11:
129 case context::tlsv11_client:
130 case context::tlsv11_server:
131 boost::asio::detail::throw_error(
132 boost::asio::error::invalid_argument, "context");
133 break;
134 #endif // defined(SSL_TXT_TLSV1_1)
135 #if defined(SSL_TXT_TLSV1_2)
136 case context::tlsv12:
137 handle_ = ::SSL_CTX_new(::TLSv1_2_method());
138 break;
139 case context::tlsv12_client:
140 handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());
141 break;
142 case context::tlsv12_server:
143 handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
144 break;
145 #else // defined(SSL_TXT_TLSV1_2)
146 case context::tlsv12:
147 case context::tlsv12_client:
148 case context::tlsv12_server:
149 boost::asio::detail::throw_error(
150 boost::asio::error::invalid_argument, "context");
151 break;
152 #endif // defined(SSL_TXT_TLSV1_2)
153 default:
154 handle_ = ::SSL_CTX_new(0);
155 break;
156 }
157
158 if (handle_ == 0)
159 {
160 boost::system::error_code ec(
161 static_cast<int>(::ERR_get_error()),
162 boost::asio::error::get_ssl_category());
163 boost::asio::detail::throw_error(ec, "context");
164 }
165
166 set_options(no_compression);
167 }
168
169 context::context(boost::asio::io_service&, context::method m)
170 : handle_(0)
171 {
172 context tmp(m);
173 handle_ = tmp.handle_;
174 tmp.handle_ = 0;
175 }
176
177 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
178 context::context(context&& other)
179 {
180 handle_ = other.handle_;
181 other.handle_ = 0;
182 }
183
184 context& context::operator=(context&& other)
185 {
186 context tmp(BOOST_ASIO_MOVE_CAST(context)(*this));
187 handle_ = other.handle_;
188 other.handle_ = 0;
189 return *this;
190 }
191 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
192
193 context::~context()
194 {
195 if (handle_)
196 {
197 if (handle_->default_passwd_callback_userdata)
198 {
199 detail::password_callback_base* callback =
200 static_cast<detail::password_callback_base*>(
201 handle_->default_passwd_callback_userdata);
202 delete callback;
203 handle_->default_passwd_callback_userdata = 0;
204 }
205
206 if (SSL_CTX_get_app_data(handle_))
207 {
208 detail::verify_callback_base* callback =
209 static_cast<detail::verify_callback_base*>(
210 SSL_CTX_get_app_data(handle_));
211 delete callback;
212 SSL_CTX_set_app_data(handle_, 0);
213 }
214
215 ::SSL_CTX_free(handle_);
216 }
217 }
218
219 context::native_handle_type context::native_handle()
220 {
221 return handle_;
222 }
223
224 context::impl_type context::impl()
225 {
226 return handle_;
227 }
228
229 void context::clear_options(context::options o)
230 {
231 boost::system::error_code ec;
232 clear_options(o, ec);
233 boost::asio::detail::throw_error(ec, "clear_options");
234 }
235
236 boost::system::error_code context::clear_options(
237 context::options o, boost::system::error_code& ec)
238 {
239 #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
240 && (OPENSSL_VERSION_NUMBER != 0x00909000L)
241 # if !defined(SSL_OP_NO_COMPRESSION)
242 if ((o & context::no_compression) != 0)
243 {
244 # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
245 handle_->comp_methods = SSL_COMP_get_compression_methods();
246 # endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
247 o ^= context::no_compression;
248 }
249 # endif // !defined(SSL_OP_NO_COMPRESSION)
250
251 ::SSL_CTX_clear_options(handle_, o);
252
253 ec = boost::system::error_code();
254 #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
255 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
256 (void)o;
257 ec = boost::asio::error::operation_not_supported;
258 #endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
259 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
260 return ec;
261 }
262
263 void context::set_options(context::options o)
264 {
265 boost::system::error_code ec;
266 set_options(o, ec);
267 boost::asio::detail::throw_error(ec, "set_options");
268 }
269
270 boost::system::error_code context::set_options(
271 context::options o, boost::system::error_code& ec)
272 {
273 #if !defined(SSL_OP_NO_COMPRESSION)
274 if ((o & context::no_compression) != 0)
275 {
276 #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
277 handle_->comp_methods =
278 boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
279 #endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
280 o ^= context::no_compression;
281 }
282 #endif // !defined(SSL_OP_NO_COMPRESSION)
283
284 ::SSL_CTX_set_options(handle_, o);
285
286 ec = boost::system::error_code();
287 return ec;
288 }
289
290 void context::set_verify_mode(verify_mode v)
291 {
292 boost::system::error_code ec;
293 set_verify_mode(v, ec);
294 boost::asio::detail::throw_error(ec, "set_verify_mode");
295 }
296
297 boost::system::error_code context::set_verify_mode(
298 verify_mode v, boost::system::error_code& ec)
299 {
300 ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
301
302 ec = boost::system::error_code();
303 return ec;
304 }
305
306 void context::set_verify_depth(int depth)
307 {
308 boost::system::error_code ec;
309 set_verify_depth(depth, ec);
310 boost::asio::detail::throw_error(ec, "set_verify_depth");
311 }
312
313 boost::system::error_code context::set_verify_depth(
314 int depth, boost::system::error_code& ec)
315 {
316 ::SSL_CTX_set_verify_depth(handle_, depth);
317
318 ec = boost::system::error_code();
319 return ec;
320 }
321
322 void context::load_verify_file(const std::string& filename)
323 {
324 boost::system::error_code ec;
325 load_verify_file(filename, ec);
326 boost::asio::detail::throw_error(ec, "load_verify_file");
327 }
328
329 boost::system::error_code context::load_verify_file(
330 const std::string& filename, boost::system::error_code& ec)
331 {
332 if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
333 {
334 ec = boost::system::error_code(
335 static_cast<int>(::ERR_get_error()),
336 boost::asio::error::get_ssl_category());
337 return ec;
338 }
339
340 ec = boost::system::error_code();
341 return ec;
342 }
343
344 void context::add_certificate_authority(const const_buffer& ca)
345 {
346 boost::system::error_code ec;
347 add_certificate_authority(ca, ec);
348 boost::asio::detail::throw_error(ec, "add_certificate_authority");
349 }
350
351 boost::system::error_code context::add_certificate_authority(
352 const const_buffer& ca, boost::system::error_code& ec)
353 {
354 ::ERR_clear_error();
355
356 bio_cleanup bio = { make_buffer_bio(ca) };
357 if (bio.p)
358 {
359 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
360 if (cert.p)
361 {
362 if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
363 {
364 if (::X509_STORE_add_cert(store, cert.p) == 1)
365 {
366 ec = boost::system::error_code();
367 return ec;
368 }
369 }
370 }
371 }
372
373 ec = boost::system::error_code(
374 static_cast<int>(::ERR_get_error()),
375 boost::asio::error::get_ssl_category());
376 return ec;
377 }
378
379 void context::set_default_verify_paths()
380 {
381 boost::system::error_code ec;
382 set_default_verify_paths(ec);
383 boost::asio::detail::throw_error(ec, "set_default_verify_paths");
384 }
385
386 boost::system::error_code context::set_default_verify_paths(
387 boost::system::error_code& ec)
388 {
389 if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
390 {
391 ec = boost::system::error_code(
392 static_cast<int>(::ERR_get_error()),
393 boost::asio::error::get_ssl_category());
394 return ec;
395 }
396
397 ec = boost::system::error_code();
398 return ec;
399 }
400
401 void context::add_verify_path(const std::string& path)
402 {
403 boost::system::error_code ec;
404 add_verify_path(path, ec);
405 boost::asio::detail::throw_error(ec, "add_verify_path");
406 }
407
408 boost::system::error_code context::add_verify_path(
409 const std::string& path, boost::system::error_code& ec)
410 {
411 if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
412 {
413 ec = boost::system::error_code(
414 static_cast<int>(::ERR_get_error()),
415 boost::asio::error::get_ssl_category());
416 return ec;
417 }
418
419 ec = boost::system::error_code();
420 return ec;
421 }
422
423 void context::use_certificate(
424 const const_buffer& certificate, file_format format)
425 {
426 boost::system::error_code ec;
427 use_certificate(certificate, format, ec);
428 boost::asio::detail::throw_error(ec, "use_certificate");
429 }
430
431 boost::system::error_code context::use_certificate(
432 const const_buffer& certificate, file_format format,
433 boost::system::error_code& ec)
434 {
435 ::ERR_clear_error();
436
437 if (format == context_base::asn1)
438 {
439 if (::SSL_CTX_use_certificate_ASN1(handle_,
440 static_cast<int>(buffer_size(certificate)),
441 buffer_cast<const unsigned char*>(certificate)) == 1)
442 {
443 ec = boost::system::error_code();
444 return ec;
445 }
446 }
447 else if (format == context_base::pem)
448 {
449 bio_cleanup bio = { make_buffer_bio(certificate) };
450 if (bio.p)
451 {
452 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
453 if (cert.p)
454 {
455 if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
456 {
457 ec = boost::system::error_code();
458 return ec;
459 }
460 }
461 }
462 }
463 else
464 {
465 ec = boost::asio::error::invalid_argument;
466 return ec;
467 }
468
469 ec = boost::system::error_code(
470 static_cast<int>(::ERR_get_error()),
471 boost::asio::error::get_ssl_category());
472 return ec;
473 }
474
475 void context::use_certificate_file(
476 const std::string& filename, file_format format)
477 {
478 boost::system::error_code ec;
479 use_certificate_file(filename, format, ec);
480 boost::asio::detail::throw_error(ec, "use_certificate_file");
481 }
482
483 boost::system::error_code context::use_certificate_file(
484 const std::string& filename, file_format format,
485 boost::system::error_code& ec)
486 {
487 int file_type;
488 switch (format)
489 {
490 case context_base::asn1:
491 file_type = SSL_FILETYPE_ASN1;
492 break;
493 case context_base::pem:
494 file_type = SSL_FILETYPE_PEM;
495 break;
496 default:
497 {
498 ec = boost::asio::error::invalid_argument;
499 return ec;
500 }
501 }
502
503 if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
504 {
505 ec = boost::system::error_code(
506 static_cast<int>(::ERR_get_error()),
507 boost::asio::error::get_ssl_category());
508 return ec;
509 }
510
511 ec = boost::system::error_code();
512 return ec;
513 }
514
515 void context::use_certificate_chain(const const_buffer& chain)
516 {
517 boost::system::error_code ec;
518 use_certificate_chain(chain, ec);
519 boost::asio::detail::throw_error(ec, "use_certificate_chain");
520 }
521
522 boost::system::error_code context::use_certificate_chain(
523 const const_buffer& chain, boost::system::error_code& ec)
524 {
525 ::ERR_clear_error();
526
527 bio_cleanup bio = { make_buffer_bio(chain) };
528 if (bio.p)
529 {
530 x509_cleanup cert = {
531 ::PEM_read_bio_X509_AUX(bio.p, 0,
532 handle_->default_passwd_callback,
533 handle_->default_passwd_callback_userdata) };
534 if (!cert.p)
535 {
536 ec = boost::system::error_code(ERR_R_PEM_LIB,
537 boost::asio::error::get_ssl_category());
538 return ec;
539 }
540
541 int result = ::SSL_CTX_use_certificate(handle_, cert.p);
542 if (result == 0 || ::ERR_peek_error() != 0)
543 {
544 ec = boost::system::error_code(
545 static_cast<int>(::ERR_get_error()),
546 boost::asio::error::get_ssl_category());
547 return ec;
548 }
549
550 if (handle_->extra_certs)
551 {
552 ::sk_X509_pop_free(handle_->extra_certs, X509_free);
553 handle_->extra_certs = 0;
554 }
555
556 while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
557 handle_->default_passwd_callback,
558 handle_->default_passwd_callback_userdata))
559 {
560 if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
561 {
562 ec = boost::system::error_code(
563 static_cast<int>(::ERR_get_error()),
564 boost::asio::error::get_ssl_category());
565 return ec;
566 }
567 }
568
569 result = ::ERR_peek_last_error();
570 if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
571 && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
572 {
573 ::ERR_clear_error();
574 ec = boost::system::error_code();
575 return ec;
576 }
577 }
578
579 ec = boost::system::error_code(
580 static_cast<int>(::ERR_get_error()),
581 boost::asio::error::get_ssl_category());
582 return ec;
583 }
584
585 void context::use_certificate_chain_file(const std::string& filename)
586 {
587 boost::system::error_code ec;
588 use_certificate_chain_file(filename, ec);
589 boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
590 }
591
592 boost::system::error_code context::use_certificate_chain_file(
593 const std::string& filename, boost::system::error_code& ec)
594 {
595 if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
596 {
597 ec = boost::system::error_code(
598 static_cast<int>(::ERR_get_error()),
599 boost::asio::error::get_ssl_category());
600 return ec;
601 }
602
603 ec = boost::system::error_code();
604 return ec;
605 }
606
607 void context::use_private_key(
608 const const_buffer& private_key, context::file_format format)
609 {
610 boost::system::error_code ec;
611 use_private_key(private_key, format, ec);
612 boost::asio::detail::throw_error(ec, "use_private_key");
613 }
614
615 boost::system::error_code context::use_private_key(
616 const const_buffer& private_key, context::file_format format,
617 boost::system::error_code& ec)
618 {
619 ::ERR_clear_error();
620
621 bio_cleanup bio = { make_buffer_bio(private_key) };
622 if (bio.p)
623 {
624 evp_pkey_cleanup evp_private_key = { 0 };
625 switch (format)
626 {
627 case context_base::asn1:
628 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
629 break;
630 case context_base::pem:
631 evp_private_key.p = ::PEM_read_bio_PrivateKey(bio.p, 0, 0, 0);
632 break;
633 default:
634 {
635 ec = boost::asio::error::invalid_argument;
636 return ec;
637 }
638 }
639
640 if (evp_private_key.p)
641 {
642 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
643 {
644 ec = boost::system::error_code();
645 return ec;
646 }
647 }
648 }
649
650 ec = boost::system::error_code(
651 static_cast<int>(::ERR_get_error()),
652 boost::asio::error::get_ssl_category());
653 return ec;
654 }
655
656 void context::use_private_key_file(
657 const std::string& filename, context::file_format format)
658 {
659 boost::system::error_code ec;
660 use_private_key_file(filename, format, ec);
661 boost::asio::detail::throw_error(ec, "use_private_key_file");
662 }
663
664 void context::use_rsa_private_key(
665 const const_buffer& private_key, context::file_format format)
666 {
667 boost::system::error_code ec;
668 use_rsa_private_key(private_key, format, ec);
669 boost::asio::detail::throw_error(ec, "use_rsa_private_key");
670 }
671
672 boost::system::error_code context::use_rsa_private_key(
673 const const_buffer& private_key, context::file_format format,
674 boost::system::error_code& ec)
675 {
676 ::ERR_clear_error();
677
678 bio_cleanup bio = { make_buffer_bio(private_key) };
679 if (bio.p)
680 {
681 rsa_cleanup rsa_private_key = { 0 };
682 switch (format)
683 {
684 case context_base::asn1:
685 rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
686 break;
687 case context_base::pem:
688 rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(bio.p, 0, 0, 0);
689 break;
690 default:
691 {
692 ec = boost::asio::error::invalid_argument;
693 return ec;
694 }
695 }
696
697 if (rsa_private_key.p)
698 {
699 if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
700 {
701 ec = boost::system::error_code();
702 return ec;
703 }
704 }
705 }
706
707 ec = boost::system::error_code(
708 static_cast<int>(::ERR_get_error()),
709 boost::asio::error::get_ssl_category());
710 return ec;
711 }
712
713 boost::system::error_code context::use_private_key_file(
714 const std::string& filename, context::file_format format,
715 boost::system::error_code& ec)
716 {
717 int file_type;
718 switch (format)
719 {
720 case context_base::asn1:
721 file_type = SSL_FILETYPE_ASN1;
722 break;
723 case context_base::pem:
724 file_type = SSL_FILETYPE_PEM;
725 break;
726 default:
727 {
728 ec = boost::asio::error::invalid_argument;
729 return ec;
730 }
731 }
732
733 if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
734 {
735 ec = boost::system::error_code(
736 static_cast<int>(::ERR_get_error()),
737 boost::asio::error::get_ssl_category());
738 return ec;
739 }
740
741 ec = boost::system::error_code();
742 return ec;
743 }
744
745 void context::use_rsa_private_key_file(
746 const std::string& filename, context::file_format format)
747 {
748 boost::system::error_code ec;
749 use_rsa_private_key_file(filename, format, ec);
750 boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
751 }
752
753 boost::system::error_code context::use_rsa_private_key_file(
754 const std::string& filename, context::file_format format,
755 boost::system::error_code& ec)
756 {
757 int file_type;
758 switch (format)
759 {
760 case context_base::asn1:
761 file_type = SSL_FILETYPE_ASN1;
762 break;
763 case context_base::pem:
764 file_type = SSL_FILETYPE_PEM;
765 break;
766 default:
767 {
768 ec = boost::asio::error::invalid_argument;
769 return ec;
770 }
771 }
772
773 if (::SSL_CTX_use_RSAPrivateKey_file(
774 handle_, filename.c_str(), file_type) != 1)
775 {
776 ec = boost::system::error_code(
777 static_cast<int>(::ERR_get_error()),
778 boost::asio::error::get_ssl_category());
779 return ec;
780 }
781
782 ec = boost::system::error_code();
783 return ec;
784 }
785
786 void context::use_tmp_dh(const const_buffer& dh)
787 {
788 boost::system::error_code ec;
789 use_tmp_dh(dh, ec);
790 boost::asio::detail::throw_error(ec, "use_tmp_dh");
791 }
792
793 boost::system::error_code context::use_tmp_dh(
794 const const_buffer& dh, boost::system::error_code& ec)
795 {
796 bio_cleanup bio = { make_buffer_bio(dh) };
797 if (bio.p)
798 {
799 return do_use_tmp_dh(bio.p, ec);
800 }
801
802 ec = boost::system::error_code(
803 static_cast<int>(::ERR_get_error()),
804 boost::asio::error::get_ssl_category());
805 return ec;
806 }
807
808 void context::use_tmp_dh_file(const std::string& filename)
809 {
810 boost::system::error_code ec;
811 use_tmp_dh_file(filename, ec);
812 boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
813 }
814
815 boost::system::error_code context::use_tmp_dh_file(
816 const std::string& filename, boost::system::error_code& ec)
817 {
818 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
819 if (bio.p)
820 {
821 return do_use_tmp_dh(bio.p, ec);
822 }
823
824 ec = boost::system::error_code(
825 static_cast<int>(::ERR_get_error()),
826 boost::asio::error::get_ssl_category());
827 return ec;
828 }
829
830 boost::system::error_code context::do_use_tmp_dh(
831 BIO* bio, boost::system::error_code& ec)
832 {
833 ::ERR_clear_error();
834
835 dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
836 if (dh.p)
837 {
838 if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
839 {
840 ec = boost::system::error_code();
841 return ec;
842 }
843 }
844
845 ec = boost::system::error_code(
846 static_cast<int>(::ERR_get_error()),
847 boost::asio::error::get_ssl_category());
848 return ec;
849 }
850
851 boost::system::error_code context::do_set_verify_callback(
852 detail::verify_callback_base* callback, boost::system::error_code& ec)
853 {
854 if (SSL_CTX_get_app_data(handle_))
855 {
856 delete static_cast<detail::verify_callback_base*>(
857 SSL_CTX_get_app_data(handle_));
858 }
859
860 SSL_CTX_set_app_data(handle_, callback);
861
862 ::SSL_CTX_set_verify(handle_,
863 ::SSL_CTX_get_verify_mode(handle_),
864 &context::verify_callback_function);
865
866 ec = boost::system::error_code();
867 return ec;
868 }
869
870 int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
871 {
872 if (ctx)
873 {
874 if (SSL* ssl = static_cast<SSL*>(
875 ::X509_STORE_CTX_get_ex_data(
876 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
877 {
878 if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
879 {
880 if (SSL_CTX_get_app_data(handle))
881 {
882 detail::verify_callback_base* callback =
883 static_cast<detail::verify_callback_base*>(
884 SSL_CTX_get_app_data(handle));
885
886 verify_context verify_ctx(ctx);
887 return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
888 }
889 }
890 }
891 }
892
893 return 0;
894 }
895
896 boost::system::error_code context::do_set_password_callback(
897 detail::password_callback_base* callback, boost::system::error_code& ec)
898 {
899 if (handle_->default_passwd_callback_userdata)
900 delete static_cast<detail::password_callback_base*>(
901 handle_->default_passwd_callback_userdata);
902
903 handle_->default_passwd_callback_userdata = callback;
904
905 SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
906
907 ec = boost::system::error_code();
908 return ec;
909 }
910
911 int context::password_callback_function(
912 char* buf, int size, int purpose, void* data)
913 {
914 using namespace std; // For strncat and strlen.
915
916 if (data)
917 {
918 detail::password_callback_base* callback =
919 static_cast<detail::password_callback_base*>(data);
920
921 std::string passwd = callback->call(static_cast<std::size_t>(size),
922 purpose ? context_base::for_writing : context_base::for_reading);
923
924 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
925 strcpy_s(buf, size, passwd.c_str());
926 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
927 *buf = '\0';
928 strncat(buf, passwd.c_str(), size);
929 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
930
931 return static_cast<int>(strlen(buf));
932 }
933
934 return 0;
935 }
936
937 BIO* context::make_buffer_bio(const const_buffer& b)
938 {
939 return ::BIO_new_mem_buf(
940 const_cast<void*>(buffer_cast<const void*>(b)),
941 static_cast<int>(buffer_size(b)));
942 }
943
944 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
945
946 } // namespace ssl
947 } // namespace asio
948 } // namespace boost
949
950 #include <boost/asio/detail/pop_options.hpp>
951
952 #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP