context.ipp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. //
  2. // ssl/impl/context.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
  6. // Copyright (c) 2005-2019 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. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  347. context::context(context&& other)
  348. {
  349. handle_ = other.handle_;
  350. other.handle_ = 0;
  351. }
  352. context& context::operator=(context&& other)
  353. {
  354. context tmp(BOOST_ASIO_MOVE_CAST(context)(*this));
  355. handle_ = other.handle_;
  356. other.handle_ = 0;
  357. return *this;
  358. }
  359. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  360. context::~context()
  361. {
  362. if (handle_)
  363. {
  364. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  365. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  366. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  367. void* cb_userdata = handle_->default_passwd_callback_userdata;
  368. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  369. if (cb_userdata)
  370. {
  371. detail::password_callback_base* callback =
  372. static_cast<detail::password_callback_base*>(
  373. cb_userdata);
  374. delete callback;
  375. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  376. ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
  377. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  378. handle_->default_passwd_callback_userdata = 0;
  379. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  380. }
  381. if (SSL_CTX_get_app_data(handle_))
  382. {
  383. detail::verify_callback_base* callback =
  384. static_cast<detail::verify_callback_base*>(
  385. SSL_CTX_get_app_data(handle_));
  386. delete callback;
  387. SSL_CTX_set_app_data(handle_, 0);
  388. }
  389. ::SSL_CTX_free(handle_);
  390. }
  391. }
  392. context::native_handle_type context::native_handle()
  393. {
  394. return handle_;
  395. }
  396. void context::clear_options(context::options o)
  397. {
  398. boost::system::error_code ec;
  399. clear_options(o, ec);
  400. boost::asio::detail::throw_error(ec, "clear_options");
  401. }
  402. BOOST_ASIO_SYNC_OP_VOID context::clear_options(
  403. context::options o, boost::system::error_code& ec)
  404. {
  405. #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
  406. && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  407. # if !defined(SSL_OP_NO_COMPRESSION)
  408. if ((o & context::no_compression) != 0)
  409. {
  410. # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  411. handle_->comp_methods = SSL_COMP_get_compression_methods();
  412. # endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  413. o ^= context::no_compression;
  414. }
  415. # endif // !defined(SSL_OP_NO_COMPRESSION)
  416. ::SSL_CTX_clear_options(handle_, o);
  417. ec = boost::system::error_code();
  418. #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
  419. // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  420. (void)o;
  421. ec = boost::asio::error::operation_not_supported;
  422. #endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
  423. // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  424. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  425. }
  426. void context::set_options(context::options o)
  427. {
  428. boost::system::error_code ec;
  429. set_options(o, ec);
  430. boost::asio::detail::throw_error(ec, "set_options");
  431. }
  432. BOOST_ASIO_SYNC_OP_VOID context::set_options(
  433. context::options o, boost::system::error_code& ec)
  434. {
  435. #if !defined(SSL_OP_NO_COMPRESSION)
  436. if ((o & context::no_compression) != 0)
  437. {
  438. #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  439. handle_->comp_methods =
  440. boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
  441. #endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  442. o ^= context::no_compression;
  443. }
  444. #endif // !defined(SSL_OP_NO_COMPRESSION)
  445. ::SSL_CTX_set_options(handle_, o);
  446. ec = boost::system::error_code();
  447. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  448. }
  449. void context::set_verify_mode(verify_mode v)
  450. {
  451. boost::system::error_code ec;
  452. set_verify_mode(v, ec);
  453. boost::asio::detail::throw_error(ec, "set_verify_mode");
  454. }
  455. BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
  456. verify_mode v, boost::system::error_code& ec)
  457. {
  458. ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
  459. ec = boost::system::error_code();
  460. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  461. }
  462. void context::set_verify_depth(int depth)
  463. {
  464. boost::system::error_code ec;
  465. set_verify_depth(depth, ec);
  466. boost::asio::detail::throw_error(ec, "set_verify_depth");
  467. }
  468. BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
  469. int depth, boost::system::error_code& ec)
  470. {
  471. ::SSL_CTX_set_verify_depth(handle_, depth);
  472. ec = boost::system::error_code();
  473. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  474. }
  475. void context::load_verify_file(const std::string& filename)
  476. {
  477. boost::system::error_code ec;
  478. load_verify_file(filename, ec);
  479. boost::asio::detail::throw_error(ec, "load_verify_file");
  480. }
  481. BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
  482. const std::string& filename, boost::system::error_code& ec)
  483. {
  484. ::ERR_clear_error();
  485. if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
  486. {
  487. ec = boost::system::error_code(
  488. static_cast<int>(::ERR_get_error()),
  489. boost::asio::error::get_ssl_category());
  490. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  491. }
  492. ec = boost::system::error_code();
  493. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  494. }
  495. void context::add_certificate_authority(const const_buffer& ca)
  496. {
  497. boost::system::error_code ec;
  498. add_certificate_authority(ca, ec);
  499. boost::asio::detail::throw_error(ec, "add_certificate_authority");
  500. }
  501. BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
  502. const const_buffer& ca, boost::system::error_code& ec)
  503. {
  504. ::ERR_clear_error();
  505. bio_cleanup bio = { make_buffer_bio(ca) };
  506. if (bio.p)
  507. {
  508. if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
  509. {
  510. for (;;)
  511. {
  512. x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
  513. if (!cert.p)
  514. break;
  515. if (::X509_STORE_add_cert(store, cert.p) != 1)
  516. {
  517. ec = boost::system::error_code(
  518. static_cast<int>(::ERR_get_error()),
  519. boost::asio::error::get_ssl_category());
  520. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  521. }
  522. }
  523. }
  524. }
  525. ec = boost::system::error_code();
  526. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  527. }
  528. void context::set_default_verify_paths()
  529. {
  530. boost::system::error_code ec;
  531. set_default_verify_paths(ec);
  532. boost::asio::detail::throw_error(ec, "set_default_verify_paths");
  533. }
  534. BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
  535. boost::system::error_code& ec)
  536. {
  537. ::ERR_clear_error();
  538. if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
  539. {
  540. ec = boost::system::error_code(
  541. static_cast<int>(::ERR_get_error()),
  542. boost::asio::error::get_ssl_category());
  543. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  544. }
  545. ec = boost::system::error_code();
  546. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  547. }
  548. void context::add_verify_path(const std::string& path)
  549. {
  550. boost::system::error_code ec;
  551. add_verify_path(path, ec);
  552. boost::asio::detail::throw_error(ec, "add_verify_path");
  553. }
  554. BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
  555. const std::string& path, boost::system::error_code& ec)
  556. {
  557. ::ERR_clear_error();
  558. if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
  559. {
  560. ec = boost::system::error_code(
  561. static_cast<int>(::ERR_get_error()),
  562. boost::asio::error::get_ssl_category());
  563. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  564. }
  565. ec = boost::system::error_code();
  566. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  567. }
  568. void context::use_certificate(
  569. const const_buffer& certificate, file_format format)
  570. {
  571. boost::system::error_code ec;
  572. use_certificate(certificate, format, ec);
  573. boost::asio::detail::throw_error(ec, "use_certificate");
  574. }
  575. BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
  576. const const_buffer& certificate, file_format format,
  577. boost::system::error_code& ec)
  578. {
  579. ::ERR_clear_error();
  580. if (format == context_base::asn1)
  581. {
  582. if (::SSL_CTX_use_certificate_ASN1(handle_,
  583. static_cast<int>(certificate.size()),
  584. static_cast<const unsigned char*>(certificate.data())) == 1)
  585. {
  586. ec = boost::system::error_code();
  587. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  588. }
  589. }
  590. else if (format == context_base::pem)
  591. {
  592. bio_cleanup bio = { make_buffer_bio(certificate) };
  593. if (bio.p)
  594. {
  595. x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
  596. if (cert.p)
  597. {
  598. if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
  599. {
  600. ec = boost::system::error_code();
  601. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  602. }
  603. }
  604. }
  605. }
  606. else
  607. {
  608. ec = boost::asio::error::invalid_argument;
  609. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  610. }
  611. ec = boost::system::error_code(
  612. static_cast<int>(::ERR_get_error()),
  613. boost::asio::error::get_ssl_category());
  614. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  615. }
  616. void context::use_certificate_file(
  617. const std::string& filename, file_format format)
  618. {
  619. boost::system::error_code ec;
  620. use_certificate_file(filename, format, ec);
  621. boost::asio::detail::throw_error(ec, "use_certificate_file");
  622. }
  623. BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
  624. const std::string& filename, file_format format,
  625. boost::system::error_code& ec)
  626. {
  627. int file_type;
  628. switch (format)
  629. {
  630. case context_base::asn1:
  631. file_type = SSL_FILETYPE_ASN1;
  632. break;
  633. case context_base::pem:
  634. file_type = SSL_FILETYPE_PEM;
  635. break;
  636. default:
  637. {
  638. ec = boost::asio::error::invalid_argument;
  639. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  640. }
  641. }
  642. ::ERR_clear_error();
  643. if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
  644. {
  645. ec = boost::system::error_code(
  646. static_cast<int>(::ERR_get_error()),
  647. boost::asio::error::get_ssl_category());
  648. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  649. }
  650. ec = boost::system::error_code();
  651. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  652. }
  653. void context::use_certificate_chain(const const_buffer& chain)
  654. {
  655. boost::system::error_code ec;
  656. use_certificate_chain(chain, ec);
  657. boost::asio::detail::throw_error(ec, "use_certificate_chain");
  658. }
  659. BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
  660. const const_buffer& chain, boost::system::error_code& ec)
  661. {
  662. ::ERR_clear_error();
  663. bio_cleanup bio = { make_buffer_bio(chain) };
  664. if (bio.p)
  665. {
  666. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  667. pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
  668. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  669. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  670. pem_password_cb* callback = handle_->default_passwd_callback;
  671. void* cb_userdata = handle_->default_passwd_callback_userdata;
  672. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  673. x509_cleanup cert = {
  674. ::PEM_read_bio_X509_AUX(bio.p, 0,
  675. callback,
  676. cb_userdata) };
  677. if (!cert.p)
  678. {
  679. ec = boost::system::error_code(ERR_R_PEM_LIB,
  680. boost::asio::error::get_ssl_category());
  681. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  682. }
  683. int result = ::SSL_CTX_use_certificate(handle_, cert.p);
  684. if (result == 0 || ::ERR_peek_error() != 0)
  685. {
  686. ec = boost::system::error_code(
  687. static_cast<int>(::ERR_get_error()),
  688. boost::asio::error::get_ssl_category());
  689. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  690. }
  691. #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER)
  692. ::SSL_CTX_clear_chain_certs(handle_);
  693. #else
  694. if (handle_->extra_certs)
  695. {
  696. ::sk_X509_pop_free(handle_->extra_certs, X509_free);
  697. handle_->extra_certs = 0;
  698. }
  699. #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
  700. while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
  701. callback,
  702. cb_userdata))
  703. {
  704. if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
  705. {
  706. ec = boost::system::error_code(
  707. static_cast<int>(::ERR_get_error()),
  708. boost::asio::error::get_ssl_category());
  709. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  710. }
  711. }
  712. result = ::ERR_peek_last_error();
  713. if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
  714. && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
  715. {
  716. ::ERR_clear_error();
  717. ec = boost::system::error_code();
  718. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  719. }
  720. }
  721. ec = boost::system::error_code(
  722. static_cast<int>(::ERR_get_error()),
  723. boost::asio::error::get_ssl_category());
  724. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  725. }
  726. void context::use_certificate_chain_file(const std::string& filename)
  727. {
  728. boost::system::error_code ec;
  729. use_certificate_chain_file(filename, ec);
  730. boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
  731. }
  732. BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
  733. const std::string& filename, boost::system::error_code& ec)
  734. {
  735. ::ERR_clear_error();
  736. if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
  737. {
  738. ec = boost::system::error_code(
  739. static_cast<int>(::ERR_get_error()),
  740. boost::asio::error::get_ssl_category());
  741. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  742. }
  743. ec = boost::system::error_code();
  744. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  745. }
  746. void context::use_private_key(
  747. const const_buffer& private_key, context::file_format format)
  748. {
  749. boost::system::error_code ec;
  750. use_private_key(private_key, format, ec);
  751. boost::asio::detail::throw_error(ec, "use_private_key");
  752. }
  753. BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
  754. const const_buffer& private_key, context::file_format format,
  755. boost::system::error_code& ec)
  756. {
  757. ::ERR_clear_error();
  758. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  759. pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
  760. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  761. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  762. pem_password_cb* callback = handle_->default_passwd_callback;
  763. void* cb_userdata = handle_->default_passwd_callback_userdata;
  764. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  765. bio_cleanup bio = { make_buffer_bio(private_key) };
  766. if (bio.p)
  767. {
  768. evp_pkey_cleanup evp_private_key = { 0 };
  769. switch (format)
  770. {
  771. case context_base::asn1:
  772. evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
  773. break;
  774. case context_base::pem:
  775. evp_private_key.p = ::PEM_read_bio_PrivateKey(
  776. bio.p, 0, callback,
  777. cb_userdata);
  778. break;
  779. default:
  780. {
  781. ec = boost::asio::error::invalid_argument;
  782. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  783. }
  784. }
  785. if (evp_private_key.p)
  786. {
  787. if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
  788. {
  789. ec = boost::system::error_code();
  790. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  791. }
  792. }
  793. }
  794. ec = boost::system::error_code(
  795. static_cast<int>(::ERR_get_error()),
  796. boost::asio::error::get_ssl_category());
  797. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  798. }
  799. void context::use_private_key_file(
  800. const std::string& filename, context::file_format format)
  801. {
  802. boost::system::error_code ec;
  803. use_private_key_file(filename, format, ec);
  804. boost::asio::detail::throw_error(ec, "use_private_key_file");
  805. }
  806. void context::use_rsa_private_key(
  807. const const_buffer& private_key, context::file_format format)
  808. {
  809. boost::system::error_code ec;
  810. use_rsa_private_key(private_key, format, ec);
  811. boost::asio::detail::throw_error(ec, "use_rsa_private_key");
  812. }
  813. BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
  814. const const_buffer& private_key, context::file_format format,
  815. boost::system::error_code& ec)
  816. {
  817. ::ERR_clear_error();
  818. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  819. pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
  820. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  821. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  822. pem_password_cb* callback = handle_->default_passwd_callback;
  823. void* cb_userdata = handle_->default_passwd_callback_userdata;
  824. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  825. bio_cleanup bio = { make_buffer_bio(private_key) };
  826. if (bio.p)
  827. {
  828. rsa_cleanup rsa_private_key = { 0 };
  829. switch (format)
  830. {
  831. case context_base::asn1:
  832. rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
  833. break;
  834. case context_base::pem:
  835. rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
  836. bio.p, 0, callback,
  837. cb_userdata);
  838. break;
  839. default:
  840. {
  841. ec = boost::asio::error::invalid_argument;
  842. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  843. }
  844. }
  845. if (rsa_private_key.p)
  846. {
  847. if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
  848. {
  849. ec = boost::system::error_code();
  850. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  851. }
  852. }
  853. }
  854. ec = boost::system::error_code(
  855. static_cast<int>(::ERR_get_error()),
  856. boost::asio::error::get_ssl_category());
  857. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  858. }
  859. BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file(
  860. const std::string& filename, context::file_format format,
  861. boost::system::error_code& ec)
  862. {
  863. int file_type;
  864. switch (format)
  865. {
  866. case context_base::asn1:
  867. file_type = SSL_FILETYPE_ASN1;
  868. break;
  869. case context_base::pem:
  870. file_type = SSL_FILETYPE_PEM;
  871. break;
  872. default:
  873. {
  874. ec = boost::asio::error::invalid_argument;
  875. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  876. }
  877. }
  878. ::ERR_clear_error();
  879. if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
  880. {
  881. ec = boost::system::error_code(
  882. static_cast<int>(::ERR_get_error()),
  883. boost::asio::error::get_ssl_category());
  884. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  885. }
  886. ec = boost::system::error_code();
  887. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  888. }
  889. void context::use_rsa_private_key_file(
  890. const std::string& filename, context::file_format format)
  891. {
  892. boost::system::error_code ec;
  893. use_rsa_private_key_file(filename, format, ec);
  894. boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
  895. }
  896. BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(
  897. const std::string& filename, context::file_format format,
  898. boost::system::error_code& ec)
  899. {
  900. int file_type;
  901. switch (format)
  902. {
  903. case context_base::asn1:
  904. file_type = SSL_FILETYPE_ASN1;
  905. break;
  906. case context_base::pem:
  907. file_type = SSL_FILETYPE_PEM;
  908. break;
  909. default:
  910. {
  911. ec = boost::asio::error::invalid_argument;
  912. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  913. }
  914. }
  915. ::ERR_clear_error();
  916. if (::SSL_CTX_use_RSAPrivateKey_file(
  917. handle_, filename.c_str(), file_type) != 1)
  918. {
  919. ec = boost::system::error_code(
  920. static_cast<int>(::ERR_get_error()),
  921. boost::asio::error::get_ssl_category());
  922. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  923. }
  924. ec = boost::system::error_code();
  925. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  926. }
  927. void context::use_tmp_dh(const const_buffer& dh)
  928. {
  929. boost::system::error_code ec;
  930. use_tmp_dh(dh, ec);
  931. boost::asio::detail::throw_error(ec, "use_tmp_dh");
  932. }
  933. BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
  934. const const_buffer& dh, boost::system::error_code& ec)
  935. {
  936. ::ERR_clear_error();
  937. bio_cleanup bio = { make_buffer_bio(dh) };
  938. if (bio.p)
  939. {
  940. return do_use_tmp_dh(bio.p, ec);
  941. }
  942. ec = boost::system::error_code(
  943. static_cast<int>(::ERR_get_error()),
  944. boost::asio::error::get_ssl_category());
  945. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  946. }
  947. void context::use_tmp_dh_file(const std::string& filename)
  948. {
  949. boost::system::error_code ec;
  950. use_tmp_dh_file(filename, ec);
  951. boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
  952. }
  953. BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
  954. const std::string& filename, boost::system::error_code& ec)
  955. {
  956. ::ERR_clear_error();
  957. bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
  958. if (bio.p)
  959. {
  960. return do_use_tmp_dh(bio.p, ec);
  961. }
  962. ec = boost::system::error_code(
  963. static_cast<int>(::ERR_get_error()),
  964. boost::asio::error::get_ssl_category());
  965. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  966. }
  967. BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
  968. BIO* bio, boost::system::error_code& ec)
  969. {
  970. ::ERR_clear_error();
  971. dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
  972. if (dh.p)
  973. {
  974. if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
  975. {
  976. ec = boost::system::error_code();
  977. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  978. }
  979. }
  980. ec = boost::system::error_code(
  981. static_cast<int>(::ERR_get_error()),
  982. boost::asio::error::get_ssl_category());
  983. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  984. }
  985. BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
  986. detail::verify_callback_base* callback, boost::system::error_code& ec)
  987. {
  988. if (SSL_CTX_get_app_data(handle_))
  989. {
  990. delete static_cast<detail::verify_callback_base*>(
  991. SSL_CTX_get_app_data(handle_));
  992. }
  993. SSL_CTX_set_app_data(handle_, callback);
  994. ::SSL_CTX_set_verify(handle_,
  995. ::SSL_CTX_get_verify_mode(handle_),
  996. &context::verify_callback_function);
  997. ec = boost::system::error_code();
  998. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  999. }
  1000. int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
  1001. {
  1002. if (ctx)
  1003. {
  1004. if (SSL* ssl = static_cast<SSL*>(
  1005. ::X509_STORE_CTX_get_ex_data(
  1006. ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
  1007. {
  1008. if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
  1009. {
  1010. if (SSL_CTX_get_app_data(handle))
  1011. {
  1012. detail::verify_callback_base* callback =
  1013. static_cast<detail::verify_callback_base*>(
  1014. SSL_CTX_get_app_data(handle));
  1015. verify_context verify_ctx(ctx);
  1016. return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
  1017. }
  1018. }
  1019. }
  1020. }
  1021. return 0;
  1022. }
  1023. BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
  1024. detail::password_callback_base* callback, boost::system::error_code& ec)
  1025. {
  1026. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  1027. void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  1028. ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
  1029. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  1030. void* old_callback = handle_->default_passwd_callback_userdata;
  1031. handle_->default_passwd_callback_userdata = callback;
  1032. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  1033. if (old_callback)
  1034. delete static_cast<detail::password_callback_base*>(
  1035. old_callback);
  1036. SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
  1037. ec = boost::system::error_code();
  1038. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  1039. }
  1040. int context::password_callback_function(
  1041. char* buf, int size, int purpose, void* data)
  1042. {
  1043. using namespace std; // For strncat and strlen.
  1044. if (data)
  1045. {
  1046. detail::password_callback_base* callback =
  1047. static_cast<detail::password_callback_base*>(data);
  1048. std::string passwd = callback->call(static_cast<std::size_t>(size),
  1049. purpose ? context_base::for_writing : context_base::for_reading);
  1050. #if defined(BOOST_ASIO_HAS_SECURE_RTL)
  1051. strcpy_s(buf, size, passwd.c_str());
  1052. #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
  1053. *buf = '\0';
  1054. if (size > 0)
  1055. strncat(buf, passwd.c_str(), size - 1);
  1056. #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
  1057. return static_cast<int>(strlen(buf));
  1058. }
  1059. return 0;
  1060. }
  1061. BIO* context::make_buffer_bio(const const_buffer& b)
  1062. {
  1063. return ::BIO_new_mem_buf(
  1064. const_cast<void*>(b.data()),
  1065. static_cast<int>(b.size()));
  1066. }
  1067. } // namespace ssl
  1068. } // namespace asio
  1069. } // namespace boost
  1070. #include <boost/asio/detail/pop_options.hpp>
  1071. #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP