From b86bf43090444ef92e789b1bd93f7064b288a634 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 11 Aug 2018 21:47:50 +0200 Subject: [PATCH] Fixed: Simplify certificates management --HG-- branch : develop --- code/nel/include/nel/gui/curl_certificates.h | 3 - code/nel/include/nel/gui/group_html.h | 2 - code/nel/src/gui/curl_certificates.cpp | 121 +++++++++++------- code/nel/src/gui/group_html.cpp | 12 -- code/ryzom/client/src/http_client_curl.cpp | 3 - .../src/interface_v3/interface_manager.cpp | 12 +- 6 files changed, 78 insertions(+), 75 deletions(-) diff --git a/code/nel/include/nel/gui/curl_certificates.h b/code/nel/include/nel/gui/curl_certificates.h index ee6938842..9d5ad4855 100644 --- a/code/nel/include/nel/gui/curl_certificates.h +++ b/code/nel/include/nel/gui/curl_certificates.h @@ -27,9 +27,6 @@ namespace NLGUI class CCurlCertificates { public: - // check if compiled with OpenSSL backend - static void init(CURL *curl); - // allow to use custom PEM certificates static void addCertificateFile(const std::string &cert); diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 811cd3503..c96b67456 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -66,8 +66,6 @@ namespace NLGUI std::vector< std::string > trustedDomains; /// Maximum concurrent MultiCurl connections per CGroupHTML instance sint32 curlMaxConnections; - /// cacert.pem location - std::string curlCABundle; SWebOptions(): curlMaxConnections(2) { diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 7d26e7e5a..fa3cd10f0 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -40,29 +40,43 @@ namespace NLGUI class SX509Certificates { public: - std::vector CertList; - std::vector FilesList; + struct CertEntry + { + X509 *cert; + std::string name; + std::string file; + + bool operator == (const std::string &str) + { + return file == str; + } + }; + + std::vector CertList; bool isUsingOpenSSLBackend; bool isInitialized; SX509Certificates():isUsingOpenSSLBackend(false), isInitialized(false) { + init(); } ~SX509Certificates() { for (uint i = 0; i < CertList.size(); ++i) { - X509_free(CertList[i]); + X509_free(CertList[i].cert); } CertList.clear(); } - void init(CURL *curl) + void init() { - if (isInitialized) return; + // init CURL + CURL *curl = curl_easy_init(); + if (!curl) return; // get information on CURL curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); @@ -98,9 +112,39 @@ namespace NLGUI isUsingOpenSSLBackend = false; } + // clean up CURL + curl_easy_cleanup(curl); + isInitialized = true; } + static std::string getCertName(X509 *cert) + { + // NULL certificate + if (!cert) return ""; + + X509_NAME *subject = X509_get_subject_name(cert); + + std::string name; + unsigned char *tmp = NULL; + + // construct a multiline string with name + for (int j = 0, jlen = X509_NAME_entry_count(subject); j < jlen; ++j) + { + X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, j); + ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); + + if (ASN1_STRING_to_UTF8(&tmp, d) > 0) + { + name += NLMISC::toString("%s\n", tmp); + + OPENSSL_free(tmp); + } + } + + return name; + } + #ifdef NL_OS_WINDOWS void addCertificatesFrom(LPCSTR root) { @@ -114,38 +158,36 @@ namespace NLGUI { x509 = NULL; x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded); + if (x509) { - CertList.push_back(x509); + CertEntry entry; + entry.cert = x509; + entry.file = root; + entry.name = getCertName(x509); + + CertList.push_back(entry); } } + CertFreeCertificateContext(pContext); CertCloseStore(hStore, 0); } // this is called before debug context is set and log ends up in log.log - nlinfo("Loaded %d certificates from '%s' certificate store", (int)CertList.size(), root); + //nlinfo("Loaded %d certificates from '%s' certificate store", (int)CertList.size(), root); } #endif void addCertificatesFromFile(const std::string &cert) { - if (!isUsingOpenSSLBackend) return; - - if (!isInitialized) - { - nlwarning("You MUST call NLGUI::CCurlCertificates::init before adding new certificates"); - return; - } + if (!isInitialized || !isUsingOpenSSLBackend) return; // this file was already loaded - if (std::find(FilesList.begin(), FilesList.end(), cert) != FilesList.end()) return; - - FilesList.push_back(cert); + if (std::find(CertList.begin(), CertList.end(), cert) != CertList.end()) return; // look for certificate in search paths string path = CPath::lookup(cert, false); - nlinfo("Cert path '%s'", path.c_str()); if (path.empty()) { @@ -153,6 +195,8 @@ namespace NLGUI return; } + nlinfo("CURL CA bundle '%s'", path.c_str()); + CIFile file; // open certificate @@ -184,7 +228,12 @@ namespace NLGUI if (itmp && itmp->x509) { - CertList.push_back(X509_dup(itmp->x509)); + CertEntry entry; + entry.cert = X509_dup(itmp->x509); + entry.file = cert; + entry.name = getCertName(entry.cert); + + CertList.push_back(entry); } } @@ -224,27 +273,10 @@ namespace NLGUI for (uint i = 0, ilen = x509CertListManager.CertList.size(); i < ilen; ++i) { - X509_NAME *subject = X509_get_subject_name(x509CertListManager.CertList[i]); - - std::string name; - unsigned char *tmp = NULL; - - // construct a multiline string with name - for (int j = 0, jlen = X509_NAME_entry_count(subject); j < jlen; ++j) - { - X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, j); - ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); - - if (ASN1_STRING_to_UTF8(&tmp, d) > 0) - { - name += NLMISC::toString("%s\n", tmp); - - OPENSSL_free(tmp); - } - } + SX509Certificates::CertEntry entry = x509CertListManager.CertList[i]; // add our certificate to this store - if (X509_STORE_add_cert(x509store, x509CertListManager.CertList[i]) == 0) + if (X509_STORE_add_cert(x509store, entry.cert) == 0) { uint errCode = ERR_get_error(); @@ -252,13 +284,13 @@ namespace NLGUI if (ERR_GET_LIB(errCode) != ERR_LIB_X509 || ERR_GET_REASON(errCode) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { ERR_error_string_n(errCode, errorBuffer, 1024); - nlwarning("Error adding certificate %s: %s", name.c_str(), errorBuffer); + nlwarning("Error adding certificate %s: %s", entry.name.c_str(), errorBuffer); res = CURLE_SSL_CACERT; } } else { - nldebug("Added certificate %s", name.c_str()); + nldebug("Added certificate %s", entry.name.c_str()); } } } @@ -275,13 +307,6 @@ namespace NLGUI return res; } - // *************************************************************************** - // static - void CCurlCertificates::init(CURL *curl) - { - x509CertListManager.init(curl); - } - // *************************************************************************** // static void CCurlCertificates::addCertificateFile(const std::string &cert) @@ -294,7 +319,7 @@ namespace NLGUI 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; + if (!curl || !x509CertListManager.isInitialized || !x509CertListManager.isUsingOpenSSLBackend || x509CertListManager.CertList.empty()) return; curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index e8a2ac889..9a987d450 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -398,12 +398,6 @@ namespace NLGUI // https:// if (toLower(download.url.substr(0, 8)) == "https://") { - // 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); } @@ -5410,12 +5404,6 @@ namespace NLGUI // https:// if (toLower(url.substr(0, 8)) == "https://") { - // 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); } diff --git a/code/ryzom/client/src/http_client_curl.cpp b/code/ryzom/client/src/http_client_curl.cpp index 2887543c3..16436516b 100644 --- a/code/ryzom/client/src/http_client_curl.cpp +++ b/code/ryzom/client/src/http_client_curl.cpp @@ -71,9 +71,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); - // check if compiled with OpenSSL backend - NLGUI::CCurlCertificates::init(_Curl); - // specify custom CA certs NLGUI::CCurlCertificates::addCertificateFile(CAFilename); diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 53eddd7b9..6ec32a34d 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -113,6 +113,8 @@ #include "nel/gui/lua_helper.h" using namespace NLGUI; #include "nel/gui/lua_ihm.h" +#include "nel/gui/curl_certificates.h" + #include "lua_ihm_ryzom.h" #include "add_on_manager.h" @@ -471,15 +473,11 @@ CInterfaceManager::CInterfaceManager() CGroupHTML::options.appName = getUserAgentName(); CGroupHTML::options.appVersion = getUserAgentVersion(); CGroupHTML::options.curlMaxConnections = ClientCfg.CurlMaxConnections; + if (!ClientCfg.CurlCABundle.empty()) { - string filename = CPath::lookup(ClientCfg.CurlCABundle, false); - if (!filename.empty()) - { - filename = CPath::getFullPath(filename, false); - CGroupHTML::options.curlCABundle = filename; - nlinfo("curl ca bundle '%s'", filename.c_str()); - } + // specify custom CA certs, lookup will be made in this function + NLGUI::CCurlCertificates::addCertificateFile(ClientCfg.CurlCABundle); } NLGUI::CDBManager::getInstance()->resizeBanks( NB_CDB_BANKS );