context.ipp 24 KB

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