11/*
2- * Copyright (C) 2019-2020 HERE Europe B.V.
2+ * Copyright (C) 2019-2022 HERE Europe B.V.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
2222#include < algorithm>
2323#include < cstring>
2424
25- #include < errno.h>
2625#include < fcntl.h>
27- #include < sys/stat.h>
2826#include < unistd.h>
27+ #include < cerrno>
2928
3029#if defined(HAVE_SIGNAL_H)
3130#include < signal.h>
3231#endif
3332
34- #ifdef OLP_SDK_NETWORK_HAS_OPENSSL
35- #include < openssl/crypto.h>
36- #endif
37- #ifdef NETWORK_USE_TIMEPROVIDER
33+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
3834#include < openssl/ssl.h>
35+ #include < openssl/x509_vfy.h>
36+ #include < sys/stat.h>
37+ #include < cstdio>
38+ #elif OLP_SDK_NETWORK_HAS_OPENSSL
39+ #include " olp/core/utils/Dir.h"
3940#endif
4041
41- #ifdef NETWORK_USE_TIMEPROVIDER
42- #include " timeprovider/TimeProvider.h"
43- #endif
4442#include " olp/core/http/HttpStatusCode.h"
4543#include " olp/core/http/NetworkUtils.h"
4644#include " olp/core/logging/Log.h"
47- #include " olp/core/porting/platform.h"
48- #include " olp/core/utils/Dir.h"
4945
5046namespace olp {
5147namespace http {
@@ -56,10 +52,56 @@ const char* kLogTag = "CURL";
5652
5753#ifdef OLP_SDK_ENABLE_ANDROID_CURL
5854const auto kCurlAndroidCaBundleFolder = " /system/etc/security/cacerts" ;
59- #endif
6055
61- #ifdef OLP_SDK_NETWORK_HAS_OPENSSL
56+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
57+ const char * kLookupMethodName = " DataSDKMd5Lookup" ;
58+
59+ int Md5LookupCtrl (X509_LOOKUP* ctx, int , const char *, long , char **) {
60+ const auto * cert_path = kCurlAndroidCaBundleFolder ;
61+ X509_LOOKUP_set_method_data (ctx, const_cast <char *>(cert_path));
62+ return 1 ;
63+ }
64+
65+ int Md5LookupGetBySubject (X509_LOOKUP* ctx, X509_LOOKUP_TYPE type,
66+ X509_NAME* name, X509_OBJECT* ret) {
67+ if (type != X509_LU_X509) {
68+ OLP_SDK_LOG_ERROR_F (kLogTag , " Unsupported lookup type, type=%d" , type);
69+ return 0 ;
70+ }
71+
72+ const char * base_path =
73+ static_cast <const char *>(X509_LOOKUP_get_method_data (ctx));
74+ const auto name_hash = X509_NAME_hash_old (name);
75+
76+ char buf[256 ];
77+ for (auto idx = 0 ;; ++idx) {
78+ snprintf (buf, sizeof (buf), " %s/%08lx.%d" , base_path, name_hash, idx);
79+
80+ struct stat st {};
81+ if (stat (buf, &st) < 0 ) {
82+ // There is no such certificate
83+ break ;
84+ }
85+
86+ // `X509_load_cert_file` returns number of loaded objects
87+ const auto load_cert_ret = X509_load_cert_file (ctx, buf, X509_FILETYPE_PEM);
88+ if (load_cert_ret == 0 ) {
89+ OLP_SDK_LOG_ERROR_F (kLogTag , " Failed to load certificate file, buf=%s" ,
90+ buf);
91+ return 0 ;
92+ }
93+ }
6294
95+ // Update return result
96+ auto * x509_data = X509_new ();
97+ X509_set_subject_name (x509_data, name);
98+ X509_OBJECT_set1_X509 (ret, x509_data);
99+
100+ return 1 ;
101+ }
102+ #endif
103+
104+ #elif OLP_SDK_NETWORK_HAS_OPENSSL
63105const auto kCurlCaBundleName = " ca-bundle.crt" ;
64106
65107std::string DefaultCaBundlePath () { return kCurlCaBundleName ; }
@@ -155,26 +197,6 @@ int ConvertErrorCode(CURLcode curl_code) {
155197 }
156198}
157199
158- #ifdef OLP_SDK_NETWORK_HAS_OPENSSL
159- #ifdef NETWORK_USE_TIMEPROVIDER
160- static curl_code SslctxFunction (CURL* curl, void * sslctx, void *) {
161- // get the current time in seconds since epoch
162- std::uint64_t time = static_cast <std::uint64_t >(
163- TimeProvider::getClock ()->timeSinceEpochMs () / 1000 );
164- #if OPENSSL_VERSION_NUMBER < 0x10100000L
165- X509_STORE* store = SSL_CTX_get_cert_store (static_cast <SSL_CTX*>(sslctx));
166- X509_VERIFY_PARAM_set_time (store->param , time_t (time));
167- #else
168- X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new ();
169- X509_VERIFY_PARAM_set_time (param, time_t (time));
170- SSL_CTX_set1_param (static_cast <SSL_CTX*>(sslctx), param);
171- X509_VERIFY_PARAM_free (param);
172- #endif
173- return CURLE_OK;
174- }
175- #endif
176- #endif
177-
178200/* *
179201 * @brief CURL get upload/download data.
180202 * @param[in] handle CURL easy handle.
@@ -210,7 +232,11 @@ void GetTrafficData(CURL* handle, uint64_t& upload_bytes,
210232
211233CURLcode SetCaBundlePaths (CURL* handle) {
212234 OLP_SDK_CORE_UNUSED (handle);
235+
213236#ifdef OLP_SDK_ENABLE_ANDROID_CURL
237+ // FIXME: We could disable this lookup as it won't work on most devices
238+ // (probably all of them) since OpenSSL still will be trying to find
239+ // certificate with SHA1 lookup
214240 return curl_easy_setopt (handle, CURLOPT_CAPATH, kCurlAndroidCaBundleFolder );
215241#elif OLP_SDK_NETWORK_HAS_OPENSSL
216242 const auto curl_ca_bundle = CaBundlePath ();
@@ -227,7 +253,6 @@ int64_t GetElapsedTime(std::chrono::steady_clock::time_point start) {
227253 std::chrono::steady_clock::now () - start)
228254 .count ();
229255}
230-
231256} // anonymous namespace
232257
233258NetworkCurl::NetworkCurl (size_t max_requests_count)
@@ -300,12 +325,23 @@ bool NetworkCurl::Initialize() {
300325 return false ;
301326 }
302327
328+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
329+ md5_lookup_method_ = X509_LOOKUP_meth_new (kLookupMethodName );
330+
331+ X509_LOOKUP_meth_set_ctrl (md5_lookup_method_, Md5LookupCtrl);
332+ X509_LOOKUP_meth_set_get_by_subject (md5_lookup_method_,
333+ Md5LookupGetBySubject);
334+ #endif
335+
303336 // handles setup
304337 std::shared_ptr<NetworkCurl> that = shared_from_this ();
305338 for (auto & handle : handles_) {
306339 handle.handle = nullptr ;
307340 handle.in_use = false ;
308341 handle.self = that;
342+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
343+ handle.md5_lookup_method = md5_lookup_method_;
344+ #endif
309345 }
310346
311347 std::unique_lock<std::mutex> lock (event_mutex_);
@@ -320,6 +356,11 @@ bool NetworkCurl::Initialize() {
320356
321357void NetworkCurl::Deinitialize () {
322358 std::lock_guard<std::mutex> init_lock (init_mutex_);
359+
360+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
361+ X509_LOOKUP_meth_free (md5_lookup_method_);
362+ #endif
363+
323364 // Stop worker thread
324365 if (!IsStarted ()) {
325366 OLP_SDK_LOG_DEBUG (kLogTag , " Already deinitialized, this=" << this );
@@ -467,8 +508,9 @@ ErrorCode NetworkCurl::SendImplementation(
467508
468509 const auto & config = request.GetSettings ();
469510
470- RequestHandle* handle = GetHandle (id, callback, header_callback,
471- data_callback, payload, request.GetBody ());
511+ RequestHandle* handle =
512+ GetHandle (id, std::move (callback), std::move (header_callback),
513+ std::move (data_callback), payload, request.GetBody ());
472514 if (!handle) {
473515 return ErrorCode::NETWORK_OVERLOAD_ERROR;
474516 }
@@ -572,8 +614,11 @@ ErrorCode NetworkCurl::SendImplementation(
572614
573615 curl_easy_setopt (handle->handle , CURLOPT_SSL_VERIFYPEER, 1L );
574616 curl_easy_setopt (handle->handle , CURLOPT_SSL_VERIFYHOST, 2L );
575- #ifdef NETWORK_USE_TIMEPROVIDER
576- curl_easy_setopt (handle->handle , CURLOPT_SSL_CTX_FUNCTION, SslctxFunction);
617+
618+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
619+ curl_easy_setopt (handle->handle , CURLOPT_SSL_CTX_FUNCTION,
620+ &NetworkCurl::AddMd5LookupMethod);
621+ curl_easy_setopt (handle->handle , CURLOPT_SSL_CTX_DATA, handle);
577622#endif
578623
579624 curl_easy_setopt (handle->handle , CURLOPT_FOLLOWLOCATION, 1L );
@@ -671,9 +716,9 @@ NetworkCurl::RequestHandle* NetworkCurl::GetHandle(
671716 curl_easy_setopt (handle.handle , CURLOPT_NOSIGNAL, 1L );
672717 }
673718 handle.in_use = true ;
674- handle.callback = callback;
675- handle.header_callback = header_callback;
676- handle.data_callback = data_callback;
719+ handle.callback = std::move ( callback) ;
720+ handle.header_callback = std::move ( header_callback) ;
721+ handle.data_callback = std::move ( data_callback) ;
677722 handle.id = id;
678723 handle.count = 0u ;
679724 handle.offset = 0u ;
@@ -1105,5 +1150,27 @@ void NetworkCurl::Run() {
11051150 OLP_SDK_LOG_DEBUG (kLogTag , " Thread exit, this=" << this );
11061151}
11071152
1153+ #ifdef OLP_SDK_USE_MD5_CERT_LOOKUP
1154+ CURLcode NetworkCurl::AddMd5LookupMethod (CURL*, SSL_CTX* ssl_ctx,
1155+ RequestHandle* handle) {
1156+ auto self = handle->self .lock ();
1157+ if (!self) {
1158+ OLP_SDK_LOG_ERROR (kLogTag , " Unable to lock cURL handle" );
1159+ return CURLE_ABORTED_BY_CALLBACK;
1160+ }
1161+
1162+ auto * cert_store = SSL_CTX_get_cert_store (ssl_ctx);
1163+ auto * lookup = X509_STORE_add_lookup (cert_store, handle->md5_lookup_method );
1164+ if (lookup) {
1165+ X509_LOOKUP_add_dir (lookup, NULL , X509_FILETYPE_PEM);
1166+ } else {
1167+ OLP_SDK_LOG_ERROR (kLogTag , " Failed to add lookup method" );
1168+ return CURLE_ABORTED_BY_CALLBACK;
1169+ }
1170+
1171+ return CURLE_OK;
1172+ }
1173+ #endif
1174+
11081175} // namespace http
11091176} // namespace olp
0 commit comments