annotate DEPENDENCIES/generic/include/boost/asio/ssl/impl/context.ipp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // ssl/impl/context.ipp
Chris@16 3 // ~~~~~~~~~~~~~~~~~~~~
Chris@16 4 //
Chris@16 5 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
Chris@101 6 // Copyright (c) 2005-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Chris@16 7 //
Chris@16 8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10 //
Chris@16 11
Chris@16 12 #ifndef BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
Chris@16 13 #define BOOST_ASIO_SSL_IMPL_CONTEXT_IPP
Chris@16 14
Chris@16 15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 16 # pragma once
Chris@16 17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 18
Chris@16 19 #include <boost/asio/detail/config.hpp>
Chris@16 20
Chris@16 21 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
Chris@16 22 # include <cstring>
Chris@16 23 # include <boost/asio/detail/throw_error.hpp>
Chris@16 24 # include <boost/asio/error.hpp>
Chris@16 25 # include <boost/asio/ssl/context.hpp>
Chris@16 26 # include <boost/asio/ssl/error.hpp>
Chris@16 27 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
Chris@16 28
Chris@16 29 #include <boost/asio/detail/push_options.hpp>
Chris@16 30
Chris@16 31 namespace boost {
Chris@16 32 namespace asio {
Chris@16 33 namespace ssl {
Chris@16 34
Chris@16 35 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
Chris@16 36
Chris@16 37 struct context::bio_cleanup
Chris@16 38 {
Chris@16 39 BIO* p;
Chris@16 40 ~bio_cleanup() { if (p) ::BIO_free(p); }
Chris@16 41 };
Chris@16 42
Chris@16 43 struct context::x509_cleanup
Chris@16 44 {
Chris@16 45 X509* p;
Chris@16 46 ~x509_cleanup() { if (p) ::X509_free(p); }
Chris@16 47 };
Chris@16 48
Chris@16 49 struct context::evp_pkey_cleanup
Chris@16 50 {
Chris@16 51 EVP_PKEY* p;
Chris@16 52 ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }
Chris@16 53 };
Chris@16 54
Chris@16 55 struct context::rsa_cleanup
Chris@16 56 {
Chris@16 57 RSA* p;
Chris@16 58 ~rsa_cleanup() { if (p) ::RSA_free(p); }
Chris@16 59 };
Chris@16 60
Chris@16 61 struct context::dh_cleanup
Chris@16 62 {
Chris@16 63 DH* p;
Chris@16 64 ~dh_cleanup() { if (p) ::DH_free(p); }
Chris@16 65 };
Chris@16 66
Chris@16 67 context::context(context::method m)
Chris@16 68 : handle_(0)
Chris@16 69 {
Chris@101 70 ::ERR_clear_error();
Chris@101 71
Chris@16 72 switch (m)
Chris@16 73 {
Chris@16 74 #if defined(OPENSSL_NO_SSL2)
Chris@16 75 case context::sslv2:
Chris@16 76 case context::sslv2_client:
Chris@16 77 case context::sslv2_server:
Chris@16 78 boost::asio::detail::throw_error(
Chris@16 79 boost::asio::error::invalid_argument, "context");
Chris@16 80 break;
Chris@16 81 #else // defined(OPENSSL_NO_SSL2)
Chris@16 82 case context::sslv2:
Chris@16 83 handle_ = ::SSL_CTX_new(::SSLv2_method());
Chris@16 84 break;
Chris@16 85 case context::sslv2_client:
Chris@16 86 handle_ = ::SSL_CTX_new(::SSLv2_client_method());
Chris@16 87 break;
Chris@16 88 case context::sslv2_server:
Chris@16 89 handle_ = ::SSL_CTX_new(::SSLv2_server_method());
Chris@16 90 break;
Chris@16 91 #endif // defined(OPENSSL_NO_SSL2)
Chris@16 92 case context::sslv3:
Chris@16 93 handle_ = ::SSL_CTX_new(::SSLv3_method());
Chris@16 94 break;
Chris@16 95 case context::sslv3_client:
Chris@16 96 handle_ = ::SSL_CTX_new(::SSLv3_client_method());
Chris@16 97 break;
Chris@16 98 case context::sslv3_server:
Chris@16 99 handle_ = ::SSL_CTX_new(::SSLv3_server_method());
Chris@16 100 break;
Chris@16 101 case context::tlsv1:
Chris@16 102 handle_ = ::SSL_CTX_new(::TLSv1_method());
Chris@16 103 break;
Chris@16 104 case context::tlsv1_client:
Chris@16 105 handle_ = ::SSL_CTX_new(::TLSv1_client_method());
Chris@16 106 break;
Chris@16 107 case context::tlsv1_server:
Chris@16 108 handle_ = ::SSL_CTX_new(::TLSv1_server_method());
Chris@16 109 break;
Chris@16 110 case context::sslv23:
Chris@16 111 handle_ = ::SSL_CTX_new(::SSLv23_method());
Chris@16 112 break;
Chris@16 113 case context::sslv23_client:
Chris@16 114 handle_ = ::SSL_CTX_new(::SSLv23_client_method());
Chris@16 115 break;
Chris@16 116 case context::sslv23_server:
Chris@16 117 handle_ = ::SSL_CTX_new(::SSLv23_server_method());
Chris@16 118 break;
Chris@16 119 #if defined(SSL_TXT_TLSV1_1)
Chris@16 120 case context::tlsv11:
Chris@16 121 handle_ = ::SSL_CTX_new(::TLSv1_1_method());
Chris@16 122 break;
Chris@16 123 case context::tlsv11_client:
Chris@16 124 handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());
Chris@16 125 break;
Chris@16 126 case context::tlsv11_server:
Chris@16 127 handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());
Chris@16 128 break;
Chris@16 129 #else // defined(SSL_TXT_TLSV1_1)
Chris@16 130 case context::tlsv11:
Chris@16 131 case context::tlsv11_client:
Chris@16 132 case context::tlsv11_server:
Chris@16 133 boost::asio::detail::throw_error(
Chris@16 134 boost::asio::error::invalid_argument, "context");
Chris@16 135 break;
Chris@16 136 #endif // defined(SSL_TXT_TLSV1_1)
Chris@16 137 #if defined(SSL_TXT_TLSV1_2)
Chris@16 138 case context::tlsv12:
Chris@16 139 handle_ = ::SSL_CTX_new(::TLSv1_2_method());
Chris@16 140 break;
Chris@16 141 case context::tlsv12_client:
Chris@16 142 handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());
Chris@16 143 break;
Chris@16 144 case context::tlsv12_server:
Chris@16 145 handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
Chris@16 146 break;
Chris@16 147 #else // defined(SSL_TXT_TLSV1_2)
Chris@16 148 case context::tlsv12:
Chris@16 149 case context::tlsv12_client:
Chris@16 150 case context::tlsv12_server:
Chris@16 151 boost::asio::detail::throw_error(
Chris@16 152 boost::asio::error::invalid_argument, "context");
Chris@16 153 break;
Chris@16 154 #endif // defined(SSL_TXT_TLSV1_2)
Chris@16 155 default:
Chris@16 156 handle_ = ::SSL_CTX_new(0);
Chris@16 157 break;
Chris@16 158 }
Chris@16 159
Chris@16 160 if (handle_ == 0)
Chris@16 161 {
Chris@16 162 boost::system::error_code ec(
Chris@16 163 static_cast<int>(::ERR_get_error()),
Chris@16 164 boost::asio::error::get_ssl_category());
Chris@16 165 boost::asio::detail::throw_error(ec, "context");
Chris@16 166 }
Chris@16 167
Chris@16 168 set_options(no_compression);
Chris@16 169 }
Chris@16 170
Chris@16 171 context::context(boost::asio::io_service&, context::method m)
Chris@16 172 : handle_(0)
Chris@16 173 {
Chris@16 174 context tmp(m);
Chris@16 175 handle_ = tmp.handle_;
Chris@16 176 tmp.handle_ = 0;
Chris@16 177 }
Chris@16 178
Chris@16 179 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
Chris@16 180 context::context(context&& other)
Chris@16 181 {
Chris@16 182 handle_ = other.handle_;
Chris@16 183 other.handle_ = 0;
Chris@16 184 }
Chris@16 185
Chris@16 186 context& context::operator=(context&& other)
Chris@16 187 {
Chris@16 188 context tmp(BOOST_ASIO_MOVE_CAST(context)(*this));
Chris@16 189 handle_ = other.handle_;
Chris@16 190 other.handle_ = 0;
Chris@16 191 return *this;
Chris@16 192 }
Chris@16 193 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
Chris@16 194
Chris@16 195 context::~context()
Chris@16 196 {
Chris@16 197 if (handle_)
Chris@16 198 {
Chris@16 199 if (handle_->default_passwd_callback_userdata)
Chris@16 200 {
Chris@16 201 detail::password_callback_base* callback =
Chris@16 202 static_cast<detail::password_callback_base*>(
Chris@16 203 handle_->default_passwd_callback_userdata);
Chris@16 204 delete callback;
Chris@16 205 handle_->default_passwd_callback_userdata = 0;
Chris@16 206 }
Chris@16 207
Chris@16 208 if (SSL_CTX_get_app_data(handle_))
Chris@16 209 {
Chris@16 210 detail::verify_callback_base* callback =
Chris@16 211 static_cast<detail::verify_callback_base*>(
Chris@16 212 SSL_CTX_get_app_data(handle_));
Chris@16 213 delete callback;
Chris@16 214 SSL_CTX_set_app_data(handle_, 0);
Chris@16 215 }
Chris@16 216
Chris@16 217 ::SSL_CTX_free(handle_);
Chris@16 218 }
Chris@16 219 }
Chris@16 220
Chris@16 221 context::native_handle_type context::native_handle()
Chris@16 222 {
Chris@16 223 return handle_;
Chris@16 224 }
Chris@16 225
Chris@16 226 context::impl_type context::impl()
Chris@16 227 {
Chris@16 228 return handle_;
Chris@16 229 }
Chris@16 230
Chris@16 231 void context::clear_options(context::options o)
Chris@16 232 {
Chris@16 233 boost::system::error_code ec;
Chris@16 234 clear_options(o, ec);
Chris@16 235 boost::asio::detail::throw_error(ec, "clear_options");
Chris@16 236 }
Chris@16 237
Chris@16 238 boost::system::error_code context::clear_options(
Chris@16 239 context::options o, boost::system::error_code& ec)
Chris@16 240 {
Chris@16 241 #if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
Chris@16 242 && (OPENSSL_VERSION_NUMBER != 0x00909000L)
Chris@16 243 # if !defined(SSL_OP_NO_COMPRESSION)
Chris@16 244 if ((o & context::no_compression) != 0)
Chris@16 245 {
Chris@16 246 # if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
Chris@16 247 handle_->comp_methods = SSL_COMP_get_compression_methods();
Chris@16 248 # endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
Chris@16 249 o ^= context::no_compression;
Chris@16 250 }
Chris@16 251 # endif // !defined(SSL_OP_NO_COMPRESSION)
Chris@16 252
Chris@16 253 ::SSL_CTX_clear_options(handle_, o);
Chris@16 254
Chris@16 255 ec = boost::system::error_code();
Chris@16 256 #else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
Chris@16 257 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
Chris@16 258 (void)o;
Chris@16 259 ec = boost::asio::error::operation_not_supported;
Chris@16 260 #endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
Chris@16 261 // && (OPENSSL_VERSION_NUMBER != 0x00909000L)
Chris@16 262 return ec;
Chris@16 263 }
Chris@16 264
Chris@16 265 void context::set_options(context::options o)
Chris@16 266 {
Chris@16 267 boost::system::error_code ec;
Chris@16 268 set_options(o, ec);
Chris@16 269 boost::asio::detail::throw_error(ec, "set_options");
Chris@16 270 }
Chris@16 271
Chris@16 272 boost::system::error_code context::set_options(
Chris@16 273 context::options o, boost::system::error_code& ec)
Chris@16 274 {
Chris@16 275 #if !defined(SSL_OP_NO_COMPRESSION)
Chris@16 276 if ((o & context::no_compression) != 0)
Chris@16 277 {
Chris@16 278 #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
Chris@16 279 handle_->comp_methods =
Chris@16 280 boost::asio::ssl::detail::openssl_init<>::get_null_compression_methods();
Chris@16 281 #endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)
Chris@16 282 o ^= context::no_compression;
Chris@16 283 }
Chris@16 284 #endif // !defined(SSL_OP_NO_COMPRESSION)
Chris@16 285
Chris@16 286 ::SSL_CTX_set_options(handle_, o);
Chris@16 287
Chris@16 288 ec = boost::system::error_code();
Chris@16 289 return ec;
Chris@16 290 }
Chris@16 291
Chris@16 292 void context::set_verify_mode(verify_mode v)
Chris@16 293 {
Chris@16 294 boost::system::error_code ec;
Chris@16 295 set_verify_mode(v, ec);
Chris@16 296 boost::asio::detail::throw_error(ec, "set_verify_mode");
Chris@16 297 }
Chris@16 298
Chris@16 299 boost::system::error_code context::set_verify_mode(
Chris@16 300 verify_mode v, boost::system::error_code& ec)
Chris@16 301 {
Chris@16 302 ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
Chris@16 303
Chris@16 304 ec = boost::system::error_code();
Chris@16 305 return ec;
Chris@16 306 }
Chris@16 307
Chris@16 308 void context::set_verify_depth(int depth)
Chris@16 309 {
Chris@16 310 boost::system::error_code ec;
Chris@16 311 set_verify_depth(depth, ec);
Chris@16 312 boost::asio::detail::throw_error(ec, "set_verify_depth");
Chris@16 313 }
Chris@16 314
Chris@16 315 boost::system::error_code context::set_verify_depth(
Chris@16 316 int depth, boost::system::error_code& ec)
Chris@16 317 {
Chris@16 318 ::SSL_CTX_set_verify_depth(handle_, depth);
Chris@16 319
Chris@16 320 ec = boost::system::error_code();
Chris@16 321 return ec;
Chris@16 322 }
Chris@16 323
Chris@16 324 void context::load_verify_file(const std::string& filename)
Chris@16 325 {
Chris@16 326 boost::system::error_code ec;
Chris@16 327 load_verify_file(filename, ec);
Chris@16 328 boost::asio::detail::throw_error(ec, "load_verify_file");
Chris@16 329 }
Chris@16 330
Chris@16 331 boost::system::error_code context::load_verify_file(
Chris@16 332 const std::string& filename, boost::system::error_code& ec)
Chris@16 333 {
Chris@101 334 ::ERR_clear_error();
Chris@101 335
Chris@16 336 if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)
Chris@16 337 {
Chris@16 338 ec = boost::system::error_code(
Chris@16 339 static_cast<int>(::ERR_get_error()),
Chris@16 340 boost::asio::error::get_ssl_category());
Chris@16 341 return ec;
Chris@16 342 }
Chris@16 343
Chris@16 344 ec = boost::system::error_code();
Chris@16 345 return ec;
Chris@16 346 }
Chris@16 347
Chris@16 348 void context::add_certificate_authority(const const_buffer& ca)
Chris@16 349 {
Chris@16 350 boost::system::error_code ec;
Chris@16 351 add_certificate_authority(ca, ec);
Chris@16 352 boost::asio::detail::throw_error(ec, "add_certificate_authority");
Chris@16 353 }
Chris@16 354
Chris@16 355 boost::system::error_code context::add_certificate_authority(
Chris@16 356 const const_buffer& ca, boost::system::error_code& ec)
Chris@16 357 {
Chris@16 358 ::ERR_clear_error();
Chris@16 359
Chris@16 360 bio_cleanup bio = { make_buffer_bio(ca) };
Chris@16 361 if (bio.p)
Chris@16 362 {
Chris@16 363 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
Chris@16 364 if (cert.p)
Chris@16 365 {
Chris@16 366 if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))
Chris@16 367 {
Chris@16 368 if (::X509_STORE_add_cert(store, cert.p) == 1)
Chris@16 369 {
Chris@16 370 ec = boost::system::error_code();
Chris@16 371 return ec;
Chris@16 372 }
Chris@16 373 }
Chris@16 374 }
Chris@16 375 }
Chris@16 376
Chris@16 377 ec = boost::system::error_code(
Chris@16 378 static_cast<int>(::ERR_get_error()),
Chris@16 379 boost::asio::error::get_ssl_category());
Chris@16 380 return ec;
Chris@16 381 }
Chris@16 382
Chris@16 383 void context::set_default_verify_paths()
Chris@16 384 {
Chris@16 385 boost::system::error_code ec;
Chris@16 386 set_default_verify_paths(ec);
Chris@16 387 boost::asio::detail::throw_error(ec, "set_default_verify_paths");
Chris@16 388 }
Chris@16 389
Chris@16 390 boost::system::error_code context::set_default_verify_paths(
Chris@16 391 boost::system::error_code& ec)
Chris@16 392 {
Chris@101 393 ::ERR_clear_error();
Chris@101 394
Chris@16 395 if (::SSL_CTX_set_default_verify_paths(handle_) != 1)
Chris@16 396 {
Chris@16 397 ec = boost::system::error_code(
Chris@16 398 static_cast<int>(::ERR_get_error()),
Chris@16 399 boost::asio::error::get_ssl_category());
Chris@16 400 return ec;
Chris@16 401 }
Chris@16 402
Chris@16 403 ec = boost::system::error_code();
Chris@16 404 return ec;
Chris@16 405 }
Chris@16 406
Chris@16 407 void context::add_verify_path(const std::string& path)
Chris@16 408 {
Chris@16 409 boost::system::error_code ec;
Chris@16 410 add_verify_path(path, ec);
Chris@16 411 boost::asio::detail::throw_error(ec, "add_verify_path");
Chris@16 412 }
Chris@16 413
Chris@16 414 boost::system::error_code context::add_verify_path(
Chris@16 415 const std::string& path, boost::system::error_code& ec)
Chris@16 416 {
Chris@101 417 ::ERR_clear_error();
Chris@101 418
Chris@16 419 if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)
Chris@16 420 {
Chris@16 421 ec = boost::system::error_code(
Chris@16 422 static_cast<int>(::ERR_get_error()),
Chris@16 423 boost::asio::error::get_ssl_category());
Chris@16 424 return ec;
Chris@16 425 }
Chris@16 426
Chris@16 427 ec = boost::system::error_code();
Chris@16 428 return ec;
Chris@16 429 }
Chris@16 430
Chris@16 431 void context::use_certificate(
Chris@16 432 const const_buffer& certificate, file_format format)
Chris@16 433 {
Chris@16 434 boost::system::error_code ec;
Chris@16 435 use_certificate(certificate, format, ec);
Chris@16 436 boost::asio::detail::throw_error(ec, "use_certificate");
Chris@16 437 }
Chris@16 438
Chris@16 439 boost::system::error_code context::use_certificate(
Chris@16 440 const const_buffer& certificate, file_format format,
Chris@16 441 boost::system::error_code& ec)
Chris@16 442 {
Chris@16 443 ::ERR_clear_error();
Chris@16 444
Chris@16 445 if (format == context_base::asn1)
Chris@16 446 {
Chris@16 447 if (::SSL_CTX_use_certificate_ASN1(handle_,
Chris@16 448 static_cast<int>(buffer_size(certificate)),
Chris@16 449 buffer_cast<const unsigned char*>(certificate)) == 1)
Chris@16 450 {
Chris@16 451 ec = boost::system::error_code();
Chris@16 452 return ec;
Chris@16 453 }
Chris@16 454 }
Chris@16 455 else if (format == context_base::pem)
Chris@16 456 {
Chris@16 457 bio_cleanup bio = { make_buffer_bio(certificate) };
Chris@16 458 if (bio.p)
Chris@16 459 {
Chris@16 460 x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };
Chris@16 461 if (cert.p)
Chris@16 462 {
Chris@16 463 if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
Chris@16 464 {
Chris@16 465 ec = boost::system::error_code();
Chris@16 466 return ec;
Chris@16 467 }
Chris@16 468 }
Chris@16 469 }
Chris@16 470 }
Chris@16 471 else
Chris@16 472 {
Chris@16 473 ec = boost::asio::error::invalid_argument;
Chris@16 474 return ec;
Chris@16 475 }
Chris@16 476
Chris@16 477 ec = boost::system::error_code(
Chris@16 478 static_cast<int>(::ERR_get_error()),
Chris@16 479 boost::asio::error::get_ssl_category());
Chris@16 480 return ec;
Chris@16 481 }
Chris@16 482
Chris@16 483 void context::use_certificate_file(
Chris@16 484 const std::string& filename, file_format format)
Chris@16 485 {
Chris@16 486 boost::system::error_code ec;
Chris@16 487 use_certificate_file(filename, format, ec);
Chris@16 488 boost::asio::detail::throw_error(ec, "use_certificate_file");
Chris@16 489 }
Chris@16 490
Chris@16 491 boost::system::error_code context::use_certificate_file(
Chris@16 492 const std::string& filename, file_format format,
Chris@16 493 boost::system::error_code& ec)
Chris@16 494 {
Chris@16 495 int file_type;
Chris@16 496 switch (format)
Chris@16 497 {
Chris@16 498 case context_base::asn1:
Chris@16 499 file_type = SSL_FILETYPE_ASN1;
Chris@16 500 break;
Chris@16 501 case context_base::pem:
Chris@16 502 file_type = SSL_FILETYPE_PEM;
Chris@16 503 break;
Chris@16 504 default:
Chris@16 505 {
Chris@16 506 ec = boost::asio::error::invalid_argument;
Chris@16 507 return ec;
Chris@16 508 }
Chris@16 509 }
Chris@16 510
Chris@101 511 ::ERR_clear_error();
Chris@101 512
Chris@16 513 if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)
Chris@16 514 {
Chris@16 515 ec = boost::system::error_code(
Chris@16 516 static_cast<int>(::ERR_get_error()),
Chris@16 517 boost::asio::error::get_ssl_category());
Chris@16 518 return ec;
Chris@16 519 }
Chris@16 520
Chris@16 521 ec = boost::system::error_code();
Chris@16 522 return ec;
Chris@16 523 }
Chris@16 524
Chris@16 525 void context::use_certificate_chain(const const_buffer& chain)
Chris@16 526 {
Chris@16 527 boost::system::error_code ec;
Chris@16 528 use_certificate_chain(chain, ec);
Chris@16 529 boost::asio::detail::throw_error(ec, "use_certificate_chain");
Chris@16 530 }
Chris@16 531
Chris@16 532 boost::system::error_code context::use_certificate_chain(
Chris@16 533 const const_buffer& chain, boost::system::error_code& ec)
Chris@16 534 {
Chris@16 535 ::ERR_clear_error();
Chris@16 536
Chris@16 537 bio_cleanup bio = { make_buffer_bio(chain) };
Chris@16 538 if (bio.p)
Chris@16 539 {
Chris@16 540 x509_cleanup cert = {
Chris@16 541 ::PEM_read_bio_X509_AUX(bio.p, 0,
Chris@16 542 handle_->default_passwd_callback,
Chris@16 543 handle_->default_passwd_callback_userdata) };
Chris@16 544 if (!cert.p)
Chris@16 545 {
Chris@16 546 ec = boost::system::error_code(ERR_R_PEM_LIB,
Chris@16 547 boost::asio::error::get_ssl_category());
Chris@16 548 return ec;
Chris@16 549 }
Chris@16 550
Chris@16 551 int result = ::SSL_CTX_use_certificate(handle_, cert.p);
Chris@16 552 if (result == 0 || ::ERR_peek_error() != 0)
Chris@16 553 {
Chris@16 554 ec = boost::system::error_code(
Chris@16 555 static_cast<int>(::ERR_get_error()),
Chris@16 556 boost::asio::error::get_ssl_category());
Chris@16 557 return ec;
Chris@16 558 }
Chris@16 559
Chris@16 560 if (handle_->extra_certs)
Chris@16 561 {
Chris@16 562 ::sk_X509_pop_free(handle_->extra_certs, X509_free);
Chris@16 563 handle_->extra_certs = 0;
Chris@16 564 }
Chris@16 565
Chris@16 566 while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,
Chris@16 567 handle_->default_passwd_callback,
Chris@16 568 handle_->default_passwd_callback_userdata))
Chris@16 569 {
Chris@16 570 if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))
Chris@16 571 {
Chris@16 572 ec = boost::system::error_code(
Chris@16 573 static_cast<int>(::ERR_get_error()),
Chris@16 574 boost::asio::error::get_ssl_category());
Chris@16 575 return ec;
Chris@16 576 }
Chris@16 577 }
Chris@16 578
Chris@16 579 result = ::ERR_peek_last_error();
Chris@16 580 if ((ERR_GET_LIB(result) == ERR_LIB_PEM)
Chris@16 581 && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))
Chris@16 582 {
Chris@16 583 ::ERR_clear_error();
Chris@16 584 ec = boost::system::error_code();
Chris@16 585 return ec;
Chris@16 586 }
Chris@16 587 }
Chris@16 588
Chris@16 589 ec = boost::system::error_code(
Chris@16 590 static_cast<int>(::ERR_get_error()),
Chris@16 591 boost::asio::error::get_ssl_category());
Chris@16 592 return ec;
Chris@16 593 }
Chris@16 594
Chris@16 595 void context::use_certificate_chain_file(const std::string& filename)
Chris@16 596 {
Chris@16 597 boost::system::error_code ec;
Chris@16 598 use_certificate_chain_file(filename, ec);
Chris@16 599 boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
Chris@16 600 }
Chris@16 601
Chris@16 602 boost::system::error_code context::use_certificate_chain_file(
Chris@16 603 const std::string& filename, boost::system::error_code& ec)
Chris@16 604 {
Chris@101 605 ::ERR_clear_error();
Chris@101 606
Chris@16 607 if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)
Chris@16 608 {
Chris@16 609 ec = boost::system::error_code(
Chris@16 610 static_cast<int>(::ERR_get_error()),
Chris@16 611 boost::asio::error::get_ssl_category());
Chris@16 612 return ec;
Chris@16 613 }
Chris@16 614
Chris@16 615 ec = boost::system::error_code();
Chris@16 616 return ec;
Chris@16 617 }
Chris@16 618
Chris@16 619 void context::use_private_key(
Chris@16 620 const const_buffer& private_key, context::file_format format)
Chris@16 621 {
Chris@16 622 boost::system::error_code ec;
Chris@16 623 use_private_key(private_key, format, ec);
Chris@16 624 boost::asio::detail::throw_error(ec, "use_private_key");
Chris@16 625 }
Chris@16 626
Chris@16 627 boost::system::error_code context::use_private_key(
Chris@16 628 const const_buffer& private_key, context::file_format format,
Chris@16 629 boost::system::error_code& ec)
Chris@16 630 {
Chris@16 631 ::ERR_clear_error();
Chris@16 632
Chris@16 633 bio_cleanup bio = { make_buffer_bio(private_key) };
Chris@16 634 if (bio.p)
Chris@16 635 {
Chris@16 636 evp_pkey_cleanup evp_private_key = { 0 };
Chris@16 637 switch (format)
Chris@16 638 {
Chris@16 639 case context_base::asn1:
Chris@16 640 evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);
Chris@16 641 break;
Chris@16 642 case context_base::pem:
Chris@101 643 evp_private_key.p = ::PEM_read_bio_PrivateKey(
Chris@101 644 bio.p, 0, handle_->default_passwd_callback,
Chris@101 645 handle_->default_passwd_callback_userdata);
Chris@16 646 break;
Chris@16 647 default:
Chris@16 648 {
Chris@16 649 ec = boost::asio::error::invalid_argument;
Chris@16 650 return ec;
Chris@16 651 }
Chris@16 652 }
Chris@16 653
Chris@16 654 if (evp_private_key.p)
Chris@16 655 {
Chris@16 656 if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
Chris@16 657 {
Chris@16 658 ec = boost::system::error_code();
Chris@16 659 return ec;
Chris@16 660 }
Chris@16 661 }
Chris@16 662 }
Chris@16 663
Chris@16 664 ec = boost::system::error_code(
Chris@16 665 static_cast<int>(::ERR_get_error()),
Chris@16 666 boost::asio::error::get_ssl_category());
Chris@16 667 return ec;
Chris@16 668 }
Chris@16 669
Chris@16 670 void context::use_private_key_file(
Chris@16 671 const std::string& filename, context::file_format format)
Chris@16 672 {
Chris@16 673 boost::system::error_code ec;
Chris@16 674 use_private_key_file(filename, format, ec);
Chris@16 675 boost::asio::detail::throw_error(ec, "use_private_key_file");
Chris@16 676 }
Chris@16 677
Chris@16 678 void context::use_rsa_private_key(
Chris@16 679 const const_buffer& private_key, context::file_format format)
Chris@16 680 {
Chris@16 681 boost::system::error_code ec;
Chris@16 682 use_rsa_private_key(private_key, format, ec);
Chris@16 683 boost::asio::detail::throw_error(ec, "use_rsa_private_key");
Chris@16 684 }
Chris@16 685
Chris@16 686 boost::system::error_code context::use_rsa_private_key(
Chris@16 687 const const_buffer& private_key, context::file_format format,
Chris@16 688 boost::system::error_code& ec)
Chris@16 689 {
Chris@16 690 ::ERR_clear_error();
Chris@16 691
Chris@16 692 bio_cleanup bio = { make_buffer_bio(private_key) };
Chris@16 693 if (bio.p)
Chris@16 694 {
Chris@16 695 rsa_cleanup rsa_private_key = { 0 };
Chris@16 696 switch (format)
Chris@16 697 {
Chris@16 698 case context_base::asn1:
Chris@16 699 rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);
Chris@16 700 break;
Chris@16 701 case context_base::pem:
Chris@101 702 rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(
Chris@101 703 bio.p, 0, handle_->default_passwd_callback,
Chris@101 704 handle_->default_passwd_callback_userdata);
Chris@16 705 break;
Chris@16 706 default:
Chris@16 707 {
Chris@16 708 ec = boost::asio::error::invalid_argument;
Chris@16 709 return ec;
Chris@16 710 }
Chris@16 711 }
Chris@16 712
Chris@16 713 if (rsa_private_key.p)
Chris@16 714 {
Chris@16 715 if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
Chris@16 716 {
Chris@16 717 ec = boost::system::error_code();
Chris@16 718 return ec;
Chris@16 719 }
Chris@16 720 }
Chris@16 721 }
Chris@16 722
Chris@16 723 ec = boost::system::error_code(
Chris@16 724 static_cast<int>(::ERR_get_error()),
Chris@16 725 boost::asio::error::get_ssl_category());
Chris@16 726 return ec;
Chris@16 727 }
Chris@16 728
Chris@16 729 boost::system::error_code context::use_private_key_file(
Chris@16 730 const std::string& filename, context::file_format format,
Chris@16 731 boost::system::error_code& ec)
Chris@16 732 {
Chris@16 733 int file_type;
Chris@16 734 switch (format)
Chris@16 735 {
Chris@16 736 case context_base::asn1:
Chris@16 737 file_type = SSL_FILETYPE_ASN1;
Chris@16 738 break;
Chris@16 739 case context_base::pem:
Chris@16 740 file_type = SSL_FILETYPE_PEM;
Chris@16 741 break;
Chris@16 742 default:
Chris@16 743 {
Chris@16 744 ec = boost::asio::error::invalid_argument;
Chris@16 745 return ec;
Chris@16 746 }
Chris@16 747 }
Chris@16 748
Chris@101 749 ::ERR_clear_error();
Chris@101 750
Chris@16 751 if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)
Chris@16 752 {
Chris@16 753 ec = boost::system::error_code(
Chris@16 754 static_cast<int>(::ERR_get_error()),
Chris@16 755 boost::asio::error::get_ssl_category());
Chris@16 756 return ec;
Chris@16 757 }
Chris@16 758
Chris@16 759 ec = boost::system::error_code();
Chris@16 760 return ec;
Chris@16 761 }
Chris@16 762
Chris@16 763 void context::use_rsa_private_key_file(
Chris@16 764 const std::string& filename, context::file_format format)
Chris@16 765 {
Chris@16 766 boost::system::error_code ec;
Chris@16 767 use_rsa_private_key_file(filename, format, ec);
Chris@16 768 boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
Chris@16 769 }
Chris@16 770
Chris@16 771 boost::system::error_code context::use_rsa_private_key_file(
Chris@16 772 const std::string& filename, context::file_format format,
Chris@16 773 boost::system::error_code& ec)
Chris@16 774 {
Chris@16 775 int file_type;
Chris@16 776 switch (format)
Chris@16 777 {
Chris@16 778 case context_base::asn1:
Chris@16 779 file_type = SSL_FILETYPE_ASN1;
Chris@16 780 break;
Chris@16 781 case context_base::pem:
Chris@16 782 file_type = SSL_FILETYPE_PEM;
Chris@16 783 break;
Chris@16 784 default:
Chris@16 785 {
Chris@16 786 ec = boost::asio::error::invalid_argument;
Chris@16 787 return ec;
Chris@16 788 }
Chris@16 789 }
Chris@16 790
Chris@101 791 ::ERR_clear_error();
Chris@101 792
Chris@16 793 if (::SSL_CTX_use_RSAPrivateKey_file(
Chris@16 794 handle_, filename.c_str(), file_type) != 1)
Chris@16 795 {
Chris@16 796 ec = boost::system::error_code(
Chris@16 797 static_cast<int>(::ERR_get_error()),
Chris@16 798 boost::asio::error::get_ssl_category());
Chris@16 799 return ec;
Chris@16 800 }
Chris@16 801
Chris@16 802 ec = boost::system::error_code();
Chris@16 803 return ec;
Chris@16 804 }
Chris@16 805
Chris@16 806 void context::use_tmp_dh(const const_buffer& dh)
Chris@16 807 {
Chris@16 808 boost::system::error_code ec;
Chris@16 809 use_tmp_dh(dh, ec);
Chris@16 810 boost::asio::detail::throw_error(ec, "use_tmp_dh");
Chris@16 811 }
Chris@16 812
Chris@16 813 boost::system::error_code context::use_tmp_dh(
Chris@16 814 const const_buffer& dh, boost::system::error_code& ec)
Chris@16 815 {
Chris@101 816 ::ERR_clear_error();
Chris@101 817
Chris@16 818 bio_cleanup bio = { make_buffer_bio(dh) };
Chris@16 819 if (bio.p)
Chris@16 820 {
Chris@16 821 return do_use_tmp_dh(bio.p, ec);
Chris@16 822 }
Chris@16 823
Chris@16 824 ec = boost::system::error_code(
Chris@16 825 static_cast<int>(::ERR_get_error()),
Chris@16 826 boost::asio::error::get_ssl_category());
Chris@16 827 return ec;
Chris@16 828 }
Chris@16 829
Chris@16 830 void context::use_tmp_dh_file(const std::string& filename)
Chris@16 831 {
Chris@16 832 boost::system::error_code ec;
Chris@16 833 use_tmp_dh_file(filename, ec);
Chris@16 834 boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
Chris@16 835 }
Chris@16 836
Chris@16 837 boost::system::error_code context::use_tmp_dh_file(
Chris@16 838 const std::string& filename, boost::system::error_code& ec)
Chris@16 839 {
Chris@101 840 ::ERR_clear_error();
Chris@101 841
Chris@16 842 bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };
Chris@16 843 if (bio.p)
Chris@16 844 {
Chris@16 845 return do_use_tmp_dh(bio.p, ec);
Chris@16 846 }
Chris@16 847
Chris@16 848 ec = boost::system::error_code(
Chris@16 849 static_cast<int>(::ERR_get_error()),
Chris@16 850 boost::asio::error::get_ssl_category());
Chris@16 851 return ec;
Chris@16 852 }
Chris@16 853
Chris@16 854 boost::system::error_code context::do_use_tmp_dh(
Chris@16 855 BIO* bio, boost::system::error_code& ec)
Chris@16 856 {
Chris@16 857 ::ERR_clear_error();
Chris@16 858
Chris@16 859 dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };
Chris@16 860 if (dh.p)
Chris@16 861 {
Chris@16 862 if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
Chris@16 863 {
Chris@16 864 ec = boost::system::error_code();
Chris@16 865 return ec;
Chris@16 866 }
Chris@16 867 }
Chris@16 868
Chris@16 869 ec = boost::system::error_code(
Chris@16 870 static_cast<int>(::ERR_get_error()),
Chris@16 871 boost::asio::error::get_ssl_category());
Chris@16 872 return ec;
Chris@16 873 }
Chris@16 874
Chris@16 875 boost::system::error_code context::do_set_verify_callback(
Chris@16 876 detail::verify_callback_base* callback, boost::system::error_code& ec)
Chris@16 877 {
Chris@16 878 if (SSL_CTX_get_app_data(handle_))
Chris@16 879 {
Chris@16 880 delete static_cast<detail::verify_callback_base*>(
Chris@16 881 SSL_CTX_get_app_data(handle_));
Chris@16 882 }
Chris@16 883
Chris@16 884 SSL_CTX_set_app_data(handle_, callback);
Chris@16 885
Chris@16 886 ::SSL_CTX_set_verify(handle_,
Chris@16 887 ::SSL_CTX_get_verify_mode(handle_),
Chris@16 888 &context::verify_callback_function);
Chris@16 889
Chris@16 890 ec = boost::system::error_code();
Chris@16 891 return ec;
Chris@16 892 }
Chris@16 893
Chris@16 894 int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
Chris@16 895 {
Chris@16 896 if (ctx)
Chris@16 897 {
Chris@16 898 if (SSL* ssl = static_cast<SSL*>(
Chris@16 899 ::X509_STORE_CTX_get_ex_data(
Chris@16 900 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))
Chris@16 901 {
Chris@16 902 if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))
Chris@16 903 {
Chris@16 904 if (SSL_CTX_get_app_data(handle))
Chris@16 905 {
Chris@16 906 detail::verify_callback_base* callback =
Chris@16 907 static_cast<detail::verify_callback_base*>(
Chris@16 908 SSL_CTX_get_app_data(handle));
Chris@16 909
Chris@16 910 verify_context verify_ctx(ctx);
Chris@16 911 return callback->call(preverified != 0, verify_ctx) ? 1 : 0;
Chris@16 912 }
Chris@16 913 }
Chris@16 914 }
Chris@16 915 }
Chris@16 916
Chris@16 917 return 0;
Chris@16 918 }
Chris@16 919
Chris@16 920 boost::system::error_code context::do_set_password_callback(
Chris@16 921 detail::password_callback_base* callback, boost::system::error_code& ec)
Chris@16 922 {
Chris@16 923 if (handle_->default_passwd_callback_userdata)
Chris@16 924 delete static_cast<detail::password_callback_base*>(
Chris@16 925 handle_->default_passwd_callback_userdata);
Chris@16 926
Chris@16 927 handle_->default_passwd_callback_userdata = callback;
Chris@16 928
Chris@16 929 SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
Chris@16 930
Chris@16 931 ec = boost::system::error_code();
Chris@16 932 return ec;
Chris@16 933 }
Chris@16 934
Chris@16 935 int context::password_callback_function(
Chris@16 936 char* buf, int size, int purpose, void* data)
Chris@16 937 {
Chris@16 938 using namespace std; // For strncat and strlen.
Chris@16 939
Chris@16 940 if (data)
Chris@16 941 {
Chris@16 942 detail::password_callback_base* callback =
Chris@16 943 static_cast<detail::password_callback_base*>(data);
Chris@16 944
Chris@16 945 std::string passwd = callback->call(static_cast<std::size_t>(size),
Chris@16 946 purpose ? context_base::for_writing : context_base::for_reading);
Chris@16 947
Chris@16 948 #if defined(BOOST_ASIO_HAS_SECURE_RTL)
Chris@16 949 strcpy_s(buf, size, passwd.c_str());
Chris@16 950 #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
Chris@16 951 *buf = '\0';
Chris@16 952 strncat(buf, passwd.c_str(), size);
Chris@16 953 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
Chris@16 954
Chris@16 955 return static_cast<int>(strlen(buf));
Chris@16 956 }
Chris@16 957
Chris@16 958 return 0;
Chris@16 959 }
Chris@16 960
Chris@16 961 BIO* context::make_buffer_bio(const const_buffer& b)
Chris@16 962 {
Chris@16 963 return ::BIO_new_mem_buf(
Chris@16 964 const_cast<void*>(buffer_cast<const void*>(b)),
Chris@16 965 static_cast<int>(buffer_size(b)));
Chris@16 966 }
Chris@16 967
Chris@16 968 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
Chris@16 969
Chris@16 970 } // namespace ssl
Chris@16 971 } // namespace asio
Chris@16 972 } // namespace boost
Chris@16 973
Chris@16 974 #include <boost/asio/detail/pop_options.hpp>
Chris@16 975
Chris@16 976 #endif // BOOST_ASIO_SSL_IMPL_CONTEXT_IPP