context.ipp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  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. #if !defined(ASIO_ENABLE_OLD_SSL)
  18. # include <cstring>
  19. # include "asio/detail/throw_error.hpp"
  20. # include "asio/error.hpp"
  21. # include "asio/ssl/context.hpp"
  22. # include "asio/ssl/error.hpp"
  23. #endif // !defined(ASIO_ENABLE_OLD_SSL)
  24. #include "asio/detail/push_options.hpp"
  25. namespace asio {
  26. namespace ssl {
  27. #if !defined(ASIO_ENABLE_OLD_SSL)
  28. struct context::bio_cleanup
  29. {
  30. BIO* p;
  31. ~bio_cleanup() { if (p) ::BIO_free(p); }
  32. };
  33. struct context::x509_cleanup
  34. {
  35. X509* p;
  36. ~x509_cleanup() { if (p) ::X509_free(p); }
  37. };
  38. struct context::evp_pkey_cleanup
  39. {
  40. EVP_PKEY* p;
  41. ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }
  42. };
  43. struct context::rsa_cleanup
  44. {
  45. RSA* p;
  46. ~rsa_cleanup() { if (p) ::RSA_free(p); }
  47. };
  48. struct context::dh_cleanup
  49. {
  50. DH* p;
  51. ~dh_cleanup() { if (p) ::DH_free(p); }
  52. };
  53. context::context(context::method m)
  54. : handle_(0)
  55. {
  56. ::ERR_clear_error();
  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. asio::detail::throw_error(
  64. 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. asio::detail::throw_error(
  119. 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. asio::detail::throw_error(
  137. 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. asio::error_code ec(
  147. static_cast<int>(::ERR_get_error()),
  148. asio::error::get_ssl_category());
  149. asio::detail::throw_error(ec, "context");
  150. }
  151. set_options(no_compression);
  152. }
  153. context::context(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(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(ASIO_MOVE_CAST(context)(*this));
  169. handle_ = other.handle_;
  170. other.handle_ = 0;
  171. return *this;
  172. }
  173. #endif // defined(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. asio::error_code ec;
  208. clear_options(o, ec);
  209. asio::detail::throw_error(ec, "clear_options");
  210. }
  211. asio::error_code context::clear_options(
  212. context::options o, asio::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 = asio::error_code();
  227. #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
  228. // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  229. (void)o;
  230. ec = 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. asio::error_code ec;
  238. set_options(o, ec);
  239. asio::detail::throw_error(ec, "set_options");
  240. }
  241. asio::error_code context::set_options(
  242. context::options o, asio::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. 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 = asio::error_code();
  256. return ec;
  257. }
  258. void context::set_verify_mode(verify_mode v)
  259. {
  260. asio::error_code ec;
  261. set_verify_mode(v, ec);
  262. asio::detail::throw_error(ec, "set_verify_mode");
  263. }
  264. asio::error_code context::set_verify_mode(
  265. verify_mode v, asio::error_code& ec)
  266. {
  267. ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
  268. ec = asio::error_code();
  269. return ec;
  270. }
  271. void context::set_verify_depth(int depth)
  272. {
  273. asio::error_code ec;
  274. set_verify_depth(depth, ec);
  275. asio::detail::throw_error(ec, "set_verify_depth");
  276. }
  277. asio::error_code context::set_verify_depth(
  278. int depth, asio::error_code& ec)
  279. {
  280. ::SSL_CTX_set_verify_depth(handle_, depth);
  281. ec = asio::error_code();
  282. return ec;
  283. }
  284. void context::load_verify_file(const std::string& filename)
  285. {
  286. asio::error_code ec;
  287. load_verify_file(filename, ec);
  288. asio::detail::throw_error(ec, "load_verify_file");
  289. }
  290. asio::error_code context::load_verify_file(
  291. const std::string& filename, asio::error_code& ec)
  292. {
  293. ::ERR_clear_error();
  294. if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
  295. {
  296. ec = asio::error_code(
  297. static_cast<int>(::ERR_get_error()),
  298. asio::error::get_ssl_category());
  299. return ec;
  300. }
  301. ec = asio::error_code();
  302. return ec;
  303. }
  304. void context::add_certificate_authority(const const_buffer& ca)
  305. {
  306. asio::error_code ec;
  307. add_certificate_authority(ca, ec);
  308. asio::detail::throw_error(ec, "add_certificate_authority");
  309. }
  310. asio::error_code context::add_certificate_authority(
  311. const const_buffer& ca, asio::error_code& ec)
  312. {
  313. ::ERR_clear_error();
  314. bio_cleanup bio = { make_buffer_bio(ca) };
  315. if (bio.p)
  316. {
  317. x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
  318. if (cert.p)
  319. {
  320. if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
  321. {
  322. if (::X509_STORE_add_cert(store, cert.p) == 1)
  323. {
  324. ec = asio::error_code();
  325. return ec;
  326. }
  327. }
  328. }
  329. }
  330. ec = asio::error_code(
  331. static_cast<int>(::ERR_get_error()),
  332. asio::error::get_ssl_category());
  333. return ec;
  334. }
  335. void context::set_default_verify_paths()
  336. {
  337. asio::error_code ec;
  338. set_default_verify_paths(ec);
  339. asio::detail::throw_error(ec, "set_default_verify_paths");
  340. }
  341. asio::error_code context::set_default_verify_paths(
  342. asio::error_code& ec)
  343. {
  344. ::ERR_clear_error();
  345. if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
  346. {
  347. ec = asio::error_code(
  348. static_cast<int>(::ERR_get_error()),
  349. asio::error::get_ssl_category());
  350. return ec;
  351. }
  352. ec = asio::error_code();
  353. return ec;
  354. }
  355. void context::add_verify_path(const std::string& path)
  356. {
  357. asio::error_code ec;
  358. add_verify_path(path, ec);
  359. asio::detail::throw_error(ec, "add_verify_path");
  360. }
  361. asio::error_code context::add_verify_path(
  362. const std::string& path, asio::error_code& ec)
  363. {
  364. ::ERR_clear_error();
  365. if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
  366. {
  367. ec = asio::error_code(
  368. static_cast<int>(::ERR_get_error()),
  369. asio::error::get_ssl_category());
  370. return ec;
  371. }
  372. ec = asio::error_code();
  373. return ec;
  374. }
  375. void context::use_certificate(
  376. const const_buffer& certificate, file_format format)
  377. {
  378. asio::error_code ec;
  379. use_certificate(certificate, format, ec);
  380. asio::detail::throw_error(ec, "use_certificate");
  381. }
  382. asio::error_code context::use_certificate(
  383. const const_buffer& certificate, file_format format,
  384. asio::error_code& ec)
  385. {
  386. ::ERR_clear_error();
  387. if (format == context_base::asn1)
  388. {
  389. if (::SSL_CTX_use_certificate_ASN1(handle_,
  390. static_cast<int>(buffer_size(certificate)),
  391. buffer_cast<const unsigned char*>(certificate)) == 1)
  392. {
  393. ec = asio::error_code();
  394. return ec;
  395. }
  396. }
  397. else if (format == context_base::pem)
  398. {
  399. bio_cleanup bio = { make_buffer_bio(certificate) };
  400. if (bio.p)
  401. {
  402. x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
  403. if (cert.p)
  404. {
  405. if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
  406. {
  407. ec = asio::error_code();
  408. return ec;
  409. }
  410. }
  411. }
  412. }
  413. else
  414. {
  415. ec = asio::error::invalid_argument;
  416. return ec;
  417. }
  418. ec = asio::error_code(
  419. static_cast<int>(::ERR_get_error()),
  420. asio::error::get_ssl_category());
  421. return ec;
  422. }
  423. void context::use_certificate_file(
  424. const std::string& filename, file_format format)
  425. {
  426. asio::error_code ec;
  427. use_certificate_file(filename, format, ec);
  428. asio::detail::throw_error(ec, "use_certificate_file");
  429. }
  430. asio::error_code context::use_certificate_file(
  431. const std::string& filename, file_format format,
  432. asio::error_code& ec)
  433. {
  434. int file_type;
  435. switch (format)
  436. {
  437. case context_base::asn1:
  438. file_type = SSL_FILETYPE_ASN1;
  439. break;
  440. case context_base::pem:
  441. file_type = SSL_FILETYPE_PEM;
  442. break;
  443. default:
  444. {
  445. ec = asio::error::invalid_argument;
  446. return ec;
  447. }
  448. }
  449. ::ERR_clear_error();
  450. if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
  451. {
  452. ec = asio::error_code(
  453. static_cast<int>(::ERR_get_error()),
  454. asio::error::get_ssl_category());
  455. return ec;
  456. }
  457. ec = asio::error_code();
  458. return ec;
  459. }
  460. void context::use_certificate_chain(const const_buffer& chain)
  461. {
  462. asio::error_code ec;
  463. use_certificate_chain(chain, ec);
  464. asio::detail::throw_error(ec, "use_certificate_chain");
  465. }
  466. asio::error_code context::use_certificate_chain(
  467. const const_buffer& chain, asio::error_code& ec)
  468. {
  469. ::ERR_clear_error();
  470. bio_cleanup bio = { make_buffer_bio(chain) };
  471. if (bio.p)
  472. {
  473. x509_cleanup cert = {
  474. ::PEM_read_bio_X509_AUX(bio.p, 0,
  475. handle_->default_passwd_callback,
  476. handle_->default_passwd_callback_userdata) };
  477. if (!cert.p)
  478. {
  479. ec = asio::error_code(ERR_R_PEM_LIB,
  480. asio::error::get_ssl_category());
  481. return ec;
  482. }
  483. int result = ::SSL_CTX_use_certificate(handle_, cert.p);
  484. if (result == 0 || ::ERR_peek_error() != 0)
  485. {
  486. ec = asio::error_code(
  487. static_cast<int>(::ERR_get_error()),
  488. asio::error::get_ssl_category());
  489. return ec;
  490. }
  491. if (handle_->extra_certs)
  492. {
  493. ::sk_X509_pop_free(handle_->extra_certs, X509_free);
  494. handle_->extra_certs = 0;
  495. }
  496. while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
  497. handle_->default_passwd_callback,
  498. handle_->default_passwd_callback_userdata))
  499. {
  500. if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
  501. {
  502. ec = asio::error_code(
  503. static_cast<int>(::ERR_get_error()),
  504. asio::error::get_ssl_category());
  505. return ec;
  506. }
  507. }
  508. result = ::ERR_peek_last_error();
  509. if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
  510. && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
  511. {
  512. ::ERR_clear_error();
  513. ec = asio::error_code();
  514. return ec;
  515. }
  516. }
  517. ec = asio::error_code(
  518. static_cast<int>(::ERR_get_error()),
  519. asio::error::get_ssl_category());
  520. return ec;
  521. }
  522. void context::use_certificate_chain_file(const std::string& filename)
  523. {
  524. asio::error_code ec;
  525. use_certificate_chain_file(filename, ec);
  526. asio::detail::throw_error(ec, "use_certificate_chain_file");
  527. }
  528. asio::error_code context::use_certificate_chain_file(
  529. const std::string& filename, asio::error_code& ec)
  530. {
  531. ::ERR_clear_error();
  532. if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
  533. {
  534. ec = asio::error_code(
  535. static_cast<int>(::ERR_get_error()),
  536. asio::error::get_ssl_category());
  537. return ec;
  538. }
  539. ec = asio::error_code();
  540. return ec;
  541. }
  542. void context::use_private_key(
  543. const const_buffer& private_key, context::file_format format)
  544. {
  545. asio::error_code ec;
  546. use_private_key(private_key, format, ec);
  547. asio::detail::throw_error(ec, "use_private_key");
  548. }
  549. asio::error_code context::use_private_key(
  550. const const_buffer& private_key, context::file_format format,
  551. asio::error_code& ec)
  552. {
  553. ::ERR_clear_error();
  554. bio_cleanup bio = { make_buffer_bio(private_key) };
  555. if (bio.p)
  556. {
  557. evp_pkey_cleanup evp_private_key = { 0 };
  558. switch (format)
  559. {
  560. case context_base::asn1:
  561. evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
  562. break;
  563. case context_base::pem:
  564. evp_private_key.p = ::PEM_read_bio_PrivateKey(
  565. bio.p, 0, handle_->default_passwd_callback,
  566. handle_->default_passwd_callback_userdata);
  567. break;
  568. default:
  569. {
  570. ec = asio::error::invalid_argument;
  571. return ec;
  572. }
  573. }
  574. if (evp_private_key.p)
  575. {
  576. if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
  577. {
  578. ec = asio::error_code();
  579. return ec;
  580. }
  581. }
  582. }
  583. ec = asio::error_code(
  584. static_cast<int>(::ERR_get_error()),
  585. asio::error::get_ssl_category());
  586. return ec;
  587. }
  588. void context::use_private_key_file(
  589. const std::string& filename, context::file_format format)
  590. {
  591. asio::error_code ec;
  592. use_private_key_file(filename, format, ec);
  593. asio::detail::throw_error(ec, "use_private_key_file");
  594. }
  595. void context::use_rsa_private_key(
  596. const const_buffer& private_key, context::file_format format)
  597. {
  598. asio::error_code ec;
  599. use_rsa_private_key(private_key, format, ec);
  600. asio::detail::throw_error(ec, "use_rsa_private_key");
  601. }
  602. asio::error_code context::use_rsa_private_key(
  603. const const_buffer& private_key, context::file_format format,
  604. asio::error_code& ec)
  605. {
  606. ::ERR_clear_error();
  607. bio_cleanup bio = { make_buffer_bio(private_key) };
  608. if (bio.p)
  609. {
  610. rsa_cleanup rsa_private_key = { 0 };
  611. switch (format)
  612. {
  613. case context_base::asn1:
  614. rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
  615. break;
  616. case context_base::pem:
  617. rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
  618. bio.p, 0, handle_->default_passwd_callback,
  619. handle_->default_passwd_callback_userdata);
  620. break;
  621. default:
  622. {
  623. ec = asio::error::invalid_argument;
  624. return ec;
  625. }
  626. }
  627. if (rsa_private_key.p)
  628. {
  629. if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
  630. {
  631. ec = asio::error_code();
  632. return ec;
  633. }
  634. }
  635. }
  636. ec = asio::error_code(
  637. static_cast<int>(::ERR_get_error()),
  638. asio::error::get_ssl_category());
  639. return ec;
  640. }
  641. asio::error_code context::use_private_key_file(
  642. const std::string& filename, context::file_format format,
  643. asio::error_code& ec)
  644. {
  645. int file_type;
  646. switch (format)
  647. {
  648. case context_base::asn1:
  649. file_type = SSL_FILETYPE_ASN1;
  650. break;
  651. case context_base::pem:
  652. file_type = SSL_FILETYPE_PEM;
  653. break;
  654. default:
  655. {
  656. ec = asio::error::invalid_argument;
  657. return ec;
  658. }
  659. }
  660. ::ERR_clear_error();
  661. if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
  662. {
  663. ec = asio::error_code(
  664. static_cast<int>(::ERR_get_error()),
  665. asio::error::get_ssl_category());
  666. return ec;
  667. }
  668. ec = asio::error_code();
  669. return ec;
  670. }
  671. void context::use_rsa_private_key_file(
  672. const std::string& filename, context::file_format format)
  673. {
  674. asio::error_code ec;
  675. use_rsa_private_key_file(filename, format, ec);
  676. asio::detail::throw_error(ec, "use_rsa_private_key_file");
  677. }
  678. asio::error_code context::use_rsa_private_key_file(
  679. const std::string& filename, context::file_format format,
  680. asio::error_code& ec)
  681. {
  682. int file_type;
  683. switch (format)
  684. {
  685. case context_base::asn1:
  686. file_type = SSL_FILETYPE_ASN1;
  687. break;
  688. case context_base::pem:
  689. file_type = SSL_FILETYPE_PEM;
  690. break;
  691. default:
  692. {
  693. ec = asio::error::invalid_argument;
  694. return ec;
  695. }
  696. }
  697. ::ERR_clear_error();
  698. if (::SSL_CTX_use_RSAPrivateKey_file(
  699. handle_, filename.c_str(), file_type) != 1)
  700. {
  701. ec = asio::error_code(
  702. static_cast<int>(::ERR_get_error()),
  703. asio::error::get_ssl_category());
  704. return ec;
  705. }
  706. ec = asio::error_code();
  707. return ec;
  708. }
  709. void context::use_tmp_dh(const const_buffer& dh)
  710. {
  711. asio::error_code ec;
  712. use_tmp_dh(dh, ec);
  713. asio::detail::throw_error(ec, "use_tmp_dh");
  714. }
  715. asio::error_code context::use_tmp_dh(
  716. const const_buffer& dh, asio::error_code& ec)
  717. {
  718. ::ERR_clear_error();
  719. bio_cleanup bio = { make_buffer_bio(dh) };
  720. if (bio.p)
  721. {
  722. return do_use_tmp_dh(bio.p, ec);
  723. }
  724. ec = asio::error_code(
  725. static_cast<int>(::ERR_get_error()),
  726. asio::error::get_ssl_category());
  727. return ec;
  728. }
  729. void context::use_tmp_dh_file(const std::string& filename)
  730. {
  731. asio::error_code ec;
  732. use_tmp_dh_file(filename, ec);
  733. asio::detail::throw_error(ec, "use_tmp_dh_file");
  734. }
  735. asio::error_code context::use_tmp_dh_file(
  736. const std::string& filename, asio::error_code& ec)
  737. {
  738. ::ERR_clear_error();
  739. bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
  740. if (bio.p)
  741. {
  742. return do_use_tmp_dh(bio.p, ec);
  743. }
  744. ec = asio::error_code(
  745. static_cast<int>(::ERR_get_error()),
  746. asio::error::get_ssl_category());
  747. return ec;
  748. }
  749. asio::error_code context::do_use_tmp_dh(
  750. BIO* bio, asio::error_code& ec)
  751. {
  752. ::ERR_clear_error();
  753. dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
  754. if (dh.p)
  755. {
  756. if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
  757. {
  758. ec = asio::error_code();
  759. return ec;
  760. }
  761. }
  762. ec = asio::error_code(
  763. static_cast<int>(::ERR_get_error()),
  764. asio::error::get_ssl_category());
  765. return ec;
  766. }
  767. asio::error_code context::do_set_verify_callback(
  768. detail::verify_callback_base* callback, asio::error_code& ec)
  769. {
  770. if (SSL_CTX_get_app_data(handle_))
  771. {
  772. delete static_cast<detail::verify_callback_base*>(
  773. SSL_CTX_get_app_data(handle_));
  774. }
  775. SSL_CTX_set_app_data(handle_, callback);
  776. ::SSL_CTX_set_verify(handle_,
  777. ::SSL_CTX_get_verify_mode(handle_),
  778. &context::verify_callback_function);
  779. ec = asio::error_code();
  780. return ec;
  781. }
  782. int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
  783. {
  784. if (ctx)
  785. {
  786. if (SSL* ssl = static_cast<SSL*>(
  787. ::X509_STORE_CTX_get_ex_data(
  788. ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
  789. {
  790. if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
  791. {
  792. if (SSL_CTX_get_app_data(handle))
  793. {
  794. detail::verify_callback_base* callback =
  795. static_cast<detail::verify_callback_base*>(
  796. SSL_CTX_get_app_data(handle));
  797. verify_context verify_ctx(ctx);
  798. return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
  799. }
  800. }
  801. }
  802. }
  803. return 0;
  804. }
  805. asio::error_code context::do_set_password_callback(
  806. detail::password_callback_base* callback, asio::error_code& ec)
  807. {
  808. if (handle_->default_passwd_callback_userdata)
  809. delete static_cast<detail::password_callback_base*>(
  810. handle_->default_passwd_callback_userdata);
  811. handle_->default_passwd_callback_userdata = callback;
  812. SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
  813. ec = asio::error_code();
  814. return ec;
  815. }
  816. int context::password_callback_function(
  817. char* buf, int size, int purpose, void* data)
  818. {
  819. using namespace std; // For strncat and strlen.
  820. if (data)
  821. {
  822. detail::password_callback_base* callback =
  823. static_cast<detail::password_callback_base*>(data);
  824. std::string passwd = callback->call(static_cast<std::size_t>(size),
  825. purpose ? context_base::for_writing : context_base::for_reading);
  826. #if defined(ASIO_HAS_SECURE_RTL)
  827. strcpy_s(buf, size, passwd.c_str());
  828. #else // defined(ASIO_HAS_SECURE_RTL)
  829. *buf = '\0';
  830. strncat(buf, passwd.c_str(), size);
  831. #endif // defined(ASIO_HAS_SECURE_RTL)
  832. return static_cast<int>(strlen(buf));
  833. }
  834. return 0;
  835. }
  836. BIO* context::make_buffer_bio(const const_buffer& b)
  837. {
  838. return ::BIO_new_mem_buf(
  839. const_cast<void*>(buffer_cast<const void*>(b)),
  840. static_cast<int>(buffer_size(b)));
  841. }
  842. #endif // !defined(ASIO_ENABLE_OLD_SSL)
  843. } // namespace ssl
  844. } // namespace asio
  845. #include "asio/detail/pop_options.hpp"
  846. #endif // ASIO_SSL_IMPL_CONTEXT_IPP