summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2021-05-12 20:39:40 +0200
committerSébastien Helleu <flashcode@flashtux.org>2021-05-12 20:39:40 +0200
commitc588ee21bc8fd33678893d5c67616033281032e3 (patch)
tree6b082610e625ca846417043edc1297e1b404cd41 /src
parentb7112e409060160ccb865c7a749579d18b914110 (diff)
downloadweechat-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.c35
-rw-r--r--src/core/wee-config.h3
-rw-r--r--src/core/wee-network.c173
-rw-r--r--src/core/wee-network.h3
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,