context.ipp 34 KB

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