#include "ace/INet/SSL_CallbackManager.h" #if !defined (__ACE_INLINE__) #include "ace/INet/SSL_CallbackManager.inl" #endif #include "ace/Truncate.h" #include "ace/Singleton.h" #include "ace/INet/INet_Log.h" #include ACE_BEGIN_VERSIONED_NAMESPACE_DECL namespace ACE { namespace INet { int SSL_CallbackManager::ssl_ctx_mngr_index_ = (-2); SSL_CallbackManager::SSL_CallbackManager () { } SSL_CallbackManager::~SSL_CallbackManager () { } void SSL_CallbackManager::initialize_callbacks (ACE_SSL_Context* ssl_ctx) { if (ssl_ctx_mngr_index_ < -1) { ssl_ctx_mngr_index_ = ::SSL_CTX_get_ex_new_index (0, 0, 0,0,0); if (ssl_ctx_mngr_index_ < 0) { INET_ERROR (1, (LM_ERROR, DLINFO ACE_TEXT ("SSL_CallbackManager::initialize_callbacks - ") ACE_TEXT ("failed to allocate SSL_CTX ex_data index.\n"))); return; } } this->ssl_ctx_ = ssl_ctx == 0 ? ACE_SSL_Context::instance () : ssl_ctx; ::SSL_CTX_set_ex_data (this->ssl_ctx_->context (), ssl_ctx_mngr_index_, this); this->ssl_ctx_->default_verify_callback (extern_C_verify_certificate_callback); ::SSL_CTX_set_default_passwd_cb (ssl_ctx->context(), extern_C_passwd_callback); ::SSL_CTX_set_default_passwd_cb_userdata (ssl_ctx->context(), this); } SSL_CallbackManager* SSL_CallbackManager::instance () { return ACE_Singleton::instance (); } int SSL_CallbackManager::verify_certificate_callback (SSL_CertificateCallbackArg& arg) { TCertificateCallback cert_cb = this->cert_callback_; if (cert_cb) { cert_cb->handle_certificate_failure (arg); } return (arg.ignore_error () ? 1 : 0); } void SSL_CallbackManager::passwd_callback (ACE_CString& pwd) { TPasswordCallback pw_cb = passwd_callback_; if (pw_cb) { pw_cb->get_privatekey_password (pwd); } } int extern_C_verify_certificate_callback (int ok, X509_STORE_CTX* cert_ctx) { if (!ok && SSL_CallbackManager::ssl_ctx_mngr_index_>=0) { // Retrieve the pointer to the SSL of the connection currently treated void* ex_data = ::X509_STORE_CTX_get_ex_data (cert_ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx()); ::SSL* ssl = reinterpret_cast< ::SSL* > (ex_data); // Retrieve SSL_CTX pointer of the connection currently treated ::SSL_CTX* ssl_ctx = ::SSL_get_SSL_CTX (ssl); // Retrieve our SSL_CallbackManager ex_data = ::SSL_CTX_get_ex_data (ssl_ctx, SSL_CallbackManager::ssl_ctx_mngr_index_); SSL_CallbackManager* cbmngr = reinterpret_cast (ex_data); SSL_CertificateCallbackArg arg (cbmngr->context(), cert_ctx); ok = cbmngr->verify_certificate_callback (arg); } return ok; } int extern_C_passwd_callback (char* buf, int size, int /*rwflag*/, void* user_data) { if (user_data == 0) return 0; SSL_CallbackManager* cbmngr = reinterpret_cast (user_data); ACE_CString pwd; cbmngr->passwd_callback (pwd); if (!pwd.empty ()) { ACE_OS::strncpy (buf, pwd.c_str (), size); buf[size - 1] = '\0'; if (size > ACE_Utils::truncate_cast (pwd.length ())) size = ACE_Utils::truncate_cast (pwd.length ()); return size; } else return 0; } } } ACE_END_VERSIONED_NAMESPACE_DECL