]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // ssl/impl/context.ipp | |
3 | // ~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com | |
92f5a8d4 | 6 | // Copyright (c) 2005-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
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 | ||
b32b8144 FG |
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> | |
7c673cae FG |
26 | |
27 | #include <boost/asio/detail/push_options.hpp> | |
28 | ||
29 | namespace boost { | |
30 | namespace asio { | |
31 | namespace ssl { | |
32 | ||
7c673cae FG |
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 | { | |
b32b8144 FG |
70 | // SSL v2. |
71 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2) | |
7c673cae FG |
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; | |
b32b8144 | 78 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2) |
7c673cae FG |
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; | |
b32b8144 FG |
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) | |
7c673cae FG |
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) | |
b32b8144 FG |
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; | |
92f5a8d4 | 161 | #elif defined(SSL_TXT_TLSV1) |
7c673cae FG |
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; | |
92f5a8d4 TL |
171 | #else // defined(SSL_TXT_TLSV1) |
172 | case context::tlsv1: | |
173 | case context::tlsv1_client: | |
174 | case context::tlsv1_server: | |
175 | boost::asio::detail::throw_error( | |
176 | boost::asio::error::invalid_argument, "context"); | |
177 | break; | |
178 | #endif // defined(SSL_TXT_TLSV1) | |
b32b8144 FG |
179 | |
180 | // TLS v1.1. | |
181 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) | |
182 | case context::tlsv11: | |
183 | handle_ = ::SSL_CTX_new(::TLS_method()); | |
184 | if (handle_) | |
185 | { | |
186 | SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION); | |
187 | SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION); | |
188 | } | |
7c673cae | 189 | break; |
b32b8144 FG |
190 | case context::tlsv11_client: |
191 | handle_ = ::SSL_CTX_new(::TLS_client_method()); | |
192 | if (handle_) | |
193 | { | |
194 | SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION); | |
195 | SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION); | |
196 | } | |
7c673cae | 197 | break; |
b32b8144 FG |
198 | case context::tlsv11_server: |
199 | handle_ = ::SSL_CTX_new(::TLS_server_method()); | |
200 | if (handle_) | |
201 | { | |
202 | SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION); | |
203 | SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION); | |
204 | } | |
7c673cae | 205 | break; |
b32b8144 | 206 | #elif defined(SSL_TXT_TLSV1_1) |
7c673cae FG |
207 | case context::tlsv11: |
208 | handle_ = ::SSL_CTX_new(::TLSv1_1_method()); | |
209 | break; | |
210 | case context::tlsv11_client: | |
211 | handle_ = ::SSL_CTX_new(::TLSv1_1_client_method()); | |
212 | break; | |
213 | case context::tlsv11_server: | |
214 | handle_ = ::SSL_CTX_new(::TLSv1_1_server_method()); | |
215 | break; | |
216 | #else // defined(SSL_TXT_TLSV1_1) | |
217 | case context::tlsv11: | |
218 | case context::tlsv11_client: | |
219 | case context::tlsv11_server: | |
220 | boost::asio::detail::throw_error( | |
221 | boost::asio::error::invalid_argument, "context"); | |
222 | break; | |
223 | #endif // defined(SSL_TXT_TLSV1_1) | |
b32b8144 FG |
224 | |
225 | // TLS v1.2. | |
226 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) | |
227 | case context::tlsv12: | |
228 | handle_ = ::SSL_CTX_new(::TLS_method()); | |
229 | if (handle_) | |
230 | { | |
231 | SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION); | |
232 | SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION); | |
233 | } | |
234 | break; | |
235 | case context::tlsv12_client: | |
236 | handle_ = ::SSL_CTX_new(::TLS_client_method()); | |
237 | if (handle_) | |
238 | { | |
239 | SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION); | |
240 | SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION); | |
241 | } | |
242 | break; | |
243 | case context::tlsv12_server: | |
244 | handle_ = ::SSL_CTX_new(::TLS_server_method()); | |
245 | if (handle_) | |
246 | { | |
247 | SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION); | |
248 | SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION); | |
249 | } | |
250 | break; | |
92f5a8d4 | 251 | #elif defined(SSL_TXT_TLSV1_2) |
7c673cae FG |
252 | case context::tlsv12: |
253 | handle_ = ::SSL_CTX_new(::TLSv1_2_method()); | |
254 | break; | |
255 | case context::tlsv12_client: | |
256 | handle_ = ::SSL_CTX_new(::TLSv1_2_client_method()); | |
257 | break; | |
258 | case context::tlsv12_server: | |
259 | handle_ = ::SSL_CTX_new(::TLSv1_2_server_method()); | |
260 | break; | |
92f5a8d4 | 261 | #else // defined(SSL_TXT_TLSV1_2) |
7c673cae FG |
262 | case context::tlsv12: |
263 | case context::tlsv12_client: | |
264 | case context::tlsv12_server: | |
265 | boost::asio::detail::throw_error( | |
266 | boost::asio::error::invalid_argument, "context"); | |
267 | break; | |
92f5a8d4 TL |
268 | #endif // defined(SSL_TXT_TLSV1_2) |
269 | ||
270 | // TLS v1.3. | |
271 | #if (OPENSSL_VERSION_NUMBER >= 0x10101000L) \ | |
272 | && !defined(LIBRESSL_VERSION_NUMBER) | |
273 | case context::tlsv13: | |
274 | handle_ = ::SSL_CTX_new(::TLS_method()); | |
275 | if (handle_) | |
276 | { | |
277 | SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION); | |
278 | SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION); | |
279 | } | |
280 | break; | |
281 | case context::tlsv13_client: | |
282 | handle_ = ::SSL_CTX_new(::TLS_client_method()); | |
283 | if (handle_) | |
284 | { | |
285 | SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION); | |
286 | SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION); | |
287 | } | |
288 | break; | |
289 | case context::tlsv13_server: | |
290 | handle_ = ::SSL_CTX_new(::TLS_server_method()); | |
291 | if (handle_) | |
292 | { | |
293 | SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION); | |
294 | SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION); | |
295 | } | |
296 | break; | |
297 | #else // (OPENSSL_VERSION_NUMBER >= 0x10101000L) | |
298 | // && !defined(LIBRESSL_VERSION_NUMBER) | |
299 | case context::tlsv13: | |
300 | case context::tlsv13_client: | |
301 | case context::tlsv13_server: | |
302 | boost::asio::detail::throw_error( | |
303 | boost::asio::error::invalid_argument, "context"); | |
304 | break; | |
305 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10101000L) | |
306 | // && !defined(LIBRESSL_VERSION_NUMBER) | |
b32b8144 FG |
307 | |
308 | // Any supported SSL/TLS version. | |
309 | case context::sslv23: | |
310 | handle_ = ::SSL_CTX_new(::SSLv23_method()); | |
311 | break; | |
312 | case context::sslv23_client: | |
313 | handle_ = ::SSL_CTX_new(::SSLv23_client_method()); | |
314 | break; | |
315 | case context::sslv23_server: | |
316 | handle_ = ::SSL_CTX_new(::SSLv23_server_method()); | |
317 | break; | |
318 | ||
319 | // Any supported TLS version. | |
320 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) | |
321 | case context::tls: | |
7c673cae | 322 | handle_ = ::SSL_CTX_new(::TLS_method()); |
b32b8144 FG |
323 | if (handle_) |
324 | SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION); | |
7c673cae | 325 | break; |
b32b8144 | 326 | case context::tls_client: |
7c673cae | 327 | handle_ = ::SSL_CTX_new(::TLS_client_method()); |
b32b8144 FG |
328 | if (handle_) |
329 | SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION); | |
7c673cae | 330 | break; |
b32b8144 | 331 | case context::tls_server: |
7c673cae | 332 | handle_ = ::SSL_CTX_new(::TLS_server_method()); |
b32b8144 FG |
333 | if (handle_) |
334 | SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION); | |
335 | break; | |
336 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
337 | case context::tls: | |
338 | handle_ = ::SSL_CTX_new(::SSLv23_method()); | |
339 | if (handle_) | |
340 | SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); | |
341 | break; | |
342 | case context::tls_client: | |
343 | handle_ = ::SSL_CTX_new(::SSLv23_client_method()); | |
344 | if (handle_) | |
345 | SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); | |
7c673cae | 346 | break; |
b32b8144 FG |
347 | case context::tls_server: |
348 | handle_ = ::SSL_CTX_new(::SSLv23_server_method()); | |
349 | if (handle_) | |
350 | SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); | |
351 | break; | |
352 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
353 | ||
7c673cae FG |
354 | default: |
355 | handle_ = ::SSL_CTX_new(0); | |
356 | break; | |
357 | } | |
358 | ||
359 | if (handle_ == 0) | |
360 | { | |
361 | boost::system::error_code ec( | |
362 | static_cast<int>(::ERR_get_error()), | |
363 | boost::asio::error::get_ssl_category()); | |
364 | boost::asio::detail::throw_error(ec, "context"); | |
365 | } | |
366 | ||
367 | set_options(no_compression); | |
368 | } | |
369 | ||
7c673cae FG |
370 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
371 | context::context(context&& other) | |
372 | { | |
373 | handle_ = other.handle_; | |
374 | other.handle_ = 0; | |
375 | } | |
376 | ||
377 | context& context::operator=(context&& other) | |
378 | { | |
379 | context tmp(BOOST_ASIO_MOVE_CAST(context)(*this)); | |
380 | handle_ = other.handle_; | |
381 | other.handle_ = 0; | |
382 | return *this; | |
383 | } | |
384 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
385 | ||
386 | context::~context() | |
387 | { | |
388 | if (handle_) | |
389 | { | |
92f5a8d4 TL |
390 | #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \ |
391 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
392 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
393 | void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); |
394 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
395 | void* cb_userdata = handle_->default_passwd_callback_userdata; | |
396 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
397 | if (cb_userdata) | |
398 | { | |
399 | detail::password_callback_base* callback = | |
400 | static_cast<detail::password_callback_base*>( | |
401 | cb_userdata); | |
402 | delete callback; | |
92f5a8d4 TL |
403 | #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \ |
404 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
405 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
406 | ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0); |
407 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
408 | handle_->default_passwd_callback_userdata = 0; | |
409 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
410 | } | |
411 | ||
412 | if (SSL_CTX_get_app_data(handle_)) | |
413 | { | |
414 | detail::verify_callback_base* callback = | |
415 | static_cast<detail::verify_callback_base*>( | |
416 | SSL_CTX_get_app_data(handle_)); | |
417 | delete callback; | |
418 | SSL_CTX_set_app_data(handle_, 0); | |
419 | } | |
420 | ||
421 | ::SSL_CTX_free(handle_); | |
422 | } | |
423 | } | |
424 | ||
425 | context::native_handle_type context::native_handle() | |
426 | { | |
427 | return handle_; | |
428 | } | |
429 | ||
7c673cae FG |
430 | void context::clear_options(context::options o) |
431 | { | |
432 | boost::system::error_code ec; | |
433 | clear_options(o, ec); | |
434 | boost::asio::detail::throw_error(ec, "clear_options"); | |
435 | } | |
436 | ||
b32b8144 | 437 | BOOST_ASIO_SYNC_OP_VOID context::clear_options( |
7c673cae FG |
438 | context::options o, boost::system::error_code& ec) |
439 | { | |
440 | #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \ | |
441 | && (OPENSSL_VERSION_NUMBER != 0x00909000L) | |
442 | # if !defined(SSL_OP_NO_COMPRESSION) | |
443 | if ((o & context::no_compression) != 0) | |
444 | { | |
445 | # if (OPENSSL_VERSION_NUMBER >= 0x00908000L) | |
446 | handle_->comp_methods = SSL_COMP_get_compression_methods(); | |
447 | # endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L) | |
448 | o ^= context::no_compression; | |
449 | } | |
450 | # endif // !defined(SSL_OP_NO_COMPRESSION) | |
451 | ||
452 | ::SSL_CTX_clear_options(handle_, o); | |
453 | ||
454 | ec = boost::system::error_code(); | |
455 | #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL) | |
456 | // && (OPENSSL_VERSION_NUMBER != 0x00909000L) | |
457 | (void)o; | |
458 | ec = boost::asio::error::operation_not_supported; | |
459 | #endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL) | |
460 | // && (OPENSSL_VERSION_NUMBER != 0x00909000L) | |
b32b8144 | 461 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
462 | } |
463 | ||
464 | void context::set_options(context::options o) | |
465 | { | |
466 | boost::system::error_code ec; | |
467 | set_options(o, ec); | |
468 | boost::asio::detail::throw_error(ec, "set_options"); | |
469 | } | |
470 | ||
b32b8144 | 471 | BOOST_ASIO_SYNC_OP_VOID context::set_options( |
7c673cae FG |
472 | context::options o, boost::system::error_code& ec) |
473 | { | |
474 | #if !defined(SSL_OP_NO_COMPRESSION) | |
475 | if ((o & context::no_compression) != 0) | |
476 | { | |
477 | #if (OPENSSL_VERSION_NUMBER >= 0x00908000L) | |
478 | handle_->comp_methods = | |
479 | boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods(); | |
480 | #endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L) | |
481 | o ^= context::no_compression; | |
482 | } | |
483 | #endif // !defined(SSL_OP_NO_COMPRESSION) | |
484 | ||
485 | ::SSL_CTX_set_options(handle_, o); | |
486 | ||
487 | ec = boost::system::error_code(); | |
b32b8144 | 488 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
489 | } |
490 | ||
491 | void context::set_verify_mode(verify_mode v) | |
492 | { | |
493 | boost::system::error_code ec; | |
494 | set_verify_mode(v, ec); | |
495 | boost::asio::detail::throw_error(ec, "set_verify_mode"); | |
496 | } | |
497 | ||
b32b8144 | 498 | BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode( |
7c673cae FG |
499 | verify_mode v, boost::system::error_code& ec) |
500 | { | |
501 | ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_)); | |
502 | ||
503 | ec = boost::system::error_code(); | |
b32b8144 | 504 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
505 | } |
506 | ||
507 | void context::set_verify_depth(int depth) | |
508 | { | |
509 | boost::system::error_code ec; | |
510 | set_verify_depth(depth, ec); | |
511 | boost::asio::detail::throw_error(ec, "set_verify_depth"); | |
512 | } | |
513 | ||
b32b8144 | 514 | BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth( |
7c673cae FG |
515 | int depth, boost::system::error_code& ec) |
516 | { | |
517 | ::SSL_CTX_set_verify_depth(handle_, depth); | |
518 | ||
519 | ec = boost::system::error_code(); | |
b32b8144 | 520 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
521 | } |
522 | ||
523 | void context::load_verify_file(const std::string& filename) | |
524 | { | |
525 | boost::system::error_code ec; | |
526 | load_verify_file(filename, ec); | |
527 | boost::asio::detail::throw_error(ec, "load_verify_file"); | |
528 | } | |
529 | ||
b32b8144 | 530 | BOOST_ASIO_SYNC_OP_VOID context::load_verify_file( |
7c673cae FG |
531 | const std::string& filename, boost::system::error_code& ec) |
532 | { | |
533 | ::ERR_clear_error(); | |
534 | ||
535 | if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1) | |
536 | { | |
537 | ec = boost::system::error_code( | |
538 | static_cast<int>(::ERR_get_error()), | |
539 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 540 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
541 | } |
542 | ||
543 | ec = boost::system::error_code(); | |
b32b8144 | 544 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
545 | } |
546 | ||
547 | void context::add_certificate_authority(const const_buffer& ca) | |
548 | { | |
549 | boost::system::error_code ec; | |
550 | add_certificate_authority(ca, ec); | |
551 | boost::asio::detail::throw_error(ec, "add_certificate_authority"); | |
552 | } | |
553 | ||
b32b8144 | 554 | BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority( |
7c673cae FG |
555 | const const_buffer& ca, boost::system::error_code& ec) |
556 | { | |
557 | ::ERR_clear_error(); | |
558 | ||
559 | bio_cleanup bio = { make_buffer_bio(ca) }; | |
560 | if (bio.p) | |
561 | { | |
11fdf7f2 | 562 | if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_)) |
7c673cae | 563 | { |
11fdf7f2 | 564 | for (;;) |
7c673cae | 565 | { |
11fdf7f2 TL |
566 | x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) }; |
567 | if (!cert.p) | |
568 | break; | |
569 | ||
570 | if (::X509_STORE_add_cert(store, cert.p) != 1) | |
7c673cae | 571 | { |
11fdf7f2 TL |
572 | ec = boost::system::error_code( |
573 | static_cast<int>(::ERR_get_error()), | |
574 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 575 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
576 | } |
577 | } | |
578 | } | |
579 | } | |
580 | ||
11fdf7f2 | 581 | ec = boost::system::error_code(); |
b32b8144 | 582 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
583 | } |
584 | ||
585 | void context::set_default_verify_paths() | |
586 | { | |
587 | boost::system::error_code ec; | |
588 | set_default_verify_paths(ec); | |
589 | boost::asio::detail::throw_error(ec, "set_default_verify_paths"); | |
590 | } | |
591 | ||
b32b8144 | 592 | BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths( |
7c673cae FG |
593 | boost::system::error_code& ec) |
594 | { | |
595 | ::ERR_clear_error(); | |
596 | ||
597 | if (::SSL_CTX_set_default_verify_paths(handle_) != 1) | |
598 | { | |
599 | ec = boost::system::error_code( | |
600 | static_cast<int>(::ERR_get_error()), | |
601 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 602 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
603 | } |
604 | ||
605 | ec = boost::system::error_code(); | |
b32b8144 | 606 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
607 | } |
608 | ||
609 | void context::add_verify_path(const std::string& path) | |
610 | { | |
611 | boost::system::error_code ec; | |
612 | add_verify_path(path, ec); | |
613 | boost::asio::detail::throw_error(ec, "add_verify_path"); | |
614 | } | |
615 | ||
b32b8144 | 616 | BOOST_ASIO_SYNC_OP_VOID context::add_verify_path( |
7c673cae FG |
617 | const std::string& path, boost::system::error_code& ec) |
618 | { | |
619 | ::ERR_clear_error(); | |
620 | ||
621 | if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1) | |
622 | { | |
623 | ec = boost::system::error_code( | |
624 | static_cast<int>(::ERR_get_error()), | |
625 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 626 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
627 | } |
628 | ||
629 | ec = boost::system::error_code(); | |
b32b8144 | 630 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
631 | } |
632 | ||
633 | void context::use_certificate( | |
634 | const const_buffer& certificate, file_format format) | |
635 | { | |
636 | boost::system::error_code ec; | |
637 | use_certificate(certificate, format, ec); | |
638 | boost::asio::detail::throw_error(ec, "use_certificate"); | |
639 | } | |
640 | ||
b32b8144 | 641 | BOOST_ASIO_SYNC_OP_VOID context::use_certificate( |
7c673cae FG |
642 | const const_buffer& certificate, file_format format, |
643 | boost::system::error_code& ec) | |
644 | { | |
645 | ::ERR_clear_error(); | |
646 | ||
647 | if (format == context_base::asn1) | |
648 | { | |
649 | if (::SSL_CTX_use_certificate_ASN1(handle_, | |
b32b8144 FG |
650 | static_cast<int>(certificate.size()), |
651 | static_cast<const unsigned char*>(certificate.data())) == 1) | |
7c673cae FG |
652 | { |
653 | ec = boost::system::error_code(); | |
b32b8144 | 654 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
655 | } |
656 | } | |
657 | else if (format == context_base::pem) | |
658 | { | |
659 | bio_cleanup bio = { make_buffer_bio(certificate) }; | |
660 | if (bio.p) | |
661 | { | |
662 | x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) }; | |
663 | if (cert.p) | |
664 | { | |
665 | if (::SSL_CTX_use_certificate(handle_, cert.p) == 1) | |
666 | { | |
667 | ec = boost::system::error_code(); | |
b32b8144 | 668 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
669 | } |
670 | } | |
671 | } | |
672 | } | |
673 | else | |
674 | { | |
675 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 676 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
677 | } |
678 | ||
679 | ec = boost::system::error_code( | |
680 | static_cast<int>(::ERR_get_error()), | |
681 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 682 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
683 | } |
684 | ||
685 | void context::use_certificate_file( | |
686 | const std::string& filename, file_format format) | |
687 | { | |
688 | boost::system::error_code ec; | |
689 | use_certificate_file(filename, format, ec); | |
690 | boost::asio::detail::throw_error(ec, "use_certificate_file"); | |
691 | } | |
692 | ||
b32b8144 | 693 | BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file( |
7c673cae FG |
694 | const std::string& filename, file_format format, |
695 | boost::system::error_code& ec) | |
696 | { | |
697 | int file_type; | |
698 | switch (format) | |
699 | { | |
700 | case context_base::asn1: | |
701 | file_type = SSL_FILETYPE_ASN1; | |
702 | break; | |
703 | case context_base::pem: | |
704 | file_type = SSL_FILETYPE_PEM; | |
705 | break; | |
706 | default: | |
707 | { | |
708 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 709 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
710 | } |
711 | } | |
712 | ||
713 | ::ERR_clear_error(); | |
714 | ||
715 | if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1) | |
716 | { | |
717 | ec = boost::system::error_code( | |
718 | static_cast<int>(::ERR_get_error()), | |
719 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 720 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
721 | } |
722 | ||
723 | ec = boost::system::error_code(); | |
b32b8144 | 724 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
725 | } |
726 | ||
727 | void context::use_certificate_chain(const const_buffer& chain) | |
728 | { | |
729 | boost::system::error_code ec; | |
730 | use_certificate_chain(chain, ec); | |
731 | boost::asio::detail::throw_error(ec, "use_certificate_chain"); | |
732 | } | |
733 | ||
b32b8144 | 734 | BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain( |
7c673cae FG |
735 | const const_buffer& chain, boost::system::error_code& ec) |
736 | { | |
737 | ::ERR_clear_error(); | |
738 | ||
739 | bio_cleanup bio = { make_buffer_bio(chain) }; | |
740 | if (bio.p) | |
741 | { | |
92f5a8d4 TL |
742 | #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \ |
743 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
744 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
745 | pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); |
746 | void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); | |
747 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
748 | pem_password_cb* callback = handle_->default_passwd_callback; | |
749 | void* cb_userdata = handle_->default_passwd_callback_userdata; | |
750 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
751 | x509_cleanup cert = { | |
752 | ::PEM_read_bio_X509_AUX(bio.p, 0, | |
753 | callback, | |
754 | cb_userdata) }; | |
755 | if (!cert.p) | |
756 | { | |
757 | ec = boost::system::error_code(ERR_R_PEM_LIB, | |
758 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 759 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
760 | } |
761 | ||
762 | int result = ::SSL_CTX_use_certificate(handle_, cert.p); | |
763 | if (result == 0 || ::ERR_peek_error() != 0) | |
764 | { | |
765 | ec = boost::system::error_code( | |
766 | static_cast<int>(::ERR_get_error()), | |
767 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 768 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
769 | } |
770 | ||
92f5a8d4 TL |
771 | #if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \ |
772 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
773 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
774 | ::SSL_CTX_clear_chain_certs(handle_); |
775 | #else | |
776 | if (handle_->extra_certs) | |
777 | { | |
778 | ::sk_X509_pop_free(handle_->extra_certs, X509_free); | |
779 | handle_->extra_certs = 0; | |
780 | } | |
781 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L) | |
782 | ||
783 | while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0, | |
784 | callback, | |
785 | cb_userdata)) | |
786 | { | |
787 | if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert)) | |
788 | { | |
789 | ec = boost::system::error_code( | |
790 | static_cast<int>(::ERR_get_error()), | |
791 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 792 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
793 | } |
794 | } | |
795 | ||
796 | result = ::ERR_peek_last_error(); | |
797 | if ((ERR_GET_LIB(result) == ERR_LIB_PEM) | |
798 | && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE)) | |
799 | { | |
800 | ::ERR_clear_error(); | |
801 | ec = boost::system::error_code(); | |
b32b8144 | 802 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
803 | } |
804 | } | |
805 | ||
806 | ec = boost::system::error_code( | |
807 | static_cast<int>(::ERR_get_error()), | |
808 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 809 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
810 | } |
811 | ||
812 | void context::use_certificate_chain_file(const std::string& filename) | |
813 | { | |
814 | boost::system::error_code ec; | |
815 | use_certificate_chain_file(filename, ec); | |
816 | boost::asio::detail::throw_error(ec, "use_certificate_chain_file"); | |
817 | } | |
818 | ||
b32b8144 | 819 | BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file( |
7c673cae FG |
820 | const std::string& filename, boost::system::error_code& ec) |
821 | { | |
822 | ::ERR_clear_error(); | |
823 | ||
824 | if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1) | |
825 | { | |
826 | ec = boost::system::error_code( | |
827 | static_cast<int>(::ERR_get_error()), | |
828 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 829 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
830 | } |
831 | ||
832 | ec = boost::system::error_code(); | |
b32b8144 | 833 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
834 | } |
835 | ||
836 | void context::use_private_key( | |
837 | const const_buffer& private_key, context::file_format format) | |
838 | { | |
839 | boost::system::error_code ec; | |
840 | use_private_key(private_key, format, ec); | |
841 | boost::asio::detail::throw_error(ec, "use_private_key"); | |
842 | } | |
843 | ||
b32b8144 | 844 | BOOST_ASIO_SYNC_OP_VOID context::use_private_key( |
7c673cae FG |
845 | const const_buffer& private_key, context::file_format format, |
846 | boost::system::error_code& ec) | |
847 | { | |
848 | ::ERR_clear_error(); | |
849 | ||
92f5a8d4 TL |
850 | #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \ |
851 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
852 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
853 | pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); |
854 | void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); | |
855 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
856 | pem_password_cb* callback = handle_->default_passwd_callback; | |
857 | void* cb_userdata = handle_->default_passwd_callback_userdata; | |
858 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
859 | ||
860 | bio_cleanup bio = { make_buffer_bio(private_key) }; | |
861 | if (bio.p) | |
862 | { | |
863 | evp_pkey_cleanup evp_private_key = { 0 }; | |
864 | switch (format) | |
865 | { | |
866 | case context_base::asn1: | |
867 | evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0); | |
868 | break; | |
869 | case context_base::pem: | |
870 | evp_private_key.p = ::PEM_read_bio_PrivateKey( | |
871 | bio.p, 0, callback, | |
872 | cb_userdata); | |
873 | break; | |
874 | default: | |
875 | { | |
876 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 877 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
878 | } |
879 | } | |
880 | ||
881 | if (evp_private_key.p) | |
882 | { | |
883 | if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1) | |
884 | { | |
885 | ec = boost::system::error_code(); | |
b32b8144 | 886 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
887 | } |
888 | } | |
889 | } | |
890 | ||
891 | ec = boost::system::error_code( | |
892 | static_cast<int>(::ERR_get_error()), | |
893 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 894 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
895 | } |
896 | ||
897 | void context::use_private_key_file( | |
898 | const std::string& filename, context::file_format format) | |
899 | { | |
900 | boost::system::error_code ec; | |
901 | use_private_key_file(filename, format, ec); | |
902 | boost::asio::detail::throw_error(ec, "use_private_key_file"); | |
903 | } | |
904 | ||
905 | void context::use_rsa_private_key( | |
906 | const const_buffer& private_key, context::file_format format) | |
907 | { | |
908 | boost::system::error_code ec; | |
909 | use_rsa_private_key(private_key, format, ec); | |
910 | boost::asio::detail::throw_error(ec, "use_rsa_private_key"); | |
911 | } | |
912 | ||
b32b8144 | 913 | BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key( |
7c673cae FG |
914 | const const_buffer& private_key, context::file_format format, |
915 | boost::system::error_code& ec) | |
916 | { | |
917 | ::ERR_clear_error(); | |
918 | ||
92f5a8d4 TL |
919 | #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \ |
920 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
921 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
922 | pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); |
923 | void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); | |
924 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
925 | pem_password_cb* callback = handle_->default_passwd_callback; | |
926 | void* cb_userdata = handle_->default_passwd_callback_userdata; | |
927 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
928 | ||
929 | bio_cleanup bio = { make_buffer_bio(private_key) }; | |
930 | if (bio.p) | |
931 | { | |
932 | rsa_cleanup rsa_private_key = { 0 }; | |
933 | switch (format) | |
934 | { | |
935 | case context_base::asn1: | |
936 | rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0); | |
937 | break; | |
938 | case context_base::pem: | |
939 | rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey( | |
940 | bio.p, 0, callback, | |
941 | cb_userdata); | |
942 | break; | |
943 | default: | |
944 | { | |
945 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 946 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
947 | } |
948 | } | |
949 | ||
950 | if (rsa_private_key.p) | |
951 | { | |
952 | if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1) | |
953 | { | |
954 | ec = boost::system::error_code(); | |
b32b8144 | 955 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
956 | } |
957 | } | |
958 | } | |
959 | ||
960 | ec = boost::system::error_code( | |
961 | static_cast<int>(::ERR_get_error()), | |
962 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 963 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
964 | } |
965 | ||
b32b8144 | 966 | BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file( |
7c673cae FG |
967 | const std::string& filename, context::file_format format, |
968 | boost::system::error_code& ec) | |
969 | { | |
970 | int file_type; | |
971 | switch (format) | |
972 | { | |
973 | case context_base::asn1: | |
974 | file_type = SSL_FILETYPE_ASN1; | |
975 | break; | |
976 | case context_base::pem: | |
977 | file_type = SSL_FILETYPE_PEM; | |
978 | break; | |
979 | default: | |
980 | { | |
981 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 982 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
983 | } |
984 | } | |
985 | ||
986 | ::ERR_clear_error(); | |
987 | ||
988 | if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1) | |
989 | { | |
990 | ec = boost::system::error_code( | |
991 | static_cast<int>(::ERR_get_error()), | |
992 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 993 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
994 | } |
995 | ||
996 | ec = boost::system::error_code(); | |
b32b8144 | 997 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
998 | } |
999 | ||
1000 | void context::use_rsa_private_key_file( | |
1001 | const std::string& filename, context::file_format format) | |
1002 | { | |
1003 | boost::system::error_code ec; | |
1004 | use_rsa_private_key_file(filename, format, ec); | |
1005 | boost::asio::detail::throw_error(ec, "use_rsa_private_key_file"); | |
1006 | } | |
1007 | ||
b32b8144 | 1008 | BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file( |
7c673cae FG |
1009 | const std::string& filename, context::file_format format, |
1010 | boost::system::error_code& ec) | |
1011 | { | |
1012 | int file_type; | |
1013 | switch (format) | |
1014 | { | |
1015 | case context_base::asn1: | |
1016 | file_type = SSL_FILETYPE_ASN1; | |
1017 | break; | |
1018 | case context_base::pem: | |
1019 | file_type = SSL_FILETYPE_PEM; | |
1020 | break; | |
1021 | default: | |
1022 | { | |
1023 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 1024 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1025 | } |
1026 | } | |
1027 | ||
1028 | ::ERR_clear_error(); | |
1029 | ||
1030 | if (::SSL_CTX_use_RSAPrivateKey_file( | |
1031 | handle_, filename.c_str(), file_type) != 1) | |
1032 | { | |
1033 | ec = boost::system::error_code( | |
1034 | static_cast<int>(::ERR_get_error()), | |
1035 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 1036 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1037 | } |
1038 | ||
1039 | ec = boost::system::error_code(); | |
b32b8144 | 1040 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1041 | } |
1042 | ||
1043 | void context::use_tmp_dh(const const_buffer& dh) | |
1044 | { | |
1045 | boost::system::error_code ec; | |
1046 | use_tmp_dh(dh, ec); | |
1047 | boost::asio::detail::throw_error(ec, "use_tmp_dh"); | |
1048 | } | |
1049 | ||
b32b8144 | 1050 | BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh( |
7c673cae FG |
1051 | const const_buffer& dh, boost::system::error_code& ec) |
1052 | { | |
1053 | ::ERR_clear_error(); | |
1054 | ||
1055 | bio_cleanup bio = { make_buffer_bio(dh) }; | |
1056 | if (bio.p) | |
1057 | { | |
1058 | return do_use_tmp_dh(bio.p, ec); | |
1059 | } | |
1060 | ||
1061 | ec = boost::system::error_code( | |
1062 | static_cast<int>(::ERR_get_error()), | |
1063 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 1064 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1065 | } |
1066 | ||
1067 | void context::use_tmp_dh_file(const std::string& filename) | |
1068 | { | |
1069 | boost::system::error_code ec; | |
1070 | use_tmp_dh_file(filename, ec); | |
1071 | boost::asio::detail::throw_error(ec, "use_tmp_dh_file"); | |
1072 | } | |
1073 | ||
b32b8144 | 1074 | BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file( |
7c673cae FG |
1075 | const std::string& filename, boost::system::error_code& ec) |
1076 | { | |
1077 | ::ERR_clear_error(); | |
1078 | ||
1079 | bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") }; | |
1080 | if (bio.p) | |
1081 | { | |
1082 | return do_use_tmp_dh(bio.p, ec); | |
1083 | } | |
1084 | ||
1085 | ec = boost::system::error_code( | |
1086 | static_cast<int>(::ERR_get_error()), | |
1087 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 1088 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1089 | } |
1090 | ||
b32b8144 | 1091 | BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh( |
7c673cae FG |
1092 | BIO* bio, boost::system::error_code& ec) |
1093 | { | |
1094 | ::ERR_clear_error(); | |
1095 | ||
1096 | dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) }; | |
1097 | if (dh.p) | |
1098 | { | |
1099 | if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1) | |
1100 | { | |
1101 | ec = boost::system::error_code(); | |
b32b8144 | 1102 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1103 | } |
1104 | } | |
1105 | ||
1106 | ec = boost::system::error_code( | |
1107 | static_cast<int>(::ERR_get_error()), | |
1108 | boost::asio::error::get_ssl_category()); | |
b32b8144 | 1109 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1110 | } |
1111 | ||
b32b8144 | 1112 | BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback( |
7c673cae FG |
1113 | detail::verify_callback_base* callback, boost::system::error_code& ec) |
1114 | { | |
1115 | if (SSL_CTX_get_app_data(handle_)) | |
1116 | { | |
1117 | delete static_cast<detail::verify_callback_base*>( | |
1118 | SSL_CTX_get_app_data(handle_)); | |
1119 | } | |
1120 | ||
1121 | SSL_CTX_set_app_data(handle_, callback); | |
1122 | ||
1123 | ::SSL_CTX_set_verify(handle_, | |
1124 | ::SSL_CTX_get_verify_mode(handle_), | |
1125 | &context::verify_callback_function); | |
1126 | ||
1127 | ec = boost::system::error_code(); | |
b32b8144 | 1128 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1129 | } |
1130 | ||
1131 | int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx) | |
1132 | { | |
1133 | if (ctx) | |
1134 | { | |
1135 | if (SSL* ssl = static_cast<SSL*>( | |
1136 | ::X509_STORE_CTX_get_ex_data( | |
1137 | ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx()))) | |
1138 | { | |
1139 | if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl)) | |
1140 | { | |
1141 | if (SSL_CTX_get_app_data(handle)) | |
1142 | { | |
1143 | detail::verify_callback_base* callback = | |
1144 | static_cast<detail::verify_callback_base*>( | |
1145 | SSL_CTX_get_app_data(handle)); | |
1146 | ||
1147 | verify_context verify_ctx(ctx); | |
1148 | return callback->call(preverified != 0, verify_ctx) ? 1 : 0; | |
1149 | } | |
1150 | } | |
1151 | } | |
1152 | } | |
1153 | ||
1154 | return 0; | |
1155 | } | |
1156 | ||
b32b8144 | 1157 | BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback( |
7c673cae FG |
1158 | detail::password_callback_base* callback, boost::system::error_code& ec) |
1159 | { | |
92f5a8d4 TL |
1160 | #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \ |
1161 | && !defined(LIBRESSL_VERSION_NUMBER)) \ | |
1162 | || defined(BOOST_ASIO_USE_WOLFSSL) | |
7c673cae FG |
1163 | void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); |
1164 | ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback); | |
1165 | #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
1166 | void* old_callback = handle_->default_passwd_callback_userdata; | |
1167 | handle_->default_passwd_callback_userdata = callback; | |
1168 | #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) | |
1169 | ||
1170 | if (old_callback) | |
1171 | delete static_cast<detail::password_callback_base*>( | |
1172 | old_callback); | |
1173 | ||
1174 | SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function); | |
1175 | ||
1176 | ec = boost::system::error_code(); | |
b32b8144 | 1177 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
1178 | } |
1179 | ||
1180 | int context::password_callback_function( | |
1181 | char* buf, int size, int purpose, void* data) | |
1182 | { | |
1183 | using namespace std; // For strncat and strlen. | |
1184 | ||
1185 | if (data) | |
1186 | { | |
1187 | detail::password_callback_base* callback = | |
1188 | static_cast<detail::password_callback_base*>(data); | |
1189 | ||
1190 | std::string passwd = callback->call(static_cast<std::size_t>(size), | |
1191 | purpose ? context_base::for_writing : context_base::for_reading); | |
1192 | ||
1193 | #if defined(BOOST_ASIO_HAS_SECURE_RTL) | |
1194 | strcpy_s(buf, size, passwd.c_str()); | |
1195 | #else // defined(BOOST_ASIO_HAS_SECURE_RTL) | |
1196 | *buf = '\0'; | |
1197 | if (size > 0) | |
1198 | strncat(buf, passwd.c_str(), size - 1); | |
1199 | #endif // defined(BOOST_ASIO_HAS_SECURE_RTL) | |
1200 | ||
1201 | return static_cast<int>(strlen(buf)); | |
1202 | } | |
1203 | ||
1204 | return 0; | |
1205 | } | |
1206 | ||
1207 | BIO* context::make_buffer_bio(const const_buffer& b) | |
1208 | { | |
1209 | return ::BIO_new_mem_buf( | |
b32b8144 FG |
1210 | const_cast<void*>(b.data()), |
1211 | static_cast<int>(b.size())); | |
7c673cae FG |
1212 | } |
1213 | ||
7c673cae FG |
1214 | } // namespace ssl |
1215 | } // namespace asio | |
1216 | } // namespace boost | |
1217 | ||
1218 | #include <boost/asio/detail/pop_options.hpp> | |
1219 | ||
1220 | #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP |