Mercurial > pidgin
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, |