diff options
| -rw-r--r-- | docs/source/usage/environmentvars.rst | 8 | ||||
| -rw-r--r-- | scripts/reference_exported_symbols.txt | 1 | ||||
| -rw-r--r-- | src/ctx.cpp | 10 | ||||
| -rw-r--r-- | src/filemanager.cpp | 31 | ||||
| -rw-r--r-- | src/networkfilemanager.cpp | 24 | ||||
| -rw-r--r-- | src/proj.h | 2 | ||||
| -rw-r--r-- | src/proj_internal.h | 2 | ||||
| -rw-r--r-- | src/proj_symbol_rename.h | 1 | ||||
| -rw-r--r-- | test/unit/proj_context_test.cpp | 10 |
9 files changed, 85 insertions, 4 deletions
diff --git a/docs/source/usage/environmentvars.rst b/docs/source/usage/environmentvars.rst index e519a80b..0717a9fa 100644 --- a/docs/source/usage/environmentvars.rst +++ b/docs/source/usage/environmentvars.rst @@ -74,3 +74,11 @@ done by setting the variable with no content:: configuration file locale in :envvar:`PROJ_LIB`. Alternatively, the :c:func:`proj_context_set_url_endpoint` function can be used. + +.. envvar:: PROJ_CURL_CA_BUNDLE + + .. versionadded:: 7.2.0 + + Define a custum path to the CA Bundle file. This can be useful if `curl` + and :envvar:`PROJ_NETWORK` are enabled. Alternatively, the + :c:func:`proj_curl_set_ca_bundle_path` function can be used. diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt index f38d708b..3d738c9b 100644 --- a/scripts/reference_exported_symbols.txt +++ b/scripts/reference_exported_symbols.txt @@ -844,6 +844,7 @@ proj_context_set_file_finder proj_context_set_network_callbacks proj_context_set(PJconsts*, projCtx_t*) proj_context_set_search_paths +proj_context_set_ca_bundle_path proj_context_set_sqlite3_vfs_name proj_context_set_url_endpoint proj_context_use_proj4_init_rules diff --git a/src/ctx.cpp b/src/ctx.cpp index 6172b3c8..1e97e58a 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -126,6 +126,15 @@ void projCtx_t::set_search_paths(const std::vector<std::string>& search_paths_in } } +/**************************************************************************/ +/* set_ca_bundle_path() */ +/**************************************************************************/ + +void projCtx_t::set_ca_bundle_path(const std::string& ca_bundle_path_in) +{ + ca_bundle_path = ca_bundle_path_in; +} + /************************************************************************/ /* projCtx_t(const projCtx_t& other) */ /************************************************************************/ @@ -142,6 +151,7 @@ projCtx_t::projCtx_t(const projCtx_t& other) file_finder_legacy = other.file_finder_legacy; file_finder_user_data = other.file_finder_user_data; networking = other.networking; + ca_bundle_path = other.ca_bundle_path; } /************************************************************************/ diff --git a/src/filemanager.cpp b/src/filemanager.cpp index 9652087b..29e85fbc 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -1988,3 +1988,34 @@ void pj_set_searchpath(int count, const char **path) { proj_context_set_search_paths(nullptr, count, const_cast<const char *const *>(path)); } + + +/************************************************************************/ +/* proj_context_set_ca_bundle_path() */ +/************************************************************************/ + +/** \brief Sets CA Bundle path. + * + * Those CA Bundle path will be used by PROJ when curl and PROJ_NETWORK + * are enabled. + * + * If set on the default context, they will be inherited by contexts created + * later. + * + * The path should be encoded in UTF-8. + * + * @param ctx PROJ context, or NULL for the default context. + * @param path Path. May be NULL. + * + * @since PROJ 7.2 + */ +void proj_context_set_ca_bundle_path(PJ_CONTEXT *ctx, const char *path) { + if (!ctx) + ctx = pj_get_default_ctx(); + if (!ctx) + return; + try { + ctx->set_ca_bundle_path(path != nullptr ? path : ""); + } catch (const std::exception &) { + } +} diff --git a/src/networkfilemanager.cpp b/src/networkfilemanager.cpp index 4d6f425c..7587bb72 100644 --- a/src/networkfilemanager.cpp +++ b/src/networkfilemanager.cpp @@ -1522,7 +1522,7 @@ struct CurlFileHandle { CurlFileHandle(const CurlFileHandle &) = delete; CurlFileHandle &operator=(const CurlFileHandle &) = delete; - explicit CurlFileHandle(const char *url, CURL *handle); + explicit CurlFileHandle(const char *url, CURL *handle, const char *ca_bundle_path); ~CurlFileHandle(); static PROJ_NETWORK_HANDLE * @@ -1594,7 +1594,7 @@ static std::string GetExecutableName() { // --------------------------------------------------------------------------- -CurlFileHandle::CurlFileHandle(const char *url, CURL *handle) +CurlFileHandle::CurlFileHandle(const char *url, CURL *handle, const char *ca_bundle_path) : m_url(url), m_handle(handle) { curl_easy_setopt(handle, CURLOPT_URL, m_url.c_str()); @@ -1615,6 +1615,23 @@ CurlFileHandle::CurlFileHandle(const char *url, CURL *handle) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L); } + // Custom path to SSL certificates. + if (ca_bundle_path == nullptr) { + ca_bundle_path = getenv("PROJ_CURL_CA_BUNDLE"); + } + if (ca_bundle_path == nullptr) { + // Name of environment variable used by the curl binary + ca_bundle_path = getenv("CURL_CA_BUNDLE"); + } + if (ca_bundle_path == nullptr) { + // Name of environment variable used by the curl binary (tested + // after CURL_CA_BUNDLE + ca_bundle_path = getenv("SSL_CERT_FILE"); + } + if (ca_bundle_path != nullptr) { + curl_easy_setopt(handle, CURLOPT_CAINFO, ca_bundle_path); + } + curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, m_szCurlErrBuf); if (getenv("PROJ_NO_USERAGENT") == nullptr) { @@ -1683,7 +1700,8 @@ PROJ_NETWORK_HANDLE *CurlFileHandle::open(PJ_CONTEXT *ctx, const char *url, return nullptr; auto file = - std::unique_ptr<CurlFileHandle>(new CurlFileHandle(url, hCurlHandle)); + std::unique_ptr<CurlFileHandle>(new CurlFileHandle( + url, hCurlHandle, ctx->ca_bundle_path.empty() ? nullptr : ctx->ca_bundle_path.c_str())); double oldDelay = MIN_RETRY_DELAY_MS; std::string headers; @@ -367,7 +367,7 @@ typedef const char* (*proj_file_finder) (PJ_CONTEXT *ctx, const char*, void* use void PROJ_DLL proj_context_set_file_finder(PJ_CONTEXT *ctx, proj_file_finder finder, void* user_data); void PROJ_DLL proj_context_set_search_paths(PJ_CONTEXT *ctx, int count_paths, const char* const* paths); - +void PROJ_DLL proj_context_set_ca_bundle_path(PJ_CONTEXT *ctx, const char *path); void PROJ_DLL proj_context_use_proj4_init_rules(PJ_CONTEXT *ctx, int enable); int PROJ_DLL proj_context_get_use_proj4_init_rules(PJ_CONTEXT *ctx, int from_legacy_code_path); diff --git a/src/proj_internal.h b/src/proj_internal.h index 738e8ac0..3a0db980 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -725,6 +725,7 @@ struct projCtx_t { struct projCppContext* cpp_context = nullptr; /* internal context for C++ code */ int use_proj4_init_rules = -1; /* -1 = unknown, 0 = no, 1 = yes */ int epsg_file_exists = -1; /* -1 = unknown, 0 = no, 1 = yes */ + std::string ca_bundle_path{}; std::string env_var_proj_lib{}; // content of PROJ_LIB environment variable. Use Filemanager::getProjLibEnvVar() to access std::vector<std::string> search_paths{}; @@ -758,6 +759,7 @@ struct projCtx_t { projCtx_t& operator= (const projCtx_t&) = delete; void set_search_paths(const std::vector<std::string>& search_paths_in); + void set_ca_bundle_path(const std::string& ca_bundle_path_in); static projCtx_t createDefault(); }; diff --git a/src/proj_symbol_rename.h b/src/proj_symbol_rename.h index 24015fb5..cb6fcd23 100644 --- a/src/proj_symbol_rename.h +++ b/src/proj_symbol_rename.h @@ -108,6 +108,7 @@ #define proj_context_guess_wkt_dialect internal_proj_context_guess_wkt_dialect #define proj_context_is_network_enabled internal_proj_context_is_network_enabled #define proj_context_set_autoclose_database internal_proj_context_set_autoclose_database +#define proj_context_set_ca_bundle_path internal_proj_context_set_ca_bundle_path #define proj_context_set_database_path internal_proj_context_set_database_path #define proj_context_set_enable_network internal_proj_context_set_enable_network #define proj_context_set_fileapi internal_proj_context_set_fileapi diff --git a/test/unit/proj_context_test.cpp b/test/unit/proj_context_test.cpp index 4d8df380..979eb2f0 100644 --- a/test/unit/proj_context_test.cpp +++ b/test/unit/proj_context_test.cpp @@ -179,4 +179,14 @@ TEST(proj_context, read_grid_from_user_writable_directory) { MyUnlink(filename); } +// --------------------------------------------------------------------------- + +TEST(proj_context, proj_context_set_ca_bundle_path) { + std::string dirname("/tmp/dummmy/path/cacert.pem"); + auto ctx = proj_context_create(); + proj_context_set_ca_bundle_path(ctx, dirname.c_str()); + ASSERT_EQ(ctx->ca_bundle_path, dirname); + proj_context_destroy(ctx); +} + } // namespace |
