From eb45409e35df2fa610aeab0cb867615dc5b12617 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 23 Mar 2021 08:54:20 +0100 Subject: [PATCH] tls: added ca_path config option - used to provide path to directory with CA files in pem format, to be given as parameter to SSL_CTX_load_verify_locations() - GH #2682 --- src/modules/tls/tls_cfg.c | 9 +++++++-- src/modules/tls/tls_cfg.h | 1 + src/modules/tls/tls_config.c | 2 ++ src/modules/tls/tls_domain.c | 38 ++++++++++++++++++++++++------------ src/modules/tls/tls_domain.h | 1 + src/modules/tls/tls_mod.c | 6 +++++- 6 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/modules/tls/tls_cfg.c b/src/modules/tls/tls_cfg.c index a79d7f718aa..e7d54e8b24b 100644 --- a/src/modules/tls/tls_cfg.c +++ b/src/modules/tls/tls_cfg.c @@ -44,6 +44,7 @@ struct cfg_group_tls default_tls_cfg = { STR_STATIC_INIT("off"), /* verify_client */ STR_NULL, /* private_key (default value set in fix_tls_cfg) */ STR_NULL, /* ca_list (default value set in fix_tls_cfg) */ + STR_NULL, /* ca_path (default value set in fix_tls_cfg) */ STR_NULL, /* crl (default value set in fix_tls_cfg) */ STR_NULL, /* certificate (default value set in fix_tls_cfg) */ STR_NULL, /* cipher_list (default value set in fix_tls_cfg) */ @@ -163,6 +164,8 @@ cfg_def_t tls_cfg_def[] = { " contained in the certificate file" }, {"ca_list", CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0, "name of the file containing the trusted CA list (pem format)" }, + {"ca_path", CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0, + "name of the directory containing the trusted CA files (pem format)" }, {"crl", CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0, "name of the file containing the CRL (certificare revocation list" " in pem format)" }, @@ -266,7 +269,7 @@ static int fix_initial_pathname(str* path, char* def) int fix_tls_cfg(struct cfg_group_tls* cfg) { cfg->con_lifetime = S_TO_TICKS(cfg->con_lifetime); - fix_timeout("tls_connection_timeout", &cfg->con_lifetime, + fix_timeout("tls_connection_timeout", &cfg->con_lifetime, MAX_TLS_CON_LIFETIME, MAX_TLS_CON_LIFETIME); /* Update relative paths of files configured through modparams, relative * pathnames will be converted to absolute and the directory of the main @@ -278,11 +281,13 @@ int fix_tls_cfg(struct cfg_group_tls* cfg) return -1; if (fix_initial_pathname(&cfg->ca_list, TLS_CA_FILE) < 0 ) return -1; + if (fix_initial_pathname(&cfg->ca_path, TLS_CA_PATH) < 0 ) + return -1; if (fix_initial_pathname(&cfg->crl, TLS_CRL_FILE) < 0 ) return -1; if (fix_initial_pathname(&cfg->certificate, TLS_CERT_FILE) < 0) return -1; - + return 0; } diff --git a/src/modules/tls/tls_cfg.h b/src/modules/tls/tls_cfg.h index 8f9a62d89d5..b2f6919b25a 100644 --- a/src/modules/tls/tls_cfg.h +++ b/src/modules/tls/tls_cfg.h @@ -49,6 +49,7 @@ struct cfg_group_tls { str verify_client; str private_key; str ca_list; + str ca_path; str crl; str certificate; str cipher_list; diff --git a/src/modules/tls/tls_config.c b/src/modules/tls/tls_config.c index 8d1661ff8df..4134aeb7a44 100644 --- a/src/modules/tls/tls_config.c +++ b/src/modules/tls/tls_config.c @@ -183,6 +183,7 @@ static cfg_option_t options[] = { {"server_name_mode", .f = cfg_parse_int_opt}, {"server_id", .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM}, {"verify_client", .param = verify_client_params, .f = cfg_parse_enum_opt}, + {"ca_path", .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM}, {0} }; @@ -212,6 +213,7 @@ static void update_opt_variables(void) for(i = 0; verify_client_params[i].name; i++) { verify_client_params[i].param = &_ksr_tls_domain->verify_client; } + options[19].param = &_ksr_tls_domain->ca_path; } diff --git a/src/modules/tls/tls_domain.c b/src/modules/tls/tls_domain.c index 2930bde2be1..620f8682eae 100644 --- a/src/modules/tls/tls_domain.c +++ b/src/modules/tls/tls_domain.c @@ -192,7 +192,7 @@ void tls_free_domain(tls_domain_t* d) { int i; int procs_no; - + if (!d) return; if (d->ctx) { procs_no=get_max_procs(); @@ -204,6 +204,7 @@ void tls_free_domain(tls_domain_t* d) if (d->cipher_list.s) shm_free(d->cipher_list.s); if (d->ca_file.s) shm_free(d->ca_file.s); + if (d->ca_path.s) shm_free(d->ca_path.s); if (d->crl_file.s) shm_free(d->crl_file.s); if (d->pkey_file.s) shm_free(d->pkey_file.s); if (d->cert_file.s) shm_free(d->cert_file.s); @@ -327,6 +328,13 @@ static int ksr_tls_fill_missing(tls_domain_t* d, tls_domain_t* parent) } LOG(L_INFO, "%s: ca_list='%s'\n", tls_domain_str(d), d->ca_file.s); + if (!d->ca_path.s){ + if (shm_asciiz_dup(&d->ca_path.s, parent->ca_path.s) < 0) + return -1; + d->ca_path.len = parent->ca_path.len; + } + LOG(L_INFO, "%s: ca_path='%s'\n", tls_domain_str(d), d->ca_path.s); + if (!d->crl_file.s) { if (shm_asciiz_dup(&d->crl_file.s, parent->crl_file.s) < 0) return -1; @@ -568,26 +576,32 @@ static int load_ca_list(tls_domain_t* d) int i; int procs_no; - if (!d->ca_file.s || !d->ca_file.len) { + if ((!d->ca_file.s || !d->ca_file.len) && (!d->ca_path.s || !d->ca_path.len)) { DBG("%s: No CA list configured\n", tls_domain_str(d)); return 0; } - if (fix_shm_pathname(&d->ca_file) < 0) + if (d->ca_file.len>0 && fix_shm_pathname(&d->ca_file) < 0) + return -1; + if (d->ca_path.len>0 && fix_shm_pathname(&d->ca_path) < 0) return -1; procs_no=get_max_procs(); for(i = 0; i < procs_no; i++) { - if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file.s, 0) != 1) { - ERR("%s: Unable to load CA list '%s'\n", tls_domain_str(d), - d->ca_file.s); + if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file.s, + d->ca_path.s) != 1) { + ERR("%s: Unable to load CA list file '%s' dir '%s'\n", + tls_domain_str(d), (d->ca_file.s)?d->ca_file.s:"", + (d->ca_path.s)?d->ca_path.s:""); TLS_ERR("load_ca_list:"); return -1; } - SSL_CTX_set_client_CA_list(d->ctx[i], - SSL_load_client_CA_file(d->ca_file.s)); - if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) { - ERR("%s: Error while setting client CA list\n", tls_domain_str(d)); - TLS_ERR("load_ca_list:"); - return -1; + if(d->ca_file.len>0) { + SSL_CTX_set_client_CA_list(d->ctx[i], + SSL_load_client_CA_file(d->ca_file.s)); + if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) { + ERR("%s: Error while setting client CA list\n", tls_domain_str(d)); + TLS_ERR("load_ca_list:"); + return -1; + } } } return 0; diff --git a/src/modules/tls/tls_domain.h b/src/modules/tls/tls_domain.h index 341577b644c..d81b4f0e319 100644 --- a/src/modules/tls/tls_domain.h +++ b/src/modules/tls/tls_domain.h @@ -117,6 +117,7 @@ typedef struct tls_domain { int verify_cert; int verify_depth; str ca_file; + str ca_path; int require_cert; str cipher_list; enum tls_method method; diff --git a/src/modules/tls/tls_mod.c b/src/modules/tls/tls_mod.c index 18f35630eb9..f329498e215 100644 --- a/src/modules/tls/tls_mod.c +++ b/src/modules/tls/tls_mod.c @@ -101,8 +101,9 @@ static tls_domain_t mod_params = { 0, /* Verify certificate */ 9, /* Verify depth */ STR_STATIC_INIT(TLS_CA_FILE), /* CA file */ + STR_STATIC_INIT(TLS_CA_PATH), /* CA path */ 0, /* Require certificate */ - {0, }, /* Cipher list */ + {0, 0}, /* Cipher list */ TLS_USE_TLSv1_PLUS, /* TLS method */ STR_STATIC_INIT(TLS_CRL_FILE), /* Certificate revocation list */ {0, 0}, /* Server name (SNI) */ @@ -126,6 +127,7 @@ tls_domain_t srv_defaults = { 0, /* Verify certificate */ 9, /* Verify depth */ STR_STATIC_INIT(TLS_CA_FILE), /* CA file */ + STR_STATIC_INIT(TLS_CA_PATH), /* CA path */ 0, /* Require certificate */ {0, 0}, /* Cipher list */ TLS_USE_TLSv1_PLUS, /* TLS method */ @@ -168,6 +170,7 @@ tls_domain_t cli_defaults = { 0, /* Verify certificate */ 9, /* Verify depth */ STR_STATIC_INIT(TLS_CA_FILE), /* CA file */ + STR_STATIC_INIT(TLS_CA_PATH), /* CA path */ 0, /* Require certificate */ {0, 0}, /* Cipher list */ TLS_USE_TLSv1_PLUS, /* TLS method */ @@ -212,6 +215,7 @@ static param_export_t params[] = { {"verify_client", PARAM_STR, &default_tls_cfg.verify_client}, {"private_key", PARAM_STR, &default_tls_cfg.private_key }, {"ca_list", PARAM_STR, &default_tls_cfg.ca_list }, + {"ca_path", PARAM_STR, &default_tls_cfg.ca_path }, {"certificate", PARAM_STR, &default_tls_cfg.certificate }, {"crl", PARAM_STR, &default_tls_cfg.crl }, {"cipher_list", PARAM_STR, &default_tls_cfg.cipher_list },