commit 57e0b0d5d8b901d82155af0a313ba7ab94b52173 parent bfd8acbc1190673497931d5ccbcbc736ceb87905 Author: Colin Leroy <colin@colino.net> Date: Mon, 28 Mar 2016 00:00:41 +0200 Merge branch 'master' of ssh://git.claws-mail.org/home/git/claws Diffstat:
26 files changed, 256 insertions(+), 165 deletions(-)
diff --git a/configure.ac b/configure.ac @@ -523,13 +523,11 @@ AC_ARG_WITH(password-encryption, [ --with-password-encryption=PROVIDER Which pwd_crypto="$withval", pwd_crypto="default") if test x"$pwd_crypto" = xdefault; then -dnl ===Default set to "old" for testing, remove the dnls to restore -dnl ===intended functionality. -dnl if test x"$enable_gnutls" = xyes; then -dnl pwd_crypto="gnutls" -dnl else + if test x"$enable_gnutls" = xyes; then + pwd_crypto="gnutls" + else pwd_crypto="old" -dnl fi + fi fi case $pwd_crypto in diff --git a/manual/es/keyboard.xml b/manual/es/keyboard.xml @@ -211,7 +211,7 @@ <entry>Abrir la ventana de traza</entry> </row> <row> - <entry><option>F12</option></entry> + <entry><option>Ctrl+F12</option></entry> <entry>Conmuta la visibilidad de la barra de menú</entry> </row> </tbody> diff --git a/manual/keyboard.xml b/manual/keyboard.xml @@ -85,7 +85,7 @@ <row><entry><option>Shift+Ctrl+a</option></entry><entry>Open address book</entry></row> <row><entry><option>x</option></entry><entry>Execute</entry></row> <row><entry><option>Shift+Ctrl+l</option></entry><entry>Open log window</entry></row> - <row><entry><option>F12</option></entry><entry>Toggles menu bar visibility</entry></row> + <row><entry><option>Ctrl+F12</option></entry><entry>Toggles menu bar visibility</entry></row> </tbody> </tgroup> </informaltable> diff --git a/po/zh_TW.po b/po/zh_TW.po @@ -15698,7 +15698,7 @@ msgstr "郵件必需滿足" #: src/prefs_matcher.c:823 msgid "at least one" -msgstr "至少包含一鉻" +msgstr "至少包含一個" #: src/prefs_matcher.c:824 msgid "all" diff --git a/src/account.c b/src/account.c @@ -54,6 +54,7 @@ #include "filtering.h" #include "prefs_actions.h" #include "hooks.h" +#include "passwordstore.h" enum { ACCOUNT_IS_DEFAULT, @@ -1103,6 +1104,10 @@ static void account_delete(GtkWidget *widget, gpointer data) GINT_TO_POINTER(ac_prefs->account_id)); } + gchar *uid = g_strdup_printf("%d", ac_prefs->account_id); + passwd_store_delete_block(PWS_ACCOUNT, uid); + g_free(uid); + debug_print("Removing filter rules relative to this account...\n"); for(cur = filtering_rules ; cur != NULL ;) { FilteringProp * prop = (FilteringProp *) cur->data; diff --git a/src/imap.c b/src/imap.c @@ -1288,7 +1288,7 @@ static gint imap_session_authenticate(IMAPSession *session, Xstrdup_a(acc_pass, pass, {g_free(pass); return MAILIMAP_NO_ERROR;}); g_free(pass); } else { - acc_pass = passwd_store_get(PWS_ACCOUNT, account->account_name, + acc_pass = passwd_store_get_account(account->account_id, PWS_ACCOUNT_RECV); } try_again: diff --git a/src/inc.c b/src/inc.c @@ -570,35 +570,35 @@ static gint inc_start(IncProgressDialog *inc_dialog) pop3_session = POP3_SESSION(session->session); pop3_session->user = g_strdup(pop3_session->ac_prefs->userid); + if (inc_dialog->show_dialog) + manage_window_focus_in + (inc_dialog->dialog->window, + NULL, NULL); + if (password_get(pop3_session->user, pop3_session->ac_prefs->recv_server, "pop3", pop3_get_port(pop3_session), &(pop3_session->pass))) { /* NOP */; - } else if ((pop3_session->pass = passwd_store_get(PWS_ACCOUNT, - pop3_session->ac_prefs->account_name, PWS_ACCOUNT_RECV)) == NULL) { + } else if ((pop3_session->pass = passwd_store_get_account( + pop3_session->ac_prefs->account_id, PWS_ACCOUNT_RECV)) == NULL) { gchar *pass; - if (inc_dialog->show_dialog) - manage_window_focus_in - (inc_dialog->dialog->window, - NULL, NULL); - pass = input_dialog_query_password_keep (pop3_session->ac_prefs->recv_server, pop3_session->user, &(pop3_session->ac_prefs->session_passwd)); - if (inc_dialog->show_dialog) - manage_window_focus_out - (inc_dialog->dialog->window, - NULL, NULL); - if (pass) { pop3_session->pass = pass; } } + if (inc_dialog->show_dialog) + manage_window_focus_out + (inc_dialog->dialog->window, + NULL, NULL); + qlist = next; } diff --git a/src/mainwindow.c b/src/mainwindow.c @@ -815,7 +815,7 @@ static GtkActionEntry mainwin_entries[] = static GtkToggleActionEntry mainwin_toggle_entries[] = { {"File/OfflineMode", NULL, N_("Offline _mode"), "<control>W", NULL, G_CALLBACK(toggle_work_offline_cb) }, /*toggle*/ - {"View/ShowHide/MenuBar", NULL, N_("Men_ubar"), "F12", NULL, G_CALLBACK(toggle_menubar_cb) }, /* toggle */ + {"View/ShowHide/MenuBar", NULL, N_("Men_ubar"), "<control>F12", NULL, G_CALLBACK(toggle_menubar_cb) }, /* toggle */ {"View/ShowHide/MessageView", NULL, N_("_Message view"), "V", NULL, G_CALLBACK(toggle_message_cb) }, /* toggle */ #ifndef GENERIC_UMPC {"View/ShowHide/StatusBar", NULL, N_("Status _bar"), NULL, NULL, G_CALLBACK(toggle_statusbar_cb) }, /* toggle */ diff --git a/src/news.c b/src/news.c @@ -405,11 +405,12 @@ static Session *news_session_new_for_folder(Folder *folder) userid = ac->userid; if (password_get(userid, ac->nntp_server, "nntp", port, &passwd)) { /* NOP */; - } else if ((passwd = passwd_store_get(PWS_ACCOUNT, ac->account_name, - PWS_ACCOUNT_RECV)) == NULL) + } else if ((passwd = passwd_store_get_account(ac->account_id, + PWS_ACCOUNT_RECV)) == NULL) { passwd = input_dialog_query_password_keep(ac->nntp_server, userid, &(ac->session_passwd)); + } } if (session != NULL) diff --git a/src/password.c b/src/password.c @@ -98,8 +98,9 @@ const gboolean master_passphrase_is_set() const gboolean master_passphrase_is_correct(const gchar *input) { gchar *hash; + gchar **tokens; gchar *stored_hash = prefs_common_get_prefs()->master_passphrase_hash; - const GChecksumType hashtype = G_CHECKSUM_SHA512; + const GChecksumType hashtype = G_CHECKSUM_SHA256; const gssize hashlen = g_checksum_type_get_length(hashtype); gssize stored_len; @@ -108,7 +109,16 @@ const gboolean master_passphrase_is_correct(const gchar *input) if (stored_hash == NULL) return FALSE; - debug_print("|stored_hash|%s|\n", stored_hash); + tokens = g_strsplit_set(stored_hash, "{}", 3); + if (strlen(tokens[0]) != 0 || + strcmp(tokens[1], "SHA-256") || + strlen(tokens[2]) == 0) { + debug_print("Mangled master_passphrase_hash in config, can not use it.\n"); + g_strfreev(tokens); + return FALSE; + } + + stored_hash = tokens[2]; stored_len = strlen(stored_hash); g_return_val_if_fail(stored_len == 2*hashlen, FALSE); @@ -116,8 +126,10 @@ const gboolean master_passphrase_is_correct(const gchar *input) if (!strncasecmp(hash, stored_hash, stored_len)) { g_free(hash); + g_strfreev(tokens); return TRUE; } + g_strfreev(tokens); g_free(hash); return FALSE; @@ -135,12 +147,15 @@ void master_passphrase_forget() if (_master_passphrase != NULL) { memset(_master_passphrase, 0, strlen(_master_passphrase)); g_free(_master_passphrase); + _master_passphrase = NULL; } - _master_passphrase = NULL; } void master_passphrase_change(const gchar *oldp, const gchar *newp) { + const GChecksumType hashtype = G_CHECKSUM_SHA256; + gchar *hash; + if (oldp == NULL) { /* If oldp is NULL, make sure the user has to enter the * current master passphrase before being able to change it. */ @@ -155,8 +170,10 @@ void master_passphrase_change(const gchar *oldp, const gchar *newp) if (newp != NULL) { debug_print("Storing hash of new master passphrase\n"); + hash = g_compute_checksum_for_string(hashtype, newp, -1); prefs_common_get_prefs()->master_passphrase_hash = - g_compute_checksum_for_string(G_CHECKSUM_SHA512, newp, -1); + g_strconcat("{SHA-256}", hash, NULL); + g_free(hash); } else { debug_print("Setting master_passphrase_hash to NULL\n"); prefs_common_get_prefs()->master_passphrase_hash = NULL; @@ -221,6 +238,10 @@ gchar *password_decrypt_old(const gchar *password) #ifdef PASSWORD_CRYPTO_GNUTLS #define BUFSIZE 128 +/* Since we can't count on having GnuTLS new enough to have + * gnutls_cipher_get_iv_size(), we hardcode the IV length for now. */ +#define IVLEN 16 + gchar *password_encrypt_gnutls(const gchar *password, const gchar *encryption_passphrase) { @@ -231,7 +252,7 @@ gchar *password_encrypt_gnutls(const gchar *password, gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA512; gnutls_cipher_hd_t handle; gnutls_datum_t key, iv; - int ivlen, keylen, digestlen, blocklen, ret, i; + int keylen, digestlen, blocklen, ret, i; unsigned char hashbuf[BUFSIZE], *buf, *encbuf, *base, *output; #if defined G_OS_UNIX int rnd; @@ -242,7 +263,7 @@ gchar *password_encrypt_gnutls(const gchar *password, g_return_val_if_fail(password != NULL, NULL); g_return_val_if_fail(encryption_passphrase != NULL, NULL); - ivlen = gnutls_cipher_get_iv_size(algo); +/* ivlen = gnutls_cipher_get_iv_size(algo);*/ keylen = gnutls_cipher_get_key_size(algo); blocklen = gnutls_cipher_get_block_size(algo); digestlen = gnutls_hash_get_len(digest); @@ -274,20 +295,19 @@ gchar *password_encrypt_gnutls(const gchar *password, debug_print("Could not acquire a CSP handle.\n"); #endif g_free(key.data); - g_free(iv.data); return NULL; } /* Prepare random IV for cipher */ - iv.data = malloc(ivlen); - iv.size = ivlen; + iv.data = malloc(IVLEN); + iv.size = IVLEN; #if defined G_OS_UNIX - ret = read(rnd, iv.data, ivlen); - if (ret != ivlen) { + ret = read(rnd, iv.data, IVLEN); + if (ret != IVLEN) { perror("read into iv"); close(rnd); #elif defined G_OS_WIN32 - if (!CryptGenRandom(rnd, ivlen, iv.data)) { + if (!CryptGenRandom(rnd, IVLEN, iv.data)) { debug_print("Could not read random data for IV\n"); CryptReleaseContext(rnd, 0); #endif @@ -377,7 +397,7 @@ gchar *password_decrypt_gnutls(const gchar *password, gnutls_digest_algorithm_t digest = GNUTLS_DIG_UNKNOWN; gnutls_cipher_hd_t handle; gnutls_datum_t key, iv; - int ivlen, keylen, digestlen, blocklen, ret, i; + int keylen, digestlen, blocklen, ret, i; gsize len; unsigned char hashbuf[BUFSIZE], *buf; #if defined G_OS_UNIX @@ -413,7 +433,7 @@ gchar *password_decrypt_gnutls(const gchar *password, return NULL; } - ivlen = gnutls_cipher_get_iv_size(algo); +/* ivlen = gnutls_cipher_get_iv_size(algo); */ keylen = gnutls_cipher_get_key_size(algo); blocklen = gnutls_cipher_get_block_size(algo); digestlen = gnutls_hash_get_len(digest); @@ -447,21 +467,20 @@ gchar *password_decrypt_gnutls(const gchar *password, debug_print("Could not acquire a CSP handle.\n"); #endif g_free(key.data); - g_free(iv.data); g_strfreev(tokens); return NULL; } /* Prepare random IV for cipher */ - iv.data = malloc(ivlen); - iv.size = ivlen; + iv.data = malloc(IVLEN); + iv.size = IVLEN; #if defined G_OS_UNIX - ret = read(rnd, iv.data, ivlen); - if (ret != ivlen) { + ret = read(rnd, iv.data, IVLEN); + if (ret != IVLEN) { perror("read into iv"); close(rnd); #elif defined G_OS_WIN32 - if (!CryptGenRandom(rnd, ivlen, iv.data)) { + if (!CryptGenRandom(rnd, IVLEN, iv.data)) { debug_print("Could not read random data for IV\n"); CryptReleaseContext(rnd, 0); #endif @@ -530,9 +549,9 @@ gchar *password_encrypt(const gchar *password, encryption_passphrase = master_passphrase(); return password_encrypt_real(password, encryption_passphrase); -#endif - +#else return password_encrypt_old(password); +#endif } gchar *password_decrypt(const gchar *password, diff --git a/src/passwordstore.c b/src/passwordstore.c @@ -107,6 +107,7 @@ gboolean passwd_store_set(PasswordBlockType block_type, const gchar *password, gboolean encrypted) { + const gchar *p = password; PasswordBlock *block; gchar *encrypted_password; @@ -115,20 +116,30 @@ gboolean passwd_store_set(PasswordBlockType block_type, g_return_val_if_fail(block_name != NULL, FALSE); g_return_val_if_fail(password_id != NULL, FALSE); + /* Empty password string equals null password for us. */ + if (strlen(password) == 0) + p = NULL; + debug_print("%s password '%s' in block (%d/%s)%s\n", - (password == NULL ? "Deleting" : "Storing"), + (p == NULL ? "Deleting" : "Storing"), password_id, block_type, block_name, (encrypted ? ", already encrypted" : "") ); // find correct block (create if needed) - if ((block = _get_block(block_type, block_name)) == NULL && - (block = _new_block(block_type, block_name)) == NULL) { - debug_print("Could not create password block (%d/%s)\n", - block_type, block_name); - return FALSE; + if ((block = _get_block(block_type, block_name)) == NULL) { + /* If caller wants to delete a password, and even its block + * doesn't exist, we're done. */ + if (p == NULL) + return TRUE; + + if ((block = _new_block(block_type, block_name)) == NULL) { + debug_print("Could not create password block (%d/%s)\n", + block_type, block_name); + return FALSE; + } } - if (password == NULL) { + if (p == NULL) { /* NULL password was passed to us, so delete the entry with * corresponding id */ g_hash_table_remove(block->entries, password_id); @@ -136,14 +147,14 @@ gboolean passwd_store_set(PasswordBlockType block_type, if (!encrypted) { /* encrypt password before saving it */ if ((encrypted_password = - password_encrypt(password, NULL)) == NULL) { + password_encrypt(p, NULL)) == NULL) { debug_print("Could not encrypt password '%s' for block (%d/%s).\n", password_id, block_type, block_name); return FALSE; } } else { /* password is already in encrypted form already */ - encrypted_password = g_strdup(password); + encrypted_password = g_strdup(p); } // add encrypted password to the block @@ -197,6 +208,49 @@ gchar *passwd_store_get(PasswordBlockType block_type, return password; } +gboolean passwd_store_delete_block(PasswordBlockType block_type, + const gchar *block_name) +{ + PasswordBlock *block; + + g_return_val_if_fail(block_type >= 0 && block_type < NUM_PWS_TYPES, + FALSE); + g_return_val_if_fail(block_name != NULL, FALSE); + + debug_print("Deleting block (%d/%s)\n", block_type, block_name); + + // find correct block + if ((block = _get_block(block_type, block_name)) == NULL) { + debug_print("Block (%d/%s) not found.\n", block_type, block_name); + return FALSE; + } + + g_hash_table_destroy(block->entries); + block->entries = NULL; + return TRUE; +} + +gboolean passwd_store_set_account(gint account_id, + const gchar *password_id, + const gchar *password, + gboolean encrypted) +{ + gchar *uid = g_strdup_printf("%d", account_id); + gboolean ret = passwd_store_set(PWS_ACCOUNT, uid, + password_id, password, encrypted); + g_free(uid); + return ret; +} + +gchar *passwd_store_get_account(gint account_id, + const gchar *password_id) +{ + gchar *uid = g_strdup_printf("%d", account_id); + gchar *ret = passwd_store_get(PWS_ACCOUNT, uid, password_id); + g_free(uid); + return ret; +} + /* Reencrypts all stored passwords. */ void passwd_store_reencrypt_all(const gchar *old_mpwd, const gchar *new_mpwd) diff --git a/src/passwordstore.h b/src/passwordstore.h @@ -57,6 +57,9 @@ gchar *passwd_store_get(PasswordBlockType block_type, const gchar *block_name, const gchar *password_id); +gboolean passwd_store_delete_block(PasswordBlockType block_type, + const gchar *block_name); + /* Reencrypts all stored passwords using new_mpwd as an encryption * password. */ void passwd_store_reencrypt_all(const gchar *old_mpwd, @@ -66,6 +69,15 @@ void passwd_store_reencrypt_all(const gchar *old_mpwd, void passwd_store_write_config(void); void passwd_store_read_config(void); +/* Convenience wrappers for handling account passwords. + * (This is to save some boilerplate code converting account_id to + * a string and freeing the string afterwards.) */ +gboolean passwd_store_set_account(gint account_id, + const gchar *password_id, + const gchar *password, + gboolean encrypted); +gchar *passwd_store_get_account(gint account_id, const gchar *block_name); + /* Macros for standard, predefined password IDs. */ #define PWS_ACCOUNT_RECV "recv" #define PWS_ACCOUNT_SEND "send" diff --git a/src/plugins/gdata/cm_gdata_contacts.c b/src/plugins/gdata/cm_gdata_contacts.c @@ -31,7 +31,7 @@ #include "addr_compl.h" #include "main.h" -#include "password.h" +#include "passwordstore.h" #include "prefs_common.h" #include "mainwindow.h" #include "common/log.h" @@ -522,6 +522,8 @@ static guchar* decode(const gchar *in) static void query() { + gchar *token; + if(cm_gdata_contacts_query_running) { debug_print("GData plugin: Network query already in progress"); @@ -552,14 +554,12 @@ static void query() { #if GDATA_CHECK_VERSION(0,17,2) /* Try to restore from saved refresh token.*/ - if(cm_gdata_config.oauth2_refresh_token) + if((token = passwd_store_get(PWS_PLUGIN, + "GData", GDATA_TOKEN_PWD_STRING)) != NULL) { - gchar *token = password_decrypt(cm_gdata_config.oauth2_refresh_token, NULL); log_message(LOG_PROTOCOL, _("GData plugin: Trying to refresh authorization\n")); - gdata_oauth2_authorizer_set_refresh_token(authorizer, (token != NULL ? token : "")); - if (token != NULL) { - memset(token, 0, strlen(token)); - } + gdata_oauth2_authorizer_set_refresh_token(authorizer, token); + memset(token, 0, strlen(token)); g_free(token); gdata_authorizer_refresh_authorization_async(GDATA_AUTHORIZER(authorizer), NULL, (GAsyncReadyCallback)cm_gdata_refresh_ready, NULL); } @@ -638,9 +638,13 @@ void cm_gdata_contacts_done(void) #if GDATA_CHECK_VERSION(0,17,2) /* store refresh token */ pass = gdata_oauth2_authorizer_dup_refresh_token(authorizer); - cm_gdata_config.oauth2_refresh_token = password_encrypt(pass, NULL); - memset(pass, 0, strlen(pass)); - g_free(pass); + passwd_store_set(PWS_PLUGIN, "GData", GDATA_TOKEN_PWD_STRING, + pass, FALSE); + if (pass != NULL) { + memset(pass, 0, strlen(pass)); + g_free(pass); + } + passwd_store_write_config(); #endif g_object_unref(G_OBJECT(authorizer)); diff --git a/src/plugins/gdata/cm_gdata_prefs.c b/src/plugins/gdata/cm_gdata_prefs.c @@ -152,16 +152,3 @@ void cm_gdata_prefs_done(void) prefs_gtk_unregister_page((PrefsPage*) &gdata_page); } } - -void cm_gdata_prefs_master_passphrase_change(const gchar *oldp, const gchar *newp) { - gchar *pass; - int i; - - pass = password_decrypt(cm_gdata_config.oauth2_refresh_token, oldp); - if (pass != NULL) { - g_free(cm_gdata_config.oauth2_refresh_token); - cm_gdata_config.oauth2_refresh_token = password_encrypt(pass, newp); - memset(pass, 0, strlen(pass)); - } - g_free(pass); -} diff --git a/src/plugins/gdata/cm_gdata_prefs.h b/src/plugins/gdata/cm_gdata_prefs.h @@ -20,6 +20,8 @@ #include "prefs_gtk.h" +#define GDATA_TOKEN_PWD_STRING "oauth2_refresh_token" + typedef struct { char *username; char *password; @@ -33,6 +35,5 @@ extern PrefParam cm_gdata_param[]; void cm_gdata_prefs_init(void); void cm_gdata_prefs_done(void); -void cm_gdata_prefs_master_passphrase_change(const gchar *oldp, const gchar *newp); #endif /* CM_GDATA_PREFS_H_ */ diff --git a/src/plugins/gdata/gdata_plugin.c b/src/plugins/gdata/gdata_plugin.c @@ -37,6 +37,7 @@ #include "main.h" #include "mainwindow.h" #include "addr_compl.h" +#include "passwordstore.h" #include "cm_gdata_contacts.h" #include "cm_gdata_prefs.h" @@ -121,6 +122,14 @@ gint plugin_init(gchar **error) prefs_read_config(cm_gdata_param, "GDataPlugin", rcpath, NULL); g_free(rcpath); + /* If the refresh token is still stored in config, save it to + * password store. */ + if(cm_gdata_config.oauth2_refresh_token != NULL) { + passwd_store_set(PWS_PLUGIN, "GData", GDATA_TOKEN_PWD_STRING, + cm_gdata_config.oauth2_refresh_token, FALSE); + passwd_store_write_config(); + } + cm_gdata_prefs_init(); debug_print("GData plugin loaded\n"); @@ -181,11 +190,6 @@ const gchar *plugin_version(void) return VERSION; } -void plugin_master_passphrase_change (const gchar *oldp, const gchar *newp) -{ - cm_gdata_prefs_master_passphrase_change(oldp, newp); -} - struct PluginFeature *plugin_provides(void) { static struct PluginFeature features[] = diff --git a/src/plugins/managesieve/managesieve.c b/src/plugins/managesieve/managesieve.c @@ -25,6 +25,7 @@ #include "claws.h" #include "account.h" +#include "passwordstore.h" #include "gtk/inputdialog.h" #include "md5.h" #include "utils.h" @@ -1055,10 +1056,10 @@ static void sieve_session_reset(SieveSession *session) g_free(session->pass); if (config->auth == SIEVEAUTH_NONE) { session->pass = NULL; - } else if (reuse_auth && account->passwd) { - session->pass = g_strdup(account->passwd); - } else if (config->passwd && config->passwd[0]) { - session->pass = g_strdup(config->passwd); + } else if (reuse_auth && (session->pass = passwd_store_get_account( + account->account_id, PWS_ACCOUNT_RECV))) { + } else if ((session->pass = passwd_store_get_account( + account->account_id, "sieve"))) { } else if (password_get(session->user, session->host, "sieve", session->port, &session->pass)) { } else { diff --git a/src/plugins/managesieve/sieve_prefs.c b/src/plugins/managesieve/sieve_prefs.c @@ -32,6 +32,8 @@ #include "gtk/combobox.h" #include "alertpanel.h" #include "passcrypt.h" +#include "password.h" +#include "passwordstore.h" #include "utils.h" #include "prefs.h" #include "prefs_gtk.h" @@ -113,6 +115,7 @@ static void sieve_prefs_account_create_widget_func(PrefsPage *_page, struct SieveAccountPage *page = (struct SieveAccountPage *) _page; PrefsAccount *account = (PrefsAccount *) data; SieveAccountConfig *config; + gchar *pass; GtkWidget *page_vbox, *sieve_vbox; GtkWidget *hbox; @@ -288,8 +291,12 @@ static void sieve_prefs_account_create_widget_func(PrefsPage *_page, gtk_entry_set_text(GTK_ENTRY(host_entry), config->host); if (config->userid != NULL) gtk_entry_set_text(GTK_ENTRY(uid_entry), config->userid); - if (config->passwd != NULL) - gtk_entry_set_text(GTK_ENTRY(pass_entry), config->passwd); + if ((pass = passwd_store_get_account(account->account_id, + "sieve")) != NULL) { + gtk_entry_set_text(GTK_ENTRY(pass_entry), pass); + memset(pass, 0, strlen(pass)); + g_free(pass); + } combobox_select_by_data(GTK_COMBO_BOX(auth_menu), config->auth_type); @@ -363,9 +370,14 @@ static gint sieve_prefs_account_apply(struct SieveAccountPage *page) SIEVE_TLS_MAYBE : SIEVE_TLS_YES; + g_free(config->host); + g_free(config->userid); + config->host = gtk_editable_get_chars(GTK_EDITABLE(page->host_entry), 0, -1); config->userid = gtk_editable_get_chars(GTK_EDITABLE(page->uid_entry), 0, -1); - config->passwd = gtk_editable_get_chars(GTK_EDITABLE(page->pass_entry), 0, -1); + passwd_store_set_account(page->account->account_id, "sieve", + gtk_editable_get_chars(GTK_EDITABLE(page->pass_entry), 0, -1), + FALSE); config->auth_type = combobox_get_active_data(GTK_COMBO_BOX(page->auth_menu)); sieve_prefs_account_set_config(page->account, config); @@ -484,7 +496,6 @@ struct SieveAccountConfig *sieve_prefs_account_get_config( config->auth = SIEVEAUTH_REUSE; config->auth_type = SIEVEAUTH_AUTO; config->userid = NULL; - config->passwd = NULL; confstr = prefs_account_get_privacy_prefs(account, "sieve"); if (confstr == NULL) @@ -527,8 +538,14 @@ struct SieveAccountConfig *sieve_prefs_account_get_config( } config->userid = g_base64_decode(enc_userid, &len); - config->passwd = g_base64_decode(enc_passwd, &len); - passcrypt_decrypt(config->passwd, len); + if (enc_passwd[0]) { + // migrate password from passcrypt to passwordstore + gchar *pass = g_base64_decode(enc_passwd, &len); + passcrypt_decrypt(pass, len); + passwd_store_set_account(account->account_id, "sieve", + pass, FALSE); + g_free(pass); + } return config; } @@ -538,8 +555,6 @@ void sieve_prefs_account_set_config( { gchar *confstr = NULL; gchar *enc_userid = NULL; - gchar *enc_passwd = NULL; - gchar *tmp; gsize len; if (config->userid) { @@ -547,14 +562,6 @@ void sieve_prefs_account_set_config( enc_userid = g_base64_encode(config->userid, len); } - if (config->passwd) { - tmp = g_strdup(config->passwd); - len = strlen(tmp); - passcrypt_encrypt(tmp, len); - enc_passwd = g_base64_encode(tmp, len); - g_free(tmp); - } - confstr = g_strdup_printf("%c%c %s %c%hu %hhu %hhu %hhu %s %s", config->enable ? 'y' : 'n', config->use_host ? 'y' : 'n', @@ -565,12 +572,10 @@ void sieve_prefs_account_set_config( config->auth, config->auth_type, enc_userid ? enc_userid : "", - enc_passwd ? enc_passwd : ""); + ""); if (enc_userid) g_free(enc_userid); - if (enc_passwd) - g_free(enc_passwd); prefs_account_set_privacy_prefs(account, "sieve", confstr); @@ -583,7 +588,6 @@ void sieve_prefs_account_free_config(SieveAccountConfig *config) { g_free(config->host); g_free(config->userid); - g_free(config->passwd); g_free(config); } diff --git a/src/plugins/managesieve/sieve_prefs.h b/src/plugins/managesieve/sieve_prefs.h @@ -44,7 +44,6 @@ struct SieveAccountConfig SieveAuthType auth_type; SieveTLSType tls_type; gchar *userid; - gchar *passwd; }; extern SieveConfig sieve_config; diff --git a/src/plugins/spam_report/claws.def b/src/plugins/spam_report/claws.def @@ -33,8 +33,6 @@ matcherlist_free matcherlist_match matcherlist_new matcherprop_new -password_decrypt -password_encrypt pref_get_escaped_pref pref_get_unescaped_pref prefs_common diff --git a/src/plugins/spam_report/spam_report.c b/src/plugins/spam_report/spam_report.c @@ -222,7 +222,7 @@ static void report_spam(gint id, ReportInterface *intf, MsgInfo *msginfo, gchar switch(intf->type) { case INTF_HTTP_AUTH: if (spamreport_prefs.user[id] && *(spamreport_prefs.user[id])) { - gchar *pass = password_decrypt(spamreport_prefs.pass[id], NULL); + gchar *pass = spamreport_passwd_get(spam_interfaces[id].name); auth = g_strdup_printf("%s:%s", spamreport_prefs.user[id], (pass != NULL ? pass : "")); if (pass != NULL) { memset(pass, 0, strlen(pass)); @@ -407,11 +407,6 @@ const gchar *plugin_version(void) return VERSION; } -void plugin_master_passphrase_change (const gchar *oldp, const gchar *newp) -{ - spamreport_master_passphrase_change(oldp, newp); -} - struct PluginFeature *plugin_provides(void) { static struct PluginFeature features[] = diff --git a/src/plugins/spam_report/spam_report_prefs.c b/src/plugins/spam_report/spam_report_prefs.c @@ -76,6 +76,8 @@ void spamreport_prefs_init(void) { static gchar *path[3]; gchar *rcpath; + guint i; + gboolean passwords_migrated = FALSE; path[0] = _("Plugins"); path[1] = _("SpamReport"); @@ -85,7 +87,18 @@ void spamreport_prefs_init(void) rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL); prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL); g_free(rcpath); - + + /* Move passwords that are still in main config to password store. */ + for (i = 0; i < INTF_LAST; i++) { + if (spamreport_prefs.pass[i] != NULL) { + spamreport_passwd_set(spam_interfaces[i].name, + spamreport_prefs.pass[i]); + passwords_migrated = TRUE; + } + } + if (passwords_migrated) + passwd_store_write_config(); + spamreport_prefs_page.page.path = path; spamreport_prefs_page.page.create_widget = create_spamreport_prefs_page; spamreport_prefs_page.page.destroy_widget = destroy_spamreport_prefs_page; @@ -128,7 +141,7 @@ static void create_spamreport_prefs_page(PrefsPage *page, gtk_entry_set_text(GTK_ENTRY(prefs_page->user_entry[i]), spamreport_prefs.user[i] ? spamreport_prefs.user[i]:""); - pass = password_decrypt(spamreport_prefs.pass[i], NULL); + pass = spamreport_passwd_get(spam_interfaces[i].name); gtk_entry_set_text(GTK_ENTRY(prefs_page->pass_entry[i]), pass ? pass:""); if (pass != NULL) { memset(pass, 0, strlen(pass)); @@ -209,7 +222,7 @@ static void save_spamreport_prefs(PrefsPage *page) GTK_EDITABLE(prefs_page->user_entry[i]), 0, -1); pass = gtk_editable_get_chars(GTK_EDITABLE(prefs_page->pass_entry[i]), 0, -1); - spamreport_prefs.pass[i] = password_encrypt(pass, NULL); + spamreport_passwd_set(spam_interfaces[i].name, pass); memset(pass, 0, strlen(pass)); g_free(pass); } @@ -231,19 +244,6 @@ static void save_spamreport_prefs(PrefsPage *page) prefs_file_close_revert(pref_file); } else prefs_file_close(pref_file); -} -void spamreport_master_passphrase_change(const gchar *oldp, const gchar *newp) { - gchar *pass; - int i; - - for (i = 0; i < INTF_LAST; i++) { - pass = password_decrypt(spamreport_prefs.pass[i], oldp); - if (pass != NULL) { - g_free(spamreport_prefs.pass[i]); - spamreport_prefs.pass[i] = password_encrypt(pass, newp); - memset(pass, 0, strlen(pass)); - } - g_free(pass); - } + passwd_store_write_config(); } diff --git a/src/plugins/spam_report/spam_report_prefs.h b/src/plugins/spam_report/spam_report_prefs.h @@ -24,6 +24,7 @@ #include <glib.h> #include "procmsg.h" +#include "passwordstore.h" #define SPAM_REPORT_USERAGENT "Claws Mail SpamReport plugin " @@ -65,6 +66,10 @@ extern SpamReportPrefs spamreport_prefs; void spamreport_prefs_init(void); void spamreport_prefs_done(void); -void spamreport_master_passphrase_change(const gchar *oldp, const gchar *newp); + +#define spamreport_passwd_set(id, pwd) \ + passwd_store_set(PWS_PLUGIN, "SpamReport", id, pwd, FALSE) +#define spamreport_passwd_get(id) \ + passwd_store_get(PWS_PLUGIN, "SpamReport", id) #endif diff --git a/src/prefs_account.c b/src/prefs_account.c @@ -1364,7 +1364,7 @@ static void basic_create_widget_func(PrefsPage * _page, prefs_set_dialog(basic_param); /* Passwords are handled outside of PrefParams. */ - buf = passwd_store_get(PWS_ACCOUNT, ac_prefs->account_name, + buf = passwd_store_get_account(ac_prefs->account_id, PWS_ACCOUNT_RECV); gtk_entry_set_text(GTK_ENTRY(page->pass_entry), buf); g_free(buf); @@ -1901,7 +1901,7 @@ static void send_create_widget_func(PrefsPage * _page, prefs_set_dialog(send_param); /* Passwords are handled outside of PrefParams. */ - buf = passwd_store_get(PWS_ACCOUNT, ac_prefs->account_name, + buf = passwd_store_get_account(ac_prefs->account_id, PWS_ACCOUNT_SEND); gtk_entry_set_text(GTK_ENTRY(page->smtp_pass_entry), buf); g_free(buf); @@ -2629,11 +2629,11 @@ static void ssl_create_widget_func(PrefsPage * _page, prefs_set_dialog(ssl_param); /* Passwords are handled outside of PrefParams. */ - buf = passwd_store_get(PWS_ACCOUNT, ac_prefs->account_name, + buf = passwd_store_get_account(ac_prefs->account_id, PWS_ACCOUNT_RECV_CERT); gtk_entry_set_text(GTK_ENTRY(page->entry_in_cert_pass), buf); g_free(buf); - buf = passwd_store_get(PWS_ACCOUNT, ac_prefs->account_name, + buf = passwd_store_get_account(ac_prefs->account_id, PWS_ACCOUNT_SEND_CERT); gtk_entry_set_text(GTK_ENTRY(page->entry_out_cert_pass), buf); g_free(buf); @@ -2974,7 +2974,7 @@ static gint prefs_basic_apply(void) prefs_set_data_from_dialog(basic_param); /* Passwords are stored outside of PrefParams. */ - passwd_store_set(PWS_ACCOUNT, tmp_ac_prefs.account_name, + passwd_store_set_account(tmp_ac_prefs.account_id, PWS_ACCOUNT_RECV, gtk_entry_get_text(GTK_ENTRY(basic_page.pass_entry)), FALSE); @@ -3003,7 +3003,7 @@ static gint prefs_send_apply(void) prefs_set_data_from_dialog(send_param); /* Passwords are stored outside of PrefParams. */ - passwd_store_set(PWS_ACCOUNT, tmp_ac_prefs.account_name, + passwd_store_set_account(tmp_ac_prefs.account_id, PWS_ACCOUNT_SEND, gtk_entry_get_text(GTK_ENTRY(send_page.smtp_pass_entry)), FALSE); @@ -3035,11 +3035,11 @@ static gint prefs_ssl_apply(void) prefs_set_data_from_dialog(ssl_param); /* Passwords are stored outside of PrefParams. */ - passwd_store_set(PWS_ACCOUNT, tmp_ac_prefs.account_name, + passwd_store_set_account(tmp_ac_prefs.account_id, PWS_ACCOUNT_RECV_CERT, gtk_entry_get_text(GTK_ENTRY(ssl_page.entry_in_cert_pass)), FALSE); - passwd_store_set(PWS_ACCOUNT, tmp_ac_prefs.account_name, + passwd_store_set_account(tmp_ac_prefs.account_id, PWS_ACCOUNT_SEND_CERT, gtk_entry_get_text(GTK_ENTRY(ssl_page.entry_out_cert_pass)), FALSE); @@ -3431,8 +3431,7 @@ static gboolean sslcert_get_client_cert_hook(gpointer source, gpointer data) pwd_id = PWS_ACCOUNT_RECV_CERT; } - hookdata->password = passwd_store_get(PWS_ACCOUNT, - account->account_name, pwd_id); + hookdata->password = passwd_store_get_account(account->account_id, pwd_id); return TRUE; } @@ -3598,25 +3597,36 @@ void prefs_account_read_config(PrefsAccount *ac_prefs, const gchar *label) privacy_prefs = NULL; } + gboolean passwords_migrated = FALSE; + if (ac_prefs->passwd != NULL && strlen(ac_prefs->passwd) > 1) { - passwd_store_set(PWS_ACCOUNT, ac_prefs->account_name, + passwd_store_set_account(ac_prefs->account_id, PWS_ACCOUNT_RECV, ac_prefs->passwd, TRUE); + passwords_migrated = TRUE; } if (ac_prefs->smtp_passwd != NULL && strlen(ac_prefs->smtp_passwd) > 1) { - passwd_store_set(PWS_ACCOUNT, ac_prefs->account_name, + passwd_store_set_account(ac_prefs->account_id, PWS_ACCOUNT_SEND, ac_prefs->smtp_passwd, TRUE); + passwords_migrated = TRUE; } if (ac_prefs->in_ssl_client_cert_pass != NULL && strlen(ac_prefs->in_ssl_client_cert_pass) > 1) { - passwd_store_set(PWS_ACCOUNT, ac_prefs->account_name, + passwd_store_set_account(ac_prefs->account_id, PWS_ACCOUNT_RECV_CERT, ac_prefs->in_ssl_client_cert_pass, TRUE); + passwords_migrated = TRUE; } if (ac_prefs->out_ssl_client_cert_pass != NULL && strlen(ac_prefs->out_ssl_client_cert_pass) > 1) { - passwd_store_set(PWS_ACCOUNT, ac_prefs->account_name, + passwd_store_set_account(ac_prefs->account_id, PWS_ACCOUNT_SEND_CERT, ac_prefs->out_ssl_client_cert_pass, TRUE); + passwords_migrated = TRUE; } + /* Write out password store to file immediately after their move + * from accountrc there. */ + if (passwords_migrated) + passwd_store_write_config(); + ac_prefs->receive_in_progress = FALSE; prefs_custom_header_read_config(ac_prefs); @@ -3694,6 +3704,8 @@ void prefs_account_write_config_all(GList *account_list) if (prefs_file_close(pfile) < 0) g_warning("failed to write configuration to file"); + + passwd_store_write_config(); } #undef WRITE_PARAM diff --git a/src/send_message.c b/src/send_message.c @@ -305,7 +305,7 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g &(smtp_session->pass))) { /* NOP */; } else if ((smtp_session->pass = - passwd_store_get(PWS_ACCOUNT, ac_prefs->account_name, + passwd_store_get_account(ac_prefs->account_id, PWS_ACCOUNT_SEND)) == NULL) { smtp_session->pass = input_dialog_query_password_keep @@ -323,8 +323,8 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g ac_prefs->smtp_server, "smtp", port, &(smtp_session->pass))) { /* NOP */; - } else if ((smtp_session->pass = passwd_store_get(PWS_ACCOUNT, - ac_prefs->account_name, PWS_ACCOUNT_RECV)) == NULL) { + } else if ((smtp_session->pass = passwd_store_get_account( + ac_prefs->account_id, PWS_ACCOUNT_RECV)) == NULL) { smtp_session->pass = input_dialog_query_password_keep (ac_prefs->smtp_server, diff --git a/src/wizard.c b/src/wizard.c @@ -760,14 +760,10 @@ static gboolean wizard_write_config(WizardWindow *wizard) prefs_account->smtp_userid = g_strdup( gtk_entry_get_text(GTK_ENTRY(wizard->smtp_username))); - passwd_store_set(PWS_ACCOUNT, - prefs_account->account_name, - PWS_ACCOUNT_RECV, + passwd_store_set_account(prefs_account->account_id, PWS_ACCOUNT_RECV, gtk_entry_get_text(GTK_ENTRY(wizard->recv_password)), FALSE); - passwd_store_set(PWS_ACCOUNT, - prefs_account->account_name, - PWS_ACCOUNT_SEND, + passwd_store_set_account(prefs_account->account_id, PWS_ACCOUNT_SEND, gtk_entry_get_text(GTK_ENTRY(wizard->smtp_password)), FALSE); @@ -804,14 +800,10 @@ static gboolean wizard_write_config(WizardWindow *wizard) prefs_account->in_ssl_client_cert_file = g_strdup( gtk_entry_get_text(GTK_ENTRY(wizard->recv_ssl_cert_file))); - passwd_store_set(PWS_ACCOUNT, - prefs_account->account_name, - PWS_ACCOUNT_SEND_CERT, + passwd_store_set_account(prefs_account->account_id, PWS_ACCOUNT_SEND_CERT, gtk_entry_get_text(GTK_ENTRY(wizard->smtp_ssl_cert_pass)), FALSE); - passwd_store_set(PWS_ACCOUNT, - prefs_account->account_name, - PWS_ACCOUNT_RECV_CERT, + passwd_store_set_account(prefs_account->account_id, PWS_ACCOUNT_RECV_CERT, gtk_entry_get_text(GTK_ENTRY(wizard->recv_ssl_cert_pass)), FALSE); #endif