comparison libpurple/protocols/msn/nexus.c @ 25452:6a0304f317cf

I was hoping this wouldn't be necessary, but it seems that the possibility has increased now that we update the display name in the AB. If two SOAP requests fail because of outdated tokens for the same server, it's possible that the second one could fail miserably. That's because both times, the update request would be made with the original cipher secret. However, the response for the first request would overwrite this secret, and the second response would attempt decryption with this new secret instead of the original. Now, we queue up the callbacks if a token-update is already in progress. This results in a single update if there happens to be multiple failures at a time, and it stops this incorrect decryption problem. Fixes #8415.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 15 Feb 2009 02:11:58 +0000
parents 25667ca518d6
children 3f6dbc414357
comparison
equal deleted inserted replaced
25451:4f2953f909fb 25452:6a0304f317cf
233 /* Used to specify which token to update when only doing single updates */ 233 /* Used to specify which token to update when only doing single updates */
234 typedef struct _MsnNexusUpdateData MsnNexusUpdateData; 234 typedef struct _MsnNexusUpdateData MsnNexusUpdateData;
235 struct _MsnNexusUpdateData { 235 struct _MsnNexusUpdateData {
236 MsnNexus *nexus; 236 MsnNexus *nexus;
237 int id; 237 int id;
238 };
239
240 typedef struct _MsnNexusUpdateCallback MsnNexusUpdateCallback;
241 struct _MsnNexusUpdateCallback {
238 GSourceFunc cb; 242 GSourceFunc cb;
239 gpointer data; 243 gpointer data;
240 }; 244 };
241 245
242 #if !GLIB_CHECK_VERSION(2, 12, 0) 246 #if !GLIB_CHECK_VERSION(2, 12, 0)
426 xmlnode *enckey; 430 xmlnode *enckey;
427 char *tmp; 431 char *tmp;
428 char *nonce; 432 char *nonce;
429 gsize len; 433 gsize len;
430 char *key; 434 char *key;
435 GSList *updates;
431 436
432 #if 0 437 #if 0
433 char *decrypted_pp; 438 char *decrypted_pp;
434 #endif 439 #endif
435 char *decrypted_data; 440 char *decrypted_data;
487 else 492 else
488 nexus_parse_collection(nexus, ud->id, rstresponse); 493 nexus_parse_collection(nexus, ud->id, rstresponse);
489 g_free(decrypted_data); 494 g_free(decrypted_data);
490 } 495 }
491 496
492 if (ud->cb) 497 updates = nexus->tokens[ud->id].updates;
493 purple_timeout_add(0, ud->cb, ud->data); 498 nexus->tokens[ud->id].updates = NULL;
499 while (updates != NULL) {
500 MsnNexusUpdateCallback *update = updates->data;
501 if (update->cb)
502 purple_timeout_add(0, update->cb, update->data);
503 g_free(update);
504 updates = g_slist_delete_link(updates, updates);
505 }
494 506
495 g_free(ud); 507 g_free(ud);
496 } 508 }
497 509
498 void 510 void
499 msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) 511 msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data)
500 { 512 {
501 MsnSession *session = nexus->session; 513 MsnSession *session = nexus->session;
502 MsnNexusUpdateData *ud; 514 MsnNexusUpdateData *ud;
515 MsnNexusUpdateCallback *update;
503 PurpleCipherContext *sha1; 516 PurpleCipherContext *sha1;
504 PurpleCipherContext *hmac; 517 PurpleCipherContext *hmac;
505 518
506 char *key; 519 char *key;
507 520
524 guchar signature[20]; 537 guchar signature[20];
525 538
526 char *request; 539 char *request;
527 MsnSoapMessage *soap; 540 MsnSoapMessage *soap;
528 541
529 purple_debug_info("msn", 542 update = g_new0(MsnNexusUpdateCallback, 1);
530 "Updating ticket for user '%s' on domain '%s'\n", 543 update->cb = cb;
531 purple_account_get_username(session->account), 544 update->data = data;
532 ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); 545
546 if (nexus->tokens[id].updates != NULL) {
547 /* Update already in progress. Just add to list and return. */
548 purple_debug_info("msn",
549 "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n",
550 purple_account_get_username(session->account),
551 ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
552 nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
553 update);
554 return;
555 } else {
556 purple_debug_info("msn",
557 "Updating ticket for user '%s' on domain '%s'\n",
558 purple_account_get_username(session->account),
559 ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
560 nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
561 update);
562 }
533 563
534 ud = g_new0(MsnNexusUpdateData, 1); 564 ud = g_new0(MsnNexusUpdateData, 1);
535 ud->nexus = nexus; 565 ud->nexus = nexus;
536 ud->id = id; 566 ud->id = id;
537 ud->cb = cb;
538 ud->data = data;
539 567
540 sha1 = purple_cipher_context_new_by_name("sha1", NULL); 568 sha1 = purple_cipher_context_new_by_name("sha1", NULL);
541 569
542 domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE, 570 domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE,
543 id, 571 id,