diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2021-05-12 20:39:40 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2021-05-12 20:39:40 +0200 |
commit | c588ee21bc8fd33678893d5c67616033281032e3 (patch) | |
tree | 6b082610e625ca846417043edc1297e1b404cd41 /src | |
parent | b7112e409060160ccb865c7a749579d18b914110 (diff) | |
download | weechat-c588ee21bc8fd33678893d5c67616033281032e3.zip |
core: improve options to load GnuTLS system/user CAs (closes #972)
Changes:
* new option: weechat.network.gnutls_ca_system
* option weechat.network.gnutls_ca_file renamed to
weechat.network.gnutls_ca_user
* reload certificates when options are changed
* remove build option CA_FILE
Diffstat (limited to 'src')
-rw-r--r-- | src/core/wee-config.c | 35 | ||||
-rw-r--r-- | src/core/wee-config.h | 3 | ||||
-rw-r--r-- | src/core/wee-network.c | 173 | ||||
-rw-r--r-- | src/core/wee-network.h | 3 |
4 files changed, 172 insertions, 42 deletions
diff --git a/src/core/wee-config.c b/src/core/wee-config.c index 0abbc896a..33f5372eb 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -291,7 +291,8 @@ struct t_config_option *config_history_max_visited_buffers; /* config, network section */ struct t_config_option *config_network_connection_timeout; -struct t_config_option *config_network_gnutls_ca_file; +struct t_config_option *config_network_gnutls_ca_system; +struct t_config_option *config_network_gnutls_ca_user; struct t_config_option *config_network_gnutls_handshake_timeout; struct t_config_option *config_network_proxy_curl; @@ -1278,12 +1279,13 @@ config_change_completion_partial_completion_templates (const void *pointer, } /* - * Callback for changes on option "weechat.network.gnutls_ca_file". + * Callback for changes on options "weechat.network.gnutls_ca_system" + * and "weechat.network.gnutls_ca_user". */ void -config_change_network_gnutls_ca_file (const void *pointer, void *data, - struct t_config_option *option) +config_change_network_gnutls_ca (const void *pointer, void *data, + struct t_config_option *option) { /* make C compiler happy */ (void) pointer; @@ -1291,7 +1293,7 @@ config_change_network_gnutls_ca_file (const void *pointer, void *data, (void) option; if (network_init_gnutls_ok) - network_set_gnutls_ca_file (); + network_reload_ca_files (1); } /* @@ -4494,15 +4496,26 @@ config_weechat_init_options () "child process)"), NULL, 1, INT_MAX, "60", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_network_gnutls_ca_file = config_file_new_option ( + config_network_gnutls_ca_system = config_file_new_option ( weechat_config_file, ptr_section, - "gnutls_ca_file", "string", - N_("file containing the certificate authorities " - "(path is evaluated, see function string_eval_path_home in " + "gnutls_ca_system", "boolean", + N_("load system's default trusted certificate authorities on startup; " + "this can be turned off to save some memory only if you are not " + "using SSL connections at all"), + NULL, 0, 0, "on", NULL, 0, + NULL, NULL, NULL, + &config_change_network_gnutls_ca, NULL, NULL, + NULL, NULL, NULL); + config_network_gnutls_ca_user = config_file_new_option ( + weechat_config_file, ptr_section, + "gnutls_ca_user", "string", + N_("extra file(s) with certificate authorities; multiple files must " + "be separated by colons " + "(each path is evaluated, see function string_eval_path_home in " "plugin API reference)"), - NULL, 0, 0, CA_FILE, NULL, 0, + NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, - &config_change_network_gnutls_ca_file, NULL, NULL, + &config_change_network_gnutls_ca, NULL, NULL, NULL, NULL, NULL); config_network_gnutls_handshake_timeout = config_file_new_option ( weechat_config_file, ptr_section, diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 356641e6a..303dbd01d 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -336,7 +336,8 @@ extern struct t_config_option *config_history_max_commands; extern struct t_config_option *config_history_max_visited_buffers; extern struct t_config_option *config_network_connection_timeout; -extern struct t_config_option *config_network_gnutls_ca_file; +extern struct t_config_option *config_network_gnutls_ca_system; +extern struct t_config_option *config_network_gnutls_ca_user; extern struct t_config_option *config_network_gnutls_handshake_timeout; extern struct t_config_option *config_network_proxy_curl; diff --git a/src/core/wee-network.c b/src/core/wee-network.c index 3fdaf01b6..32b975cf1 100644 --- a/src/core/wee-network.c +++ b/src/core/wee-network.c @@ -56,6 +56,7 @@ #include "weechat.h" #include "wee-network.h" +#include "wee-config.h" #include "wee-eval.h" #include "wee-hashtable.h" #include "wee-hook.h" @@ -67,6 +68,7 @@ int network_init_gnutls_ok = 0; +int network_num_certs = 0; /* number of certs loaded (system + user) */ gnutls_certificate_credentials_t gnutls_xcred; /* GnuTLS client credentials */ @@ -87,57 +89,171 @@ network_init_gcrypt () } /* - * Sets trust file with option "gnutls_ca_file". + * Loads system's default trusted certificate authorities. + * + * Returns the number of certificates loaded. */ -void -network_set_gnutls_ca_file () +int +network_load_system_ca_file (int force_display) +{ + int rc; + + if (weechat_no_gnutls) + return 0; + + if (!CONFIG_BOOLEAN(config_network_gnutls_ca_system)) + return 0; + + rc = gnutls_certificate_set_x509_system_trust (gnutls_xcred); + if (rc < 0) + { + gui_chat_printf ( + NULL, + _("%sWarning: failed to load system certificate authorities"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); + return 0; + } + + if (force_display || (weechat_debug_core >= 1)) + { + gui_chat_printf ( + NULL, + NG_("%d certificate loaded (system)", + "%d certificates loaded (system)", + rc), + rc); + } + + return rc; +} + +/* + * Loads user's trusted certificate authorities. + */ + +int +network_load_user_ca_files (int force_display) { - char *ca_path; + int i, rc, num_loaded, num_paths; + char **paths, *ca_path; struct t_hashtable *options; if (weechat_no_gnutls) - return; + return 0; + + num_loaded = 0; + paths = NULL; + options = NULL; + + paths = string_split (CONFIG_STRING(config_network_gnutls_ca_user), ":", + NULL, 0, 0, &num_paths); + if (!paths) + goto end; options = hashtable_new ( 32, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, NULL, NULL); - if (options) - hashtable_set (options, "directory", "config"); - ca_path = string_eval_path_home ( - CONFIG_STRING(config_network_gnutls_ca_file), - NULL, NULL, options); - if (options) - hashtable_free (options); + if (!options) + goto end; + hashtable_set (options, "directory", "config"); - if (ca_path) + for (i = 0; i < num_paths; i++) { - if (access (ca_path, R_OK) == 0) + ca_path = string_eval_path_home (paths[i], NULL, NULL, options); + if (ca_path && ca_path[0]) { - if (gnutls_certificate_set_x509_trust_file (gnutls_xcred, ca_path, - GNUTLS_X509_FMT_PEM) < 0) + if (access (ca_path, R_OK) == 0) + { + rc = gnutls_certificate_set_x509_trust_file ( + gnutls_xcred, ca_path, GNUTLS_X509_FMT_PEM); + if (rc < 0) + { + gui_chat_printf ( + NULL, + _("%sWarning: failed to load certificate authorities " + "from file %s"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + ca_path); + } + else + { + num_loaded += rc; + if (force_display || (weechat_debug_core >= 1)) + { + gui_chat_printf ( + NULL, + NG_("%d certificate loaded (file: %s)", + "%d certificates loaded (file: %s)", + rc), + rc, ca_path); + } + } + } + else { gui_chat_printf ( NULL, _("%sWarning: failed to load certificate authorities " - "from file %s"), + "from file %s (file not found)"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], ca_path); } } - else - { - gui_chat_printf ( - NULL, - _("%sWarning: no certificate authorities loaded " - "(file not found: %s)"), - gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], - ca_path); - } - free (ca_path); + if (ca_path) + free (ca_path); + } + +end: + if (paths) + string_free_split (paths); + if (options) + hashtable_free (options); + + return num_loaded; +} + +/* + * Loads system's default and user's trusted certificate authorities. + */ + +void +network_load_ca_files (int force_display) +{ + if (weechat_no_gnutls) + return; + + network_num_certs = 0; + + network_num_certs += network_load_system_ca_file (force_display); + network_num_certs += network_load_user_ca_files (force_display); +} + +/* + * Reloads system's default and user's trusted certificate authorities. + */ + +void +network_reload_ca_files (int force_display) +{ + if (weechat_no_gnutls) + return; + + gnutls_certificate_free_credentials (gnutls_xcred); + if (force_display || (weechat_debug_core >= 1)) + { + gui_chat_printf (NULL, + NG_("%d certificate purged", + "%d certificates purged", + network_num_certs), + network_num_certs); } + + gnutls_certificate_allocate_credentials (&gnutls_xcred); + + network_load_ca_files (force_display); } /* @@ -151,8 +267,7 @@ network_init_gnutls () { gnutls_global_init (); gnutls_certificate_allocate_credentials (&gnutls_xcred); - - network_set_gnutls_ca_file (); + network_load_ca_files (0); #if LIBGNUTLS_VERSION_NUMBER >= 0x02090a /* 2.9.10 */ gnutls_certificate_set_verify_function (gnutls_xcred, &hook_connect_gnutls_verify_certificates); diff --git a/src/core/wee-network.h b/src/core/wee-network.h index d6c2e13fa..dcd441c8f 100644 --- a/src/core/wee-network.h +++ b/src/core/wee-network.h @@ -46,7 +46,8 @@ struct t_network_socks5 extern int network_init_gnutls_ok; extern void network_init_gcrypt (); -extern void network_set_gnutls_ca_file (); +extern void network_load_ca_files (int force_display); +extern void network_reload_ca_files (int force_display); extern void network_init_gnutls (); extern void network_end (); extern int network_pass_proxy (const char *proxy, int sock, |