diff options
Diffstat (limited to 'boost/asio/ssl/old/detail/openssl_context_service.hpp')
-rw-r--r-- | boost/asio/ssl/old/detail/openssl_context_service.hpp | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/boost/asio/ssl/old/detail/openssl_context_service.hpp b/boost/asio/ssl/old/detail/openssl_context_service.hpp new file mode 100644 index 0000000000..260a05c66f --- /dev/null +++ b/boost/asio/ssl/old/detail/openssl_context_service.hpp @@ -0,0 +1,388 @@ +// +// ssl/old/detail/openssl_context_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP +#define BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstring> +#include <string> +#include <boost/function.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/ssl/context_base.hpp> +#include <boost/asio/ssl/detail/openssl_init.hpp> +#include <boost/asio/ssl/detail/openssl_types.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace old { +namespace detail { + +class openssl_context_service + : public boost::asio::detail::service_base<openssl_context_service> +{ +public: + // The native type of the context. + typedef ::SSL_CTX* impl_type; + + // The type for the password callback function object. + typedef boost::function<std::string(std::size_t, + context_base::password_purpose)> password_callback_type; + + // Constructor. + openssl_context_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base<openssl_context_service>(io_service) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Return a null context implementation. + static impl_type null() + { + return 0; + } + + // Create a new context implementation. + void create(impl_type& impl, context_base::method m) + { + switch (m) + { +#if defined(OPENSSL_NO_SSL2) + case context_base::sslv2: + case context_base::sslv2_client: + case context_base::sslv2_server: + boost::asio::detail::throw_error(boost::asio::error::invalid_argument); + break; +#else // defined(OPENSSL_NO_SSL2) + case context_base::sslv2: + impl = ::SSL_CTX_new(::SSLv2_method()); + break; + case context_base::sslv2_client: + impl = ::SSL_CTX_new(::SSLv2_client_method()); + break; + case context_base::sslv2_server: + impl = ::SSL_CTX_new(::SSLv2_server_method()); + break; +#endif // defined(OPENSSL_NO_SSL2) + case context_base::sslv3: + impl = ::SSL_CTX_new(::SSLv3_method()); + break; + case context_base::sslv3_client: + impl = ::SSL_CTX_new(::SSLv3_client_method()); + break; + case context_base::sslv3_server: + impl = ::SSL_CTX_new(::SSLv3_server_method()); + break; + case context_base::tlsv1: + impl = ::SSL_CTX_new(::TLSv1_method()); + break; + case context_base::tlsv1_client: + impl = ::SSL_CTX_new(::TLSv1_client_method()); + break; + case context_base::tlsv1_server: + impl = ::SSL_CTX_new(::TLSv1_server_method()); + break; + case context_base::sslv23: + impl = ::SSL_CTX_new(::SSLv23_method()); + break; + case context_base::sslv23_client: + impl = ::SSL_CTX_new(::SSLv23_client_method()); + break; + case context_base::sslv23_server: + impl = ::SSL_CTX_new(::SSLv23_server_method()); + break; + default: + impl = ::SSL_CTX_new(0); + break; + } + } + + // Destroy a context implementation. + void destroy(impl_type& impl) + { + if (impl != null()) + { + if (impl->default_passwd_callback_userdata) + { + password_callback_type* callback = + static_cast<password_callback_type*>( + impl->default_passwd_callback_userdata); + delete callback; + impl->default_passwd_callback_userdata = 0; + } + + ::SSL_CTX_free(impl); + impl = null(); + } + } + + // Set options on the context. + boost::system::error_code set_options(impl_type& impl, + context_base::options o, boost::system::error_code& ec) + { + ::SSL_CTX_set_options(impl, o); + + ec = boost::system::error_code(); + return ec; + } + + // Set peer verification mode. + boost::system::error_code set_verify_mode(impl_type& impl, + context_base::verify_mode v, boost::system::error_code& ec) + { + ::SSL_CTX_set_verify(impl, v, 0); + + ec = boost::system::error_code(); + return ec; + } + + // Load a certification authority file for performing verification. + boost::system::error_code load_verify_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Add a directory containing certification authority files to be used for + // performing verification. + boost::system::error_code add_verify_path(impl_type& impl, + const std::string& path, boost::system::error_code& ec) + { + if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use a certificate from a file. + boost::system::error_code use_certificate_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + int file_type; + switch (format) + { + case context_base::asn1: + file_type = SSL_FILETYPE_ASN1; + break; + case context_base::pem: + file_type = SSL_FILETYPE_PEM; + break; + default: + { + ec = boost::asio::error::invalid_argument; + return ec; + } + } + + if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use a certificate chain from a file. + boost::system::error_code use_certificate_chain_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use a private key from a file. + boost::system::error_code use_private_key_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + int file_type; + switch (format) + { + case context_base::asn1: + file_type = SSL_FILETYPE_ASN1; + break; + case context_base::pem: + file_type = SSL_FILETYPE_PEM; + break; + default: + { + ec = boost::asio::error::invalid_argument; + return ec; + } + } + + if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use an RSA private key from a file. + boost::system::error_code use_rsa_private_key_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + int file_type; + switch (format) + { + case context_base::asn1: + file_type = SSL_FILETYPE_ASN1; + break; + case context_base::pem: + file_type = SSL_FILETYPE_PEM; + break; + default: + { + ec = boost::asio::error::invalid_argument; + return ec; + } + } + + if (::SSL_CTX_use_RSAPrivateKey_file( + impl, filename.c_str(), file_type) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use the specified file to obtain the temporary Diffie-Hellman parameters. + boost::system::error_code use_tmp_dh_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + ::BIO* bio = ::BIO_new_file(filename.c_str(), "r"); + if (!bio) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0); + if (!dh) + { + ::BIO_free(bio); + ec = boost::asio::error::invalid_argument; + return ec; + } + + ::BIO_free(bio); + int result = ::SSL_CTX_set_tmp_dh(impl, dh); + ::DH_free(dh); + if (result != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + static int password_callback(char* buf, int size, int purpose, void* data) + { + using namespace std; // For strncat and strlen. + + if (data) + { + password_callback_type* callback = + static_cast<password_callback_type*>(data); + std::string passwd = (*callback)(static_cast<std::size_t>(size), + purpose ? context_base::for_writing : context_base::for_reading); + *buf = '\0'; + strncat(buf, passwd.c_str(), size); + return strlen(buf); + } + + return 0; + } + + // Set the password callback. + template <typename Password_Callback> + boost::system::error_code set_password_callback(impl_type& impl, + Password_Callback callback, boost::system::error_code& ec) + { + // Allocate callback function object if not already present. + if (impl->default_passwd_callback_userdata) + { + password_callback_type* callback_function = + static_cast<password_callback_type*>( + impl->default_passwd_callback_userdata); + *callback_function = callback; + } + else + { + password_callback_type* callback_function = + new password_callback_type(callback); + impl->default_passwd_callback_userdata = callback_function; + } + + // Set the password callback. + SSL_CTX_set_default_passwd_cb(impl, + &openssl_context_service::password_callback); + + ec = boost::system::error_code(); + return ec; + } + +private: + // Ensure openssl is initialised. + boost::asio::ssl::detail::openssl_init<> init_; +}; + +} // namespace detail +} // namespace old +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP |