如果使用curl访问
https(注意不是http),则会牵涉到
OpenSSL,就需要注意多线程安全问题。
一是
OpenSSL需要编译成多线程安全版本,二是需要为
OpenSSL注册两个回调函数。如果不这样多线程环境应用时,会遇到coredump问题。
OpenSSL编程入门(含完整示例).pdf ssl_test.zip ssl_manager.zip
OpenSSL初始化和注册两个回调函数可参考如下代码:
-
CSSLmanager::CSSLmanager()
-
: m_ctx(NULL), m_lock_cs(NULL)
-
{
-
}
-
-
void CSSLmanager::SSLFini()
-
{
-
CRYPTO_set_locking_callback(NULL);
-
for (int i = 0; i < CRYPTO_num_locks(); i++)
-
{
-
pthread_mutex_destroy(&m_lock_cs[i]);
-
}
-
-
OPENSSL_free(m_lock_cs);
-
if (m_ctx != NULL)
-
{
-
SSL_CTX_free((SSL_CTX *)m_ctx);
-
m_ctx = NULL;
-
}
-
-
ERR_free_strings();
-
EVP_cleanup();
-
}
-
-
bool CSSLmanager::SSLInit(const TChar* cacert, const TChar * privkey)
-
{
-
SSL_library_init(); // SSL库初始化
-
OpenSSL_add_all_algorithms(); // 载入所有 SSL 算法
-
SSL_load_error_strings(); // 载入所有SSL错误消息
-
-
while (true)
-
{
-
// 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text
-
SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
-
if (NULL == ctx)
-
break;
-
-
// 载入用户的数字证书, 此证书用来发送给客户端,证书里包含有公钥
-
if (SSL_CTX_use_certificate_file(ctx, cacert, SSL_FILETYPE_PEM) != 1)
-
break;
-
-
// 载入用户私钥
-
if (SSL_CTX_use_PrivateKey_file(ctx, privkey, SSL_FILETYPE_PEM) != 1)
-
break;
-
-
// 检查用户私钥是否正确
-
if (SSL_CTX_check_private_key(ctx) != 1)
-
break;
-
-
m_ctx = (void *)ctx;
-
m_lock_cs = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
-
for (int i = 0; i < CRYPTO_num_locks(); ++i)
-
{
-
pthread_mutex_init(&(m_lock_cs[i]),NULL);
-
}
-
-
CRYPTO_set_id_callback(IDFunction); // 注册回调
-
CRYPTO_set_locking_callback(LockingFunction); // 注册回调
-
return true;
-
}
-
-
SSLFini();
-
return false;
-
}
-
-
unsigned long CSSLmanager::IDFunction( void )
-
{
-
return ((unsigned long)pthread_self());
-
}
-
-
void CSSLmanager::LockingFunction(int mode, int type, const char *file, int line)
-
{
-
pthread_mutex_t* lock = CSSLmanager::singleton()->GetLock();
-
-
if (mode & CRYPTO_LOCK) {
-
pthread_mutex_lock(&lock[type]);
-
} else {
-
pthread_mutex_unlock(&lock[type]);
-
}
-
}
阅读(2946) | 评论(0) | 转发(0) |