diff options
author | Matt Caswell <matt@openssl.org> | 2018-03-30 19:19:56 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2018-04-05 15:30:12 +0100 |
commit | d8f031e890d35887047c35b60347ac385b989065 (patch) | |
tree | ee6c353be64840cf86030b5e5ffca02321310641 /crypto | |
parent | 4845aeba4c49e1bd65259a5014d7e3ab38657d42 (diff) |
Move the loading of the ssl_conf module to libcrypto
The GOST engine needs to be loaded before we initialise libssl. Otherwise
the GOST ciphersuites are not enabled. However the SSL conf module must
be loaded before we initialise libcrypto. Otherwise we will fail to read
the SSL config from a config file properly.
Another problem is that an application may make use of both libcrypto and
libssl. If it performs libcrypto stuff first and OPENSSL_init_crypto()
is called and loads a config file it will fail if that config file has
any libssl stuff in it.
This commit separates out the loading of the SSL conf module from the
interpretation of its contents. The loading piece doesn't know anything
about SSL so this can be moved to libcrypto. The interpretation of what it
means remains in libssl. This means we can load the SSL conf data before
libssl is there and interpret it when it later becomes available.
Fixes #5809
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5818)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/conf/build.info | 2 | ||||
-rw-r--r-- | crypto/conf/conf_err.c | 8 | ||||
-rw-r--r-- | crypto/conf/conf_lcl.h | 11 | ||||
-rw-r--r-- | crypto/conf/conf_mall.c | 2 | ||||
-rw-r--r-- | crypto/conf/conf_ssl.c | 178 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 5 |
6 files changed, 205 insertions, 1 deletions
diff --git a/crypto/conf/build.info b/crypto/conf/build.info index 4438eb4262..ff367994ea 100644 --- a/crypto/conf/build.info +++ b/crypto/conf/build.info @@ -1,4 +1,4 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]= \ conf_err.c conf_lib.c conf_api.c conf_def.c conf_mod.c \ - conf_mall.c conf_sap.c + conf_mall.c conf_sap.c conf_ssl.c diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index ebef728456..01f98da87a 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -36,6 +36,7 @@ static const ERR_STRING_DATA CONF_str_functs[] = { {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_FP, 0), "NCONF_load_fp"}, {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_NEW, 0), "NCONF_new"}, {ERR_PACK(ERR_LIB_CONF, CONF_F_PROCESS_INCLUDE, 0), "process_include"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_SSL_MODULE_INIT, 0), "ssl_module_init"}, {ERR_PACK(ERR_LIB_CONF, CONF_F_STR_COPY, 0), "str_copy"}, {0, NULL} }; @@ -61,6 +62,13 @@ static const ERR_STRING_DATA CONF_str_reasons[] = { {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_VALUE), "no value"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE), "recursive directory include"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_EMPTY), + "ssl command section empty"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_NOT_FOUND), + "ssl command section not found"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_SECTION_EMPTY), "ssl section empty"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_SECTION_NOT_FOUND), + "ssl section not found"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNABLE_TO_CREATE_NEW_SECTION), "unable to create new section"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNKNOWN_MODULE_NAME), diff --git a/crypto/conf/conf_lcl.h b/crypto/conf/conf_lcl.h new file mode 100644 index 0000000000..6e1f7fe00d --- /dev/null +++ b/crypto/conf/conf_lcl.h @@ -0,0 +1,11 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +void conf_add_ssl_module(void); + diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c index 4e7a434e0e..5aab429639 100644 --- a/crypto/conf/conf_mall.c +++ b/crypto/conf/conf_mall.c @@ -14,6 +14,7 @@ #include <openssl/x509.h> #include <openssl/asn1.h> #include <openssl/engine.h> +#include "conf_lcl.h" /* Load all OpenSSL builtin modules */ @@ -26,4 +27,5 @@ void OPENSSL_load_builtin_modules(void) ENGINE_add_conf_module(); #endif EVP_add_alg_module(); + conf_add_ssl_module(); } diff --git a/crypto/conf/conf_ssl.c b/crypto/conf/conf_ssl.c new file mode 100644 index 0000000000..015c46c6da --- /dev/null +++ b/crypto/conf/conf_ssl.c @@ -0,0 +1,178 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <string.h> +#include <openssl/conf.h> +#include <openssl/err.h> +#include "internal/sslconf.h" +#include "conf_lcl.h" + +/* + * SSL library configuration module placeholder. We load it here but defer + * all decisions about its contents to libssl. + */ + +struct ssl_conf_name_st { + /* Name of this set of commands */ + char *name; + /* List of commands */ + SSL_CONF_CMD *cmds; + /* Number of commands */ + size_t cmd_count; +}; + +struct ssl_conf_cmd_st { + /* Command */ + char *cmd; + /* Argument */ + char *arg; +}; + +static struct ssl_conf_name_st *ssl_names; +static size_t ssl_names_count; + +static void ssl_module_free(CONF_IMODULE *md) +{ + size_t i, j; + if (ssl_names == NULL) + return; + for (i = 0; i < ssl_names_count; i++) { + struct ssl_conf_name_st *tname = ssl_names + i; + + OPENSSL_free(tname->name); + for (j = 0; j < tname->cmd_count; j++) { + OPENSSL_free(tname->cmds[j].cmd); + OPENSSL_free(tname->cmds[j].arg); + } + OPENSSL_free(tname->cmds); + } + OPENSSL_free(ssl_names); + ssl_names = NULL; + ssl_names_count = 0; +} + +static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf) +{ + size_t i, j, cnt; + int rv = 0; + const char *ssl_conf_section; + STACK_OF(CONF_VALUE) *cmd_lists; + + ssl_conf_section = CONF_imodule_get_value(md); + cmd_lists = NCONF_get_section(cnf, ssl_conf_section); + if (sk_CONF_VALUE_num(cmd_lists) <= 0) { + if (cmd_lists == NULL) + CONFerr(CONF_F_SSL_MODULE_INIT, CONF_R_SSL_SECTION_NOT_FOUND); + else + CONFerr(CONF_F_SSL_MODULE_INIT, CONF_R_SSL_SECTION_EMPTY); + ERR_add_error_data(2, "section=", ssl_conf_section); + goto err; + } + cnt = sk_CONF_VALUE_num(cmd_lists); + ssl_names = OPENSSL_zalloc(sizeof(*ssl_names) * cnt); + ssl_names_count = cnt; + for (i = 0; i < ssl_names_count; i++) { + struct ssl_conf_name_st *ssl_name = ssl_names + i; + CONF_VALUE *sect = sk_CONF_VALUE_value(cmd_lists, (int)i); + STACK_OF(CONF_VALUE) *cmds = NCONF_get_section(cnf, sect->value); + + if (sk_CONF_VALUE_num(cmds) <= 0) { + if (cmds == NULL) + CONFerr(CONF_F_SSL_MODULE_INIT, + CONF_R_SSL_COMMAND_SECTION_NOT_FOUND); + else + CONFerr(CONF_F_SSL_MODULE_INIT, + CONF_R_SSL_COMMAND_SECTION_EMPTY); + ERR_add_error_data(4, "name=", sect->name, ", value=", sect->value); + goto err; + } + ssl_name->name = OPENSSL_strdup(sect->name); + if (ssl_name->name == NULL) + goto err; + cnt = sk_CONF_VALUE_num(cmds); + ssl_name->cmds = OPENSSL_zalloc(cnt * sizeof(struct ssl_conf_cmd_st)); + if (ssl_name->cmds == NULL) + goto err; + ssl_name->cmd_count = cnt; + for (j = 0; j < cnt; j++) { + const char *name; + CONF_VALUE *cmd_conf = sk_CONF_VALUE_value(cmds, (int)j); + struct ssl_conf_cmd_st *cmd = ssl_name->cmds + j; + + /* Skip any initial dot in name */ + name = strchr(cmd_conf->name, '.'); + if (name != NULL) + name++; + else + name = cmd_conf->name; + cmd->cmd = OPENSSL_strdup(name); + cmd->arg = OPENSSL_strdup(cmd_conf->value); + if (cmd->cmd == NULL || cmd->arg == NULL) + goto err; + } + + } + rv = 1; + err: + if (rv == 0) + ssl_module_free(md); + return rv; +} + +/* + * Returns the set of commands with index |idx| previously searched for via + * conf_ssl_name_find. Also stores the name of the set of commands in |*name| + * and the number of commands in the set in |*cnt|. + */ +const SSL_CONF_CMD *conf_ssl_get(size_t idx, const char **name, size_t *cnt) +{ + *name = ssl_names[idx].name; + *cnt = ssl_names[idx].cmd_count; + return ssl_names[idx].cmds; +} + +/* + * Search for the named set of commands given in |name|. On success return the + * index for the command set in |*idx|. + * Returns 1 on success or 0 on failure. + */ +int conf_ssl_name_find(const char *name, size_t *idx) +{ + size_t i; + const struct ssl_conf_name_st *nm; + + if (name == NULL) + return 0; + for (i = 0, nm = ssl_names; i < ssl_names_count; i++, nm++) { + if (strcmp(nm->name, name) == 0) { + *idx = i; + return 1; + } + } + return 0; +} + +/* + * Given a command set |cmd|, return details on the command at index |idx| which + * must be less than the number of commands in the set (as returned by + * conf_ssl_get). The name of the command will be returned in |*cmdstr| and the + * argument is returned in |*arg|. + */ +void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr, + char **arg) +{ + *cmdstr = cmd[idx].cmd; + *arg = cmd[idx].arg; +} + +void conf_add_ssl_module(void) +{ + CONF_module_add("ssl_conf", ssl_module_init, ssl_module_free); +} diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 0f15dd8d6e..51bd461316 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -335,6 +335,7 @@ CONF_F_NCONF_LOAD_BIO:110:NCONF_load_bio CONF_F_NCONF_LOAD_FP:114:NCONF_load_fp CONF_F_NCONF_NEW:111:NCONF_new CONF_F_PROCESS_INCLUDE:116:process_include +CONF_F_SSL_MODULE_INIT:122:ssl_module_init CONF_F_STR_COPY:101:str_copy CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data @@ -1952,6 +1953,10 @@ CONF_R_NO_SECTION:107:no section CONF_R_NO_SUCH_FILE:114:no such file CONF_R_NO_VALUE:108:no value CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include +CONF_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty +CONF_R_SSL_COMMAND_SECTION_NOT_FOUND:118:ssl command section not found +CONF_R_SSL_SECTION_EMPTY:119:ssl section empty +CONF_R_SSL_SECTION_NOT_FOUND:120:ssl section not found CONF_R_UNABLE_TO_CREATE_NEW_SECTION:103:unable to create new section CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long |