diff options
Diffstat (limited to 'storage_xml.c')
-rw-r--r-- | storage_xml.c | 150 |
1 files changed, 90 insertions, 60 deletions
diff --git a/storage_xml.c b/storage_xml.c index 4237e10e..20f3fe3c 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -33,11 +33,9 @@ #include <glib/gstdio.h> typedef enum { - XML_PASS_CHECK_ONLY = -1, - XML_PASS_UNKNOWN = 0, - XML_PASS_WRONG, - XML_PASS_OK -} xml_pass_st; + XML_PASS_CHECK = 0, + XML_LOAD +} xml_action; /* To make it easier later when extending the format: */ #define XML_FORMAT_VERSION "1" @@ -64,9 +62,11 @@ static void xml_init(void) static void handle_settings(struct xt_node *node, set_t **head) { struct xt_node *c; + struct set *s; for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { char *name = xt_find_attr(c, "name"); + char *locked = xt_find_attr(c, "locked"); if (!name) { continue; @@ -79,13 +79,19 @@ static void handle_settings(struct xt_node *node, set_t **head) } } set_setstr(head, name, c->text); + if (locked && !g_strcasecmp(locked, "true")) { + s = set_find(head, name); + if (s) { + s->flags |= SET_LOCKED; + } + } } } static xt_status handle_account(struct xt_node *node, gpointer data) { struct xml_parsedata *xd = data; - char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag; + char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag, *locked; char *pass_b64 = NULL; unsigned char *pass_cr = NULL; int pass_len, local = 0; @@ -98,6 +104,7 @@ static xt_status handle_account(struct xt_node *node, gpointer data) server = xt_find_attr(node, "server"); autoconnect = xt_find_attr(node, "autoconnect"); tag = xt_find_attr(node, "tag"); + locked = xt_find_attr(node, "locked"); protocol = xt_find_attr(node, "protocol"); if (protocol) { @@ -111,25 +118,35 @@ static xt_status handle_account(struct xt_node *node, gpointer data) if (!handle || !pass_b64 || !protocol || !prpl) { return XT_ABORT; - } else if ((pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr)) && - arc_decode(pass_cr, pass_len, &password, xd->given_pass) >= 0) { - acc = account_add(xd->irc->b, prpl, handle, password); - if (server) { - set_setstr(&acc->set, "server", server); - } - if (autoconnect) { - set_setstr(&acc->set, "auto_connect", autoconnect); - } - if (tag) { - set_setstr(&acc->set, "tag", tag); - } - if (local) { - acc->flags |= ACC_FLAG_LOCAL; - } + } + + pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr); + if (xd->irc->auth_backend) { + password = g_strdup((char *)pass_cr); } else { - g_free(pass_cr); - g_free(password); - return XT_ABORT; + pass_len = arc_decode(pass_cr, pass_len, &password, xd->given_pass); + if (pass_len < 0) { + g_free(pass_cr); + g_free(password); + return XT_ABORT; + } + } + + acc = account_add(xd->irc->b, prpl, handle, password); + if (server) { + set_setstr(&acc->set, "server", server); + } + if (autoconnect) { + set_setstr(&acc->set, "auto_connect", autoconnect); + } + if (tag) { + set_setstr(&acc->set, "tag", tag); + } + if (local) { + acc->flags |= ACC_FLAG_LOCAL; + } + if (locked && !g_strcasecmp(locked, "true")) { + acc->flags |= ACC_FLAG_LOCKED; } g_free(pass_cr); @@ -185,7 +202,7 @@ static const struct xt_handler_entry handlers[] = { { NULL, NULL, NULL, }, }; -static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action) +static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action) { struct xml_parsedata xd[1]; char *fn, buf[2048]; @@ -227,24 +244,27 @@ static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const cha goto error; } - { + if (action == XML_PASS_CHECK) { char *nick = xt_find_attr(node, "nick"); char *pass = xt_find_attr(node, "password"); + char *backend = xt_find_attr(node, "auth_backend"); - if (!nick || !pass) { + if (!nick || !(pass || backend)) { goto error; + } + + if (backend) { + g_free(xd->irc->auth_backend); + xd->irc->auth_backend = g_strdup(backend); + ret = STORAGE_CHECK_BACKEND; } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) { ret = STORAGE_INVALID_PASSWORD; - goto error; + } else { + ret = STORAGE_OK; } - } - - if (action == XML_PASS_CHECK_ONLY) { - ret = STORAGE_OK; goto error; } - /* DO NOT call xt_handle() before verifying the password! */ if (xt_handle(xp, NULL, 1) == XT_HANDLED) { ret = STORAGE_OK; } @@ -259,12 +279,12 @@ error: static storage_status_t xml_load(irc_t *irc, const char *password) { - return xml_load_real(irc, irc->user->nick, password, XML_PASS_UNKNOWN); + return xml_load_real(irc, irc->user->nick, password, XML_LOAD); } -static storage_status_t xml_check_pass(const char *my_nick, const char *password) +static storage_status_t xml_check_pass(irc_t *irc, const char *my_nick, const char *password) { - return xml_load_real(NULL, my_nick, password, XML_PASS_CHECK_ONLY); + return xml_load_real(irc, my_nick, password, XML_PASS_CHECK); } @@ -279,24 +299,27 @@ struct xt_node *xml_generate(irc_t *irc) GSList *l; struct xt_node *root, *cur; - /* Generate a salted md5sum of the password. Use 5 bytes for the salt - (to prevent dictionary lookups of passwords) to end up with a 21- - byte password hash, more convenient for base64 encoding. */ - random_bytes(pass_md5 + 16, 5); - md5_init(&md5_state); - md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password)); - md5_append(&md5_state, pass_md5 + 16, 5); /* Add the salt. */ - md5_finish(&md5_state, pass_md5); - /* Save the hash in base64-encoded form. */ - pass_buf = base64_encode(pass_md5, 21); - root = cur = xt_new_node("user", NULL, NULL); + if (irc->auth_backend) { + xt_add_attr(cur, "auth_backend", irc->auth_backend); + } else { + /* Generate a salted md5sum of the password. Use 5 bytes for the salt + (to prevent dictionary lookups of passwords) to end up with a 21- + byte password hash, more convenient for base64 encoding. */ + random_bytes(pass_md5 + 16, 5); + md5_init(&md5_state); + md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password)); + md5_append(&md5_state, pass_md5 + 16, 5); /* Add the salt. */ + md5_finish(&md5_state, pass_md5); + /* Save the hash in base64-encoded form. */ + pass_buf = base64_encode(pass_md5, 21); + xt_add_attr(cur, "password", pass_buf); + g_free(pass_buf); + } + xt_add_attr(cur, "nick", irc->user->nick); - xt_add_attr(cur, "password", pass_buf); xt_add_attr(cur, "version", XML_FORMAT_VERSION); - g_free(pass_buf); - xml_generate_settings(cur, &irc->b->set); for (acc = irc->b->accounts; acc; acc = acc->next) { @@ -306,9 +329,16 @@ struct xt_node *xml_generate(irc_t *irc) char *pass_b64; int pass_len; - pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12); - pass_b64 = base64_encode(pass_cr, pass_len); - g_free(pass_cr); + if(irc->auth_backend) { + /* If we don't "own" the password, it may change without us + * knowing, so we cannot encrypt the data, as we then may not be + * able to decrypt it */ + pass_b64 = base64_encode((unsigned char *)acc->pass, strlen(acc->pass)); + } else { + pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12); + pass_b64 = base64_encode(pass_cr, pass_len); + g_free(pass_cr); + } cur = xt_new_node("account", NULL, NULL); xt_add_attr(cur, "protocol", acc->prpl->name); @@ -319,6 +349,9 @@ struct xt_node *xml_generate(irc_t *irc) if (acc->server && acc->server[0]) { xt_add_attr(cur, "server", acc->server); } + if (acc->flags & ACC_FLAG_LOCKED) { + xt_add_attr(cur, "locked", "true"); + } g_free(pass_b64); @@ -363,6 +396,9 @@ static void xml_generate_settings(struct xt_node *cur, set_t **head) struct xt_node *xset; xt_add_child(cur, xset = xt_new_node("setting", set->value, NULL)); xt_add_attr(xset, "name", set->key); + if (set->flags & SET_LOCKED) { + xt_add_attr(xset, "locked", "true"); + } } } } @@ -421,15 +457,9 @@ finish: } -static storage_status_t xml_remove(const char *nick, const char *password) +static storage_status_t xml_remove(const char *nick) { char s[512], *lc; - storage_status_t status; - - status = xml_check_pass(nick, password); - if (status != STORAGE_OK) { - return status; - } lc = g_strdup(nick); nick_lc(NULL, lc); |