aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2022-02-14 14:16:27 +0100
committerGitHub <noreply@github.com>2022-02-14 14:16:27 +0100
commit4db1dd5471ccc6b714699801cacd1774e8ff9c33 (patch)
treea5a3b9ec15b277c059afa6a3955688670636751e
parent944efc557af4068be7dcf7c44ca9262516e4cc8a (diff)
parent0f4509430517b5fd5f411e4c47e51971cbdafce3 (diff)
downloadPROJ-4db1dd5471ccc6b714699801cacd1774e8ff9c33.tar.gz
PROJ-4db1dd5471ccc6b714699801cacd1774e8ff9c33.zip
Merge pull request #3049 from rouault/proj_ini_ca_bundle_path
proj.ini: add a 'ca_bundle_path' variable
-rw-r--r--data/proj.ini5
-rw-r--r--docs/source/resource_files.rst5
-rw-r--r--src/ctx.cpp2
-rw-r--r--src/filemanager.cpp40
-rw-r--r--src/malloc.cpp4
-rw-r--r--src/networkfilemanager.cpp49
-rw-r--r--src/proj_internal.h3
-rw-r--r--test/unit/test_network.cpp3
8 files changed, 64 insertions, 47 deletions
diff --git a/data/proj.ini b/data/proj.ini
index 067f0170..2353adb8 100644
--- a/data/proj.ini
+++ b/data/proj.ini
@@ -15,6 +15,11 @@ cache_size_MB = 300
cache_ttl_sec = 86400
+; Filename of the Certificate Authority (CA) bundle.
+; Can be overriden with the PROJ_CURL_CA_BUNDLE / CURL_CA_BUNDLE environment variable.
+; (added in PROJ 9.0)
+; ca_bundle_path = /path/to/cabundle.pem
+
; Transverse Mercator (and UTM) default algorithm: auto, evenden_snyder or poder_engsager
; * evenden_snyder is the fastest, but less accurate far from central meridian
; * poder_engsager is slower, but more accurate far from central meridian
diff --git a/docs/source/resource_files.rst b/docs/source/resource_files.rst
index 54c812f2..966c3f1a 100644
--- a/docs/source/resource_files.rst
+++ b/docs/source/resource_files.rst
@@ -114,6 +114,11 @@ Its default content is:
cache_ttl_sec = 86400
+ ; Filename of the Certificate Authority (CA) bundle.
+ ; Can be overriden with the PROJ_CURL_CA_BUNDLE / CURL_CA_BUNDLE environment variable.
+ ; (added in PROJ 9.0)
+ ; ca_bundle_path = /path/to/cabundle.pem
+
; Transverse Mercator (and UTM) default algorithm: auto, evenden_snyder or poder_engsager
; * evenden_snyder is the fastest, but less accurate far from central meridian
; * poder_engsager is slower, but more accurate far from central meridian
diff --git a/src/ctx.cpp b/src/ctx.cpp
index 5ec10b9e..5b2405cd 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -153,7 +153,6 @@ pj_ctx::pj_ctx(const pj_ctx& other) :
cpp_context(other.cpp_context ? other.cpp_context->clone(this) : nullptr),
use_proj4_init_rules(other.use_proj4_init_rules),
epsg_file_exists(other.epsg_file_exists),
- ca_bundle_path(other.ca_bundle_path),
env_var_proj_lib(other.env_var_proj_lib),
file_finder(other.file_finder),
file_finder_user_data(other.file_finder_user_data),
@@ -163,6 +162,7 @@ pj_ctx::pj_ctx(const pj_ctx& other) :
iniFileLoaded(other.iniFileLoaded),
endpoint(other.endpoint),
networking(other.networking),
+ ca_bundle_path(other.ca_bundle_path),
gridChunkCache(other.gridChunkCache),
defaultTmercAlgo(other.defaultTmercAlgo)
// END ini file settings
diff --git a/src/filemanager.cpp b/src/filemanager.cpp
index 5bc99bc5..97fedaa2 100644
--- a/src/filemanager.cpp
+++ b/src/filemanager.cpp
@@ -1789,11 +1789,37 @@ void pj_load_ini(PJ_CONTEXT *ctx) {
if (ctx->iniFileLoaded)
return;
+ // Start reading environment variables that have priority over the
+ // .ini file
+ const char *proj_network = getenv("PROJ_NETWORK");
+ if (proj_network && proj_network[0] != '\0') {
+ ctx->networking.enabled = ci_equal(proj_network, "ON") ||
+ ci_equal(proj_network, "YES") ||
+ ci_equal(proj_network, "TRUE");
+ } else {
+ proj_network = nullptr;
+ }
+
const char *endpoint_from_env = getenv("PROJ_NETWORK_ENDPOINT");
if (endpoint_from_env && endpoint_from_env[0] != '\0') {
ctx->endpoint = endpoint_from_env;
}
+ // Custom path to SSL certificates.
+ const char *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) {
+ ctx->ca_bundle_path = ca_bundle_path;
+ }
+
ctx->iniFileLoaded = true;
auto file = std::unique_ptr<NS_PROJ::File>(
reinterpret_cast<NS_PROJ::File *>(pj_open_lib_internal(
@@ -1825,13 +1851,10 @@ void pj_load_ini(PJ_CONTEXT *ctx) {
trim(content.substr(equal + 1, eol - (equal + 1)));
if (ctx->endpoint.empty() && key == "cdn_endpoint") {
ctx->endpoint = value;
- } else if (key == "network") {
- const char *enabled = getenv("PROJ_NETWORK");
- if (enabled == nullptr || enabled[0] == '\0') {
- ctx->networking.enabled = ci_equal(value, "ON") ||
- ci_equal(value, "YES") ||
- ci_equal(value, "TRUE");
- }
+ } else if (proj_network == nullptr && key == "network") {
+ ctx->networking.enabled = ci_equal(value, "ON") ||
+ ci_equal(value, "YES") ||
+ ci_equal(value, "TRUE");
} else if (key == "cache_enabled") {
ctx->gridChunkCache.enabled = ci_equal(value, "ON") ||
ci_equal(value, "YES") ||
@@ -1854,6 +1877,8 @@ void pj_load_ini(PJ_CONTEXT *ctx) {
ctx, PJ_LOG_ERROR,
"pj_load_ini(): Invalid value for tmerc_default_algo");
}
+ } else if (ca_bundle_path == nullptr && key == "ca_bundle_path") {
+ ctx->ca_bundle_path = value;
}
}
@@ -1957,6 +1982,7 @@ void proj_context_set_ca_bundle_path(PJ_CONTEXT *ctx, const char *path) {
ctx = pj_get_default_ctx();
if (!ctx)
return;
+ pj_load_ini(ctx);
try {
ctx->set_ca_bundle_path(path != nullptr ? path : "");
} catch (const std::exception &) {
diff --git a/src/malloc.cpp b/src/malloc.cpp
index d60a3f92..df47d64e 100644
--- a/src/malloc.cpp
+++ b/src/malloc.cpp
@@ -183,7 +183,9 @@ void proj_cleanup() {
/*****************************************************************************/
// Close the database context of the default PJ_CONTEXT
- auto cpp_context = pj_get_default_ctx()->cpp_context;
+ auto ctx = pj_get_default_ctx();
+ ctx->iniFileLoaded = false;
+ auto cpp_context = ctx->cpp_context;
if( cpp_context ) {
cpp_context->closeDb();
}
diff --git a/src/networkfilemanager.cpp b/src/networkfilemanager.cpp
index 727c7308..8427be9f 100644
--- a/src/networkfilemanager.cpp
+++ b/src/networkfilemanager.cpp
@@ -1513,8 +1513,7 @@ struct CurlFileHandle {
CurlFileHandle(const CurlFileHandle &) = delete;
CurlFileHandle &operator=(const CurlFileHandle &) = delete;
- explicit CurlFileHandle(PJ_CONTEXT *ctx, const char *url, CURL *handle,
- const char *ca_bundle_path);
+ explicit CurlFileHandle(PJ_CONTEXT *ctx, const char *url, CURL *handle);
~CurlFileHandle();
static PROJ_NETWORK_HANDLE *
@@ -1596,8 +1595,14 @@ static void checkRet(PJ_CONTEXT *ctx, CURLcode code, int line) {
// ---------------------------------------------------------------------------
-CurlFileHandle::CurlFileHandle(PJ_CONTEXT *ctx, const char *url, CURL *handle,
- const char *ca_bundle_path)
+static std::string pj_context_get_bundle_path(PJ_CONTEXT *ctx) {
+ pj_load_ini(ctx);
+ return ctx->ca_bundle_path;
+}
+
+// ---------------------------------------------------------------------------
+
+CurlFileHandle::CurlFileHandle(PJ_CONTEXT *ctx, const char *url, CURL *handle)
: m_url(url), m_handle(handle) {
CHECK_RET(ctx, curl_easy_setopt(handle, CURLOPT_URL, m_url.c_str()));
@@ -1619,22 +1624,10 @@ CurlFileHandle::CurlFileHandle(PJ_CONTEXT *ctx, const char *url, CURL *handle,
CHECK_RET(ctx, 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) {
- CHECK_RET(ctx,
- curl_easy_setopt(handle, CURLOPT_CAINFO, ca_bundle_path));
+ const auto ca_bundle_path = pj_context_get_bundle_path(ctx);
+ if (!ca_bundle_path.empty()) {
+ CHECK_RET(ctx, curl_easy_setopt(handle, CURLOPT_CAINFO,
+ ca_bundle_path.c_str()));
}
CHECK_RET(ctx,
@@ -1706,9 +1699,8 @@ PROJ_NETWORK_HANDLE *CurlFileHandle::open(PJ_CONTEXT *ctx, const char *url,
if (!hCurlHandle)
return nullptr;
- auto file = std::unique_ptr<CurlFileHandle>(new CurlFileHandle(
- ctx, url, hCurlHandle,
- ctx->ca_bundle_path.empty() ? nullptr : ctx->ca_bundle_path.c_str()));
+ auto file = std::unique_ptr<CurlFileHandle>(
+ new CurlFileHandle(ctx, url, hCurlHandle));
double oldDelay = MIN_RETRY_DELAY_MS;
std::string headers;
@@ -2046,7 +2038,6 @@ int proj_context_set_enable_network(PJ_CONTEXT *ctx, int enable) {
}
// Load ini file, now so as to override its network settings
pj_load_ini(ctx);
- ctx->networking.enabled_env_variable_checked = true;
ctx->networking.enabled = enable != FALSE;
#ifdef CURL_ENABLED
return ctx->networking.enabled;
@@ -2068,17 +2059,7 @@ int proj_context_is_network_enabled(PJ_CONTEXT *ctx) {
if (ctx == nullptr) {
ctx = pj_get_default_ctx();
}
- if (ctx->networking.enabled_env_variable_checked) {
- return ctx->networking.enabled;
- }
- const char *enabled = getenv("PROJ_NETWORK");
- if (enabled && enabled[0] != '\0') {
- ctx->networking.enabled = ci_equal(enabled, "ON") ||
- ci_equal(enabled, "YES") ||
- ci_equal(enabled, "TRUE");
- }
pj_load_ini(ctx);
- ctx->networking.enabled_env_variable_checked = true;
return ctx->networking.enabled;
}
diff --git a/src/proj_internal.h b/src/proj_internal.h
index 0ae90cf6..dd478932 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -644,7 +644,6 @@ struct projCppContext;
struct projNetworkCallbacksAndData
{
bool enabled = false;
- bool enabled_env_variable_checked = false; // whereas we have checked PROJ_NETWORK env variable
proj_network_open_cbk_type open = nullptr;
proj_network_close_cbk_type close = nullptr;
proj_network_get_header_value_cbk_type get_header_value = nullptr;
@@ -688,7 +687,6 @@ struct pj_ctx{
int use_proj4_init_rules = -1; /* -1 = unknown, 0 = no, 1 = yes */
bool forceOver = false;
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{};
@@ -708,6 +706,7 @@ struct pj_ctx{
bool iniFileLoaded = false;
std::string endpoint{};
projNetworkCallbacksAndData networking{};
+ std::string ca_bundle_path{};
projGridChunkCache gridChunkCache{};
TMercAlgo defaultTmercAlgo = TMercAlgo::PODER_ENGSAGER; // can be overridden by content of proj.ini
// END ini file settings
diff --git a/test/unit/test_network.cpp b/test/unit/test_network.cpp
index fcafdf07..f8b70ae8 100644
--- a/test/unit/test_network.cpp
+++ b/test/unit/test_network.cpp
@@ -131,9 +131,8 @@ TEST(networking, basic) {
#ifdef CURL_ENABLED
// enable through env variable
- ctx = proj_context_create();
- proj_grid_cache_set_enable(ctx, false);
putenv(const_cast<char *>("PROJ_NETWORK=ON"));
+ ctx = proj_context_create();
P = proj_create(ctx, pipeline);
if (networkAccessOK) {
ASSERT_NE(P, nullptr);