Fix #102300: SSL/HTTPS Request Unable to Get Local Issuer Certificate
Resolve an error with SSL using a hard coded path to certificates on Linux causing HTTPS access to fail. request.urlopen(..) couldn't access any HTTPS URL's.
This commit is contained in:
@@ -59,6 +59,13 @@ macro(path_ensure_trailing_slash
|
||||
unset(_path_sep)
|
||||
endmacro()
|
||||
|
||||
macro(path_strip_trailing_slash
|
||||
path_new path_input
|
||||
)
|
||||
file(TO_NATIVE_PATH "/" _path_sep)
|
||||
string(REGEX REPLACE "[${_path_sep}]+$" "" ${path_new} ${path_input})
|
||||
endmacro()
|
||||
|
||||
# Our own version of `cmake_path(IS_PREFIX ..)`.
|
||||
# This can be removed when 3.20 or greater is the minimum supported version.
|
||||
macro(path_is_prefix
|
||||
@@ -1404,6 +1411,68 @@ Path to python site-packages or dist-packages containing '${package}' module hea
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Find a file in Python's module path and cache it.
|
||||
# Re-generating cache upon changes to the Python installation.
|
||||
# `out_var_abs`: absolute path (cached).
|
||||
# `out_var_rel`: `PYTHON_ROOT` relative path (not cached).
|
||||
macro(find_python_module_file
|
||||
module_file
|
||||
out_var_abs
|
||||
out_var_rel
|
||||
)
|
||||
|
||||
# Reset if the file isn't found.
|
||||
if(DEFINED ${out_var_abs})
|
||||
if(NOT EXISTS ${${out_var_abs}})
|
||||
unset(${out_var_abs} CACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Reset if the version number or Python path changes.
|
||||
set(_python_mod_file_deps_test "${PYTHON_LIBPATH};${PYTHON_VERSION}")
|
||||
if(DEFINED _${out_var_abs}_DEPS)
|
||||
if(NOT (_${out_var_abs}_DEPS STREQUAL _python_mod_file_deps_test))
|
||||
unset(${out_var_abs} CACHE)
|
||||
endif()
|
||||
else()
|
||||
unset(${out_var_abs} CACHE)
|
||||
endif()
|
||||
|
||||
path_strip_trailing_slash(_python_root "${PYTHON_LIBPATH}")
|
||||
set(_python_base "${_python_root}/python${PYTHON_VERSION}")
|
||||
get_filename_component(_python_root "${_python_root}" DIRECTORY)
|
||||
path_ensure_trailing_slash(_python_root "${_python_root}")
|
||||
|
||||
if(NOT (DEFINED ${out_var_abs}))
|
||||
message(STATUS "Finding Python Module File: ${module_file}")
|
||||
find_file(${out_var_abs}
|
||||
NAMES
|
||||
"${module_file}"
|
||||
PATHS
|
||||
"${_python_base}"
|
||||
PATH_SUFFIXES
|
||||
"site-packages"
|
||||
"dist-packages"
|
||||
"vendor-packages"
|
||||
""
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(${out_var_abs})
|
||||
set(_${out_var_abs}_DEPS "${_python_mod_file_deps_test}" CACHE STRING "")
|
||||
|
||||
# This always moves up one level (even if there is a trailing slash).
|
||||
string(LENGTH "${_python_root}" _python_root_len)
|
||||
string(SUBSTRING ${${out_var_abs}} ${_python_root_len} -1 ${out_var_rel})
|
||||
unset(_python_root_len)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
unset(_python_mod_file_deps_test)
|
||||
unset(_python_base)
|
||||
unset(_python_root)
|
||||
endmacro()
|
||||
|
||||
|
||||
# like Python's 'print(dir())'
|
||||
function(print_all_vars)
|
||||
get_cmake_property(_vars VARIABLES)
|
||||
|
||||
@@ -141,6 +141,28 @@ if(WITH_PYTHON_MODULE)
|
||||
add_definitions(-DWITH_PYTHON_MODULE)
|
||||
endif()
|
||||
|
||||
|
||||
# Find the SSL certificate for the portable Blender installation.
|
||||
# Without this, the absolute path on the builder is used, causing HTTPS access to fail.
|
||||
# For example `urllib.request.urlopen("https://projects.blender.org")` fails
|
||||
# (or any other HTTPS site). see: #102300 for details.
|
||||
# NOTE: that this isn't necessary on WIN32.
|
||||
if(WITH_PYTHON AND WITH_PYTHON_INSTALL AND WITH_INSTALL_PORTABLE AND (NOT WIN32))
|
||||
# - `PYTHON_SSL_CERT_FILE` absolute path to the PEM file.
|
||||
find_python_module_file("certifi/cacert.pem" PYTHON_SSL_CERT_FILE _python_ssl_cert_file_relative)
|
||||
mark_as_advanced(PYTHON_SSL_CERT_FILE)
|
||||
if (PYTHON_SSL_CERT_FILE)
|
||||
# This always moves up one level (even if there is a trailing slash).
|
||||
add_definitions(-DPYTHON_SSL_CERT_FILE="${_python_ssl_cert_file_relative}")
|
||||
else()
|
||||
message(WARNING
|
||||
"Unable to find \"certifi/cacert.pem\" within \"${PYTHON_LIBPATH}\", "
|
||||
"this build will not be able to use bundled certificates with the \"ssl\" module!"
|
||||
)
|
||||
endif()
|
||||
unset(_python_ssl_cert_file_relative)
|
||||
endif()
|
||||
|
||||
if(WITH_PYTHON_SAFETY)
|
||||
add_definitions(-DWITH_PYTHON_SAFETY)
|
||||
endif()
|
||||
|
||||
@@ -450,6 +450,18 @@ void BPY_python_start(bContext *C, int argc, const char **argv)
|
||||
|
||||
status = PyConfig_SetBytesString(&config, &config.home, py_path_bundle);
|
||||
pystatus_exit_on_error(status);
|
||||
|
||||
# ifdef PYTHON_SSL_CERT_FILE
|
||||
/* Point to the portable SSL certificate to support HTTPS access, see: #102300. */
|
||||
const char *ssl_cert_file_env = "SSL_CERT_FILE";
|
||||
if (BLI_getenv(ssl_cert_file_env) == nullptr) {
|
||||
const char *ssl_cert_file_suffix = PYTHON_SSL_CERT_FILE;
|
||||
char ssl_cert_file[FILE_MAX];
|
||||
BLI_path_join(
|
||||
ssl_cert_file, sizeof(ssl_cert_file), py_path_bundle, ssl_cert_file_suffix);
|
||||
BLI_setenv(ssl_cert_file_env, ssl_cert_file);
|
||||
}
|
||||
# endif /* PYTHON_SSL_CERT_FILE */
|
||||
}
|
||||
else {
|
||||
/* Common enough to use the system Python on Linux/Unix, warn on other systems. */
|
||||
|
||||
Reference in New Issue
Block a user