context.ipp 25 KB

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