Commit 25eb9299 authored by Viktor Dukhovni's avatar Viktor Dukhovni
Browse files

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: default avatarBernd Edlinger <bernd.edlinger@hotmail.de>
Reviewed-by: default avatarMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7969)
parent 1bfd76b3
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -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);
}
+3 −0
Original line number Diff line number Diff line
@@ -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;
}

+18 −5
Original line number Diff line number Diff line
@@ -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)
+12 −0
Original line number Diff line number Diff line
@@ -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;

+25 −12
Original line number Diff line number Diff line
@@ -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(&register_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;
Loading