#include "common/utils.h"
#include "passwordstore.h"
#include "password.h"
+#include "prefs_common.h"
#include "prefs_gtk.h"
+#include "prefs_migration.h"
+#include "file-utils.h"
static GSList *_password_store;
GSList *item;
PasswordBlock *block;
- g_return_val_if_fail(block_type >= 0 && block_type < NUM_PWS_TYPES,
- NULL);
+ g_return_val_if_fail(block_type < NUM_PWS_TYPES, NULL);
g_return_val_if_fail(block_name != NULL, NULL);
for (item = _password_store; item != NULL; item = item->next) {
{
PasswordBlock *block;
- g_return_val_if_fail(block_type >= 0 && block_type < NUM_PWS_TYPES,
- NULL);
+ g_return_val_if_fail(block_type < NUM_PWS_TYPES, NULL);
g_return_val_if_fail(block_name != NULL, NULL);
/* First check to see if the block doesn't already exist. */
return block;
}
-///////////////////////////////////////////////////////////////
+/*************************************************************/
/* Stores a password. */
gboolean passwd_store_set(PasswordBlockType block_type,
const gchar *password,
gboolean encrypted)
{
- const gchar *p = password;
+ const gchar *p;
PasswordBlock *block;
gchar *encrypted_password;
- g_return_val_if_fail(block_type >= 0 && block_type < NUM_PWS_TYPES,
- FALSE);
+ g_return_val_if_fail(block_type < NUM_PWS_TYPES, FALSE);
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)
+ if (password == NULL || strlen(password) == 0)
p = NULL;
+ else
+ p = password;
- debug_print("%s password '%s' in block (%d/%s)%s\n",
- (p == NULL ? "Deleting" : "Storing"),
- password_id, block_type, block_name,
- (encrypted ? ", already encrypted" : "") );
-
- // find correct block (create if needed)
+ /* find correct block (create if needed) */
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. */
}
}
+ debug_print("%s password for '%s' in block (%d/%s)%s\n",
+ (p == NULL ? "Deleting" : "Storing"),
+ password_id, block_type, block_name,
+ (encrypted ? ", already encrypted" : "") );
+
if (p == NULL) {
/* NULL password was passed to us, so delete the entry with
* corresponding id */
encrypted_password = g_strdup(p);
}
- // add encrypted password to the block
+ /* add encrypted password to the block */
g_hash_table_insert(block->entries,
g_strdup(password_id),
encrypted_password);
PasswordBlock *block;
gchar *encrypted_password, *password;
- g_return_val_if_fail(block_type >= 0 && block_type < NUM_PWS_TYPES,
- NULL);
+ g_return_val_if_fail(block_type < NUM_PWS_TYPES, NULL);
g_return_val_if_fail(block_name != NULL, NULL);
g_return_val_if_fail(password_id != NULL, NULL);
debug_print("Getting password '%s' from block (%d/%s)\n",
password_id, block_type, block_name);
- // find correct block
+ /* 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 NULL;
}
- // grab pointer to encrypted password
+ /* grab pointer to encrypted password */
if ((encrypted_password =
g_hash_table_lookup(block->entries, password_id)) == NULL) {
debug_print("Password '%s' in block (%d/%s) not found.\n",
return NULL;
}
- // decrypt password
+ /* decrypt password */
if ((password =
password_decrypt(encrypted_password, NULL)) == NULL) {
debug_print("Could not decrypt password '%s' for block (%d/%s).\n",
return NULL;
}
- // return decrypted password
+ /* return decrypted password */
return password;
}
+/* Checks if a password exists in the password store.
+ * No decryption happens. */
+gboolean passwd_store_has_password(PasswordBlockType block_type,
+ const gchar *block_name,
+ const gchar *password_id)
+{
+ PasswordBlock *block;
+
+ g_return_val_if_fail(block_type < NUM_PWS_TYPES, FALSE);
+ g_return_val_if_fail(block_name != NULL, FALSE);
+ g_return_val_if_fail(password_id != NULL, FALSE);
+
+ /* 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;
+ }
+
+ /* do we have specified password in this block? */
+ if (g_hash_table_lookup(block->entries, password_id) != NULL) {
+ return TRUE; /* yes */
+ }
+
+ return FALSE; /* no */
+}
+
+
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_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
+ /* 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;
}
return ret;
}
+gboolean passwd_store_has_password_account(gint account_id,
+ const gchar *password_id)
+{
+ gchar *uid = g_strdup_printf("%d", account_id);
+ gboolean ret = passwd_store_has_password(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)
GList *keys, *eitem;
gchar *typestr, *line, *key, *pwd;
+ /* Write out the config_version */
+ line = g_strdup_printf("[config_version:%d]\n", CLAWS_CONFIG_VERSION);
+ if (claws_fputs(line, fp) == EOF) {
+ FILE_OP_ERROR("password store, config_version", "claws_fputs");
+ g_free(line);
+ return -1;
+ }
+ g_free(line);
+
+ /* Add a newline if needed */
+ if (_password_store != NULL && claws_fputs("\n", fp) == EOF) {
+ FILE_OP_ERROR("password store", "claws_fputs");
+ return -1;
+ }
+
+ /* Write out each password store block */
for (item = _password_store; item != NULL; item = item->next) {
block = (PasswordBlock*)item->data;
if (block == NULL)
}
line = g_strdup_printf("[%s:%s]\n", typestr, block->block_name);
- if (fputs(line, fp) == EOF) {
- FILE_OP_ERROR("password store", "fputs");
+ if (claws_fputs(line, fp) == EOF) {
+ FILE_OP_ERROR("password store", "claws_fputs");
g_free(line);
return -1;
}
continue;
line = g_strdup_printf("%s %s\n", key, pwd);
- if (fputs(line, fp) == EOF) {
- FILE_OP_ERROR("password store", "fputs");
+ if (claws_fputs(line, fp) == EOF) {
+ FILE_OP_ERROR("password store", "claws_fputs");
g_free(line);
return -1;
}
}
g_list_free(keys);
- if (item->next != NULL && fputs("\n", fp) == EOF) {
- FILE_OP_ERROR("password store", "fputs");
+ /* Add a separating new line if there is another block remaining */
+ if (item->next != NULL && claws_fputs("\n", fp) == EOF) {
+ FILE_OP_ERROR("password store", "claws_fputs");
return -1;
}
}
}
-void passwd_store_read_config(void)
+int passwd_store_read_config(void)
{
gchar *rcpath, *contents, **lines, **line, *typestr, *name;
GError *error = NULL;
guint i = 0;
PasswordBlock *block = NULL;
PasswordBlockType type;
+ gboolean reading_config_version = FALSE;
+ gint config_version = -1;
- // TODO: passwd_store_clear();
-
- debug_print("Reading password store from file...\n");
+ /* TODO: passwd_store_clear(); */
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
PASSWORD_STORE_RC, NULL);
+ debug_print("Reading password store from file '%s'\n", rcpath);
+
+ if (!g_file_test(rcpath, G_FILE_TEST_EXISTS)) {
+ debug_print("File does not exist, looks like a new configuration.\n");
+ g_free(rcpath);
+ return 0;
+ }
+
if (!g_file_get_contents(rcpath, &contents, NULL, &error)) {
- g_warning("couldn't read password store from file: %s\n", error->message);
+ g_warning("couldn't read password store from file: %s", error->message);
g_error_free(error);
g_free(rcpath);
- return;
+ return -1;
}
g_free(rcpath);
lines = g_strsplit(contents, "\n", -1);
+ g_free(contents);
+
while (lines[i] != NULL) {
if (*lines[i] == '[') {
/* Beginning of a new block */
type = PWS_ACCOUNT;
} else if (!strcmp(typestr, "plugin")) {
type = PWS_PLUGIN;
+ } else if (!strcmp(typestr, "config_version")) {
+ reading_config_version = TRUE;
+ config_version = atoi(name);
} else {
- debug_print("Uknown password block type: '%s'\n", typestr);
+ debug_print("Unknown password block type: '%s'\n", typestr);
g_strfreev(line);
i++; continue;
}
- if ((block = _new_block(type, name)) == NULL) {
- debug_print("Duplicate password block, ignoring: (%d/%s)\n",
- type, name);
- g_strfreev(line);
- i++; continue;
+ if (reading_config_version) {
+ if (config_version < 0) {
+ debug_print("config_version:%d looks invalid, ignoring it\n",
+ config_version);
+ config_version = -1; /* set to default value if missing */
+ i++; continue;
+ }
+ debug_print("config_version in file is %d\n", config_version);
+ reading_config_version = FALSE;
+ } else {
+ if ((block = _new_block(type, name)) == NULL) {
+ debug_print("Duplicate password block, ignoring: (%d/%s)\n",
+ type, name);
+ g_strfreev(line);
+ i++; continue;
+ }
}
}
g_strfreev(line);
i++;
}
g_strfreev(lines);
+
+ if (prefs_update_config_version_password_store(config_version) < 0) {
+ debug_print("Password store configuration file version upgrade failed\n");
+ return -2;
+ }
+
+ return g_slist_length(_password_store);
}