context.ipp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. //
  2. // ssl/impl/context.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
  6. // Copyright (c) 2005-2018 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. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  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. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  157. // TLS v1.1.
  158. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  159. case context::tlsv11:
  160. handle_ = ::SSL_CTX_new(::TLS_method());
  161. if (handle_)
  162. {
  163. SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
  164. SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
  165. }
  166. break;
  167. case context::tlsv11_client:
  168. handle_ = ::SSL_CTX_new(::TLS_client_method());
  169. if (handle_)
  170. {
  171. SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
  172. SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
  173. }
  174. break;
  175. case context::tlsv11_server:
  176. handle_ = ::SSL_CTX_new(::TLS_server_method());
  177. if (handle_)
  178. {
  179. SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
  180. SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
  181. }
  182. break;
  183. #elif defined(SSL_TXT_TLSV1_1)
  184. case context::tlsv11:
  185. handle_ = ::SSL_CTX_new(::TLSv1_1_method());
  186. break;
  187. case context::tlsv11_client:
  188. handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());
  189. break;
  190. case context::tlsv11_server:
  191. handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());
  192. break;
  193. #else // defined(SSL_TXT_TLSV1_1)
  194. case context::tlsv11:
  195. case context::tlsv11_client:
  196. case context::tlsv11_server:
  197. boost::asio::detail::throw_error(
  198. boost::asio::error::invalid_argument, "context");
  199. break;
  200. #endif // defined(SSL_TXT_TLSV1_1)
  201. // TLS v1.2.
  202. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  203. case context::tlsv12:
  204. handle_ = ::SSL_CTX_new(::TLS_method());
  205. if (handle_)
  206. {
  207. SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
  208. SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
  209. }
  210. break;
  211. case context::tlsv12_client:
  212. handle_ = ::SSL_CTX_new(::TLS_client_method());
  213. if (handle_)
  214. {
  215. SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
  216. SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
  217. }
  218. break;
  219. case context::tlsv12_server:
  220. handle_ = ::SSL_CTX_new(::TLS_server_method());
  221. if (handle_)
  222. {
  223. SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
  224. SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
  225. }
  226. break;
  227. #elif defined(SSL_TXT_TLSV1_1)
  228. case context::tlsv12:
  229. handle_ = ::SSL_CTX_new(::TLSv1_2_method());
  230. break;
  231. case context::tlsv12_client:
  232. handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());
  233. break;
  234. case context::tlsv12_server:
  235. handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
  236. break;
  237. #else // defined(SSL_TXT_TLSV1_1)
  238. case context::tlsv12:
  239. case context::tlsv12_client:
  240. case context::tlsv12_server:
  241. boost::asio::detail::throw_error(
  242. boost::asio::error::invalid_argument, "context");
  243. break;
  244. #endif // defined(SSL_TXT_TLSV1_1)
  245. // Any supported SSL/TLS version.
  246. case context::sslv23:
  247. handle_ = ::SSL_CTX_new(::SSLv23_method());
  248. break;
  249. case context::sslv23_client:
  250. handle_ = ::SSL_CTX_new(::SSLv23_client_method());
  251. break;
  252. case context::sslv23_server:
  253. handle_ = ::SSL_CTX_new(::SSLv23_server_method());
  254. break;
  255. // Any supported TLS version.
  256. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  257. case context::tls:
  258. handle_ = ::SSL_CTX_new(::TLS_method());
  259. if (handle_)
  260. SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
  261. break;
  262. case context::tls_client:
  263. handle_ = ::SSL_CTX_new(::TLS_client_method());
  264. if (handle_)
  265. SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
  266. break;
  267. case context::tls_server:
  268. handle_ = ::SSL_CTX_new(::TLS_server_method());
  269. if (handle_)
  270. SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
  271. break;
  272. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  273. case context::tls:
  274. handle_ = ::SSL_CTX_new(::SSLv23_method());
  275. if (handle_)
  276. SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
  277. break;
  278. case context::tls_client:
  279. handle_ = ::SSL_CTX_new(::SSLv23_client_method());
  280. if (handle_)
  281. SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
  282. break;
  283. case context::tls_server:
  284. handle_ = ::SSL_CTX_new(::SSLv23_server_method());
  285. if (handle_)
  286. SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
  287. break;
  288. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  289. default:
  290. handle_ = ::SSL_CTX_new(0);
  291. break;
  292. }
  293. if (handle_ == 0)
  294. {
  295. boost::system::error_code ec(
  296. static_cast<int>(::ERR_get_error()),
  297. boost::asio::error::get_ssl_category());
  298. boost::asio::detail::throw_error(ec, "context");
  299. }
  300. set_options(no_compression);
  301. }
  302. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  303. context::context(context&& other)
  304. {
  305. handle_ = other.handle_;
  306. other.handle_ = 0;
  307. }
  308. context& context::operator=(context&& other)
  309. {
  310. context tmp(BOOST_ASIO_MOVE_CAST(context)(*this));
  311. handle_ = other.handle_;
  312. other.handle_ = 0;
  313. return *this;
  314. }
  315. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  316. context::~context()
  317. {
  318. if (handle_)
  319. {
  320. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  321. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  322. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  323. void* cb_userdata = handle_->default_passwd_callback_userdata;
  324. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  325. if (cb_userdata)
  326. {
  327. detail::password_callback_base* callback =
  328. static_cast<detail::password_callback_base*>(
  329. cb_userdata);
  330. delete callback;
  331. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  332. ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
  333. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  334. handle_->default_passwd_callback_userdata = 0;
  335. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  336. }
  337. if (SSL_CTX_get_app_data(handle_))
  338. {
  339. detail::verify_callback_base* callback =
  340. static_cast<detail::verify_callback_base*>(
  341. SSL_CTX_get_app_data(handle_));
  342. delete callback;
  343. SSL_CTX_set_app_data(handle_, 0);
  344. }
  345. ::SSL_CTX_free(handle_);
  346. }
  347. }
  348. context::native_handle_type context::native_handle()
  349. {
  350. return handle_;
  351. }
  352. void context::clear_options(context::options o)
  353. {
  354. boost::system::error_code ec;
  355. clear_options(o, ec);
  356. boost::asio::detail::throw_error(ec, "clear_options");
  357. }
  358. BOOST_ASIO_SYNC_OP_VOID context::clear_options(
  359. context::options o, boost::system::error_code& ec)
  360. {
  361. #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
  362. && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  363. # if !defined(SSL_OP_NO_COMPRESSION)
  364. if ((o & context::no_compression) != 0)
  365. {
  366. # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  367. handle_->comp_methods = SSL_COMP_get_compression_methods();
  368. # endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  369. o ^= context::no_compression;
  370. }
  371. # endif // !defined(SSL_OP_NO_COMPRESSION)
  372. ::SSL_CTX_clear_options(handle_, o);
  373. ec = boost::system::error_code();
  374. #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
  375. // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  376. (void)o;
  377. ec = boost::asio::error::operation_not_supported;
  378. #endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
  379. // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
  380. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  381. }
  382. void context::set_options(context::options o)
  383. {
  384. boost::system::error_code ec;
  385. set_options(o, ec);
  386. boost::asio::detail::throw_error(ec, "set_options");
  387. }
  388. BOOST_ASIO_SYNC_OP_VOID context::set_options(
  389. context::options o, boost::system::error_code& ec)
  390. {
  391. #if !defined(SSL_OP_NO_COMPRESSION)
  392. if ((o & context::no_compression) != 0)
  393. {
  394. #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  395. handle_->comp_methods =
  396. boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
  397. #endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
  398. o ^= context::no_compression;
  399. }
  400. #endif // !defined(SSL_OP_NO_COMPRESSION)
  401. ::SSL_CTX_set_options(handle_, o);
  402. ec = boost::system::error_code();
  403. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  404. }
  405. void context::set_verify_mode(verify_mode v)
  406. {
  407. boost::system::error_code ec;
  408. set_verify_mode(v, ec);
  409. boost::asio::detail::throw_error(ec, "set_verify_mode");
  410. }
  411. BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
  412. verify_mode v, boost::system::error_code& ec)
  413. {
  414. ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
  415. ec = boost::system::error_code();
  416. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  417. }
  418. void context::set_verify_depth(int depth)
  419. {
  420. boost::system::error_code ec;
  421. set_verify_depth(depth, ec);
  422. boost::asio::detail::throw_error(ec, "set_verify_depth");
  423. }
  424. BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
  425. int depth, boost::system::error_code& ec)
  426. {
  427. ::SSL_CTX_set_verify_depth(handle_, depth);
  428. ec = boost::system::error_code();
  429. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  430. }
  431. void context::load_verify_file(const std::string& filename)
  432. {
  433. boost::system::error_code ec;
  434. load_verify_file(filename, ec);
  435. boost::asio::detail::throw_error(ec, "load_verify_file");
  436. }
  437. BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
  438. const std::string& filename, boost::system::error_code& ec)
  439. {
  440. ::ERR_clear_error();
  441. if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
  442. {
  443. ec = boost::system::error_code(
  444. static_cast<int>(::ERR_get_error()),
  445. boost::asio::error::get_ssl_category());
  446. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  447. }
  448. ec = boost::system::error_code();
  449. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  450. }
  451. void context::add_certificate_authority(const const_buffer& ca)
  452. {
  453. boost::system::error_code ec;
  454. add_certificate_authority(ca, ec);
  455. boost::asio::detail::throw_error(ec, "add_certificate_authority");
  456. }
  457. BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
  458. const const_buffer& ca, boost::system::error_code& ec)
  459. {
  460. ::ERR_clear_error();
  461. bio_cleanup bio = { make_buffer_bio(ca) };
  462. if (bio.p)
  463. {
  464. if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
  465. {
  466. for (;;)
  467. {
  468. x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
  469. if (!cert.p)
  470. break;
  471. if (::X509_STORE_add_cert(store, cert.p) != 1)
  472. {
  473. ec = boost::system::error_code(
  474. static_cast<int>(::ERR_get_error()),
  475. boost::asio::error::get_ssl_category());
  476. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  477. }
  478. }
  479. }
  480. }
  481. ec = boost::system::error_code();
  482. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  483. }
  484. void context::set_default_verify_paths()
  485. {
  486. boost::system::error_code ec;
  487. set_default_verify_paths(ec);
  488. boost::asio::detail::throw_error(ec, "set_default_verify_paths");
  489. }
  490. BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
  491. boost::system::error_code& ec)
  492. {
  493. ::ERR_clear_error();
  494. if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
  495. {
  496. ec = boost::system::error_code(
  497. static_cast<int>(::ERR_get_error()),
  498. boost::asio::error::get_ssl_category());
  499. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  500. }
  501. ec = boost::system::error_code();
  502. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  503. }
  504. void context::add_verify_path(const std::string& path)
  505. {
  506. boost::system::error_code ec;
  507. add_verify_path(path, ec);
  508. boost::asio::detail::throw_error(ec, "add_verify_path");
  509. }
  510. BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
  511. const std::string& path, boost::system::error_code& ec)
  512. {
  513. ::ERR_clear_error();
  514. if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
  515. {
  516. ec = boost::system::error_code(
  517. static_cast<int>(::ERR_get_error()),
  518. boost::asio::error::get_ssl_category());
  519. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  520. }
  521. ec = boost::system::error_code();
  522. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  523. }
  524. void context::use_certificate(
  525. const const_buffer& certificate, file_format format)
  526. {
  527. boost::system::error_code ec;
  528. use_certificate(certificate, format, ec);
  529. boost::asio::detail::throw_error(ec, "use_certificate");
  530. }
  531. BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
  532. const const_buffer& certificate, file_format format,
  533. boost::system::error_code& ec)
  534. {
  535. ::ERR_clear_error();
  536. if (format == context_base::asn1)
  537. {
  538. if (::SSL_CTX_use_certificate_ASN1(handle_,
  539. static_cast<int>(certificate.size()),
  540. static_cast<const unsigned char*>(certificate.data())) == 1)
  541. {
  542. ec = boost::system::error_code();
  543. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  544. }
  545. }
  546. else if (format == context_base::pem)
  547. {
  548. bio_cleanup bio = { make_buffer_bio(certificate) };
  549. if (bio.p)
  550. {
  551. x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
  552. if (cert.p)
  553. {
  554. if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
  555. {
  556. ec = boost::system::error_code();
  557. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  558. }
  559. }
  560. }
  561. }
  562. else
  563. {
  564. ec = boost::asio::error::invalid_argument;
  565. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  566. }
  567. ec = boost::system::error_code(
  568. static_cast<int>(::ERR_get_error()),
  569. boost::asio::error::get_ssl_category());
  570. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  571. }
  572. void context::use_certificate_file(
  573. const std::string& filename, file_format format)
  574. {
  575. boost::system::error_code ec;
  576. use_certificate_file(filename, format, ec);
  577. boost::asio::detail::throw_error(ec, "use_certificate_file");
  578. }
  579. BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
  580. const std::string& filename, file_format format,
  581. boost::system::error_code& ec)
  582. {
  583. int file_type;
  584. switch (format)
  585. {
  586. case context_base::asn1:
  587. file_type = SSL_FILETYPE_ASN1;
  588. break;
  589. case context_base::pem:
  590. file_type = SSL_FILETYPE_PEM;
  591. break;
  592. default:
  593. {
  594. ec = boost::asio::error::invalid_argument;
  595. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  596. }
  597. }
  598. ::ERR_clear_error();
  599. if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
  600. {
  601. ec = boost::system::error_code(
  602. static_cast<int>(::ERR_get_error()),
  603. boost::asio::error::get_ssl_category());
  604. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  605. }
  606. ec = boost::system::error_code();
  607. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  608. }
  609. void context::use_certificate_chain(const const_buffer& chain)
  610. {
  611. boost::system::error_code ec;
  612. use_certificate_chain(chain, ec);
  613. boost::asio::detail::throw_error(ec, "use_certificate_chain");
  614. }
  615. BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
  616. const const_buffer& chain, boost::system::error_code& ec)
  617. {
  618. ::ERR_clear_error();
  619. bio_cleanup bio = { make_buffer_bio(chain) };
  620. if (bio.p)
  621. {
  622. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  623. pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
  624. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  625. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  626. pem_password_cb* callback = handle_->default_passwd_callback;
  627. void* cb_userdata = handle_->default_passwd_callback_userdata;
  628. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  629. x509_cleanup cert = {
  630. ::PEM_read_bio_X509_AUX(bio.p, 0,
  631. callback,
  632. cb_userdata) };
  633. if (!cert.p)
  634. {
  635. ec = boost::system::error_code(ERR_R_PEM_LIB,
  636. boost::asio::error::get_ssl_category());
  637. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  638. }
  639. int result = ::SSL_CTX_use_certificate(handle_, cert.p);
  640. if (result == 0 || ::ERR_peek_error() != 0)
  641. {
  642. ec = boost::system::error_code(
  643. static_cast<int>(::ERR_get_error()),
  644. boost::asio::error::get_ssl_category());
  645. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  646. }
  647. #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER)
  648. ::SSL_CTX_clear_chain_certs(handle_);
  649. #else
  650. if (handle_->extra_certs)
  651. {
  652. ::sk_X509_pop_free(handle_->extra_certs, X509_free);
  653. handle_->extra_certs = 0;
  654. }
  655. #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
  656. while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
  657. callback,
  658. cb_userdata))
  659. {
  660. if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
  661. {
  662. ec = boost::system::error_code(
  663. static_cast<int>(::ERR_get_error()),
  664. boost::asio::error::get_ssl_category());
  665. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  666. }
  667. }
  668. result = ::ERR_peek_last_error();
  669. if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
  670. && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
  671. {
  672. ::ERR_clear_error();
  673. ec = boost::system::error_code();
  674. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  675. }
  676. }
  677. ec = boost::system::error_code(
  678. static_cast<int>(::ERR_get_error()),
  679. boost::asio::error::get_ssl_category());
  680. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  681. }
  682. void context::use_certificate_chain_file(const std::string& filename)
  683. {
  684. boost::system::error_code ec;
  685. use_certificate_chain_file(filename, ec);
  686. boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
  687. }
  688. BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
  689. const std::string& filename, boost::system::error_code& ec)
  690. {
  691. ::ERR_clear_error();
  692. if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
  693. {
  694. ec = boost::system::error_code(
  695. static_cast<int>(::ERR_get_error()),
  696. boost::asio::error::get_ssl_category());
  697. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  698. }
  699. ec = boost::system::error_code();
  700. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  701. }
  702. void context::use_private_key(
  703. const const_buffer& private_key, context::file_format format)
  704. {
  705. boost::system::error_code ec;
  706. use_private_key(private_key, format, ec);
  707. boost::asio::detail::throw_error(ec, "use_private_key");
  708. }
  709. BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
  710. const const_buffer& private_key, context::file_format format,
  711. boost::system::error_code& ec)
  712. {
  713. ::ERR_clear_error();
  714. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  715. pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
  716. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  717. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  718. pem_password_cb* callback = handle_->default_passwd_callback;
  719. void* cb_userdata = handle_->default_passwd_callback_userdata;
  720. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  721. bio_cleanup bio = { make_buffer_bio(private_key) };
  722. if (bio.p)
  723. {
  724. evp_pkey_cleanup evp_private_key = { 0 };
  725. switch (format)
  726. {
  727. case context_base::asn1:
  728. evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
  729. break;
  730. case context_base::pem:
  731. evp_private_key.p = ::PEM_read_bio_PrivateKey(
  732. bio.p, 0, callback,
  733. cb_userdata);
  734. break;
  735. default:
  736. {
  737. ec = boost::asio::error::invalid_argument;
  738. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  739. }
  740. }
  741. if (evp_private_key.p)
  742. {
  743. if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
  744. {
  745. ec = boost::system::error_code();
  746. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  747. }
  748. }
  749. }
  750. ec = boost::system::error_code(
  751. static_cast<int>(::ERR_get_error()),
  752. boost::asio::error::get_ssl_category());
  753. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  754. }
  755. void context::use_private_key_file(
  756. const std::string& filename, context::file_format format)
  757. {
  758. boost::system::error_code ec;
  759. use_private_key_file(filename, format, ec);
  760. boost::asio::detail::throw_error(ec, "use_private_key_file");
  761. }
  762. void context::use_rsa_private_key(
  763. const const_buffer& private_key, context::file_format format)
  764. {
  765. boost::system::error_code ec;
  766. use_rsa_private_key(private_key, format, ec);
  767. boost::asio::detail::throw_error(ec, "use_rsa_private_key");
  768. }
  769. BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
  770. const const_buffer& private_key, context::file_format format,
  771. boost::system::error_code& ec)
  772. {
  773. ::ERR_clear_error();
  774. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  775. pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
  776. void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  777. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  778. pem_password_cb* callback = handle_->default_passwd_callback;
  779. void* cb_userdata = handle_->default_passwd_callback_userdata;
  780. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  781. bio_cleanup bio = { make_buffer_bio(private_key) };
  782. if (bio.p)
  783. {
  784. rsa_cleanup rsa_private_key = { 0 };
  785. switch (format)
  786. {
  787. case context_base::asn1:
  788. rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
  789. break;
  790. case context_base::pem:
  791. rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
  792. bio.p, 0, callback,
  793. cb_userdata);
  794. break;
  795. default:
  796. {
  797. ec = boost::asio::error::invalid_argument;
  798. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  799. }
  800. }
  801. if (rsa_private_key.p)
  802. {
  803. if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
  804. {
  805. ec = boost::system::error_code();
  806. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  807. }
  808. }
  809. }
  810. ec = boost::system::error_code(
  811. static_cast<int>(::ERR_get_error()),
  812. boost::asio::error::get_ssl_category());
  813. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  814. }
  815. BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file(
  816. const std::string& filename, context::file_format format,
  817. boost::system::error_code& ec)
  818. {
  819. int file_type;
  820. switch (format)
  821. {
  822. case context_base::asn1:
  823. file_type = SSL_FILETYPE_ASN1;
  824. break;
  825. case context_base::pem:
  826. file_type = SSL_FILETYPE_PEM;
  827. break;
  828. default:
  829. {
  830. ec = boost::asio::error::invalid_argument;
  831. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  832. }
  833. }
  834. ::ERR_clear_error();
  835. if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
  836. {
  837. ec = boost::system::error_code(
  838. static_cast<int>(::ERR_get_error()),
  839. boost::asio::error::get_ssl_category());
  840. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  841. }
  842. ec = boost::system::error_code();
  843. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  844. }
  845. void context::use_rsa_private_key_file(
  846. const std::string& filename, context::file_format format)
  847. {
  848. boost::system::error_code ec;
  849. use_rsa_private_key_file(filename, format, ec);
  850. boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
  851. }
  852. BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(
  853. const std::string& filename, context::file_format format,
  854. boost::system::error_code& ec)
  855. {
  856. int file_type;
  857. switch (format)
  858. {
  859. case context_base::asn1:
  860. file_type = SSL_FILETYPE_ASN1;
  861. break;
  862. case context_base::pem:
  863. file_type = SSL_FILETYPE_PEM;
  864. break;
  865. default:
  866. {
  867. ec = boost::asio::error::invalid_argument;
  868. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  869. }
  870. }
  871. ::ERR_clear_error();
  872. if (::SSL_CTX_use_RSAPrivateKey_file(
  873. handle_, filename.c_str(), file_type) != 1)
  874. {
  875. ec = boost::system::error_code(
  876. static_cast<int>(::ERR_get_error()),
  877. boost::asio::error::get_ssl_category());
  878. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  879. }
  880. ec = boost::system::error_code();
  881. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  882. }
  883. void context::use_tmp_dh(const const_buffer& dh)
  884. {
  885. boost::system::error_code ec;
  886. use_tmp_dh(dh, ec);
  887. boost::asio::detail::throw_error(ec, "use_tmp_dh");
  888. }
  889. BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
  890. const const_buffer& dh, boost::system::error_code& ec)
  891. {
  892. ::ERR_clear_error();
  893. bio_cleanup bio = { make_buffer_bio(dh) };
  894. if (bio.p)
  895. {
  896. return do_use_tmp_dh(bio.p, ec);
  897. }
  898. ec = boost::system::error_code(
  899. static_cast<int>(::ERR_get_error()),
  900. boost::asio::error::get_ssl_category());
  901. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  902. }
  903. void context::use_tmp_dh_file(const std::string& filename)
  904. {
  905. boost::system::error_code ec;
  906. use_tmp_dh_file(filename, ec);
  907. boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
  908. }
  909. BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
  910. const std::string& filename, boost::system::error_code& ec)
  911. {
  912. ::ERR_clear_error();
  913. bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
  914. if (bio.p)
  915. {
  916. return do_use_tmp_dh(bio.p, ec);
  917. }
  918. ec = boost::system::error_code(
  919. static_cast<int>(::ERR_get_error()),
  920. boost::asio::error::get_ssl_category());
  921. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  922. }
  923. BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
  924. BIO* bio, boost::system::error_code& ec)
  925. {
  926. ::ERR_clear_error();
  927. dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
  928. if (dh.p)
  929. {
  930. if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
  931. {
  932. ec = boost::system::error_code();
  933. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  934. }
  935. }
  936. ec = boost::system::error_code(
  937. static_cast<int>(::ERR_get_error()),
  938. boost::asio::error::get_ssl_category());
  939. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  940. }
  941. BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
  942. detail::verify_callback_base* callback, boost::system::error_code& ec)
  943. {
  944. if (SSL_CTX_get_app_data(handle_))
  945. {
  946. delete static_cast<detail::verify_callback_base*>(
  947. SSL_CTX_get_app_data(handle_));
  948. }
  949. SSL_CTX_set_app_data(handle_, callback);
  950. ::SSL_CTX_set_verify(handle_,
  951. ::SSL_CTX_get_verify_mode(handle_),
  952. &context::verify_callback_function);
  953. ec = boost::system::error_code();
  954. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  955. }
  956. int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
  957. {
  958. if (ctx)
  959. {
  960. if (SSL* ssl = static_cast<SSL*>(
  961. ::X509_STORE_CTX_get_ex_data(
  962. ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
  963. {
  964. if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
  965. {
  966. if (SSL_CTX_get_app_data(handle))
  967. {
  968. detail::verify_callback_base* callback =
  969. static_cast<detail::verify_callback_base*>(
  970. SSL_CTX_get_app_data(handle));
  971. verify_context verify_ctx(ctx);
  972. return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
  973. }
  974. }
  975. }
  976. }
  977. return 0;
  978. }
  979. BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
  980. detail::password_callback_base* callback, boost::system::error_code& ec)
  981. {
  982. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
  983. void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
  984. ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
  985. #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  986. void* old_callback = handle_->default_passwd_callback_userdata;
  987. handle_->default_passwd_callback_userdata = callback;
  988. #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  989. if (old_callback)
  990. delete static_cast<detail::password_callback_base*>(
  991. old_callback);
  992. SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
  993. ec = boost::system::error_code();
  994. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  995. }
  996. int context::password_callback_function(
  997. char* buf, int size, int purpose, void* data)
  998. {
  999. using namespace std; // For strncat and strlen.
  1000. if (data)
  1001. {
  1002. detail::password_callback_base* callback =
  1003. static_cast<detail::password_callback_base*>(data);
  1004. std::string passwd = callback->call(static_cast<std::size_t>(size),
  1005. purpose ? context_base::for_writing : context_base::for_reading);
  1006. #if defined(BOOST_ASIO_HAS_SECURE_RTL)
  1007. strcpy_s(buf, size, passwd.c_str());
  1008. #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
  1009. *buf = '\0';
  1010. if (size > 0)
  1011. strncat(buf, passwd.c_str(), size - 1);
  1012. #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
  1013. return static_cast<int>(strlen(buf));
  1014. }
  1015. return 0;
  1016. }
  1017. BIO* context::make_buffer_bio(const const_buffer& b)
  1018. {
  1019. return ::BIO_new_mem_buf(
  1020. const_cast<void*>(b.data()),
  1021. static_cast<int>(b.size()));
  1022. }
  1023. } // namespace ssl
  1024. } // namespace asio
  1025. } // namespace boost
  1026. #include <boost/asio/detail/pop_options.hpp>
  1027. #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP