同步操作将从 伤神小怪兽/HP-Socket 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/** Copyright: JessMA Open Source (ldcsaa@gmail.com)** Author : Bruce Liang* Website : https://github.com/ldcsaa* Project : https://github.com/ldcsaa/HP-Socket* Blog : http://www.cnblogs.com/ldcsaa* Wiki : http://www.oschina.net/p/hp-socket* QQ Group : 44636872, 75375912** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#include "SSLHelper.h"#ifdef _SSL_SUPPORT#include "SocketHelper.h"#include "common/FileHelper.h"#include "openssl/ssl.h"#include "openssl/err.h"#include "openssl/engine.h"#include "openssl/x509v3.h"#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0int CSSLInitializer::sm_iLockNum = 0;CSimpleRWLock* CSSLInitializer::sm_pcsLocks = nullptr;#endifCSSLInitializer CSSLInitializer::sm_instance;const DWORD CSSLSessionPool::DEFAULT_ITEM_CAPACITY = CItemPool::DEFAULT_ITEM_CAPACITY;const DWORD CSSLSessionPool::DEFAULT_ITEM_POOL_SIZE = CItemPool::DEFAULT_POOL_SIZE;const DWORD CSSLSessionPool::DEFAULT_ITEM_POOL_HOLD = CItemPool::DEFAULT_POOL_HOLD;const DWORD CSSLSessionPool::DEFAULT_SESSION_LOCK_TIME = DEFAULT_OBJECT_CACHE_LOCK_TIME;const DWORD CSSLSessionPool::DEFAULT_SESSION_POOL_SIZE = DEFAULT_OBJECT_CACHE_POOL_SIZE;const DWORD CSSLSessionPool::DEFAULT_SESSION_POOL_HOLD = DEFAULT_OBJECT_CACHE_POOL_HOLD;CSSLInitializer::CSSLInitializer(){#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0sm_iLockNum = CRYPTO_num_locks();if(sm_iLockNum > 0)sm_pcsLocks = new CSimpleRWLock[sm_iLockNum];/*#ifdef _DEBUGCRYPTO_malloc_debug_init();CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);#endif*/CRYPTO_set_locking_callback (&ssl_lock_callback);CRYPTO_set_dynlock_create_callback (&ssl_lock_dyn_create_callback);CRYPTO_set_dynlock_destroy_callback (&ssl_lock_dyn_destroy_callback);CRYPTO_set_dynlock_lock_callback (&ssl_lock_dyn_callback);SSL_library_init();SSL_load_error_strings();OpenSSL_add_all_algorithms();#elseOPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, nullptr);#endif}CSSLInitializer::~CSSLInitializer(){CleanupThreadState();#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0CONF_modules_free();ENGINE_cleanup();EVP_cleanup();CRYPTO_cleanup_all_ex_data();ERR_free_strings();#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_0_2SSL_COMP_free_compression_methods();#endifCRYPTO_set_locking_callback (nullptr);CRYPTO_set_dynlock_create_callback (nullptr);CRYPTO_set_dynlock_destroy_callback (nullptr);CRYPTO_set_dynlock_lock_callback (nullptr);if(sm_iLockNum > 0){delete[] sm_pcsLocks;sm_pcsLocks = nullptr;sm_iLockNum = 0;}#endif}void CSSLInitializer::CleanupThreadState(THR_ID dwThreadID){#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0CRYPTO_THREADID tid = {nullptr, dwThreadID};CRYPTO_THREADID_current(&tid);ERR_remove_thread_state(&tid);#elseOPENSSL_thread_stop();#endif}#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0void CSSLInitializer::ssl_lock_callback(int mode, int n, const char *file, int line){mode & CRYPTO_LOCK? (mode & CRYPTO_READ? sm_pcsLocks[n].lock_shared(): sm_pcsLocks[n].lock()): (mode & CRYPTO_READ? sm_pcsLocks[n].unlock_shared(): sm_pcsLocks[n].unlock());}CRYPTO_dynlock_value* CSSLInitializer::ssl_lock_dyn_create_callback(const char *file, int line){return new DynamicLock;}void CSSLInitializer::ssl_lock_dyn_callback(int mode, CRYPTO_dynlock_value* l, const char *file, int line){mode & CRYPTO_LOCK? (mode & CRYPTO_READ? l->cs.lock_shared(): l->cs.lock()): (mode & CRYPTO_READ? l->cs.unlock_shared(): l->cs.unlock());}void CSSLInitializer::ssl_lock_dyn_destroy_callback(CRYPTO_dynlock_value* l, const char *file, int line){delete l;}#endifBOOL CSSLContext::Initialize(EnSSLSessionMode enSessionMode, int iVerifyMode, BOOL bMemory, LPVOID lpPemCert, LPVOID lpPemKey, LPVOID lpKeyPasswod, LPVOID lpCAPemCert, HP_Fn_SNI_ServerNameCallback fnServerNameCallback){ASSERT(!IsValid());if(IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}m_enSessionMode = enSessionMode;if(AddContext(iVerifyMode, bMemory, lpPemCert, lpPemKey, lpKeyPasswod, lpCAPemCert) == 0)m_sslCtx = GetContext(0);else{EXECUTE_RESTORE_ERROR(Cleanup());return FALSE;}SetServerNameCallback(fnServerNameCallback);return TRUE;}int CSSLContext::AddServerContext(int iVerifyMode, BOOL bMemory, LPVOID lpPemCert, LPVOID lpPemKey, LPVOID lpKeyPasswod, LPVOID lpCAPemCert){ASSERT(IsValid());if(!IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}if(m_enSessionMode != SSL_SM_SERVER){::SetLastError(ERROR_INVALID_OPERATION);return FALSE;}return AddContext(iVerifyMode, bMemory, lpPemCert, lpPemKey, lpKeyPasswod, lpCAPemCert);}BOOL CSSLContext::BindServerName(LPCTSTR lpszServerName, int iContextIndex){ASSERT(lpszServerName && iContextIndex >= 0 && !::IsIPAddress(lpszServerName));if(!lpszServerName || iContextIndex < 0 || ::IsIPAddress(lpszServerName)){::SetLastError(ERROR_INVALID_PARAMETER);return FALSE;}int iLen = lstrlen(lpszServerName);LPCTSTR lpszSep = ::StrChr(lpszServerName, SSL_DOMAIN_SEP_CHAR);if(lpszSep == nullptr || lpszSep == lpszServerName || lpszSep == (lpszServerName + iLen - 1)){::SetLastError(ERROR_INVALID_PARAMETER);return FALSE;}int iSize = (int)m_lsSslCtxs.size();if(iSize <= iContextIndex){::SetLastError(ERROR_INVALID_INDEX);return FALSE;}m_sslServerNames[lpszServerName] = iContextIndex;return TRUE;}int CSSLContext::AddContext(int iVerifyMode, BOOL bMemory, LPVOID lpPemCert, LPVOID lpPemKey, LPVOID lpKeyPasswod, LPVOID lpCAPemCert){USES_CONVERSION;int iIndex = -1;#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0SSL_CTX* sslCtx = SSL_CTX_new(SSLv23_method());#elseSSL_CTX* sslCtx = SSL_CTX_new(TLS_method());#endifSSL_CTX_set_quiet_shutdown(sslCtx, 1);SSL_CTX_set_verify(sslCtx, iVerifyMode, nullptr);if(!SSL_CTX_set_cipher_list(sslCtx, T2CA(m_strCipherList)))::SetLastError(ERROR_EMPTY);else{if(m_enSessionMode == SSL_SM_SERVER){static volatile ULONG s_session_id_context = 0;ULONG session_id_context = ::InterlockedIncrement(&s_session_id_context);SSL_CTX_set_session_id_context(sslCtx, (BYTE*)&session_id_context, sizeof(session_id_context));}if(LoadCertAndKey(sslCtx, iVerifyMode, bMemory, lpPemCert, lpPemKey, lpKeyPasswod, lpCAPemCert)){iIndex = (int)m_lsSslCtxs.size();m_lsSslCtxs.push_back(sslCtx);}}if(iIndex < 0)EXECUTE_RESTORE_ERROR(SSL_CTX_free(sslCtx));return iIndex;}BOOL CSSLContext::LoadCertAndKey(SSL_CTX* sslCtx, int iVerifyMode, BOOL bMemory, LPVOID lpPemCert, LPVOID lpPemKey, LPVOID lpKeyPasswod, LPVOID lpCAPemCert){if(bMemory)return LoadCertAndKeyByMemory(sslCtx, iVerifyMode, (LPCSTR)lpPemCert, (LPCSTR)lpPemKey, (LPCSTR)lpKeyPasswod, (LPCSTR)lpCAPemCert);elsereturn LoadCertAndKeyByFile(sslCtx, iVerifyMode, (LPCTSTR)lpPemCert, (LPCTSTR)lpPemKey, (LPCTSTR)lpKeyPasswod, (LPCTSTR)lpCAPemCert);}BOOL CSSLContext::LoadCertAndKeyByFile(SSL_CTX* sslCtx, int iVerifyMode, LPCTSTR lpszPemCertFile, LPCTSTR lpszPemKeyFile, LPCTSTR lpszKeyPassword, LPCTSTR lpszCAPemCertFileOrPath){USES_CONVERSION;if(::IsStrNotEmpty(lpszCAPemCertFileOrPath)){LPCTSTR lpszCAPemCertFile = nullptr;LPCTSTR lpszCAPemCertPath = nullptr;CFile fCAPemCertFile(lpszCAPemCertFileOrPath, O_RDONLY | O_CLOEXEC);if(!fCAPemCertFile.IsExist()){::SetLastError(ERROR_FILE_NOT_FOUND);return FALSE;}if(fCAPemCertFile.IsFile())lpszCAPemCertFile = lpszCAPemCertFileOrPath;else if(fCAPemCertFile.IsDirectory())lpszCAPemCertPath = lpszCAPemCertFileOrPath;else{::SetLastError(ERROR_BAD_FILE_TYPE);return FALSE;}if(!SSL_CTX_load_verify_locations(sslCtx, T2CA(lpszCAPemCertFile), T2CA(lpszCAPemCertPath))){::SetLastError(ERROR_INVALID_DATA);return FALSE;}if(!SSL_CTX_set_default_verify_paths(sslCtx)){::SetLastError(ERROR_FUNCTION_FAILED);return FALSE;}if(m_enSessionMode == SSL_SM_SERVER && (iVerifyMode & SSL_VM_PEER) && lpszCAPemCertFile != nullptr){STACK_OF(X509_NAME)* caCertNames = SSL_load_client_CA_file(T2CA(lpszCAPemCertFile));if(caCertNames == nullptr){::SetLastError(ERROR_EMPTY);return FALSE;}SSL_CTX_set_client_CA_list(sslCtx, caCertNames);}}if(::IsStrNotEmpty(lpszPemCertFile)){CFile fPemCertFile(lpszPemCertFile, O_RDONLY | O_CLOEXEC);if(!fPemCertFile.IsFile()){::SetLastError(ERROR_FILE_NOT_FOUND);return FALSE;}if(::IsStrEmpty(lpszPemKeyFile)){::SetLastError(ERROR_INVALID_PARAMETER);return FALSE;}CFile fPemKeyFile(lpszPemKeyFile, O_RDONLY | O_CLOEXEC);if(!fPemKeyFile.IsFile()){::SetLastError(ERROR_FILE_NOT_FOUND);return FALSE;}if(::IsStrNotEmpty(lpszKeyPassword))SSL_CTX_set_default_passwd_cb_userdata(sslCtx, (void*)T2CA(lpszKeyPassword));if(!SSL_CTX_use_PrivateKey_file(sslCtx, T2CA(lpszPemKeyFile), SSL_FILETYPE_PEM)){::SetLastError(ERROR_INVALID_PASSWORD);return FALSE;}if(!SSL_CTX_use_certificate_chain_file(sslCtx, T2CA(lpszPemCertFile))){::SetLastError(ERROR_INVALID_DATA);return FALSE;}if(!SSL_CTX_check_private_key(sslCtx)){::SetLastError(ERROR_INVALID_ACCESS);return FALSE;}}return TRUE;}BOOL CSSLContext::LoadCertAndKeyByMemory(SSL_CTX* sslCtx, int iVerifyMode, LPCSTR lpszPemCert, LPCSTR lpszPemKey, LPCSTR lpszKeyPassword, LPCSTR lpszCAPemCert){if(!LoadCAPemCertByMemory(sslCtx, iVerifyMode, lpszCAPemCert))return FALSE;if(!LoadPemCertAndKeyByMemory(sslCtx, lpszPemCert, lpszPemKey, lpszKeyPassword))return FALSE;return TRUE;}BOOL CSSLContext::LoadCAPemCertByMemory(SSL_CTX* sslCtx, int iVerifyMode, LPCSTR lpszCAPemCert){if(::IsStrEmptyA(lpszCAPemCert))return TRUE;if(!AddCAPemCertToStoreByMemory(sslCtx, lpszCAPemCert))return FALSE;if(!SSL_CTX_set_default_verify_paths(sslCtx)){::SetLastError(ERROR_FUNCTION_FAILED);return FALSE;}if(m_enSessionMode == SSL_SM_SERVER && (iVerifyMode & SSL_VM_PEER)){if(!SetClientCAListByMemory(sslCtx, lpszCAPemCert))return FALSE;}return TRUE;}BOOL CSSLContext::LoadPemCertAndKeyByMemory(SSL_CTX* sslCtx, LPCSTR lpszPemCert, LPCSTR lpszPemKey, LPCSTR lpszKeyPassword){if(::IsStrEmptyA(lpszPemCert))return TRUE;if(::IsStrEmptyA(lpszPemKey)){::SetLastError(ERROR_INVALID_PARAMETER);return FALSE;}if(::IsStrNotEmptyA(lpszKeyPassword))SSL_CTX_set_default_passwd_cb_userdata(sslCtx, (void*)(lpszKeyPassword));if(!SetPrivateKeyByMemory(sslCtx, lpszPemKey))return FALSE;if(!SetCertChainByMemory(sslCtx, lpszPemCert))return FALSE;if(!SSL_CTX_check_private_key(sslCtx)){::SetLastError(ERROR_INVALID_ACCESS);return FALSE;}return TRUE;}BOOL CSSLContext::AddCAPemCertToStoreByMemory(SSL_CTX* sslCtx, LPCSTR lpszPemCert){BOOL isOK = FALSE;int iCount = 0;BIO* pBIO = BIO_new_mem_buf(lpszPemCert, -1);X509_STORE* pStore = SSL_CTX_get_cert_store(sslCtx);STACK_OF(X509_INFO) * pStack = nullptr;if(pBIO == nullptr){::SetLastError(ERROR_CREATE_FAILED);goto _END;}if(pStore == nullptr){::SetLastError(ERROR_NOT_FOUND);goto _END;}pStack = PEM_X509_INFO_read_bio(pBIO, nullptr, nullptr, nullptr);if(pStack == nullptr){::SetLastError(ERROR_NO_DATA);goto _END;}for(int i = 0; i < sk_X509_INFO_num(pStack); i++){X509_INFO* pInfo = sk_X509_INFO_value(pStack, i);if(pInfo->x509){if(!X509_STORE_add_cert(pStore, pInfo->x509)){::SetLastError(ERROR_INVALID_DATA);goto _END;}++iCount;}if(pInfo->crl){if(!X509_STORE_add_crl(pStore, pInfo->crl)){::SetLastError(ERROR_INVALID_DATA);goto _END;}++iCount;}}if(iCount > 0)isOK = TRUE;else::SetLastError(ERROR_EMPTY);_END:if(pStack != nullptr)sk_X509_INFO_pop_free(pStack, X509_INFO_free);if(pBIO != nullptr)BIO_free(pBIO);return isOK;}BOOL CSSLContext::SetClientCAListByMemory(SSL_CTX* sslCtx, LPCSTR lpszPemCert){BOOL isOK = FALSE;X509* pX509 = nullptr;X509_NAME* pName = nullptr;STACK_OF(X509_NAME)* pStack = nullptr;BIO* pBIO = BIO_new_mem_buf(lpszPemCert, -1);OPENSSL_LHASH* pNameHash = (OPENSSL_LHASH*)OPENSSL_LH_new((OPENSSL_LH_HASHFUNC)FN_X509_NAME_HASH, (OPENSSL_LH_COMPFUNC)X509_NAME_cmp);if(pBIO == nullptr || pNameHash == nullptr){::SetLastError(ERROR_CREATE_FAILED);goto _ERR;}while(TRUE){if(PEM_read_bio_X509(pBIO, &pX509, nullptr, nullptr) == nullptr)break;if(pStack == nullptr){pStack = sk_X509_NAME_new_null();if(pStack == nullptr){::SetLastError(ERROR_CREATE_FAILED);goto _ERR;}}if((pName = X509_get_subject_name(pX509)) == nullptr){::SetLastError(ERROR_NO_DATA);goto _ERR;}if((pName = X509_NAME_dup(pName)) == nullptr){::SetLastError(ERROR_CREATE_FAILED);goto _ERR;}if(OPENSSL_LH_retrieve(pNameHash, pName) != nullptr){X509_NAME_free(pName);pName = nullptr;}else{OPENSSL_LH_insert(pNameHash, pName);if(!sk_X509_NAME_push(pStack, pName)){::SetLastError(ERROR_WRITE_FAULT);goto _ERR;}}}if(pStack == nullptr){::SetLastError(ERROR_EMPTY);goto _ERR;}SSL_CTX_set_client_CA_list(sslCtx, pStack);isOK = TRUE;goto _END;_ERR:if(pName != nullptr)X509_NAME_free(pName);if(pStack != nullptr){sk_X509_NAME_pop_free(pStack, X509_NAME_free);pStack = nullptr;}_END:if(pX509 != nullptr)X509_free(pX509);if(pNameHash != nullptr)OPENSSL_LH_free(pNameHash);if(pBIO != nullptr)BIO_free(pBIO);if(pStack != nullptr)ERR_clear_error();return isOK;}BOOL CSSLContext::SetPrivateKeyByMemory(SSL_CTX* sslCtx, LPCSTR lpszPemKey){BOOL isOK = FALSE;BIO* pBIO = BIO_new_mem_buf(lpszPemKey, -1);EVP_PKEY* pKey = nullptr;if(pBIO == nullptr){::SetLastError(ERROR_CREATE_FAILED);goto _END;}pKey = PEM_read_bio_PrivateKey(pBIO, nullptr, SSL_CTX_get_default_passwd_cb(sslCtx), SSL_CTX_get_default_passwd_cb_userdata(sslCtx));if(pKey == nullptr){::SetLastError(ERROR_INVALID_PASSWORD);goto _END;}if(!SSL_CTX_use_PrivateKey(sslCtx, pKey)){::SetLastError(ERROR_INVALID_DATA);goto _END;}isOK = TRUE;_END:if(pKey != nullptr)EVP_PKEY_free(pKey);if(pBIO != nullptr)BIO_free(pBIO);return isOK;}BOOL CSSLContext::SetCertChainByMemory(SSL_CTX* sslCtx, LPCSTR lpszPemCert){BOOL isOK = FALSE;ULONG err = 0;BIO* pBIO = BIO_new_mem_buf(lpszPemCert, -1);X509* pX509 = nullptr;pem_password_cb* cb = SSL_CTX_get_default_passwd_cb(sslCtx);LPVOID userdata = SSL_CTX_get_default_passwd_cb_userdata(sslCtx);if(pBIO == nullptr){::SetLastError(ERROR_CREATE_FAILED);goto _END;}pX509 = PEM_read_bio_X509_AUX(pBIO, nullptr, cb, userdata);if(pX509 == nullptr){::SetLastError(ERROR_NO_DATA);goto _END;}if(!SSL_CTX_use_certificate(sslCtx, pX509) || (ERR_peek_error() != 0)){::SetLastError(ERROR_INVALID_DATA);goto _END;}if(!SSL_CTX_clear_chain_certs(sslCtx)){::SetLastError(ERROR_FUNCTION_FAILED);goto _END;}X509* pCA;while((pCA = PEM_read_bio_X509(pBIO, nullptr, cb, userdata)) != nullptr){if(!SSL_CTX_add0_chain_cert(sslCtx, pCA)){X509_free(pCA);::SetLastError(ERROR_FUNCTION_FAILED);goto _END;}}err = ERR_peek_last_error();if(ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)ERR_clear_error();else{::SetLastError(ERROR_FUNCTION_FAILED);goto _END;}isOK = TRUE;_END:if(pX509 != nullptr)X509_free(pX509);if(pBIO != nullptr)BIO_free(pBIO);return isOK;}void CSSLContext::Cleanup(){if(IsValid()){int iCount = (int)m_lsSslCtxs.size();for(int i = 0; i < iCount; i++)SSL_CTX_free(m_lsSslCtxs[i]);m_lsSslCtxs.clear();m_sslServerNames.clear();m_sslCtx = nullptr;}m_fnServerNameCallback = nullptr;RemoveThreadLocalState();}void CSSLContext::SetServerNameCallback(Fn_SNI_ServerNameCallback fn){if(m_enSessionMode != SSL_SM_SERVER)return;if(fn == nullptr)m_fnServerNameCallback = DefaultServerNameCallback;elsem_fnServerNameCallback = fn;VERIFY(SSL_CTX_set_tlsext_servername_callback(m_sslCtx, InternalServerNameCallback));VERIFY(SSL_CTX_set_tlsext_servername_arg(m_sslCtx, this));}int CSSLContext::InternalServerNameCallback(SSL* ssl, int* ad, void* arg){USES_CONVERSION;CSSLContext* pThis = (CSSLContext*)arg;ASSERT(pThis->m_fnServerNameCallback != nullptr);const char* lpszServerName = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);if(lpszServerName == nullptr)return SSL_TLSEXT_ERR_NOACK;int iIndex = pThis->m_fnServerNameCallback(A2CT(lpszServerName), pThis);if(iIndex == 0)return SSL_TLSEXT_ERR_OK;if(iIndex < 0){::SetLastError(ERROR_INVALID_NAME);return SSL_TLSEXT_ERR_ALERT_FATAL;}SSL_CTX* sslCtx = pThis->GetContext(iIndex);if(sslCtx == nullptr){::SetLastError(ERROR_INVALID_INDEX);return SSL_TLSEXT_ERR_ALERT_FATAL;}SSL_set_SSL_CTX(ssl, sslCtx);return SSL_TLSEXT_ERR_OK;}int __HP_CALL CSSLContext::DefaultServerNameCallback(LPCTSTR lpszServerName, PVOID pContext){CSSLContext* pThis = (CSSLContext*)pContext;if(pThis->m_sslServerNames.empty())return 0;LPCTSTR lpszTmp = lpszServerName;LPCTSTR lpszSep = ::StrChr(lpszTmp, SSL_DOMAIN_SEP_CHAR);while(lpszSep != nullptr){CServerNameMap::const_iterator it = pThis->m_sslServerNames.find(lpszTmp);if(it != pThis->m_sslServerNames.end())return it->second;lpszTmp = (lpszSep + 1);lpszSep = ::StrChr(lpszTmp, SSL_DOMAIN_SEP_CHAR);}return 0;}SSL_CTX* CSSLContext::GetContext(int i) const{SSL_CTX* sslCtx = nullptr;if(i >= 0 && i < (int)m_lsSslCtxs.size())sslCtx = m_lsSslCtxs[i];return sslCtx;}BOOL CSSLSession::WriteRecvChannel(const BYTE* pData, int iLength){ASSERT(pData && iLength > 0);BOOL isOK = TRUE;int bytes = BIO_write(m_bioRecv, pData, iLength);if(bytes > 0)ASSERT(bytes == iLength);else if(!BIO_should_retry(m_bioRecv)){::SetLastError(ERROR_INVALID_DATA);isOK = FALSE;}return isOK;}BOOL CSSLSession::ReadRecvChannel(){BOOL isOK = TRUE;int bytes = SSL_read(m_ssl, m_bufRecv.buf, m_pitRecv->Capacity());if(bytes > 0)m_bufRecv.len = bytes;else if(!IsFatalError(bytes))m_bufRecv.len = 0;elseisOK = FALSE;if(isOK && m_enStatus == SSL_HSS_PROC && SSL_is_init_finished(m_ssl))m_enStatus = SSL_HSS_SUCC;return isOK;}BOOL CSSLSession::WriteSendChannel(const BYTE* pData, int iLength){ASSERT(IsReady());ASSERT(pData && iLength > 0);BOOL isOK = TRUE;int bytes = SSL_write(m_ssl, pData, iLength);if(bytes > 0)ASSERT(bytes == iLength);else if(IsFatalError(bytes))isOK = FALSE;return isOK;}BOOL CSSLSession::WriteSendChannel(const WSABUF pBuffers[], int iCount){ASSERT(pBuffers && iCount > 0);BOOL isOK = TRUE;for(int i = 0; i < iCount; i++){const WSABUF& buffer = pBuffers[i];if(buffer.len > 0){if(!WriteSendChannel((const BYTE*)buffer.buf, buffer.len)){isOK = FALSE;break;}}}return isOK;}BOOL CSSLSession::ReadSendChannel(){if(BIO_pending(m_bioSend) == 0){m_bufSend.len = 0;return TRUE;}BOOL isOK = TRUE;int bytes = BIO_read(m_bioSend, m_bufSend.buf, m_pitSend->Capacity());if(bytes > 0)m_bufSend.len = bytes;else if(BIO_should_retry(m_bioSend))m_bufSend.len = 0;else{::SetLastError(ERROR_INVALID_DATA);isOK = FALSE;}return isOK;}CSSLSession* CSSLSession::Renew(const CSSLContext& sslCtx, LPCSTR lpszHostName){ASSERT(!IsValid());ResetCount();m_ssl = SSL_new(sslCtx.GetDefaultContext());m_bioSend = BIO_new(BIO_s_mem());m_bioRecv = BIO_new(BIO_s_mem());SSL_set_bio(m_ssl, m_bioRecv, m_bioSend);if(sslCtx.GetSessionMode() == SSL_SM_SERVER)SSL_accept(m_ssl);else{USES_CONVERSION;if(lpszHostName && lpszHostName[0] != 0 && !::IsIPAddress(A2CT(lpszHostName)))SSL_set_tlsext_host_name(m_ssl, lpszHostName);SSL_connect(m_ssl);}m_pitSend = m_itPool.PickFreeItem();m_pitRecv = m_itPool.PickFreeItem();m_bufSend.buf = m_pitSend->Ptr();m_bufRecv.buf = m_pitRecv->Ptr();m_enStatus = SSL_HSS_PROC;return this;}BOOL CSSLSession::Reset(){BOOL isOK = FALSE;if(IsValid()){CCriSecLock locallock(m_csSend);if(IsValid()){m_enStatus = SSL_HSS_INIT;SSL_shutdown(m_ssl);SSL_free(m_ssl);m_itPool.PutFreeItem(m_pitSend);m_itPool.PutFreeItem(m_pitRecv);m_pitSend = nullptr;m_pitRecv = nullptr;m_ssl = nullptr;m_bioSend = nullptr;m_bioRecv = nullptr;m_dwFreeTime= ::TimeGetTime();isOK = TRUE;}}ERR_clear_error();return isOK;}inline BOOL CSSLSession::IsFatalError(int iBytes){int iErrorCode = SSL_get_error(m_ssl, iBytes);if( iErrorCode == SSL_ERROR_NONE ||iErrorCode == SSL_ERROR_WANT_READ ||iErrorCode == SSL_ERROR_WANT_WRITE ||iErrorCode == SSL_ERROR_WANT_CONNECT ||iErrorCode == SSL_ERROR_WANT_ACCEPT )return FALSE;#ifdef _DEBUGchar szBuffer[512];#endifint i = 0;ULONG iCode = iErrorCode;for(; iCode != SSL_ERROR_NONE; i++){#ifdef _DEBUGERR_error_string_n(iCode, szBuffer, sizeof(szBuffer));TRACE(" > SSL Error: %ld - %s\n", iCode, szBuffer);#endifiCode = ERR_get_error();}if(iErrorCode == SSL_ERROR_SYSCALL && i == 1)return FALSE;::SetLastError(ERROR_INVALID_DATA);return TRUE;}BOOL CSSLSession::GetSessionInfo(EnSSLSessionInfo enInfo, LPVOID* lppInfo){ASSERT(lppInfo != nullptr);*lppInfo = nullptr;if(enInfo < SSL_SSI_MIN || enInfo > SSL_SSI_MAX){::SetLastError(ERROR_INVALID_PARAMETER);return FALSE;}if(!IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}SSL_CTX* pContext = SSL_get_SSL_CTX(m_ssl);switch(enInfo){case SSL_SSI_CTX:{*lppInfo = (LPVOID)(pContext);}break;case SSL_SSI_CTX_METHOD:{if(pContext != nullptr)*lppInfo = (LPVOID)(SSL_CTX_get_ssl_method(pContext));}break;case SSL_SSI_CTX_CIPHERS:{if(pContext != nullptr)*lppInfo = (LPVOID)(SSL_CTX_get_ciphers(pContext));}break;case SSL_SSI_CTX_CERT_STORE:{if(pContext != nullptr)*lppInfo = (LPVOID)(SSL_CTX_get_cert_store(pContext));}break;case SSL_SSI_SERVER_NAME_TYPE:{*lppInfo = (LPVOID)(UINT_PTR)(SSL_get_servername_type(m_ssl));}break;case SSL_SSI_SERVER_NAME:{int type = SSL_get_servername_type(m_ssl);if(type != -1)*lppInfo = (LPVOID)(SSL_get_servername(m_ssl, type));}break;case SSL_SSI_VERSION:{*lppInfo = (LPVOID)(SSL_get_version(m_ssl));}break;case SSL_SSI_METHOD:{*lppInfo = (LPVOID)(SSL_get_ssl_method(m_ssl));}break;case SSL_SSI_CERT:{*lppInfo = (LPVOID)(SSL_get_certificate(m_ssl));}break;case SSL_SSI_PKEY:{*lppInfo = (LPVOID)(SSL_get_privatekey(m_ssl));}break;case SSL_SSI_CURRENT_CIPHER:{*lppInfo = (LPVOID)(SSL_get_current_cipher(m_ssl));}break;case SSL_SSI_CIPHERS:{*lppInfo = (LPVOID)(SSL_get_ciphers(m_ssl));}break;case SSL_SSI_CLIENT_CIPHERS:{*lppInfo = (LPVOID)(SSL_get_client_ciphers(m_ssl));}break;case SSL_SSI_PEER_CERT:{X509* pCert = SSL_get_peer_certificate(m_ssl);if(pCert != nullptr){*lppInfo = (LPVOID*)pCert;X509_free(pCert);}}break;case SSL_SSI_PEER_CERT_CHAIN:{*lppInfo = (LPVOID)(SSL_get_peer_cert_chain(m_ssl));}break;case SSL_SSI_VERIFIED_CHAIN:{*lppInfo = (LPVOID)(SSL_get0_verified_chain(m_ssl));}break;}return TRUE;}CSSLSession* CSSLSessionPool::PickFreeSession(LPCSTR lpszHostName){DWORD dwIndex;CSSLSession* pSession = nullptr;if(m_lsFreeSession.TryLock(&pSession, dwIndex)){if(::GetTimeGap32(pSession->GetFreeTime()) >= m_dwSessionLockTime)VERIFY(m_lsFreeSession.ReleaseLock(nullptr, dwIndex));else{VERIFY(m_lsFreeSession.ReleaseLock(pSession, dwIndex));pSession = nullptr;}}if(!pSession) pSession = CSSLSession::Construct(m_itPool);ASSERT(pSession);return pSession->Renew(m_sslCtx, lpszHostName);}void CSSLSessionPool::PutFreeSession(CSSLSession* pSession){if(pSession->Reset()){ReleaseGCSession();if(!m_lsFreeSession.TryPut(pSession))m_lsGCSession.PushBack(pSession);}}void CSSLSessionPool::Prepare(){m_itPool.Prepare();m_lsFreeSession.Reset(m_dwSessionPoolSize);}void CSSLSessionPool::Clear(){m_lsFreeSession.Clear();ReleaseGCSession(TRUE);VERIFY(m_lsGCSession.IsEmpty());m_itPool.Clear();}void CSSLSessionPool::ReleaseGCSession(BOOL bForce){::ReleaseGCObj(m_lsGCSession, m_dwSessionLockTime, bForce);}#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。