More configurable crypto and ssl library initialization
1. In addition to overriding the default application name, one can now also override the configuration file name and flags passed to CONF_modules_load_file(). 2. By default we still keep going when configuration file processing fails. But, applications that want to be strict about initialization errors can now make explicit flag choices via non-null OPENSSL_INIT_SETTINGS that omit the CONF_MFLAGS_IGNORE_RETURN_CODES flag (which had so far been both undocumented and unused). 3. In OPENSSL_init_ssl() do not request OPENSSL_INIT_LOAD_CONFIG if the options already include OPENSSL_INIT_NO_LOAD_CONFIG. 4. Don't set up atexit() handlers when called with opts equal to OPENSSL_INIT_BASE_ONLY (this flag should only be used alone). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7969)
This commit is contained in:
parent
1bfd76b3af
commit
25eb9299ce
11 changed files with 140 additions and 36 deletions
|
@ -358,11 +358,36 @@ OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void)
|
|||
|
||||
if (ret != NULL)
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
ret->flags = DEFAULT_CONF_MFLAGS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings,
|
||||
const char *filename)
|
||||
{
|
||||
char *newfilename = NULL;
|
||||
|
||||
if (filename != NULL) {
|
||||
newfilename = strdup(filename);
|
||||
if (newfilename == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(settings->filename);
|
||||
settings->filename = newfilename;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings,
|
||||
unsigned long flags)
|
||||
{
|
||||
settings->flags = flags;
|
||||
}
|
||||
|
||||
int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings,
|
||||
const char *appname)
|
||||
{
|
||||
|
@ -383,6 +408,7 @@ int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings,
|
|||
|
||||
void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings)
|
||||
{
|
||||
free(settings->filename);
|
||||
free(settings->appname);
|
||||
free(settings);
|
||||
}
|
||||
|
|
|
@ -142,6 +142,9 @@ int CONF_modules_load_file(const char *filename, const char *appname,
|
|||
OPENSSL_free(file);
|
||||
NCONF_free(conf);
|
||||
|
||||
if (flags & CONF_MFLAGS_IGNORE_RETURN_CODES)
|
||||
return 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,10 +39,24 @@ void OPENSSL_config(const char *appname)
|
|||
}
|
||||
#endif
|
||||
|
||||
void openssl_config_int(const char *appname)
|
||||
int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings)
|
||||
{
|
||||
int ret;
|
||||
const char *filename;
|
||||
const char *appname;
|
||||
unsigned long flags;
|
||||
|
||||
if (openssl_configured)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
filename = settings ? settings->filename : NULL;
|
||||
appname = settings ? settings->appname : NULL;
|
||||
flags = settings ? settings->flags : DEFAULT_CONF_MFLAGS;
|
||||
|
||||
#ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: openssl_config_int(%s, %s, %lu)\n",
|
||||
filename, appname, flags);
|
||||
#endif
|
||||
|
||||
OPENSSL_load_builtin_modules();
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
|
@ -51,11 +65,10 @@ void openssl_config_int(const char *appname)
|
|||
#endif
|
||||
ERR_clear_error();
|
||||
#ifndef OPENSSL_SYS_UEFI
|
||||
CONF_modules_load_file(NULL, appname,
|
||||
CONF_MFLAGS_DEFAULT_SECTION |
|
||||
CONF_MFLAGS_IGNORE_MISSING_FILE);
|
||||
ret = CONF_modules_load_file(filename, appname, flags);
|
||||
#endif
|
||||
openssl_configured = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void openssl_no_config_int(void)
|
||||
|
|
|
@ -741,6 +741,18 @@ int err_shelve_state(void **state)
|
|||
{
|
||||
int saveerrno = get_last_sys_error();
|
||||
|
||||
/*
|
||||
* Note, at present our only caller is OPENSSL_init_crypto(), indirectly
|
||||
* via ossl_init_load_crypto_nodelete(), by which point the requested
|
||||
* "base" initialization has already been performed, so the below call is a
|
||||
* NOOP, that re-enters OPENSSL_init_crypto() only to quickly return.
|
||||
*
|
||||
* If are no other valid callers of this function, the call below can be
|
||||
* removed, avoiding the re-entry into OPENSSL_init_crypto(). If there are
|
||||
* potential uses that are not from inside OPENSSL_init_crypto(), then this
|
||||
* call is needed, but some care is required to make sure that the re-entry
|
||||
* remains a NOOP.
|
||||
*/
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -288,17 +288,12 @@ DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests,
|
|||
|
||||
static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT;
|
||||
static int config_inited = 0;
|
||||
static const char *appname;
|
||||
static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
|
||||
DEFINE_RUN_ONCE_STATIC(ossl_init_config)
|
||||
{
|
||||
#ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr,
|
||||
"OPENSSL_INIT: ossl_init_config: openssl_config(%s)\n",
|
||||
appname == NULL ? "NULL" : appname);
|
||||
#endif
|
||||
openssl_config_int(appname);
|
||||
int ret = openssl_config_int(conf_settings);
|
||||
config_inited = 1;
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config)
|
||||
{
|
||||
|
@ -631,9 +626,28 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the
|
||||
* *only* option specified. With that option we return immediately after
|
||||
* doing the requested limited initialization. Note that
|
||||
* err_shelve_state() called by us via ossl_init_load_crypto_nodelete()
|
||||
* re-enters OPENSSL_init_crypto() with OPENSSL_INIT_BASE_ONLY, but with
|
||||
* base already initialized this is a harmless NOOP.
|
||||
*
|
||||
* If we remain the only caller of err_shelve_state() the recursion should
|
||||
* perhaps be removed, but if in doubt, it can be left in place.
|
||||
*/
|
||||
if (!RUN_ONCE(&base, ossl_init_base))
|
||||
return 0;
|
||||
if (opts & OPENSSL_INIT_BASE_ONLY)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Now we don't always set up exit handlers, the INIT_BASE_ONLY calls
|
||||
* should not have the side-effect of setting up exit handlers, and
|
||||
* therefore, this code block is below the INIT_BASE_ONLY-conditioned early
|
||||
* return above.
|
||||
*/
|
||||
if ((opts & OPENSSL_INIT_NO_ATEXIT) != 0) {
|
||||
if (!RUN_ONCE_ALT(®ister_atexit, ossl_init_no_register_atexit,
|
||||
ossl_init_register_atexit))
|
||||
|
@ -642,9 +656,7 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!(opts & OPENSSL_INIT_BASE_ONLY)
|
||||
&& !RUN_ONCE(&load_crypto_nodelete,
|
||||
ossl_init_load_crypto_nodelete))
|
||||
if (!RUN_ONCE(&load_crypto_nodelete, ossl_init_load_crypto_nodelete))
|
||||
return 0;
|
||||
|
||||
if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
|
||||
|
@ -686,8 +698,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
|||
if (opts & OPENSSL_INIT_LOAD_CONFIG) {
|
||||
int ret;
|
||||
CRYPTO_THREAD_write_lock(init_lock);
|
||||
appname = (settings == NULL) ? NULL : settings->appname;
|
||||
conf_settings = settings;
|
||||
ret = RUN_ONCE(&config, ossl_init_config);
|
||||
conf_settings = NULL;
|
||||
CRYPTO_THREAD_unlock(init_lock);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
|
|
@ -28,13 +28,21 @@ reads configuration information from B<cnf>.
|
|||
|
||||
The following B<flags> are currently recognized:
|
||||
|
||||
B<CONF_MFLAGS_IGNORE_ERRORS> if set errors returned by individual
|
||||
If B<CONF_MFLAGS_IGNORE_ERRORS> is set errors returned by individual
|
||||
configuration modules are ignored. If not set the first module error is
|
||||
considered fatal and no further modules are loaded.
|
||||
|
||||
Normally any modules errors will add error information to the error queue. If
|
||||
B<CONF_MFLAGS_SILENT> is set no error information is added.
|
||||
|
||||
If B<CONF_MFLAGS_IGNORE_RETURN_CODES> is set the function unconditionally
|
||||
returns success.
|
||||
This is used by default in L<OPENSSL_init_crypto(3)> to ignore any errors in
|
||||
the default system-wide configuration file, as having all OpenSSL applications
|
||||
fail to start when there are potentially minor issues in the file is too risky.
|
||||
Applications calling B<CONF_modules_load_file> explicitly should not generally
|
||||
set this flag.
|
||||
|
||||
If B<CONF_MFLAGS_NO_DSO> is set configuration module loading from DSOs is
|
||||
disabled.
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
=head1 NAME
|
||||
|
||||
OPENSSL_INIT_new, OPENSSL_INIT_set_config_appname, OPENSSL_INIT_free,
|
||||
OPENSSL_init_crypto, OPENSSL_cleanup,
|
||||
OPENSSL_atexit, OPENSSL_thread_stop - OpenSSL
|
||||
initialisation and deinitialisation functions
|
||||
OPENSSL_INIT_new, OPENSSL_INIT_set_config_filename,
|
||||
OPENSSL_INIT_set_config_appname, OPENSSL_INIT_set_config_file_flags,
|
||||
OPENSSL_INIT_free, OPENSSL_init_crypto, OPENSSL_cleanup, OPENSSL_atexit,
|
||||
OPENSSL_thread_stop - OpenSSL initialisation
|
||||
and deinitialisation functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
@ -17,6 +18,10 @@ initialisation and deinitialisation functions
|
|||
void OPENSSL_thread_stop(void);
|
||||
|
||||
OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void);
|
||||
int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *init,
|
||||
const char* filename);
|
||||
int OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *init,
|
||||
unsigned long flags);
|
||||
int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *init,
|
||||
const char* name);
|
||||
void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *init);
|
||||
|
@ -96,7 +101,7 @@ B<OPENSSL_INIT_ADD_ALL_DIGESTS> will be ignored.
|
|||
|
||||
With this option an OpenSSL configuration file will be automatically loaded and
|
||||
used by calling OPENSSL_config(). This is not a default option for libcrypto.
|
||||
From OpenSSL 1.1.1 this is a default option for libssl (see
|
||||
As of OpenSSL 1.1.1 this is a default option for libssl (see
|
||||
L<OPENSSL_init_ssl(3)> for further details about libssl initialisation). See the
|
||||
description of OPENSSL_INIT_new(), below.
|
||||
|
||||
|
@ -203,12 +208,22 @@ the library when the thread exits. This should only be called directly if
|
|||
resources should be freed at an earlier time, or under the circumstances
|
||||
described in the NOTES section below.
|
||||
|
||||
The B<OPENSSL_INIT_LOAD_CONFIG> flag will load a default configuration
|
||||
file. For optional configuration file settings, an B<OPENSSL_INIT_SETTINGS>
|
||||
must be created and used.
|
||||
The routines OPENSSL_init_new() and OPENSSL_INIT_set_config_appname() can
|
||||
be used to allocate the object and set the application name, and then the
|
||||
object can be released with OPENSSL_INIT_free() when done.
|
||||
The B<OPENSSL_INIT_LOAD_CONFIG> flag will load a configuration file, as with
|
||||
L<CONF_modules_load_file(3)> with NULL filename and application name and the
|
||||
B<CONF_MFLAGS_IGNORE_MISSING_FILE>, B<CONF_MFLAGS_IGNORE_RETURN_CODES> and
|
||||
B<CONF_MFLAGS_DEFAULT_SECTION> flags.
|
||||
The filename, application name, and flags can be customized by providing a
|
||||
non-null B<OPENSSL_INIT_SETTINGS> object.
|
||||
The object can be allocated via B<OPENSSL_init_new()>.
|
||||
The B<OPENSSL_INIT_set_config_filename()> function can be used to specify a
|
||||
non-default filename, which is copied and need not refer to persistent storage.
|
||||
Similarly, OPENSSL_INIT_set_config_appname() can be used to specify a
|
||||
non-default application name.
|
||||
Finally, OPENSSL_INIT_set_file_flags can be used to specify non-default flags.
|
||||
If the B<CONF_MFLAGS_IGNORE_RETURN_CODES> flag is not included, any errors in
|
||||
the configuration file will cause an error return from B<OPENSSL_init_crypto>
|
||||
or indirectly L<OPENSSL_init_ssl(3)>.
|
||||
The object can be released with OPENSSL_INIT_free() when done.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
|
|
|
@ -12,11 +12,18 @@
|
|||
|
||||
#include <openssl/conf.h>
|
||||
|
||||
#define DEFAULT_CONF_MFLAGS \
|
||||
(CONF_MFLAGS_DEFAULT_SECTION | \
|
||||
CONF_MFLAGS_IGNORE_MISSING_FILE | \
|
||||
CONF_MFLAGS_IGNORE_RETURN_CODES)
|
||||
|
||||
struct ossl_init_settings_st {
|
||||
char *filename;
|
||||
char *appname;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
void openssl_config_int(const char *appname);
|
||||
int openssl_config_int(const OPENSSL_INIT_SETTINGS *);
|
||||
void openssl_no_config_int(void);
|
||||
void conf_modules_free_int(void);
|
||||
|
||||
|
|
|
@ -397,8 +397,12 @@ void OPENSSL_thread_stop(void);
|
|||
/* Low-level control of initialization */
|
||||
OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void);
|
||||
# ifndef OPENSSL_NO_STDIO
|
||||
int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings,
|
||||
const char *config_filename);
|
||||
void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings,
|
||||
unsigned long flags);
|
||||
int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings,
|
||||
const char *config_file);
|
||||
const char *config_appname);
|
||||
# endif
|
||||
void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings);
|
||||
|
||||
|
|
|
@ -195,13 +195,14 @@ int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!OPENSSL_init_crypto(opts
|
||||
opts |= OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS;
|
||||
#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
|
||||
| OPENSSL_INIT_LOAD_CONFIG
|
||||
if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) == 0)
|
||||
opts |= OPENSSL_INIT_LOAD_CONFIG;
|
||||
#endif
|
||||
| OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS,
|
||||
settings))
|
||||
|
||||
if (!OPENSSL_init_crypto(opts, settings))
|
||||
return 0;
|
||||
|
||||
if (!RUN_ONCE(&ssl_base, ossl_init_ssl_base))
|
||||
|
|
|
@ -4577,3 +4577,5 @@ OCSP_resp_get0_respdata 4530 1_1_0j EXIST::FUNCTION:OCSP
|
|||
EVP_MD_CTX_set_pkey_ctx 4531 1_1_1 EXIST::FUNCTION:
|
||||
EVP_PKEY_meth_set_digest_custom 4532 1_1_1 EXIST::FUNCTION:
|
||||
EVP_PKEY_meth_get_digest_custom 4533 1_1_1 EXIST::FUNCTION:
|
||||
OPENSSL_INIT_set_config_filename 4534 1_1_1b EXIST::FUNCTION:STDIO
|
||||
OPENSSL_INIT_set_config_file_flags 4535 1_1_1b EXIST::FUNCTION:STDIO
|
||||
|
|
Loading…
Reference in a new issue