Mercurial > hg > vamp-build-and-test
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 |