context.ipp 34 KB

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