Allow OPENSSLDIR/ENGINESDIR/MODULESDIR to be NULL

To prevent inadvertent use of insecure directories, we need to be able
to detect and react when our new registry keys aren't set, which implies
allowing the values for the dynamic representations of
OPENSSLDIR/ENGINESDIR/MODULESDIR to return NULL.  This in turn requires
that we detect and handle NULL string in several call sites that
previously assumed they would never be NULL.  This commit fixes those up

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24450)
This commit is contained in:
Neil Horman 2024-06-25 10:57:52 -04:00
parent c7dae9c263
commit 917f37195a
9 changed files with 99 additions and 66 deletions

View File

@ -99,36 +99,12 @@ check the INSTALL.md file.
Installation directories
------------------------
The default installation directories are derived from environment
variables.
On most Unix platform installation directories are determined at build time via
constant defines. On Windows platforms however, installation directories are
determined via registry keys, as it is common practice to build OpenSSL and
install it to a variety of locations.
For VC-WIN32, the following defaults are use:
PREFIX: %ProgramFiles(x86)%\OpenSSL
OPENSSLDIR: %CommonProgramFiles(x86)%\SSL
For VC-WIN64, the following defaults are use:
PREFIX: %ProgramW6432%\OpenSSL
OPENSSLDIR: %CommonProgramW6432%\SSL
Should those environment variables not exist (on a pure Win32
installation for examples), these fallbacks are used:
PREFIX: %ProgramFiles%\OpenSSL
OPENSSLDIR: %CommonProgramFiles%\SSL
ALSO NOTE that those directories are usually write protected, even if
your account is in the Administrators group. To work around that,
start the command prompt by right-clicking on it and choosing "Run as
Administrator" before running `nmake install`. The other solution
is, of course, to choose a different set of directories by using
`--prefix` and `--openssldir` when configuring.
Note that, on Windows platforms (both 32 and 64 bit), the above build-time
defaults can be overridden by registry keys. This is done because it is common
practice for windows-based installers to allow users to place the installation
tree at an arbitrary location not defined at build-time. The following keys:
The following keys:
`\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL-<version>-<ctx>\OPENSSLDIR`
`\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL-<version>-<ctx>\ENGINESDIR`
@ -142,6 +118,7 @@ To enable the reading of registry keys from windows builds, add
at build-time to construct library build specific registry key paths of the
format:
`\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432node\OpenSSL-<version>-<ctx>`
Where `<version>` is the semantic major.minor.patch version of the library being
built, and `<ctx>` is the value specified by `-DOPENSSL_WINCTX`. This allows
for multiple openssl builds to be created and installed on a single system, in
@ -150,6 +127,10 @@ which each library can use its own set of registry keys.
Note the installer available at <https://github.com/openssl/installer> will set
these keys when the installer is run.
If the registry keys above do not exist on a given system, or if the
`OSSL_WINCTX` variable is not defined at build time, OpenSSL makes no attempt to
load configuration, engines of modules from disk.
Special notes for Universal Windows Platform builds, aka `VC-*-UWP`
-------------------------------------------------------------------

View File

@ -40,6 +40,7 @@ int info_main(int argc, char **argv)
int ret = 1, dirty = 0, type = 0;
char *prog;
OPTION_CHOICE o;
const char *typedata;
prog = opt_init(argc, argv, info_options);
while ((o = opt_next()) != OPT_EOF) {
@ -97,7 +98,8 @@ opthelp:
goto opthelp;
}
BIO_printf(bio_out, "%s\n", OPENSSL_info(type));
typedata = OPENSSL_info(type);
BIO_printf(bio_out, "%s\n", typedata == NULL ? "Undefined" : typedata);
ret = 0;
end:
return ret;

View File

@ -48,6 +48,7 @@ int version_main(int argc, char **argv)
int engdir = 0, moddir = 0, cpuinfo = 0, windows = 0;
char *prog;
OPTION_CHOICE o;
const char *tmp;
prog = opt_init(argc, argv, version_options);
while ((o = opt_next()) != OPT_EOF) {
@ -123,12 +124,18 @@ opthelp:
}
if (cflags)
printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS));
if (dir)
printf("OPENSSLDIR: %s\n", OpenSSL_version(OPENSSL_DIR));
if (engdir)
printf("ENGINESDIR: %s\n", OpenSSL_version(OPENSSL_ENGINES_DIR));
if (moddir)
printf("MODULESDIR: %s\n", OpenSSL_version(OPENSSL_MODULES_DIR));
if (dir) {
tmp = OpenSSL_version(OPENSSL_DIR);
printf("OPENSSLDIR: %s\n", tmp == NULL ? "Undefined" : tmp);
}
if (engdir) {
tmp = OpenSSL_version(OPENSSL_ENGINES_DIR);
printf("ENGINESDIR: %s\n", tmp == NULL ? "Undefined" : tmp);
}
if (moddir) {
tmp = OpenSSL_version(OPENSSL_MODULES_DIR);
printf("MODULESDIR: %s\n", tmp == NULL ? "Undefined" : tmp);
}
if (seed) {
const char *src = OPENSSL_info(OPENSSL_INFO_SEED_SOURCE);
printf("Seeding source: %s\n", src ? src : "N/A");
@ -136,7 +143,7 @@ opthelp:
if (cpuinfo)
printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO));
if (windows)
printf("OSSL_WINCTX: %s\n", OpenSSL_version(OPENSSL_WINCTX));
printf("OSSL_WINCTX: %s\n", OpenSSL_version(OPENSSL_WINCTX));
ret = 0;
end:
return ret;

View File

@ -692,6 +692,8 @@ char *CONF_get1_default_config_file(void)
return OPENSSL_strdup(file);
t = X509_get_default_cert_area();
if (t == NULL)
return NULL;
#ifndef OPENSSL_SYS_VMS
sep = "/";
#endif

View File

@ -71,7 +71,7 @@ const char *OpenSSL_version(int t)
else
return "CPUINFO: N/A";
case OPENSSL_WINCTX:
return ossl_get_wininstallcontext();
return ossl_get_wininstallcontext();
}
return "not available";
}

View File

@ -20,8 +20,6 @@
# define NOQUOTE(x) x
#if defined(OSSL_WINCTX)
# define REGISTRY_KEY "SOFTWARE\\WOW6432Node\\OpenSSL" ##"-"## NOQUOTE(OPENSSL_VERSION_STR) ##"-"## MAKESTR(OSSL_WINCTX)
#else
# define REGISTRY_KEY "NONE"
#endif
/**
@ -29,17 +27,32 @@
*/
static char openssldir[MAX_PATH + 1];
/**
* @brief The pointer to the opennsldir buffer
*/
static char *openssldirptr = NULL;
/**
* @brief The directory where OpenSSL engines are located.
*/
static char enginesdir[MAX_PATH + 1];
/**
* @brief The pointer to the enginesdir buffer
*/
static char *enginesdirptr = NULL;
/**
* @brief The directory where OpenSSL modules are located.
*/
static char modulesdir[MAX_PATH + 1];
/**
* @brief The pointer to the modulesdir buffer
*/
static char *modulesdirptr = NULL;
/**
* @brief Get the list of Windows registry directories.
*
@ -49,14 +62,15 @@ static char modulesdir[MAX_PATH + 1];
*/
static char *get_windows_regdirs(char *dst, LPCTSTR valuename)
{
char *retval = NULL;
#ifdef REGISTY_KEY
DWORD keysize;
DWORD ktype;
HKEY hkey;
LSTATUS ret;
DWORD index = 0;
LPCTCH tempstr = NULL;
char *retval = NULL;
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT(REGISTRY_KEY), KEY_WOW64_32KEY,
KEY_QUERY_VALUE, &hkey);
@ -90,6 +104,7 @@ static char *get_windows_regdirs(char *dst, LPCTSTR valuename)
out:
OPENSSL_free(tempstr);
RegCloseKey(hkey);
#endif
return retval;
}
@ -105,6 +120,19 @@ DEFINE_RUN_ONCE_STATIC(do_defaults_setup)
get_windows_regdirs(openssldir, TEXT("OPENSSLDIR"));
get_windows_regdirs(enginesdir, TEXT("ENGINESDIR"));
get_windows_regdirs(modulesdir, TEXT("MODULESDIR"));
/*
* Set our pointers only if the directories are fetched properly
*/
if (strlen(openssldir) > 0)
openssldirptr = openssldir;
if (strlen(enginesdir) > 0)
enginesdirptr = enginesdir;
if (strlen(modulesdir) > 0)
modulesdirptr = modulesdir;
return 1;
}
#endif
@ -116,12 +144,10 @@ DEFINE_RUN_ONCE_STATIC(do_defaults_setup)
*/
const char *ossl_get_openssldir(void)
{
#if defined(_WIN32)
# if defined(OSSL_WINCTX)
#if defined(_WIN32) && defined (OSSL_WINCTX)
if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup))
return NULL;
return (const char *)openssldir;
# endif
return (const char *)openssldirptr;
# else
return OPENSSLDIR;
#endif
@ -134,14 +160,10 @@ const char *ossl_get_openssldir(void)
*/
const char *ossl_get_enginesdir(void)
{
#if defined(_WIN32)
# if defined(OSSL_WINCTX)
#if defined(_WIN32) && defined (OSSL_WINCTX)
if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup))
return NULL;
return (const char *)enginesdir;
# else
return "UNDEFINED";
# endif
return (const char *)enginesdirptr;
#else
return ENGINESDIR;
#endif
@ -154,14 +176,10 @@ const char *ossl_get_enginesdir(void)
*/
const char *ossl_get_modulesdir(void)
{
#if defined(_WIN32)
# if defined (OSSL_WINCTX)
#if defined(_WIN32) && defined(OSSL_WINCTX)
if (!RUN_ONCE(&defaults_setup_init, do_defaults_setup))
return NULL;
return (const char *)modulesdir;
# else
return "UNDEFINED";
# endif
return (const char *)modulesdirptr;
#else
return MODULESDIR;
#endif
@ -175,8 +193,8 @@ const char *ossl_get_modulesdir(void)
const char *ossl_get_wininstallcontext(void)
{
#if defined(_WIN32) && defined (OSSL_WINCTX)
return MAKESTR(OSSL_WINCTX);
return MAKESTR(OSSL_WINCTX);
#else
return "UNDEFINED";
return "Undefined";
#endif
}

View File

@ -38,6 +38,9 @@
FILE *openssl_fopen(const char *filename, const char *mode)
{
FILE *file = NULL;
if (filename == NULL)
return NULL;
# if defined(_WIN32) && defined(CP_UTF8)
int sz, len_0 = (int)strlen(filename) + 1;
DWORD flags;

View File

@ -17,9 +17,16 @@
#if defined(_WIN32)
static char x509_private_dir[MAX_PATH + 1];
static char *x509_private_dirptr = NULL;
static char x509_cert_area[MAX_PATH + 1];
static char *x509_cert_areaptr = NULL;
static char x509_cert_dir[MAX_PATH + 1];
static char *x509_cert_dirptr = NULL;
static char x509_cert_file[MAX_PATH + 1];
static char *x509_cert_fileptr = NULL;
static void get_windows_default_path(char *pathname, const char *suffix)
{
@ -27,6 +34,9 @@ static void get_windows_default_path(char *pathname, const char *suffix)
ossldir = ossl_get_openssldir();
if (ossldir == NULL)
return;
OPENSSL_strlcpy(pathname, ossldir, MAX_PATH - 1);
if (MAX_PATH - strlen(pathname) > strlen(suffix))
strcat(pathname, suffix);
@ -36,9 +46,21 @@ static CRYPTO_ONCE openssldir_setup_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_openssldir_setup)
{
get_windows_default_path(x509_private_dir, "\\private");
if (strlen(x509_private_dir) > 0)
x509_private_dirptr = x509_private_dir;
get_windows_default_path(x509_cert_area, "\\");
if (strlen(x509_cert_area) > 0)
x509_cert_areaptr = x509_cert_area;
get_windows_default_path(x509_cert_dir, "\\certs");
if (strlen(x509_cert_dir) > 0)
x509_cert_dirptr = x509_cert_dir;
get_windows_default_path(x509_cert_file, "\\cert.pem");
if (strlen(x509_cert_file) > 0)
x509_cert_fileptr = x509_cert_file;
return 1;
}
#endif
@ -47,7 +69,7 @@ const char *X509_get_default_private_dir(void)
{
#if defined (_WIN32)
RUN_ONCE(&openssldir_setup_init, do_openssldir_setup);
return x509_private_dir;
return x509_private_dirptr;
#else
return X509_PRIVATE_DIR;
#endif
@ -57,7 +79,7 @@ const char *X509_get_default_cert_area(void)
{
#if defined (_WIN32)
RUN_ONCE(&openssldir_setup_init, do_openssldir_setup);
return x509_cert_area;
return x509_cert_areaptr;
#else
return X509_CERT_AREA;
#endif
@ -67,7 +89,7 @@ const char *X509_get_default_cert_dir(void)
{
#if defined (_WIN32)
RUN_ONCE(&openssldir_setup_init, do_openssldir_setup);
return x509_cert_dir;
return x509_cert_dirptr;
#else
return X509_CERT_DIR;
#endif
@ -77,7 +99,7 @@ const char *X509_get_default_cert_file(void)
{
#if defined (_WIN32)
RUN_ONCE(&openssldir_setup_init, do_openssldir_setup);
return x509_cert_file;
return x509_cert_fileptr;
#else
return X509_CERT_FILE;
#endif

View File

@ -81,5 +81,3 @@ $expect =~ s/.*REG_EXPAND_SZ *//;
$expect =~ s/ .*$//;
$actual =~ s/MODULESSDIR: *//;
ok(grep(/$expect/, $actual) == 1, "Confirming version output for modulesdir from registry");