openssl_context_service.hpp
Go to the documentation of this file.
00001 //
00002 // openssl_context_service.hpp
00003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
00006 // Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00007 //
00008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00010 //
00011 
00012 #ifndef ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
00013 #define ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
00014 
00015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00016 # pragma once
00017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00018 
00019 #include "asio/detail/push_options.hpp"
00020 
00021 #include "asio/detail/push_options.hpp"
00022 #include <cstring>
00023 #include <string>
00024 #include <boost/function.hpp>
00025 #include "asio/detail/pop_options.hpp"
00026 
00027 #include "asio/error.hpp"
00028 #include "asio/io_service.hpp"
00029 #include "asio/detail/service_base.hpp"
00030 #include "asio/ssl/context_base.hpp"
00031 #include "asio/ssl/detail/openssl_init.hpp"
00032 #include "asio/ssl/detail/openssl_types.hpp"
00033 
00034 namespace asio {
00035 namespace ssl {
00036 namespace detail {
00037 
00038 class openssl_context_service
00039   : public asio::detail::service_base<openssl_context_service>
00040 {
00041 public:
00042   // The native type of the context.
00043   typedef ::SSL_CTX* impl_type;
00044 
00045   // The type for the password callback function object.
00046   typedef boost::function<std::string(std::size_t,
00047       context_base::password_purpose)> password_callback_type;
00048 
00049   // Constructor.
00050   openssl_context_service(asio::io_service& io_service)
00051     : asio::detail::service_base<openssl_context_service>(io_service)
00052   {
00053   }
00054 
00055   // Destroy all user-defined handler objects owned by the service.
00056   void shutdown_service()
00057   {
00058   }
00059 
00060   // Return a null context implementation.
00061   static impl_type null()
00062   {
00063     return 0;
00064   }
00065 
00066   // Create a new context implementation.
00067   void create(impl_type& impl, context_base::method m)
00068   {
00069     ::SSL_METHOD* ssl_method = 0;
00070     switch (m)
00071     {
00072     case context_base::sslv2:
00073       ssl_method = ::SSLv2_method();
00074       break;
00075     case context_base::sslv2_client:
00076       ssl_method = ::SSLv2_client_method();
00077       break;
00078     case context_base::sslv2_server:
00079       ssl_method = ::SSLv2_server_method();
00080       break;
00081     case context_base::sslv3:
00082       ssl_method = ::SSLv3_method();
00083       break;
00084     case context_base::sslv3_client:
00085       ssl_method = ::SSLv3_client_method();
00086       break;
00087     case context_base::sslv3_server:
00088       ssl_method = ::SSLv3_server_method();
00089       break;
00090     case context_base::tlsv1:
00091       ssl_method = ::TLSv1_method();
00092       break;
00093     case context_base::tlsv1_client:
00094       ssl_method = ::TLSv1_client_method();
00095       break;
00096     case context_base::tlsv1_server:
00097       ssl_method = ::TLSv1_server_method();
00098       break;
00099     case context_base::sslv23:
00100       ssl_method = ::SSLv23_method();
00101       break;
00102     case context_base::sslv23_client:
00103       ssl_method = ::SSLv23_client_method();
00104       break;
00105     case context_base::sslv23_server:
00106       ssl_method = ::SSLv23_server_method();
00107       break;
00108     default:
00109       break;
00110     }
00111     impl = ::SSL_CTX_new(ssl_method);
00112   }
00113 
00114   // Destroy a context implementation.
00115   void destroy(impl_type& impl)
00116   {
00117     if (impl != null())
00118     {
00119       if (impl->default_passwd_callback_userdata)
00120       {
00121         password_callback_type* callback =
00122           static_cast<password_callback_type*>(
00123               impl->default_passwd_callback_userdata);
00124         delete callback;
00125         impl->default_passwd_callback_userdata = 0;
00126       }
00127 
00128       ::SSL_CTX_free(impl);
00129       impl = null();
00130     }
00131   }
00132 
00133   // Set options on the context.
00134   asio::error_code set_options(impl_type& impl,
00135       context_base::options o, asio::error_code& ec)
00136   {
00137     ::SSL_CTX_set_options(impl, o);
00138 
00139     ec = asio::error_code();
00140     return ec;
00141   }
00142 
00143   // Set peer verification mode.
00144   asio::error_code set_verify_mode(impl_type& impl,
00145       context_base::verify_mode v, asio::error_code& ec)
00146   {
00147     ::SSL_CTX_set_verify(impl, v, 0);
00148 
00149     ec = asio::error_code();
00150     return ec;
00151   }
00152 
00153   // Load a certification authority file for performing verification.
00154   asio::error_code load_verify_file(impl_type& impl,
00155       const std::string& filename, asio::error_code& ec)
00156   {
00157     if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1)
00158     {
00159       ec = asio::error::invalid_argument;
00160       return ec;
00161     }
00162 
00163     ec = asio::error_code();
00164     return ec;
00165   }
00166 
00167   // Add a directory containing certification authority files to be used for
00168   // performing verification.
00169   asio::error_code add_verify_path(impl_type& impl,
00170       const std::string& path, asio::error_code& ec)
00171   {
00172     if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1)
00173     {
00174       ec = asio::error::invalid_argument;
00175       return ec;
00176     }
00177 
00178     ec = asio::error_code();
00179     return ec;
00180   }
00181 
00182   // Use a certificate from a file.
00183   asio::error_code use_certificate_file(impl_type& impl,
00184       const std::string& filename, context_base::file_format format,
00185       asio::error_code& ec)
00186   {
00187     int file_type;
00188     switch (format)
00189     {
00190     case context_base::asn1:
00191       file_type = SSL_FILETYPE_ASN1;
00192       break;
00193     case context_base::pem:
00194       file_type = SSL_FILETYPE_PEM;
00195       break;
00196     default:
00197       {
00198         ec = asio::error::invalid_argument;
00199         return ec;
00200       }
00201     }
00202 
00203     if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1)
00204     {
00205       ec = asio::error::invalid_argument;
00206       return ec;
00207     }
00208 
00209     ec = asio::error_code();
00210     return ec;
00211   }
00212 
00213   // Use a certificate chain from a file.
00214   asio::error_code use_certificate_chain_file(impl_type& impl,
00215       const std::string& filename, asio::error_code& ec)
00216   {
00217     if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1)
00218     {
00219       ec = asio::error::invalid_argument;
00220       return ec;
00221     }
00222 
00223     ec = asio::error_code();
00224     return ec;
00225   }
00226 
00227   // Use a private key from a file.
00228   asio::error_code use_private_key_file(impl_type& impl,
00229       const std::string& filename, context_base::file_format format,
00230       asio::error_code& ec)
00231   {
00232     int file_type;
00233     switch (format)
00234     {
00235     case context_base::asn1:
00236       file_type = SSL_FILETYPE_ASN1;
00237       break;
00238     case context_base::pem:
00239       file_type = SSL_FILETYPE_PEM;
00240       break;
00241     default:
00242       {
00243         ec = asio::error::invalid_argument;
00244         return ec;
00245       }
00246     }
00247 
00248     if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1)
00249     {
00250       ec = asio::error::invalid_argument;
00251       return ec;
00252     }
00253 
00254     ec = asio::error_code();
00255     return ec;
00256   }
00257 
00258   // Use an RSA private key from a file.
00259   asio::error_code use_rsa_private_key_file(impl_type& impl,
00260       const std::string& filename, context_base::file_format format,
00261       asio::error_code& ec)
00262   {
00263     int file_type;
00264     switch (format)
00265     {
00266     case context_base::asn1:
00267       file_type = SSL_FILETYPE_ASN1;
00268       break;
00269     case context_base::pem:
00270       file_type = SSL_FILETYPE_PEM;
00271       break;
00272     default:
00273       {
00274         ec = asio::error::invalid_argument;
00275         return ec;
00276       }
00277     }
00278 
00279     if (::SSL_CTX_use_RSAPrivateKey_file(
00280           impl, filename.c_str(), file_type) != 1)
00281     {
00282       ec = asio::error::invalid_argument;
00283       return ec;
00284     }
00285 
00286     ec = asio::error_code();
00287     return ec;
00288   }
00289 
00290   // Use the specified file to obtain the temporary Diffie-Hellman parameters.
00291   asio::error_code use_tmp_dh_file(impl_type& impl,
00292       const std::string& filename, asio::error_code& ec)
00293   {
00294     ::BIO* bio = ::BIO_new_file(filename.c_str(), "r");
00295     if (!bio)
00296     {
00297       ec = asio::error::invalid_argument;
00298       return ec;
00299     }
00300 
00301     ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0);
00302     if (!dh)
00303     {
00304       ::BIO_free(bio);
00305       ec = asio::error::invalid_argument;
00306       return ec;
00307     }
00308 
00309     ::BIO_free(bio);
00310     int result = ::SSL_CTX_set_tmp_dh(impl, dh);
00311     ::DH_free(dh);
00312     if (result != 1)
00313     {
00314       ec = asio::error::invalid_argument;
00315       return ec;
00316     }
00317 
00318     ec = asio::error_code();
00319     return ec;
00320   }
00321 
00322   static int password_callback(char* buf, int size, int purpose, void* data)
00323   {
00324     using namespace std; // For strncat and strlen.
00325 
00326     if (data)
00327     {
00328       password_callback_type* callback =
00329         static_cast<password_callback_type*>(data);
00330       std::string passwd = (*callback)(static_cast<std::size_t>(size),
00331           purpose ? context_base::for_writing : context_base::for_reading);
00332       *buf = '\0';
00333       strncat(buf, passwd.c_str(), size);
00334       return strlen(buf);
00335     }
00336 
00337     return 0;
00338   }
00339 
00340   // Set the password callback.
00341   template <typename Password_Callback>
00342   asio::error_code set_password_callback(impl_type& impl,
00343       Password_Callback callback, asio::error_code& ec)
00344   {
00345     // Allocate callback function object if not already present.
00346     if (impl->default_passwd_callback_userdata)
00347     {
00348       password_callback_type* callback_function =
00349         static_cast<password_callback_type*>(
00350             impl->default_passwd_callback_userdata);
00351       *callback_function = callback;
00352     }
00353     else
00354     {
00355       password_callback_type* callback_function =
00356         new password_callback_type(callback);
00357       impl->default_passwd_callback_userdata = callback_function;
00358     }
00359 
00360     // Set the password callback.
00361     SSL_CTX_set_default_passwd_cb(impl,
00362         &openssl_context_service::password_callback);
00363 
00364     ec = asio::error_code();
00365     return ec;
00366   }
00367 
00368 private:
00369   // Ensure openssl is initialised.
00370   openssl_init<> init_;
00371 };
00372 
00373 } // namespace detail
00374 } // namespace ssl
00375 } // namespace asio
00376 
00377 #include "asio/detail/pop_options.hpp"
00378 
00379 #endif // ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39