summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/Makefile.am4
-rw-r--r--src/core/wee-command.c2
-rw-r--r--src/core/wee-secure-buffer.c229
-rw-r--r--src/core/wee-secure-buffer.h32
-rw-r--r--src/core/wee-secure-config.c628
-rw-r--r--src/core/wee-secure-config.h38
-rw-r--r--src/core/wee-secure.c834
-rw-r--r--src/core/wee-secure.h36
-rw-r--r--src/core/wee-upgrade.c2
-rw-r--r--src/core/weechat.c11
-rw-r--r--src/gui/gui-buffer.c2
12 files changed, 991 insertions, 829 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8574dcf78..788aa24d2 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -39,6 +39,8 @@ set(LIB_CORE_SRC
wee-network.c wee-network.h
wee-proxy.c wee-proxy.h
wee-secure.c wee-secure.h
+ wee-secure-buffer.c wee-secure-buffer.h
+ wee-secure-config.c wee-secure-config.h
wee-string.c wee-string.h
wee-upgrade.c wee-upgrade.h
wee-upgrade-file.c wee-upgrade-file.h
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 009f0c2cb..ba6250c16 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -59,6 +59,10 @@ lib_weechat_core_a_SOURCES = weechat.c \
wee-proxy.h \
wee-secure.c \
wee-secure.h \
+ wee-secure-buffer.c \
+ wee-secure-buffer.h \
+ wee-secure-config.c \
+ wee-secure-config.h \
wee-string.c \
wee-string.h \
wee-upgrade.c \
diff --git a/src/core/wee-command.c b/src/core/wee-command.c
index 934f3006a..2b680d723 100644
--- a/src/core/wee-command.c
+++ b/src/core/wee-command.c
@@ -54,6 +54,8 @@
#include "wee-log.h"
#include "wee-proxy.h"
#include "wee-secure.h"
+#include "wee-secure-buffer.h"
+#include "wee-secure-config.h"
#include "wee-string.h"
#include "wee-upgrade.h"
#include "wee-utf8.h"
diff --git a/src/core/wee-secure-buffer.c b/src/core/wee-secure-buffer.c
new file mode 100644
index 000000000..5a0d96342
--- /dev/null
+++ b/src/core/wee-secure-buffer.c
@@ -0,0 +1,229 @@
+/*
+ * wee-secure-buffer.c - secured data buffer
+ *
+ * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "weechat.h"
+#include "wee-config-file.h"
+#include "wee-hashtable.h"
+#include "wee-secure.h"
+#include "wee-secure-buffer.h"
+#include "wee-secure-config.h"
+#include "wee-string.h"
+#include "../gui/gui-buffer.h"
+#include "../gui/gui-chat.h"
+#include "../gui/gui-color.h"
+#include "../gui/gui-window.h"
+#include "../plugins/plugin.h"
+
+struct t_gui_buffer *secure_buffer = NULL;
+int secure_buffer_display_values = 0;
+
+
+/*
+ * Displays a secured data.
+ */
+
+void
+secure_buffer_display_data (void *data,
+ struct t_hashtable *hashtable,
+ const void *key, const void *value)
+{
+ int *line;
+
+ /* make C compiler happy */
+ (void) value;
+
+ line = (int *)data;
+
+ if (secure_buffer_display_values && (hashtable == secure_hashtable_data))
+ {
+ gui_chat_printf_y (secure_buffer, (*line)++,
+ " %s%s = %s\"%s%s%s\"",
+ key,
+ GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS),
+ GUI_COLOR(GUI_COLOR_CHAT),
+ GUI_COLOR(GUI_COLOR_CHAT_VALUE),
+ value,
+ GUI_COLOR(GUI_COLOR_CHAT));
+ }
+ else
+ {
+ gui_chat_printf_y (secure_buffer, (*line)++,
+ " %s", key);
+ }
+}
+
+/*
+ * Displays content of secured data buffer.
+ */
+
+void
+secure_buffer_display ()
+{
+ int line, count, count_encrypted;
+
+ if (!secure_buffer)
+ return;
+
+ gui_buffer_clear (secure_buffer);
+
+ /* set title buffer */
+ gui_buffer_set_title (secure_buffer,
+ _("WeeChat secured data (sec.conf) | "
+ "Keys: [alt-v] Toggle values"));
+
+ line = 0;
+
+ gui_chat_printf_y (secure_buffer, line++,
+ "Hash algo: %s Cipher: %s Salt: %s",
+ secure_hash_algo_string[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
+ secure_cipher_string[CONFIG_INTEGER(secure_config_crypt_cipher)],
+ (CONFIG_BOOLEAN(secure_config_crypt_salt)) ? _("on") : _("off"));
+
+ /* display passphrase */
+ line++;
+ gui_chat_printf_y (secure_buffer, line++,
+ (secure_passphrase) ?
+ _("Passphrase is set") : _("Passphrase is not set"));
+
+ /* display secured data */
+ count = secure_hashtable_data->items_count;
+ count_encrypted = secure_hashtable_data_encrypted->items_count;
+ if (count > 0)
+ {
+ line++;
+ gui_chat_printf_y (secure_buffer, line++, _("Secured data:"));
+ line++;
+ hashtable_map (secure_hashtable_data,
+ &secure_buffer_display_data, &line);
+ }
+ /* display secured data not decrypted */
+ if (count_encrypted > 0)
+ {
+ line++;
+ gui_chat_printf_y (secure_buffer, line++,
+ _("Secured data STILL ENCRYPTED: (use /secure decrypt, "
+ "see /help secure)"));
+ line++;
+ hashtable_map (secure_hashtable_data_encrypted,
+ &secure_buffer_display_data, &line);
+ }
+ if ((count == 0) && (count_encrypted == 0))
+ {
+ line++;
+ gui_chat_printf_y (secure_buffer, line++, _("No secured data set"));
+ }
+}
+
+/*
+ * Input callback for secured data buffer.
+ */
+
+int
+secure_buffer_input_cb (const void *pointer, void *data,
+ struct t_gui_buffer *buffer,
+ const char *input_data)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ if (string_strcasecmp (input_data, "q") == 0)
+ {
+ gui_buffer_close (buffer);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Close callback for secured data buffer.
+ */
+
+int
+secure_buffer_close_cb (const void *pointer, void *data,
+ struct t_gui_buffer *buffer)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) buffer;
+
+ secure_buffer = NULL;
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Assigns secured data buffer to pointer if it is not yet set.
+ */
+
+void
+secure_buffer_assign ()
+{
+ if (!secure_buffer)
+ {
+ secure_buffer = gui_buffer_search_by_name (NULL, SECURE_BUFFER_NAME);
+ if (secure_buffer)
+ {
+ secure_buffer->input_callback = &secure_buffer_input_cb;
+ secure_buffer->close_callback = &secure_buffer_close_cb;
+ }
+ }
+}
+
+/*
+ * Opens a buffer to display secured data.
+ */
+
+void
+secure_buffer_open ()
+{
+ if (!secure_buffer)
+ {
+ secure_buffer = gui_buffer_new (NULL, SECURE_BUFFER_NAME,
+ &secure_buffer_input_cb, NULL, NULL,
+ &secure_buffer_close_cb, NULL, NULL);
+ if (secure_buffer)
+ {
+ if (!secure_buffer->short_name)
+ secure_buffer->short_name = strdup (SECURE_BUFFER_NAME);
+ gui_buffer_set (secure_buffer, "type", "free");
+ gui_buffer_set (secure_buffer, "localvar_set_no_log", "1");
+ gui_buffer_set (secure_buffer, "key_bind_meta-v", "/secure toggle_values");
+ }
+ secure_buffer_display_values = 0;
+ }
+
+ if (!secure_buffer)
+ return;
+
+ gui_window_switch_to_buffer (gui_current_window, secure_buffer, 1);
+
+ secure_buffer_display ();
+}
diff --git a/src/core/wee-secure-buffer.h b/src/core/wee-secure-buffer.h
new file mode 100644
index 000000000..d086ec440
--- /dev/null
+++ b/src/core/wee-secure-buffer.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_SECURE_BUFFER_H
+#define WEECHAT_SECURE_BUFFER_H
+
+#define SECURE_BUFFER_NAME "secured_data"
+
+extern struct t_gui_buffer *secure_buffer;
+extern int secure_buffer_display_values;
+
+extern void secure_buffer_display ();
+extern void secure_buffer_assign ();
+extern void secure_buffer_open ();
+
+#endif /* WEECHAT_SECURE_BUFFER_H */
diff --git a/src/core/wee-secure-config.c b/src/core/wee-secure-config.c
new file mode 100644
index 000000000..6d0d93fb8
--- /dev/null
+++ b/src/core/wee-secure-config.c
@@ -0,0 +1,628 @@
+/*
+ * wee-secure-config.c - secured data configuration options (file sec.conf)
+ *
+ * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "weechat.h"
+#include "wee-config-file.h"
+#include "wee-hashtable.h"
+#include "wee-secure.h"
+#include "wee-secure-config.h"
+#include "wee-string.h"
+#include "../gui/gui-chat.h"
+#include "../gui/gui-main.h"
+#include "../gui/gui-window.h"
+#include "../plugins/plugin.h"
+
+struct t_config_file *secure_config_file = NULL;
+
+struct t_config_option *secure_config_crypt_cipher = NULL;
+struct t_config_option *secure_config_crypt_hash_algo = NULL;
+struct t_config_option *secure_config_crypt_passphrase_file = NULL;
+struct t_config_option *secure_config_crypt_salt = NULL;
+
+
+/*
+ * Gets passphrase from user and puts it in variable "secure_passphrase".
+ */
+
+void
+secure_config_get_passphrase_from_user (const char *error)
+{
+ const char *prompt[5];
+ char passphrase[1024];
+
+ prompt[0] = _("Please enter your passphrase to decrypt the data secured "
+ "by WeeChat:");
+ prompt[1] = _("(enter just one space to skip the passphrase, but this "
+ "will DISABLE all secured data!)");
+ prompt[2] = _("(press ctrl-C to exit WeeChat now)");
+ prompt[3] = error;
+ prompt[4] = NULL;
+
+ while (1)
+ {
+ gui_main_get_password (prompt, passphrase, sizeof (passphrase));
+ if (secure_passphrase)
+ {
+ free (secure_passphrase);
+ secure_passphrase = NULL;
+ }
+ if (passphrase[0])
+ {
+ /* the special value " " (one space) disables passphrase */
+ if (strcmp (passphrase, " ") == 0)
+ {
+ gui_chat_printf (NULL,
+ _("To recover your secured data, you can "
+ "use /secure decrypt (see /help secure)"));
+ }
+ else if (strcmp (passphrase, "\x03") == 0)
+ {
+ /* ctrl-C pressed, just exit now */
+ exit (1);
+ }
+ else
+ secure_passphrase = strdup (passphrase);
+ return;
+ }
+ }
+}
+
+/*
+ * Gets passphrase from a file.
+ *
+ * Returns passphrase read in file (only the first line with max length of
+ * 1024 chars), or NULL if error.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+secure_config_get_passphrase_from_file (const char *filename)
+{
+ FILE *file;
+ char *passphrase, *filename2, buffer[1024+1], *pos;
+ size_t num_read;
+
+ passphrase = NULL;
+
+ filename2 = string_expand_home (filename);
+ if (!filename2)
+ return NULL;
+
+ file = fopen (filename2, "r");
+ if (file)
+ {
+ num_read = fread (buffer, 1, sizeof (buffer) - 1, file);
+ if (num_read > 0)
+ {
+ buffer[num_read] = '\0';
+ pos = strchr (buffer, '\r');
+ if (pos)
+ pos[0] = '\0';
+ pos = strchr (buffer, '\n');
+ if (pos)
+ pos[0] = '\0';
+ if (buffer[0])
+ passphrase = strdup (buffer);
+ }
+ fclose (file);
+ }
+
+ free (filename2);
+
+ return passphrase;
+}
+
+/*
+ * Checks option "sec.crypt.passphrase_file".
+ */
+
+int
+secure_config_check_crypt_passphrase_file (const void *pointer, void *data,
+ struct t_config_option *option,
+ const char *value)
+{
+ char *passphrase;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ /* empty value is OK in option (no file used for passphrase) */
+ if (!value || !value[0])
+ return 1;
+
+ passphrase = secure_config_get_passphrase_from_file (value);
+ if (passphrase)
+ free (passphrase);
+ else
+ {
+ gui_chat_printf (NULL,
+ _("%sWarning: unable to read passphrase from file "
+ "\"%s\""),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ value);
+ }
+
+ return 1;
+}
+
+/*
+ * Reloads secured data configuration file.
+ *
+ * Returns:
+ * WEECHAT_CONFIG_READ_OK: OK
+ * WEECHAT_CONFIG_READ_MEMORY_ERROR: not enough memory
+ * WEECHAT_CONFIG_READ_FILE_NOT_FOUND: file not found
+ */
+
+int
+secure_config_reload_cb (const void *pointer, void *data,
+ struct t_config_file *config_file)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ if (secure_hashtable_data_encrypted->items_count > 0)
+ {
+ gui_chat_printf (NULL,
+ _("%sError: not possible to reload file sec.conf "
+ "because there is still encrypted data (use /secure "
+ "decrypt, see /help secure)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
+ return WEECHAT_CONFIG_READ_FILE_NOT_FOUND;
+ }
+
+ secure_data_encrypted = 0;
+
+ /* remove all secured data */
+ hashtable_remove_all (secure_hashtable_data);
+
+ return config_file_reload (config_file);
+}
+
+/*
+ * Reads a data option in secured data configuration file.
+ */
+
+int
+secure_config_data_read_cb (const void *pointer, void *data,
+ struct t_config_file *config_file,
+ struct t_config_section *section,
+ const char *option_name, const char *value)
+{
+ char *buffer, *decrypted, str_error[1024];
+ int length_buffer, length_decrypted, rc;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) config_file;
+ (void) section;
+
+ if (!option_name || !value || !value[0])
+ {
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+
+ /* special line indicating if a passphrase must be used to decrypt data */
+ if (strcmp (option_name, SECURE_DATA_PASSPHRASE_FLAG) == 0)
+ {
+ secure_data_encrypted = config_file_string_to_boolean (value);
+ if (secure_data_encrypted && !secure_passphrase && !gui_init_ok)
+ {
+ /* if a passphrase file is set, use it */
+ if (CONFIG_STRING(secure_config_crypt_passphrase_file)[0])
+ secure_passphrase = secure_config_get_passphrase_from_file (
+ CONFIG_STRING(secure_config_crypt_passphrase_file));
+
+ /* ask passphrase to the user (if no file, or file not found) */
+ if (!secure_passphrase)
+ secure_config_get_passphrase_from_user ("");
+ }
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+
+ if (!secure_data_encrypted)
+ {
+ /* clear data: just store value in hashtable */
+ hashtable_set (secure_hashtable_data, option_name, value);
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+
+ /* check that passphrase is set */
+ if (!secure_passphrase)
+ {
+ gui_chat_printf (NULL,
+ _("%sPassphrase is not set, unable to decrypt data \"%s\""),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ option_name);
+ hashtable_set (secure_hashtable_data_encrypted, option_name, value);
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+
+ /* decrypt data */
+ buffer = malloc (strlen (value) + 1);
+ if (!buffer)
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+
+ length_buffer = string_decode_base16 (value, buffer);
+ while (1)
+ {
+ decrypted = NULL;
+ length_decrypted = 0;
+ rc = secure_decrypt_data (
+ buffer,
+ length_buffer,
+ secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
+ secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)],
+ secure_passphrase,
+ &decrypted,
+ &length_decrypted);
+ if (rc == 0)
+ {
+ if (decrypted)
+ {
+ hashtable_set (secure_hashtable_data, option_name,
+ decrypted);
+ free (decrypted);
+ break;
+ }
+ }
+ else
+ {
+ if (decrypted)
+ free (decrypted);
+ if (gui_init_ok)
+ {
+ gui_chat_printf (NULL,
+ _("%sWrong passphrase, unable to decrypt data "
+ "\"%s\""),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ option_name);
+ break;
+ }
+ snprintf (str_error, sizeof (str_error),
+ _("*** Wrong passphrase (decrypt error: %s) ***"),
+ secure_decrypt_error[(rc * -1) - 1]);
+ secure_config_get_passphrase_from_user (str_error);
+ if (!secure_passphrase)
+ {
+ gui_chat_printf (NULL,
+ _("%sPassphrase is not set, unable to decrypt "
+ "data \"%s\""),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ option_name);
+ hashtable_set (secure_hashtable_data_encrypted, option_name,
+ value);
+ break;
+ }
+ }
+ }
+ free (buffer);
+
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+}
+
+/*
+ * Encrypts data and writes it in secured data configuration file.
+ */
+
+void
+secure_config_data_write_map_cb (void *data,
+ struct t_hashtable *hashtable,
+ const void *key, const void *value)
+{
+ struct t_config_file *config_file;
+ char *buffer, *buffer_base16;
+ int length_buffer, rc;
+
+ /* make C compiler happy */
+ (void) hashtable;
+
+ config_file = (struct t_config_file *)data;
+
+ buffer = NULL;
+ length_buffer = 0;
+
+ if (secure_passphrase)
+ {
+ /* encrypt password using passphrase */
+ rc = secure_encrypt_data (
+ value, strlen (value) + 1,
+ secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
+ secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)],
+ secure_passphrase,
+ &buffer,
+ &length_buffer);
+ if (rc == 0)
+ {
+ if (buffer)
+ {
+ buffer_base16 = malloc ((length_buffer * 2) + 1);
+ if (buffer_base16)
+ {
+ string_encode_base16 (buffer, length_buffer, buffer_base16);
+ config_file_write_line (config_file, key,
+ "\"%s\"", buffer_base16);
+ free (buffer_base16);
+ }
+ free (buffer);
+ }
+ }
+ else
+ {
+ gui_chat_printf (NULL,
+ _("%sError encrypting data \"%s\" (%d)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ key, rc);
+ }
+ }
+ else
+ {
+ /* store password as plain text */
+ config_file_write_line (config_file, key, "\"%s\"", value);
+ }
+}
+
+/*
+ * Writes already encrypted data in secured data configuration file.
+ */
+
+void
+secure_config_data_write_map_encrypted_cb (void *data,
+ struct t_hashtable *hashtable,
+ const void *key, const void *value)
+{
+ struct t_config_file *config_file;
+
+ /* make C compiler happy */
+ (void) hashtable;
+
+ config_file = (struct t_config_file *)data;
+
+ /* store data as-is (it is already encrypted) */
+ config_file_write_line (config_file, key, "\"%s\"", value);
+}
+
+/*
+ * Writes section "data" in secured data configuration file.
+ */
+
+int
+secure_config_data_write_cb (const void *pointer, void *data,
+ struct t_config_file *config_file,
+ const char *section_name)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ /* write name of section */
+ if (!config_file_write_line (config_file, section_name, NULL))
+ return WEECHAT_CONFIG_WRITE_ERROR;
+
+ if (secure_hashtable_data->items_count > 0)
+ {
+ /*
+ * write a special line indicating if a passphrase must be used to
+ * decrypt data (if not, then data is stored as plain text)
+ */
+ if (!config_file_write_line (config_file,
+ SECURE_DATA_PASSPHRASE_FLAG,
+ (secure_passphrase) ? "on" : "off"))
+ {
+ return WEECHAT_CONFIG_WRITE_ERROR;
+ }
+ /* encrypt and write secured data */
+ hashtable_map (secure_hashtable_data,
+ &secure_config_data_write_map_cb, config_file);
+ }
+ else if (secure_hashtable_data_encrypted->items_count > 0)
+ {
+ /*
+ * if there is encrypted data, that means passphrase was not set and
+ * we were unable to decrypt => just save the encrypted content
+ * as-is (so that content of sec.conf is not lost)
+ */
+ if (!config_file_write_line (config_file,
+ SECURE_DATA_PASSPHRASE_FLAG, "on"))
+ {
+ return WEECHAT_CONFIG_WRITE_ERROR;
+ }
+ hashtable_map (secure_hashtable_data_encrypted,
+ &secure_config_data_write_map_encrypted_cb, config_file);
+ }
+
+ return WEECHAT_CONFIG_WRITE_OK;
+}
+
+/*
+ * Creates options in secured data configuration.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+secure_config_init_options ()
+{
+ struct t_config_section *ptr_section;
+
+ secure_config_file = config_file_new (NULL, SECURE_CONFIG_NAME,
+ &secure_config_reload_cb, NULL, NULL);
+ if (!secure_config_file)
+ return 0;
+
+ /* crypt */
+ ptr_section = config_file_new_section (secure_config_file, "crypt",
+ 0, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ config_file_free (secure_config_file);
+ secure_config_file = NULL;
+ return 0;
+ }
+
+ secure_config_crypt_cipher = config_file_new_option (
+ secure_config_file, ptr_section,
+ "cipher", "integer",
+ N_("cipher used to crypt data (the number after algorithm is the size "
+ "of the key in bits)"),
+ "aes128|aes192|aes256", 0, 0, "aes256", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ secure_config_crypt_hash_algo = config_file_new_option (
+ secure_config_file, ptr_section,
+ "hash_algo", "integer",
+ N_("hash algorithm used to check the decrypted data"),
+ "sha224|sha256|sha384|sha512", 0, 0, "sha256", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ secure_config_crypt_passphrase_file = config_file_new_option (
+ secure_config_file, ptr_section,
+ "passphrase_file", "string",
+ N_("path to a file containing the passphrase to encrypt/decrypt secured "
+ "data; this option is used only when reading file sec.conf; only "
+ "first line of file is used; this file is used only if the "
+ "environment variable \"WEECHAT_PASSPHRASE\" is not set (the "
+ "environment variable has higher priority); security note: it is "
+ "recommended to keep this file readable only by you and store it "
+ "outside WeeChat home (for example in your home); example: "
+ "\"~/.weechat-passphrase\""),
+ NULL, 0, 0, "", NULL, 0,
+ &secure_config_check_crypt_passphrase_file, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ secure_config_crypt_salt = config_file_new_option (
+ secure_config_file, ptr_section,
+ "salt", "boolean",
+ N_("use salt when generating key used in encryption (recommended for "
+ "maximum security); when enabled, the content of crypted data in "
+ "file sec.conf will be different on each write of the file; if you "
+ "put the file sec.conf in a version control system, then you "
+ "can turn off this option to have always same content in file"),
+ NULL, 0, 0, "on", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* data */
+ ptr_section = config_file_new_section (
+ secure_config_file, "data",
+ 0, 0,
+ &secure_config_data_read_cb, NULL, NULL,
+ &secure_config_data_write_cb, NULL, NULL,
+ &secure_config_data_write_cb, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ config_file_free (secure_config_file);
+ secure_config_file = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Reads secured data configuration file.
+ *
+ * Returns:
+ * WEECHAT_CONFIG_READ_OK: OK
+ * WEECHAT_CONFIG_READ_MEMORY_ERROR: not enough memory
+ * WEECHAT_CONFIG_READ_FILE_NOT_FOUND: file not found
+ */
+
+int
+secure_config_read ()
+{
+ int rc;
+
+ secure_data_encrypted = 0;
+
+ rc = config_file_read (secure_config_file);
+
+ return rc;
+}
+
+/*
+ * Writes secured data configuration file.
+ *
+ * Returns:
+ * WEECHAT_CONFIG_WRITE_OK: OK
+ * WEECHAT_CONFIG_WRITE_ERROR: error
+ * WEECHAT_CONFIG_WRITE_MEMORY_ERROR: not enough memory
+ */
+
+int
+secure_config_write ()
+{
+ return config_file_write (secure_config_file);
+}
+
+/*
+ * Initializes secured data configuration.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+secure_config_init ()
+{
+ int rc;
+
+ rc = secure_config_init_options ();
+
+ if (!rc)
+ {
+ gui_chat_printf (NULL,
+ _("FATAL: error initializing configuration options"));
+ }
+
+ return rc;
+}
+
+/*
+ * Frees secured data file and variables.
+ */
+
+void
+secure_config_free ()
+{
+ config_file_free (secure_config_file);
+ secure_config_file = NULL;
+}
diff --git a/src/core/wee-secure-config.h b/src/core/wee-secure-config.h
new file mode 100644
index 000000000..b24350a4b
--- /dev/null
+++ b/src/core/wee-secure-config.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_SECURE_CONFIG_H
+#define WEECHAT_SECURE_CONFIG_H
+
+#define SECURE_CONFIG_NAME "sec"
+
+extern struct t_config_file *secure_config_file;
+extern struct t_config_section *secure_config_section_pwd;
+
+extern struct t_config_option *secure_config_crypt_cipher;
+extern struct t_config_option *secure_config_crypt_hash_algo;
+extern struct t_config_option *secure_config_crypt_passphrase_file;
+extern struct t_config_option *secure_config_crypt_salt;
+
+extern int secure_config_read ();
+extern int secure_config_write ();
+extern int secure_config_init ();
+extern void secure_config_free ();
+
+#endif /* WEECHAT_SECURE_CONFIG_H */
diff --git a/src/core/wee-secure.c b/src/core/wee-secure.c
index b30f0dd66..c4382d3f9 100644
--- a/src/core/wee-secure.c
+++ b/src/core/wee-secure.c
@@ -1,5 +1,5 @@
/*
- * wee-secure.c - secured data configuration options (file sec.conf)
+ * wee-secure.c - secured data
*
* Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org>
*
@@ -31,23 +31,10 @@
#include "wee-config-file.h"
#include "wee-hashtable.h"
#include "wee-secure.h"
+#include "wee-secure-config.h"
#include "wee-string.h"
-#include "../gui/gui-buffer.h"
-#include "../gui/gui-chat.h"
-#include "../gui/gui-color.h"
-#include "../gui/gui-main.h"
-#include "../gui/gui-window.h"
#include "../plugins/plugin.h"
-#define SALT_SIZE 8
-
-struct t_config_file *secure_config_file = NULL;
-
-struct t_config_option *secure_config_crypt_cipher = NULL;
-struct t_config_option *secure_config_crypt_hash_algo = NULL;
-struct t_config_option *secure_config_crypt_passphrase_file = NULL;
-struct t_config_option *secure_config_crypt_salt = NULL;
-
/* the passphrase used to encrypt/decrypt data */
char *secure_passphrase = NULL;
@@ -74,10 +61,6 @@ char *secure_decrypt_error[] = { "memory", "buffer", "key", "cipher", "setkey",
/* used only when reading sec.conf: 1 if flag __passphrase__ is enabled */
int secure_data_encrypted = 0;
-/* secured data buffer */
-struct t_gui_buffer *secure_buffer = NULL;
-int secure_buffer_display_values = 0;
-
/*
* Derives a key from salt + passphrase (using a hash).
@@ -97,14 +80,14 @@ secure_derive_key (const char *salt, const char *passphrase,
memset (key, 0, length_key);
- length = SALT_SIZE + strlen (passphrase);
+ length = SECURE_SALT_SIZE + strlen (passphrase);
buffer = malloc (length);
if (!buffer)
return 0;
/* build a buffer with salt + passphrase */
- memcpy (buffer, salt, SALT_SIZE);
- memcpy (buffer + SALT_SIZE, passphrase, strlen (passphrase));
+ memcpy (buffer, salt, SECURE_SALT_SIZE);
+ memcpy (buffer + SECURE_SALT_SIZE, passphrase, strlen (passphrase));
/* compute hash of buffer */
if (gcry_md_open (&hd_md, GCRY_MD_SHA512, 0) != 0)
@@ -175,7 +158,7 @@ secure_encrypt_data (const char *data, int length_data,
int hd_md_opened, hd_cipher_opened;
gcry_md_hd_t *hd_md;
gcry_cipher_hd_t *hd_cipher;
- char salt[SALT_SIZE];
+ char salt[SECURE_SALT_SIZE];
unsigned char *ptr_hash, *key, *hash_and_data;
rc = -1;
@@ -203,14 +186,15 @@ secure_encrypt_data (const char *data, int length_data,
if (!key)
goto encend;
if (CONFIG_BOOLEAN(secure_config_crypt_salt))
- gcry_randomize (salt, SALT_SIZE, GCRY_STRONG_RANDOM);
+ gcry_randomize (salt, SECURE_SALT_SIZE, GCRY_STRONG_RANDOM);
else
{
length_salt = strlen (SECURE_SALT_DEFAULT);
- if (length_salt < SALT_SIZE)
- memset (salt, 0, SALT_SIZE);
+ if (length_salt < SECURE_SALT_SIZE)
+ memset (salt, 0, SECURE_SALT_SIZE);
memcpy (salt, SECURE_SALT_DEFAULT,
- (length_salt <= SALT_SIZE) ? length_salt : SALT_SIZE);
+ (length_salt <= SECURE_SALT_SIZE) ?
+ length_salt : SECURE_SALT_SIZE);
}
if (!secure_derive_key (salt, passphrase, key, length_key))
{
@@ -262,12 +246,12 @@ secure_encrypt_data (const char *data, int length_data,
}
/* create buffer and copy salt + encrypted hash/data into this buffer*/
- *length_encrypted = SALT_SIZE + length_hash_data;
+ *length_encrypted = SECURE_SALT_SIZE + length_hash_data;
*encrypted = malloc (*length_encrypted);
if (!*encrypted)
goto encend;
- memcpy (*encrypted, salt, SALT_SIZE);
- memcpy (*encrypted + SALT_SIZE, hash_and_data, length_hash_data);
+ memcpy (*encrypted, salt, SECURE_SALT_SIZE);
+ memcpy (*encrypted + SECURE_SALT_SIZE, hash_and_data, length_hash_data);
rc = 0;
@@ -336,7 +320,7 @@ secure_decrypt_data (const char *buffer, int length_buffer,
/* check length of buffer */
length_hash = gcry_md_get_algo_dlen (hash_algo);
- if (length_buffer <= SALT_SIZE + length_hash)
+ if (length_buffer <= SECURE_SALT_SIZE + length_hash)
return -2;
hd_md = NULL;
@@ -368,7 +352,7 @@ secure_decrypt_data (const char *buffer, int length_buffer,
}
/* decrypt hash + data */
- decrypted_hash_data = malloc (length_buffer - SALT_SIZE);
+ decrypted_hash_data = malloc (length_buffer - SECURE_SALT_SIZE);
if (!decrypted_hash_data)
goto decend;
if (gcry_cipher_open (hd_cipher, cipher, GCRY_CIPHER_MODE_CFB, 0) != 0)
@@ -383,8 +367,10 @@ secure_decrypt_data (const char *buffer, int length_buffer,
goto decend;
}
if (gcry_cipher_decrypt (*hd_cipher,
- decrypted_hash_data, length_buffer - SALT_SIZE,
- buffer + SALT_SIZE, length_buffer - SALT_SIZE) != 0)
+ decrypted_hash_data,
+ length_buffer - SECURE_SALT_SIZE,
+ buffer + SECURE_SALT_SIZE,
+ length_buffer - SECURE_SALT_SIZE) != 0)
{
rc = -6;
goto decend;
@@ -398,7 +384,7 @@ secure_decrypt_data (const char *buffer, int length_buffer,
}
hd_md_opened = 1;
gcry_md_write (*hd_md, decrypted_hash_data + length_hash,
- length_buffer - SALT_SIZE - length_hash);
+ length_buffer - SECURE_SALT_SIZE - length_hash);
ptr_hash = gcry_md_read (*hd_md, hash_algo);
if (!ptr_hash)
{
@@ -412,7 +398,7 @@ secure_decrypt_data (const char *buffer, int length_buffer,
}
/* return the decrypted data */
- *length_decrypted = length_buffer - SALT_SIZE - length_hash;
+ *length_decrypted = length_buffer - SECURE_SALT_SIZE - length_hash;
*decrypted = malloc (*length_decrypted);
if (!*decrypted)
goto decend;
@@ -480,13 +466,14 @@ secure_decrypt_data_not_decrypted (const char *passphrase)
length_buffer = string_decode_base16 (value, buffer);
decrypted = NULL;
length_decrypted = 0;
- rc = secure_decrypt_data (buffer,
- length_buffer,
- secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
- secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)],
- passphrase,
- &decrypted,
- &length_decrypted);
+ rc = secure_decrypt_data (
+ buffer,
+ length_buffer,
+ secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
+ secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)],
+ passphrase,
+ &decrypted,
+ &length_decrypted);
if ((rc == 0) && decrypted)
{
hashtable_set (secure_hashtable_data, keys[i],
@@ -508,514 +495,7 @@ secure_decrypt_data_not_decrypted (const char *passphrase)
}
/*
- * Gets passphrase from user and puts it in variable "secure_passphrase".
- */
-
-void
-secure_get_passphrase_from_user (const char *error)
-{
- const char *prompt[5];
- char passphrase[1024];
-
- prompt[0] = _("Please enter your passphrase to decrypt the data secured "
- "by WeeChat:");
- prompt[1] = _("(enter just one space to skip the passphrase, but this "
- "will DISABLE all secured data!)");
- prompt[2] = _("(press ctrl-C to exit WeeChat now)");
- prompt[3] = error;
- prompt[4] = NULL;
-
- while (1)
- {
- gui_main_get_password (prompt, passphrase, sizeof (passphrase));
- if (secure_passphrase)
- {
- free (secure_passphrase);
- secure_passphrase = NULL;
- }
- if (passphrase[0])
- {
- /* the special value " " (one space) disables passphrase */
- if (strcmp (passphrase, " ") == 0)
- {
- gui_chat_printf (NULL,
- _("To recover your secured data, you can "
- "use /secure decrypt (see /help secure)"));
- }
- else if (strcmp (passphrase, "\x03") == 0)
- {
- /* ctrl-C pressed, just exit now */
- exit (1);
- }
- else
- secure_passphrase = strdup (passphrase);
- return;
- }
- }
-}
-
-/*
- * Gets passphrase from a file.
- *
- * Returns passphrase read in file (only the first line with max length of
- * 1024 chars), or NULL if error.
- *
- * Note: result must be freed after use.
- */
-
-char *
-secure_get_passphrase_from_file (const char *filename)
-{
- FILE *file;
- char *passphrase, *filename2, buffer[1024+1], *pos;
- size_t num_read;
-
- passphrase = NULL;
-
- filename2 = string_expand_home (filename);
- if (!filename2)
- return NULL;
-
- file = fopen (filename2, "r");
- if (file)
- {
- num_read = fread (buffer, 1, sizeof (buffer) - 1, file);
- if (num_read > 0)
- {
- buffer[num_read] = '\0';
- pos = strchr (buffer, '\r');
- if (pos)
- pos[0] = '\0';
- pos = strchr (buffer, '\n');
- if (pos)
- pos[0] = '\0';
- if (buffer[0])
- passphrase = strdup (buffer);
- }
- fclose (file);
- }
-
- free (filename2);
-
- return passphrase;
-}
-
-/*
- * Checks option "sec.crypt.passphrase_file".
- */
-
-int
-secure_check_crypt_passphrase_file (const void *pointer, void *data,
- struct t_config_option *option,
- const char *value)
-{
- char *passphrase;
-
- /* make C compiler happy */
- (void) pointer;
- (void) data;
- (void) option;
-
- /* empty value is OK in option (no file used for passphrase) */
- if (!value || !value[0])
- return 1;
-
- passphrase = secure_get_passphrase_from_file (value);
- if (passphrase)
- free (passphrase);
- else
- {
- gui_chat_printf (NULL,
- _("%sWarning: unable to read passphrase from file "
- "\"%s\""),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
- value);
- }
-
- return 1;
-}
-
-/*
- * Reloads secured data configuration file.
- *
- * Returns:
- * WEECHAT_CONFIG_READ_OK: OK
- * WEECHAT_CONFIG_READ_MEMORY_ERROR: not enough memory
- * WEECHAT_CONFIG_READ_FILE_NOT_FOUND: file not found
- */
-
-int
-secure_reload_cb (const void *pointer, void *data,
- struct t_config_file *config_file)
-{
- /* make C compiler happy */
- (void) pointer;
- (void) data;
-
- if (secure_hashtable_data_encrypted->items_count > 0)
- {
- gui_chat_printf (NULL,
- _("%sError: not possible to reload file sec.conf "
- "because there is still encrypted data (use /secure "
- "decrypt, see /help secure)"),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
- return WEECHAT_CONFIG_READ_FILE_NOT_FOUND;
- }
-
- secure_data_encrypted = 0;
-
- /* remove all secured data */
- hashtable_remove_all (secure_hashtable_data);
-
- return config_file_reload (config_file);
-}
-
-/*
- * Reads a data option in secured data configuration file.
- */
-
-int
-secure_data_read_cb (const void *pointer, void *data,
- struct t_config_file *config_file,
- struct t_config_section *section,
- const char *option_name, const char *value)
-{
- char *buffer, *decrypted, str_error[1024];
- int length_buffer, length_decrypted, rc;
-
- /* make C compiler happy */
- (void) pointer;
- (void) data;
- (void) config_file;
- (void) section;
-
- if (!option_name || !value || !value[0])
- {
- return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
- }
-
- /* special line indicating if a passphrase must be used to decrypt data */
- if (strcmp (option_name, SECURE_DATA_PASSPHRASE_FLAG) == 0)
- {
- secure_data_encrypted = config_file_string_to_boolean (value);
- if (secure_data_encrypted && !secure_passphrase && !gui_init_ok)
- {
- /* if a passphrase file is set, use it */
- if (CONFIG_STRING(secure_config_crypt_passphrase_file)[0])
- secure_passphrase = secure_get_passphrase_from_file (CONFIG_STRING(secure_config_crypt_passphrase_file));
-
- /* ask passphrase to the user (if no file, or file not found) */
- if (!secure_passphrase)
- secure_get_passphrase_from_user ("");
- }
- return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
- }
-
- if (!secure_data_encrypted)
- {
- /* clear data: just store value in hashtable */
- hashtable_set (secure_hashtable_data, option_name, value);
- return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
- }
-
- /* check that passphrase is set */
- if (!secure_passphrase)
- {
- gui_chat_printf (NULL,
- _("%sPassphrase is not set, unable to decrypt data \"%s\""),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
- option_name);
- hashtable_set (secure_hashtable_data_encrypted, option_name, value);
- return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
- }
-
- /* decrypt data */
- buffer = malloc (strlen (value) + 1);
- if (!buffer)
- return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
-
- length_buffer = string_decode_base16 (value, buffer);
- while (1)
- {
- decrypted = NULL;
- length_decrypted = 0;
- rc = secure_decrypt_data (buffer,
- length_buffer,
- secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
- secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)],
- secure_passphrase,
- &decrypted,
- &length_decrypted);
- if (rc == 0)
- {
- if (decrypted)
- {
- hashtable_set (secure_hashtable_data, option_name,
- decrypted);
- free (decrypted);
- break;
- }
- }
- else
- {
- if (decrypted)
- free (decrypted);
- if (gui_init_ok)
- {
- gui_chat_printf (NULL,
- _("%sWrong passphrase, unable to decrypt data "
- "\"%s\""),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
- option_name);
- break;
- }
- snprintf (str_error, sizeof (str_error),
- _("*** Wrong passphrase (decrypt error: %s) ***"),
- secure_decrypt_error[(rc * -1) - 1]);
- secure_get_passphrase_from_user (str_error);
- if (!secure_passphrase)
- {
- gui_chat_printf (NULL,
- _("%sPassphrase is not set, unable to decrypt "
- "data \"%s\""),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
- option_name);
- hashtable_set (secure_hashtable_data_encrypted, option_name,
- value);
- break;
- }
- }
- }
- free (buffer);
-
- return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
-}
-
-/*
- * Encrypts data and writes it in secured data configuration file.
- */
-
-void
-secure_data_write_map_cb (void *data,
- struct t_hashtable *hashtable,
- const void *key, const void *value)
-{
- struct t_config_file *config_file;
- char *buffer, *buffer_base16;
- int length_buffer, rc;
-
- /* make C compiler happy */
- (void) hashtable;
-
- config_file = (struct t_config_file *)data;
-
- buffer = NULL;
- length_buffer = 0;
-
- if (secure_passphrase)
- {
- /* encrypt password using passphrase */
- rc = secure_encrypt_data (value, strlen (value) + 1,
- secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
- secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)],
- secure_passphrase,
- &buffer,
- &length_buffer);
- if (rc == 0)
- {
- if (buffer)
- {
- buffer_base16 = malloc ((length_buffer * 2) + 1);
- if (buffer_base16)
- {
- string_encode_base16 (buffer, length_buffer, buffer_base16);
- config_file_write_line (config_file, key,
- "\"%s\"", buffer_base16);
- free (buffer_base16);
- }
- free (buffer);
- }
- }
- else
- {
- gui_chat_printf (NULL,
- _("%sError encrypting data \"%s\" (%d)"),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
- key, rc);
- }
- }
- else
- {
- /* store password as plain text */
- config_file_write_line (config_file, key, "\"%s\"", value);
- }
-}
-
-/*
- * Writes already encrypted data in secured data configuration file.
- */
-
-void
-secure_data_write_map_encrypted_cb (void *data,
- struct t_hashtable *hashtable,
- const void *key, const void *value)
-{
- struct t_config_file *config_file;
-
- /* make C compiler happy */
- (void) hashtable;
-
- config_file = (struct t_config_file *)data;
-
- /* store data as-is (it is already encrypted) */
- config_file_write_line (config_file, key, "\"%s\"", value);
-}
-
-/*
- * Writes section "data" in secured data configuration file.
- */
-
-int
-secure_data_write_cb (const void *pointer, void *data,
- struct t_config_file *config_file,
- const char *section_name)
-{
- /* make C compiler happy */
- (void) pointer;
- (void) data;
-
- /* write name of section */
- if (!config_file_write_line (config_file, section_name, NULL))
- return WEECHAT_CONFIG_WRITE_ERROR;
-
- if (secure_hashtable_data->items_count > 0)
- {
- /*
- * write a special line indicating if a passphrase must be used to
- * decrypt data (if not, then data is stored as plain text)
- */
- if (!config_file_write_line (config_file,
- SECURE_DATA_PASSPHRASE_FLAG,
- (secure_passphrase) ? "on" : "off"))
- {
- return WEECHAT_CONFIG_WRITE_ERROR;
- }
- /* encrypt and write secured data */
- hashtable_map (secure_hashtable_data,
- &secure_data_write_map_cb, config_file);
- }
- else if (secure_hashtable_data_encrypted->items_count > 0)
- {
- /*
- * if there is encrypted data, that means passphrase was not set and
- * we were unable to decrypt => just save the encrypted content
- * as-is (so that content of sec.conf is not lost)
- */
- if (!config_file_write_line (config_file,
- SECURE_DATA_PASSPHRASE_FLAG, "on"))
- {
- return WEECHAT_CONFIG_WRITE_ERROR;
- }
- hashtable_map (secure_hashtable_data_encrypted,
- &secure_data_write_map_encrypted_cb, config_file);
- }
-
- return WEECHAT_CONFIG_WRITE_OK;
-}
-
-/*
- * Creates options in secured data configuration.
- *
- * Returns:
- * 1: OK
- * 0: error
- */
-
-int
-secure_init_options ()
-{
- struct t_config_section *ptr_section;
-
- secure_config_file = config_file_new (NULL, SECURE_CONFIG_NAME,
- &secure_reload_cb, NULL, NULL);
- if (!secure_config_file)
- return 0;
-
- /* crypt */
- ptr_section = config_file_new_section (secure_config_file, "crypt",
- 0, 0,
- NULL, NULL, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL);
- if (!ptr_section)
- {
- config_file_free (secure_config_file);
- secure_config_file = NULL;
- return 0;
- }
-
- secure_config_crypt_cipher = config_file_new_option (
- secure_config_file, ptr_section,
- "cipher", "integer",
- N_("cipher used to crypt data (the number after algorithm is the size "
- "of the key in bits)"),
- "aes128|aes192|aes256", 0, 0, "aes256", NULL, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- secure_config_crypt_hash_algo = config_file_new_option (
- secure_config_file, ptr_section,
- "hash_algo", "integer",
- N_("hash algorithm used to check the decrypted data"),
- "sha224|sha256|sha384|sha512", 0, 0, "sha256", NULL, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- secure_config_crypt_passphrase_file = config_file_new_option (
- secure_config_file, ptr_section,
- "passphrase_file", "string",
- N_("path to a file containing the passphrase to encrypt/decrypt secured "
- "data; this option is used only when reading file sec.conf; only "
- "first line of file is used; this file is used only if the "
- "environment variable \"WEECHAT_PASSPHRASE\" is not set (the "
- "environment variable has higher priority); security note: it is "
- "recommended to keep this file readable only by you and store it "
- "outside WeeChat home (for example in your home); example: "
- "\"~/.weechat-passphrase\""),
- NULL, 0, 0, "", NULL, 0,
- &secure_check_crypt_passphrase_file, NULL, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL);
- secure_config_crypt_salt = config_file_new_option (
- secure_config_file, ptr_section,
- "salt", "boolean",
- N_("use salt when generating key used in encryption (recommended for "
- "maximum security); when enabled, the content of crypted data in "
- "file sec.conf will be different on each write of the file; if you "
- "put the file sec.conf in a version control system, then you "
- "can turn off this option to have always same content in file"),
- NULL, 0, 0, "on", NULL, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-
- /* data */
- ptr_section = config_file_new_section (
- secure_config_file, "data",
- 0, 0,
- &secure_data_read_cb, NULL, NULL,
- &secure_data_write_cb, NULL, NULL,
- &secure_data_write_cb, NULL, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL);
- if (!ptr_section)
- {
- config_file_free (secure_config_file);
- secure_config_file = NULL;
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Initializes secured data configuration.
+ * Initializes secured data.
*
* Returns:
* 1: OK
@@ -1025,7 +505,6 @@ secure_init_options ()
int
secure_init ()
{
- int rc;
char *ptr_phrase;
/* try to read passphrase (if not set) from env var "WEECHAT_PASSPHRASE" */
@@ -1057,256 +536,7 @@ secure_init ()
return 0;
}
- rc = secure_init_options ();
-
- if (!rc)
- {
- gui_chat_printf (NULL,
- _("FATAL: error initializing configuration options"));
- }
-
- return rc;
-}
-
-/*
- * Reads secured data configuration file.
- *
- * Returns:
- * WEECHAT_CONFIG_READ_OK: OK
- * WEECHAT_CONFIG_READ_MEMORY_ERROR: not enough memory
- * WEECHAT_CONFIG_READ_FILE_NOT_FOUND: file not found
- */
-
-int
-secure_read ()
-{
- int rc;
-
- secure_data_encrypted = 0;
-
- rc = config_file_read (secure_config_file);
-
- return rc;
-}
-
-/*
- * Writes secured data configuration file.
- *
- * Returns:
- * WEECHAT_CONFIG_WRITE_OK: OK
- * WEECHAT_CONFIG_WRITE_ERROR: error
- * WEECHAT_CONFIG_WRITE_MEMORY_ERROR: not enough memory
- */
-
-int
-secure_write ()
-{
- return config_file_write (secure_config_file);
-}
-
-/*
- * Frees secured data file and variables.
- */
-
-void
-secure_free ()
-{
- config_file_free (secure_config_file);
-
- if (secure_hashtable_data)
- {
- hashtable_free (secure_hashtable_data);
- secure_hashtable_data = NULL;
- }
- if (secure_hashtable_data_encrypted)
- {
- hashtable_free (secure_hashtable_data_encrypted);
- secure_hashtable_data_encrypted = NULL;
- }
-}
-
-/*
- * Displays a secured data.
- */
-
-void
-secure_buffer_display_data (void *data,
- struct t_hashtable *hashtable,
- const void *key, const void *value)
-{
- int *line;
-
- /* make C compiler happy */
- (void) value;
-
- line = (int *)data;
-
- if (secure_buffer_display_values && (hashtable == secure_hashtable_data))
- {
- gui_chat_printf_y (secure_buffer, (*line)++,
- " %s%s = %s\"%s%s%s\"",
- key,
- GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS),
- GUI_COLOR(GUI_COLOR_CHAT),
- GUI_COLOR(GUI_COLOR_CHAT_VALUE),
- value,
- GUI_COLOR(GUI_COLOR_CHAT));
- }
- else
- {
- gui_chat_printf_y (secure_buffer, (*line)++,
- " %s", key);
- }
-}
-
-/*
- * Displays content of secured data buffer.
- */
-
-void
-secure_buffer_display ()
-{
- int line, count, count_encrypted;
-
- if (!secure_buffer)
- return;
-
- gui_buffer_clear (secure_buffer);
-
- /* set title buffer */
- gui_buffer_set_title (secure_buffer,
- _("WeeChat secured data (sec.conf) | "
- "Keys: [alt-v] Toggle values"));
-
- line = 0;
-
- gui_chat_printf_y (secure_buffer, line++,
- "Hash algo: %s Cipher: %s Salt: %s",
- secure_hash_algo_string[CONFIG_INTEGER(secure_config_crypt_hash_algo)],
- secure_cipher_string[CONFIG_INTEGER(secure_config_crypt_cipher)],
- (CONFIG_BOOLEAN(secure_config_crypt_salt)) ? _("on") : _("off"));
-
- /* display passphrase */
- line++;
- gui_chat_printf_y (secure_buffer, line++,
- (secure_passphrase) ?
- _("Passphrase is set") : _("Passphrase is not set"));
-
- /* display secured data */
- count = secure_hashtable_data->items_count;
- count_encrypted = secure_hashtable_data_encrypted->items_count;
- if (count > 0)
- {
- line++;
- gui_chat_printf_y (secure_buffer, line++, _("Secured data:"));
- line++;
- hashtable_map (secure_hashtable_data,
- &secure_buffer_display_data, &line);
- }
- /* display secured data not decrypted */
- if (count_encrypted > 0)
- {
- line++;
- gui_chat_printf_y (secure_buffer, line++,
- _("Secured data STILL ENCRYPTED: (use /secure decrypt, "
- "see /help secure)"));
- line++;
- hashtable_map (secure_hashtable_data_encrypted,
- &secure_buffer_display_data, &line);
- }
- if ((count == 0) && (count_encrypted == 0))
- {
- line++;
- gui_chat_printf_y (secure_buffer, line++, _("No secured data set"));
- }
-}
-
-/*
- * Input callback for secured data buffer.
- */
-
-int
-secure_buffer_input_cb (const void *pointer, void *data,
- struct t_gui_buffer *buffer,
- const char *input_data)
-{
- /* make C compiler happy */
- (void) pointer;
- (void) data;
-
- if (string_strcasecmp (input_data, "q") == 0)
- {
- gui_buffer_close (buffer);
- }
-
- return WEECHAT_RC_OK;
-}
-
-/*
- * Close callback for secured data buffer.
- */
-
-int
-secure_buffer_close_cb (const void *pointer, void *data,
- struct t_gui_buffer *buffer)
-{
- /* make C compiler happy */
- (void) pointer;
- (void) data;
- (void) buffer;
-
- secure_buffer = NULL;
-
- return WEECHAT_RC_OK;
-}
-
-/*
- * Assigns secured data buffer to pointer if it is not yet set.
- */
-
-void
-secure_buffer_assign ()
-{
- if (!secure_buffer)
- {
- secure_buffer = gui_buffer_search_by_name (NULL, SECURE_BUFFER_NAME);
- if (secure_buffer)
- {
- secure_buffer->input_callback = &secure_buffer_input_cb;
- secure_buffer->close_callback = &secure_buffer_close_cb;
- }
- }
-}
-
-/*
- * Opens a buffer to display secured data.
- */
-
-void
-secure_buffer_open ()
-{
- if (!secure_buffer)
- {
- secure_buffer = gui_buffer_new (NULL, SECURE_BUFFER_NAME,
- &secure_buffer_input_cb, NULL, NULL,
- &secure_buffer_close_cb, NULL, NULL);
- if (secure_buffer)
- {
- if (!secure_buffer->short_name)
- secure_buffer->short_name = strdup (SECURE_BUFFER_NAME);
- gui_buffer_set (secure_buffer, "type", "free");
- gui_buffer_set (secure_buffer, "localvar_set_no_log", "1");
- gui_buffer_set (secure_buffer, "key_bind_meta-v", "/secure toggle_values");
- }
- secure_buffer_display_values = 0;
- }
-
- if (!secure_buffer)
- return;
-
- gui_window_switch_to_buffer (gui_current_window, secure_buffer, 1);
-
- secure_buffer_display ();
+ return 1;
}
/*
diff --git a/src/core/wee-secure.h b/src/core/wee-secure.h
index 9c01eb068..4a2e9dc9d 100644
--- a/src/core/wee-secure.h
+++ b/src/core/wee-secure.h
@@ -20,13 +20,10 @@
#ifndef WEECHAT_SECURE_H
#define WEECHAT_SECURE_H
-#define SECURE_CONFIG_NAME "sec"
-
#define SECURE_ENV_PASSPHRASE "WEECHAT_PASSPHRASE"
#define SECURE_SALT_DEFAULT "WeeChat!"
#define SECURE_DATA_PASSPHRASE_FLAG "__passphrase__"
-
-#define SECURE_BUFFER_NAME "secured_data"
+#define SECURE_SALT_SIZE 8
enum t_secure_config_hash_algo
{
@@ -43,29 +40,26 @@ enum t_secure_config_cipher
SECURE_CONFIG_CIPHER_AES256,
};
-extern struct t_config_file *secure_config_file;
-extern struct t_config_section *secure_config_section_pwd;
-
-extern struct t_config_option *secure_config_crypt_cipher;
-extern struct t_config_option *secure_config_crypt_hash_algo;
-extern struct t_config_option *secure_config_crypt_passphrase_file;
-extern struct t_config_option *secure_config_crypt_salt;
-
extern char *secure_passphrase;
extern struct t_hashtable *secure_hashtable_data;
extern struct t_hashtable *secure_hashtable_data_encrypted;
+extern char *secure_hash_algo_string[];
+extern int secure_hash_algo[];
+extern char *secure_cipher_string[];
+extern int secure_cipher[];
+extern int secure_data_encrypted;
+extern char *secure_decrypt_error[];
-extern struct t_gui_buffer *secure_buffer;
-extern int secure_buffer_display_values;
-
+extern int secure_encrypt_data (const char *data, int length_data,
+ int hash_algo, int cipher,
+ const char *passphrase, char **encrypted,
+ int *length_encrypted);
+extern int secure_decrypt_data (const char *buffer, int length_buffer,
+ int hash_algo, int cipher,
+ const char *passphrase, char **decrypted,
+ int *length_decrypted);
extern int secure_decrypt_data_not_decrypted (const char *passphrase);
extern int secure_init ();
-extern int secure_read ();
-extern int secure_write ();
-extern void secure_free ();
-extern void secure_buffer_display ();
-extern void secure_buffer_assign ();
-extern void secure_buffer_open ();
extern void secure_end ();
#endif /* WEECHAT_SECURE_H */
diff --git a/src/core/wee-upgrade.c b/src/core/wee-upgrade.c
index 30f131646..a78ba2873 100644
--- a/src/core/wee-upgrade.c
+++ b/src/core/wee-upgrade.c
@@ -32,7 +32,7 @@
#include "wee-upgrade.h"
#include "wee-hook.h"
#include "wee-infolist.h"
-#include "wee-secure.h"
+#include "wee-secure-buffer.h"
#include "wee-string.h"
#include "wee-util.h"
#include "../gui/gui-buffer.h"
diff --git a/src/core/weechat.c b/src/core/weechat.c
index 35a08d98b..dee813023 100644
--- a/src/core/weechat.c
+++ b/src/core/weechat.c
@@ -65,6 +65,7 @@
#include "wee-network.h"
#include "wee-proxy.h"
#include "wee-secure.h"
+#include "wee-secure-config.h"
#include "wee-string.h"
#include "wee-upgrade.h"
#include "wee-utf8.h"
@@ -702,7 +703,9 @@ weechat_init (int argc, char *argv[], void (*gui_init_cb)())
completion_init (); /* add core completion hooks */
gui_key_init (); /* init keys */
network_init_gcrypt (); /* init gcrypt */
- if (!secure_init ()) /* init secured data options (sec.*)*/
+ if (!secure_init ()) /* init secured data */
+ weechat_shutdown (EXIT_FAILURE, 0);
+ if (!secure_config_init ()) /* init secured data options (sec.*)*/
weechat_shutdown (EXIT_FAILURE, 0);
if (!config_weechat_init ()) /* init WeeChat options (weechat.*) */
weechat_shutdown (EXIT_FAILURE, 0);
@@ -710,7 +713,7 @@ weechat_init (int argc, char *argv[], void (*gui_init_cb)())
weechat_create_home_dir (); /* create WeeChat home directory */
log_init (); /* init log file */
plugin_api_init (); /* create some hooks (info,hdata,..)*/
- secure_read (); /* read secured data options */
+ secure_config_read (); /* read secured data options */
config_weechat_read (); /* read WeeChat options */
network_init_gnutls (); /* init GnuTLS */
@@ -747,14 +750,14 @@ weechat_end (void (*gui_end_cb)(int clean_exit))
plugin_end (); /* end plugin interface(s) */
if (CONFIG_BOOLEAN(config_look_save_config_on_exit))
(void) config_weechat_write (); /* save WeeChat config file */
- (void) secure_write (); /* save secured data */
+ (void) secure_config_write (); /* save secured data */
if (gui_end_cb)
(*gui_end_cb) (1); /* shut down WeeChat GUI */
proxy_free_all (); /* free all proxies */
config_weechat_free (); /* free WeeChat options */
- secure_free (); /* free secured data options */
+ secure_config_free (); /* free secured data options */
config_file_free_all (); /* free all configuration files */
gui_key_end (); /* remove all keys */
unhook_all (); /* remove all hooks */
diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c
index 19bfc03bd..f0749d995 100644
--- a/src/gui/gui-buffer.c
+++ b/src/gui/gui-buffer.c
@@ -42,7 +42,7 @@
#include "../core/wee-infolist.h"
#include "../core/wee-list.h"
#include "../core/wee-log.h"
-#include "../core/wee-secure.h"
+#include "../core/wee-secure-buffer.h"
#include "../core/wee-string.h"
#include "../core/wee-utf8.h"
#include "../plugins/plugin.h"