1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
// $Id$
#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 <openssl/x509.h>
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<SSL_CallbackManager, ACE_SYNCH::MUTEX>::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<SSL_CallbackManager*> (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<SSL_CallbackManager*> (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<int> (pwd.length ()))
size = ACE_Utils::truncate_cast<int> (pwd.length ());
return size;
}
else
return 0;
}
}
}
ACE_END_VERSIONED_NAMESPACE_DECL
|