annotate DEPENDENCIES/generic/include/boost/asio/ssl/impl/context.ipp @ 16:2665513ce2d3

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