context.ipp 36 KB

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