diff --git a/code/ryzom/client/src/http_client_curl.cpp b/code/ryzom/client/src/http_client_curl.cpp index ecbfd065b..0c433a598 100644 --- a/code/ryzom/client/src/http_client_curl.cpp +++ b/code/ryzom/client/src/http_client_curl.cpp @@ -61,21 +61,31 @@ bool CCurlHttpClient::authenticate(const std::string &user, const std::string &p const char *CAFilename = "ssl_ca_cert.pem"; // this is the certificate "Thawte Server CA" +// *************************************************************************** static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) { + // look for certificate in search paths string path = CPath::lookup(CAFilename); nldebug("Cert path '%s'", path.c_str()); + if (path.empty()) + { + nlwarning("Unable to find %s", CAFilename); + return CURLE_SSL_CACERT; + } + CIFile file; - if (!file.open(CAFilename)) + // open certificate + if (!file.open(path)) { - nlwarning("Unable to open %s", CAFilename); + nlwarning("Unable to open %s", path.c_str()); return CURLE_SSL_CACERT; } CURLcode res = CURLE_OK; + // load certificate content into memory std::vector buffer(file.getFileSize()); file.serialBuffer(&buffer[0], file.getFileSize()); @@ -84,25 +94,33 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) if (bio) { + // get a pointer to the X509 certificate store (which may be empty!) + X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx); + // use it to read the PEM formatted certificate from memory into an X509 // structure that SSL can use - X509 *cert = NULL; - PEM_read_bio_X509(bio, &cert, 0, NULL); + STACK_OF(X509_INFO) *info = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); - if (cert) + if (info) { - // get a pointer to the X509 certificate store (which may be empty!) - X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx); - - // add our certificate to this store - if (X509_STORE_add_cert(store, cert) == 0) + // iterate over all entries from the PEM file, add them to the x509_store one by one + for (sint i = 0; i < sk_X509_INFO_num(info); ++i) { - nlwarning("Error adding certificate"); - res = CURLE_SSL_CACERT; + X509_INFO *itmp = sk_X509_INFO_value(info, i); + + if (itmp->x509) + { + // add our certificate to this store + if (X509_STORE_add_cert(store, itmp->x509) == 0) + { + nlwarning("Error adding certificate"); + res = CURLE_SSL_CACERT; + } + } } - // decrease reference counts - X509_free(cert); + // cleanup + sk_X509_INFO_pop_free(info, X509_INFO_free); } else { @@ -113,9 +131,14 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) // decrease reference counts BIO_free(bio); } + else + { + nlwarning("Unable to allocate BIO buffer for certificates"); + res = CURLE_SSL_CACERT; + } // all set to go - return CURLE_OK ; + return res; } // *************************************************************************** @@ -125,7 +148,10 @@ bool CCurlHttpClient::verifyServer(bool verify) curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, verify ? 1 : 0); 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 - curl_easy_setopt(_Curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function); + if (curl_easy_setopt(_Curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function) == CURLE_NOT_BUILT_IN) + { + nlwarning("Unable to support CURLOPT_SSL_CTX_FUNCTION, curl not compiled with OpenSSL ?"); + } // don't use that anymore, because CA can't be loaded from BNP and doesn't support UTF-8 under Windows // curl_easy_setopt(_Curl, CURLOPT_CAINFO, path.c_str()); curl_easy_setopt(_Curl, CURLOPT_CAPATH, NULL); @@ -181,7 +207,7 @@ bool CCurlHttpClient::sendRequest(const std::string& methodWB, const std::string curl_easy_getinfo(_Curl, CURLINFO_RESPONSE_CODE, &r); if (verbose) { - nldebug("%u", r); + nldebug("%u", (uint)r); } return true;