Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

961 lines
22KB

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