diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 54b56017e..383ba4bb1 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -171,6 +171,7 @@ ENDIF() IF(APPLE) FIND_LIBRARY(CARBON_FRAMEWORK Carbon) FIND_LIBRARY(FOUNDATION_FRAMEWORK Foundation) + FIND_LIBRARY(SECURITY_FRAMEWORK Security) IF(APPLE_CERTIFICATE) # Find codesign_allocate @@ -230,22 +231,41 @@ IF(WITH_NEL) IF(CURL_STATIC) SET(CURL_DEFINITIONS -DCURL_STATICLIB) - SET(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR}) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES}) + LIST(APPEND CURL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + LIST(APPEND CURL_LIBRARIES ${OPENSSL_LIBRARIES}) - IF(UNIX) + IF(WIN32) + LIST(APPEND CURL_LIBRARIES Crypt32 Cryptui) + ELSE() # CURL depends on libidn FIND_LIBRARY(IDN_LIBRARY idn) IF(IDN_LIBRARY) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${IDN_LIBRARY}) + LIST(APPEND CURL_LIBRARIES ${IDN_LIBRARY}) ENDIF() - # CURL Macports version depends on libidn, libintl and libiconv too + # CURL Macports version can depend on libidn, libidn2, libintl, libpsl and libiconv too IF(APPLE) FIND_LIBRARY(INTL_LIBRARY intl) IF(INTL_LIBRARY) - SET(CURL_LIBRARIES ${CURL_LIBRARIES} ${INTL_LIBRARY}) + LIST(APPEND CURL_LIBRARIES ${INTL_LIBRARY}) ENDIF() + + FIND_LIBRARY(IDN2_LIBRARY idn2) + IF(IDN2_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${IDN2_LIBRARY}) + ENDIF() + + FIND_LIBRARY(PSL_LIBRARY psl) + IF(PSL_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${PSL_LIBRARY}) + ENDIF() + + FIND_LIBRARY(UNISTRING_LIBRARY unistring) + IF(UNISTRING_LIBRARY) + LIST(APPEND CURL_LIBRARIES ${UNISTRING_LIBRARY}) + ENDIF() + + LIST(APPEND CURL_LIBRARIES ${SECURITY_FRAMEWORK}) ENDIF() ENDIF() ENDIF() diff --git a/code/CMakeModules/FindHelpers.cmake b/code/CMakeModules/FindHelpers.cmake index d9aa3e75c..a4af37229 100644 --- a/code/CMakeModules/FindHelpers.cmake +++ b/code/CMakeModules/FindHelpers.cmake @@ -896,7 +896,7 @@ MACRO(FIND_QT5) # Network SET(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Network Qt5::Xml) - SET(QT_LIBRARIES ${QT_LIBRARIES} ${ZLIB_LIBRARIES}) + SET(QT_LIBRARIES ${QT_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) IF(WIN32) SET(QT_LIBRARIES ${QT_LIBRARIES} diff --git a/code/nel/include/nel/gui/curl_certificates.h b/code/nel/include/nel/gui/curl_certificates.h index dd4e923a0..ee6938842 100644 --- a/code/nel/include/nel/gui/curl_certificates.h +++ b/code/nel/include/nel/gui/curl_certificates.h @@ -19,7 +19,8 @@ #include "nel/misc/types_nl.h" -#include +// forward declaration to avoid curl.h inclusion everywhere +typedef void CURL; namespace NLGUI { @@ -32,8 +33,8 @@ namespace NLGUI // allow to use custom PEM certificates static void addCertificateFile(const std::string &cert); - // cURL SSL certificate loading - static CURLcode sslCtxFunction(CURL *curl, void *sslctx, void *parm); + // set all CURL options to use custom SSL context function + static void useCertificates(CURL *curl); }; } // namespace diff --git a/code/nel/src/gui/CMakeLists.txt b/code/nel/src/gui/CMakeLists.txt index a5f157c01..cb7bbe23a 100644 --- a/code/nel/src/gui/CMakeLists.txt +++ b/code/nel/src/gui/CMakeLists.txt @@ -10,10 +10,6 @@ INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${LUABIND_INCLUDE_ TARGET_LINK_LIBRARIES(nelgui nelmisc nel3d ${LUA_LIBRARIES} ${LUABIND_LIBRARIES} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES}) -IF(WIN32) - TARGET_LINK_LIBRARIES(nelgui Crypt32 Cryptui) -ENDIF() - NL_DEFAULT_PROPS(nelgui "NeL, Library: NeL GUI") NL_ADD_RUNTIME_FLAGS(nelgui) diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index e44161882..f06d92608 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -23,6 +23,8 @@ #include #include +#include + using namespace std; using namespace NLMISC; @@ -67,7 +69,16 @@ namespace NLGUI // get more information on CURL session curl_tlssessioninfo *sessionInfo; - CURLcode res = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &sessionInfo); + + CURLINFO info; + +#if CURL_AT_LEAST_VERSION(7, 48, 0) + info = CURLINFO_TLS_SSL_PTR; +#else + info = CURLINFO_TLS_SESSION; +#endif + + CURLcode res = curl_easy_getinfo(curl, info, &sessionInfo); // only use OpenSSL callback if not using Windows SSPI and using OpenSSL backend if (!res && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL && !(data && data->features & CURL_VERSION_SSPI)) @@ -201,23 +212,8 @@ namespace NLGUI /// this will be initialized on startup and cleared on exit static SX509Certificates x509CertListManager; - // *************************************************************************** - // static - void CCurlCertificates::init(CURL *curl) - { - x509CertListManager.init(curl); - } - - // *************************************************************************** - // static - void CCurlCertificates::addCertificateFile(const std::string &cert) - { - x509CertListManager.addCertificatesFromFile(cert); - } - - // *************************************************************************** - // static - CURLcode CCurlCertificates::sslCtxFunction(CURL *curl, void *sslctx, void *parm) + // cURL SSL certificate loading + static CURLcode sslCtxFunction(CURL *curl, void *sslctx, void *parm) { CURLcode res = CURLE_OK; @@ -282,5 +278,39 @@ namespace NLGUI return res; } + // *************************************************************************** + // static + void CCurlCertificates::init(CURL *curl) + { + x509CertListManager.init(curl); + } + + // *************************************************************************** + // static + void CCurlCertificates::addCertificateFile(const std::string &cert) + { + x509CertListManager.addCertificatesFromFile(cert); + } + + // *************************************************************************** + // static + void CCurlCertificates::useCertificates(CURL *curl) + { + // CURL must be valid, using OpenSSL backend and certificates must be loaded, else return + if (!curl || !x509CertListManager.isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; + + curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); + + // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL + if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &sslCtxFunction) != CURLE_OK) + { + nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); + } + + // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) + curl_easy_setopt(curl, CURLOPT_CAINFO, NULL); + curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); + } + }// namespace diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index a259766bf..c289d2135 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -404,15 +404,8 @@ namespace NLGUI // specify custom CA certs CCurlCertificates::addCertificateFile(options.curlCABundle); - // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL - if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction) != CURLE_OK) - { - nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); - } - - // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) - curl_easy_setopt(curl, CURLOPT_CAINFO, NULL); - curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); + // if supported, use custom SSL context function to load certificates + CCurlCertificates::useCertificates(curl); } download.data = new CCurlWWWData(curl, download.url); @@ -5352,14 +5345,14 @@ namespace NLGUI // https:// if (toLower(url.substr(0, 8)) == "https://") { -#if defined(NL_OS_WINDOWS) - curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction); -#else - if (!options.curlCABundle.empty()) - { - curl_easy_setopt(curl, CURLOPT_CAINFO, options.curlCABundle.c_str()); - } -#endif + // check if compiled with OpenSSL backend + CCurlCertificates::init(curl); + + // specify custom CA certs + CCurlCertificates::addCertificateFile(options.curlCABundle); + + // if supported, use custom SSL context function to load certificates + CCurlCertificates::useCertificates(curl); } // do not follow redirects, we have own handler diff --git a/code/ryzom/client/src/http_client_curl.cpp b/code/ryzom/client/src/http_client_curl.cpp index 418fc61bd..2887543c3 100644 --- a/code/ryzom/client/src/http_client_curl.cpp +++ b/code/ryzom/client/src/http_client_curl.cpp @@ -70,7 +70,6 @@ bool CCurlHttpClient::verifyServer(bool verify) { curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, verify ? 2 : 0); curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, verify ? 1 : 0); - curl_easy_setopt(_Curl, CURLOPT_SSLCERTTYPE, "PEM"); // check if compiled with OpenSSL backend NLGUI::CCurlCertificates::init(_Curl); @@ -78,15 +77,9 @@ bool CCurlHttpClient::verifyServer(bool verify) // specify custom CA certs NLGUI::CCurlCertificates::addCertificateFile(CAFilename); - // would allow to provide the CA in memory instead of using CURLOPT_CAINFO, but needs to include and link OpenSSL - if (curl_easy_setopt(_Curl, CURLOPT_SSL_CTX_FUNCTION, &NLGUI::CCurlCertificates::sslCtxFunction) != CURLE_OK) - { - nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); - } + // if supported, use custom SSL context function to load certificates + NLGUI::CCurlCertificates::useCertificates(_Curl); - // set both CURLOPT_CAINFO and CURLOPT_CAPATH to NULL to be sure we won't use default values (these files can be missing and generate errors) - curl_easy_setopt(_Curl, CURLOPT_CAINFO, NULL); - curl_easy_setopt(_Curl, CURLOPT_CAPATH, NULL); return true; }