aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/usage/environmentvars.rst8
-rw-r--r--scripts/reference_exported_symbols.txt1
-rw-r--r--src/ctx.cpp10
-rw-r--r--src/filemanager.cpp31
-rw-r--r--src/networkfilemanager.cpp24
-rw-r--r--src/proj.h2
-rw-r--r--src/proj_internal.h2
-rw-r--r--src/proj_symbol_rename.h1
-rw-r--r--test/unit/proj_context_test.cpp10
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;
diff --git a/src/proj.h b/src/proj.h
index 550d422d..512dcd84 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -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