Changeset 537d9b9 for storage_xml.c


Ignore:
Timestamp:
2016-11-20T08:40:36Z (7 years ago)
Author:
dequis <dx@…>
Children:
3f44e43
Parents:
ba52ac5 (diff), 9f03c47 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge master up to commit '9f03c47' into parson

File:
1 edited

Legend:

Unmodified
Added
Removed
  • storage_xml.c

    rba52ac5 r537d9b9  
    3434
    3535typedef enum {
    36         XML_PASS_CHECK_ONLY = -1,
    37         XML_PASS_UNKNOWN = 0,
    38         XML_PASS_WRONG,
    39         XML_PASS_OK
    40 } xml_pass_st;
     36        XML_PASS_CHECK = 0,
     37        XML_LOAD
     38} xml_action;
    4139
    4240/* To make it easier later when extending the format: */
     
    6563{
    6664        struct xt_node *c;
     65        struct set *s;
    6766
    6867        for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) {
    6968                char *name = xt_find_attr(c, "name");
     69                char *locked = xt_find_attr(c, "locked");
    7070
    7171                if (!name) {
     
    8080                }
    8181                set_setstr(head, name, c->text);
     82                if (locked && !g_strcasecmp(locked, "true")) {
     83                        s = set_find(head, name);
     84                        if (s) {
     85                                s->flags |= SET_LOCKED;
     86                        }
     87                }
    8288        }
    8389}
     
    105111{
    106112        struct xml_parsedata *xd = data;
    107         char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag;
     113        char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag, *locked;
    108114        char *pass_b64 = NULL;
    109115        unsigned char *pass_cr = NULL;
     
    118124        autoconnect = xt_find_attr(node, "autoconnect");
    119125        tag = xt_find_attr(node, "tag");
     126        locked = xt_find_attr(node, "locked");
    120127
    121128        protocol = xt_find_attr(node, "protocol");
     
    130137        if (!handle || !pass_b64 || !protocol || !prpl) {
    131138                return XT_ABORT;
    132         } else if ((pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr)) &&
    133                    arc_decode(pass_cr, pass_len, &password, xd->given_pass) >= 0) {
    134                 acc = account_add(xd->irc->b, prpl, handle, password);
    135                 if (server) {
    136                         set_setstr(&acc->set, "server", server);
    137                 }
    138                 if (autoconnect) {
    139                         set_setstr(&acc->set, "auto_connect", autoconnect);
    140                 }
    141                 if (tag) {
    142                         set_setstr(&acc->set, "tag", tag);
    143                 }
    144                 if (prpl == &protocol_missing) {
    145                         set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL);
    146                         s->flags |= SET_HIDDEN | SET_NOSAVE |
    147                                     ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
    148                 }
     139        }
     140
     141        pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr);
     142        if (xd->irc->auth_backend) {
     143                password = g_strdup((char *)pass_cr);
    149144        } else {
    150                 g_free(pass_cr);
    151                 g_free(password);
    152                 return XT_ABORT;
     145                pass_len = arc_decode(pass_cr, pass_len, &password, xd->given_pass);
     146                if (pass_len < 0) {
     147                        g_free(pass_cr);
     148                        g_free(password);
     149                        return XT_ABORT;
     150                }
     151        }
     152
     153        acc = account_add(xd->irc->b, prpl, handle, password);
     154        if (server) {
     155                set_setstr(&acc->set, "server", server);
     156        }
     157        if (autoconnect) {
     158                set_setstr(&acc->set, "auto_connect", autoconnect);
     159        }
     160        if (tag) {
     161                set_setstr(&acc->set, "tag", tag);
     162        }
     163        if (locked && !g_strcasecmp(locked, "true")) {
     164                acc->flags |= ACC_FLAG_LOCKED;
     165        }
     166        if (prpl == &protocol_missing) {
     167                set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL);
     168                s->flags |= SET_HIDDEN | SET_NOSAVE |
     169                            ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
    153170        }
    154171
     
    210227};
    211228
    212 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action)
     229static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action)
    213230{
    214231        struct xml_parsedata xd[1];
     
    252269        }
    253270
    254         {
     271        if (action == XML_PASS_CHECK) {
    255272                char *nick = xt_find_attr(node, "nick");
    256273                char *pass = xt_find_attr(node, "password");
    257 
    258                 if (!nick || !pass) {
     274                char *backend = xt_find_attr(node, "auth_backend");
     275
     276                if (!nick || !(pass || backend)) {
    259277                        goto error;
     278                }
     279
     280                if (backend) {
     281                        g_free(xd->irc->auth_backend);
     282                        xd->irc->auth_backend = g_strdup(backend);
     283                        ret = STORAGE_CHECK_BACKEND;
    260284                } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) {
    261285                        ret = STORAGE_INVALID_PASSWORD;
    262                         goto error;
    263                 }
    264         }
    265 
    266         if (action == XML_PASS_CHECK_ONLY) {
    267                 ret = STORAGE_OK;
    268                 goto error;
    269         }
    270 
    271         /* DO NOT call xt_handle() before verifying the password! */
     286                } else {
     287                        ret = STORAGE_OK;
     288                }
     289                goto error;
     290        }
     291
    272292        if (xt_handle(xp, NULL, 1) == XT_HANDLED) {
    273293                ret = STORAGE_OK;
     
    284304static storage_status_t xml_load(irc_t *irc, const char *password)
    285305{
    286         return xml_load_real(irc, irc->user->nick, password, XML_PASS_UNKNOWN);
    287 }
    288 
    289 static storage_status_t xml_check_pass(const char *my_nick, const char *password)
    290 {
    291         return xml_load_real(NULL, my_nick, password, XML_PASS_CHECK_ONLY);
     306        return xml_load_real(irc, irc->user->nick, password, XML_LOAD);
     307}
     308
     309static storage_status_t xml_check_pass(irc_t *irc, const char *my_nick, const char *password)
     310{
     311        return xml_load_real(irc, my_nick, password, XML_PASS_CHECK);
    292312}
    293313
     
    304324        struct xt_node *root, *cur;
    305325
    306         /* Generate a salted md5sum of the password. Use 5 bytes for the salt
    307            (to prevent dictionary lookups of passwords) to end up with a 21-
    308            byte password hash, more convenient for base64 encoding. */
    309         random_bytes(pass_md5 + 16, 5);
    310         md5_init(&md5_state);
    311         md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password));
    312         md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */
    313         md5_finish(&md5_state, pass_md5);
    314         /* Save the hash in base64-encoded form. */
    315         pass_buf = base64_encode(pass_md5, 21);
    316 
    317326        root = cur = xt_new_node("user", NULL, NULL);
     327        if (irc->auth_backend) {
     328                xt_add_attr(cur, "auth_backend", irc->auth_backend);
     329        } else {
     330                /* Generate a salted md5sum of the password. Use 5 bytes for the salt
     331                   (to prevent dictionary lookups of passwords) to end up with a 21-
     332                   byte password hash, more convenient for base64 encoding. */
     333                random_bytes(pass_md5 + 16, 5);
     334                md5_init(&md5_state);
     335                md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password));
     336                md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */
     337                md5_finish(&md5_state, pass_md5);
     338                /* Save the hash in base64-encoded form. */
     339                pass_buf = base64_encode(pass_md5, 21);
     340                xt_add_attr(cur, "password", pass_buf);
     341                g_free(pass_buf);
     342        }
     343
    318344        xt_add_attr(cur, "nick", irc->user->nick);
    319         xt_add_attr(cur, "password", pass_buf);
    320345        xt_add_attr(cur, "version", XML_FORMAT_VERSION);
    321 
    322         g_free(pass_buf);
    323346
    324347        xml_generate_settings(cur, &irc->b->set);
     
    331354                int pass_len;
    332355
    333                 pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12);
    334                 pass_b64 = base64_encode(pass_cr, pass_len);
    335                 g_free(pass_cr);
     356                if(irc->auth_backend) {
     357                        /* If we don't "own" the password, it may change without us
     358                         * knowing, so we cannot encrypt the data, as we then may not be
     359                         * able to decrypt it */
     360                        pass_b64 = base64_encode((unsigned char *)acc->pass, strlen(acc->pass));
     361                } else {
     362                        pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12);
     363                        pass_b64 = base64_encode(pass_cr, pass_len);
     364                        g_free(pass_cr);
     365                }
    336366
    337367                cur = xt_new_node("account", NULL, NULL);
     
    348378                        xt_add_attr(cur, "server", acc->server);
    349379                }
     380                if (acc->flags & ACC_FLAG_LOCKED) {
     381                        xt_add_attr(cur, "locked", "true");
     382                }
    350383
    351384                g_free(pass_b64);
     
    392425                        xt_add_child(cur, xset = xt_new_node("setting", set->value, NULL));
    393426                        xt_add_attr(xset, "name", set->key);
     427                        if (set->flags & SET_LOCKED) {
     428                                xt_add_attr(xset, "locked", "true");
     429                        }
    394430                }
    395431        }
     
    450486
    451487
    452 static storage_status_t xml_remove(const char *nick, const char *password)
     488static storage_status_t xml_remove(const char *nick)
    453489{
    454490        char s[512], *lc;
    455         storage_status_t status;
    456 
    457         status = xml_check_pass(nick, password);
    458         if (status != STORAGE_OK) {
    459                 return status;
    460         }
    461491
    462492        lc = g_strdup(nick);
Note: See TracChangeset for help on using the changeset viewer.