Changes in storage_xml.c [64b4263:d628339]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
storage_xml.c
r64b4263 rd628339 34 34 35 35 typedef enum { 36 XML_PASS_CHECK = 0, 37 XML_LOAD 38 } xml_action; 36 XML_PASS_CHECK_ONLY = -1, 37 XML_PASS_UNKNOWN = 0, 38 XML_PASS_WRONG, 39 XML_PASS_OK 40 } xml_pass_st; 39 41 40 42 /* To make it easier later when extending the format: */ … … 63 65 { 64 66 struct xt_node *c; 65 struct set *s;66 67 67 68 for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { 68 69 char *name = xt_find_attr(c, "name"); 69 char *locked = xt_find_attr(c, "locked");70 70 71 71 if (!name) { … … 80 80 } 81 81 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 } 82 } 83 } 84 85 /* Use for unsupported/not-found protocols. Save settings as-is but don't allow changes. */ 86 static void handle_settings_raw(struct xt_node *node, set_t **head) 87 { 88 struct xt_node *c; 89 90 for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { 91 char *name = xt_find_attr(c, "name"); 92 93 if (!name) { 94 continue; 95 } 96 97 set_t *s = set_add(head, name, NULL, NULL, NULL); 98 set_setstr(head, name, c->text); 99 s->flags |= SET_HIDDEN | 100 ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; 88 101 } 89 102 } … … 92 105 { 93 106 struct xml_parsedata *xd = data; 94 char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag , *locked;107 char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag; 95 108 char *pass_b64 = NULL; 96 109 unsigned char *pass_cr = NULL; 97 int pass_len , local = 0;110 int pass_len; 98 111 struct prpl *prpl = NULL; 99 112 account_t *acc; … … 105 118 autoconnect = xt_find_attr(node, "autoconnect"); 106 119 tag = xt_find_attr(node, "tag"); 107 locked = xt_find_attr(node, "locked");108 120 109 121 protocol = xt_find_attr(node, "protocol"); … … 111 123 prpl = find_protocol(protocol); 112 124 if (!prpl) { 113 irc_rootmsg(xd->irc, "Error loading user config: Protocol not found: `%s'", protocol); 114 return XT_ABORT; 115 } 116 local = protocol_account_islocal(protocol); 125 irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol); 126 prpl = (struct prpl*) &protocol_missing; 127 } 117 128 } 118 129 119 130 if (!handle || !pass_b64 || !protocol || !prpl) { 120 131 return XT_ABORT; 121 } 122 123 pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr); 124 if (xd->irc->auth_backend) { 125 password = g_strdup((char *)pass_cr); 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 } 126 149 } else { 127 pass_len = arc_decode(pass_cr, pass_len, &password, xd->given_pass); 128 if (pass_len < 0) { 129 g_free(pass_cr); 130 g_free(password); 131 return XT_ABORT; 132 } 133 } 134 135 acc = account_add(xd->irc->b, prpl, handle, password); 136 if (server) { 137 set_setstr(&acc->set, "server", server); 138 } 139 if (autoconnect) { 140 set_setstr(&acc->set, "auto_connect", autoconnect); 141 } 142 if (tag) { 143 set_setstr(&acc->set, "tag", tag); 144 } 145 if (local) { 146 acc->flags |= ACC_FLAG_LOCAL; 147 } 148 if (locked && !g_strcasecmp(locked, "true")) { 149 acc->flags |= ACC_FLAG_LOCKED; 150 g_free(pass_cr); 151 g_free(password); 152 return XT_ABORT; 150 153 } 151 154 … … 153 156 g_free(password); 154 157 155 handle_settings(node, &acc->set); 158 if (prpl == &protocol_missing) { 159 handle_settings_raw(node, &acc->set); 160 } else { 161 handle_settings(node, &acc->set); 162 } 156 163 157 164 for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) { … … 203 210 }; 204 211 205 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_ actionaction)212 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action) 206 213 { 207 214 struct xml_parsedata xd[1]; … … 245 252 } 246 253 247 if (action == XML_PASS_CHECK){254 { 248 255 char *nick = xt_find_attr(node, "nick"); 249 256 char *pass = xt_find_attr(node, "password"); 250 char *backend = xt_find_attr(node, "auth_backend"); 251 252 if (!nick || !(pass || backend)) { 257 258 if (!nick || !pass) { 253 259 goto error; 254 }255 256 if (backend) {257 g_free(xd->irc->auth_backend);258 xd->irc->auth_backend = g_strdup(backend);259 ret = STORAGE_CHECK_BACKEND;260 260 } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) { 261 261 ret = STORAGE_INVALID_PASSWORD; 262 } else { 263 ret = STORAGE_OK; 264 } 265 goto error; 266 } 267 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! */ 268 272 if (xt_handle(xp, NULL, 1) == XT_HANDLED) { 269 273 ret = STORAGE_OK; … … 280 284 static storage_status_t xml_load(irc_t *irc, const char *password) 281 285 { 282 return xml_load_real(irc, irc->user->nick, password, XML_ LOAD);283 } 284 285 static storage_status_t xml_check_pass( irc_t *irc,const char *my_nick, const char *password)286 { 287 return xml_load_real( irc, my_nick, password, XML_PASS_CHECK);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); 288 292 } 289 293 … … 300 304 struct xt_node *root, *cur; 301 305 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 302 317 root = cur = xt_new_node("user", NULL, NULL); 303 if (irc->auth_backend) {304 xt_add_attr(cur, "auth_backend", irc->auth_backend);305 } else {306 /* Generate a salted md5sum of the password. Use 5 bytes for the salt307 (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 xt_add_attr(cur, "password", pass_buf);317 g_free(pass_buf);318 }319 320 318 xt_add_attr(cur, "nick", irc->user->nick); 319 xt_add_attr(cur, "password", pass_buf); 321 320 xt_add_attr(cur, "version", XML_FORMAT_VERSION); 321 322 g_free(pass_buf); 322 323 323 324 xml_generate_settings(cur, &irc->b->set); … … 330 331 int pass_len; 331 332 332 if(irc->auth_backend) { 333 /* If we don't "own" the password, it may change without us 334 * knowing, so we cannot encrypt the data, as we then may not be 335 * able to decrypt it */ 336 pass_b64 = base64_encode((unsigned char *)acc->pass, strlen(acc->pass)); 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); 336 337 cur = xt_new_node("account", NULL, NULL); 338 if (acc->prpl == &protocol_missing) { 339 xt_add_attr(cur, "protocol", set_getstr(&acc->set, "_protocol_name")); 337 340 } else { 338 pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12); 339 pass_b64 = base64_encode(pass_cr, pass_len); 340 g_free(pass_cr); 341 } 342 343 cur = xt_new_node("account", NULL, NULL); 344 xt_add_attr(cur, "protocol", acc->prpl->name); 341 xt_add_attr(cur, "protocol", acc->prpl->name); 342 } 345 343 xt_add_attr(cur, "handle", acc->user); 346 344 xt_add_attr(cur, "password", pass_b64); … … 350 348 xt_add_attr(cur, "server", acc->server); 351 349 } 352 if (acc->flags & ACC_FLAG_LOCKED) {353 xt_add_attr(cur, "locked", "true");354 }355 350 356 351 g_free(pass_b64); … … 397 392 xt_add_child(cur, xset = xt_new_node("setting", set->value, NULL)); 398 393 xt_add_attr(xset, "name", set->key); 399 if (set->flags & SET_LOCKED) {400 xt_add_attr(xset, "locked", "true");401 }402 394 } 403 395 } … … 458 450 459 451 460 static storage_status_t xml_remove(const char *nick )452 static storage_status_t xml_remove(const char *nick, const char *password) 461 453 { 462 454 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 } 463 461 464 462 lc = g_strdup(nick);
Note: See TracChangeset
for help on using the changeset viewer.