libpurple/keyring.c

branch
soc.2008.masterpassword
changeset 34167
43db4e8d785a
parent 34166
8be287b0d6be
child 34168
449a39c8e26f
equal deleted inserted replaced
34166:8be287b0d6be 34167:43db4e8d785a
129 static GList *purple_keyring_loaded_plugins = NULL; 129 static GList *purple_keyring_loaded_plugins = NULL;
130 static PurpleKeyringChangeTracker *current_change_tracker = NULL; 130 static PurpleKeyringChangeTracker *current_change_tracker = NULL;
131 static gboolean purple_keyring_is_quitting = FALSE; 131 static gboolean purple_keyring_is_quitting = FALSE;
132 static GHashTable *purple_keyring_failed_imports = NULL; 132 static GHashTable *purple_keyring_failed_imports = NULL;
133 133
134 static const gchar *
135 purple_keyring_print_account(PurpleAccount *account)
136 {
137 static gchar print_buff[100];
138
139 if (account == NULL) {
140 g_snprintf(print_buff, 100, "(null)");
141 return print_buff;
142 }
143
144 g_snprintf(print_buff, 100, "%s:%s",
145 purple_account_get_protocol_id(account),
146 purple_account_get_username(account));
147 return print_buff;
148 }
134 149
135 /**************************************************************************/ 150 /**************************************************************************/
136 /* Setting used keyrings */ 151 /* Setting used keyrings */
137 /**************************************************************************/ 152 /**************************************************************************/
138 153
238 253
239 static void 254 static void
240 purple_keyring_set_inuse_save_cb(PurpleAccount *account, GError *error, 255 purple_keyring_set_inuse_save_cb(PurpleAccount *account, GError *error,
241 gpointer _tracker) 256 gpointer _tracker)
242 { 257 {
243 const gchar *account_name;
244 PurpleKeyringChangeTracker *tracker = _tracker; 258 PurpleKeyringChangeTracker *tracker = _tracker;
245 259
246 g_return_if_fail(account != NULL); 260 g_return_if_fail(account != NULL);
247 g_return_if_fail(tracker != NULL); 261 g_return_if_fail(tracker != NULL);
248 262
249 tracker->read_outstanding--; 263 tracker->read_outstanding--;
250
251 account_name = purple_account_get_username(account);
252 264
253 if (g_error_matches(error, PURPLE_KEYRING_ERROR, 265 if (g_error_matches(error, PURPLE_KEYRING_ERROR,
254 PURPLE_KEYRING_ERROR_NOPASSWORD)) { 266 PURPLE_KEYRING_ERROR_NOPASSWORD)) {
255 if (purple_debug_is_verbose()) { 267 if (purple_debug_is_verbose()) {
256 purple_debug_misc("keyring", "No password found while " 268 purple_debug_misc("keyring", "No password found while "
257 "changing keyring for account %s: %s.\n", 269 "changing keyring for account %s: %s.\n",
258 account_name, error->message); 270 purple_keyring_print_account(account),
271 error->message);
259 } 272 }
260 } else if (g_error_matches(error, PURPLE_KEYRING_ERROR, 273 } else if (g_error_matches(error, PURPLE_KEYRING_ERROR,
261 PURPLE_KEYRING_ERROR_ACCESSDENIED)) { 274 PURPLE_KEYRING_ERROR_ACCESSDENIED)) {
262 purple_debug_info("keyring", "Access denied while changing " 275 purple_debug_info("keyring", "Access denied while changing "
263 "keyring for account %s: %s.\n", 276 "keyring for account %s: %s.\n",
264 account_name, error->message); 277 purple_keyring_print_account(account), error->message);
265 tracker->abort = TRUE; 278 tracker->abort = TRUE;
266 if (tracker->error != NULL) 279 if (tracker->error != NULL)
267 g_error_free(tracker->error); 280 g_error_free(tracker->error);
268 tracker->error = g_error_copy(error); 281 tracker->error = g_error_copy(error);
269 } else if (g_error_matches(error, PURPLE_KEYRING_ERROR, 282 } else if (g_error_matches(error, PURPLE_KEYRING_ERROR,
270 PURPLE_KEYRING_ERROR_CANCELLED)) { 283 PURPLE_KEYRING_ERROR_CANCELLED)) {
271 purple_debug_info("keyring", "Operation cancelled while " 284 purple_debug_info("keyring", "Operation cancelled while "
272 "changing keyring for account %s: %s.\n", 285 "changing keyring for account %s: %s.\n",
273 account_name, error->message); 286 purple_keyring_print_account(account), error->message);
274 tracker->abort = TRUE; 287 tracker->abort = TRUE;
275 if (tracker->error == NULL) 288 if (tracker->error == NULL)
276 tracker->error = g_error_copy(error); 289 tracker->error = g_error_copy(error);
277 } else if (g_error_matches(error, PURPLE_KEYRING_ERROR, 290 } else if (g_error_matches(error, PURPLE_KEYRING_ERROR,
278 PURPLE_KEYRING_ERROR_BACKENDFAIL)) { 291 PURPLE_KEYRING_ERROR_BACKENDFAIL)) {
279 purple_debug_error("keyring", "Failed to communicate with " 292 purple_debug_error("keyring", "Failed to communicate with "
280 "backend while changing keyring for account %s: %s. " 293 "backend while changing keyring for account %s: %s. "
281 "Aborting changes.\n", account_name, error->message); 294 "Aborting changes.\n",
295 purple_keyring_print_account(account), error->message);
282 tracker->abort = TRUE; 296 tracker->abort = TRUE;
283 if (tracker->error != NULL) 297 if (tracker->error != NULL)
284 g_error_free(tracker->error); 298 g_error_free(tracker->error);
285 tracker->error = g_error_copy(error); 299 tracker->error = g_error_copy(error);
286 } else if (error != NULL) { 300 } else if (error != NULL) {
287 purple_debug_error("keyring", "Unknown error while changing " 301 purple_debug_error("keyring", "Unknown error while changing "
288 "keyring for account %s: %s. Aborting changes.\n", 302 "keyring for account %s: %s. Aborting changes.\n",
289 account_name, error->message); 303 purple_keyring_print_account(account), error->message);
290 tracker->abort = TRUE; 304 tracker->abort = TRUE;
291 if (tracker->error == NULL) 305 if (tracker->error == NULL)
292 tracker->error = g_error_copy(error); 306 tracker->error = g_error_copy(error);
293 } 307 }
294 308
447 "required fields are missing.\n", 461 "required fields are missing.\n",
448 keyring_id ? keyring_id : "(null)"); 462 keyring_id ? keyring_id : "(null)");
449 return; 463 return;
450 } 464 }
451 465
466 if (purple_keyring_find_keyring_by_id(keyring_id) != NULL) {
467 purple_debug_error("keyring",
468 "Keyring is already registered.\n");
469 return;
470 }
471
452 /* If this is the configured keyring, use it. */ 472 /* If this is the configured keyring, use it. */
453 if (purple_keyring_inuse == NULL && 473 if (purple_keyring_inuse == NULL &&
454 g_strcmp0(keyring_id, purple_keyring_to_use) == 0) { 474 g_strcmp0(keyring_id, purple_keyring_to_use) == 0) {
455 purple_debug_info("keyring", "Keyring %s matches keyring to " 475 purple_debug_info("keyring", "Keyring %s matches keyring to "
456 "use, using it.\n", keyring_id); 476 "use, using it.\n", keyring_id);
548 if (close_cb != NULL) 568 if (close_cb != NULL)
549 close_cb(); 569 close_cb();
550 } 570 }
551 571
552 static void 572 static void
553 purple_keyring_drop_passwords_cb(PurpleAccount *account, GError *error, 573 purple_keyring_drop_passwords_save_cb(PurpleAccount *account, GError *error,
554 gpointer _tracker) 574 gpointer _tracker)
555 { 575 {
556 PurpleKeyringDropTracker *tracker = _tracker; 576 PurpleKeyringDropTracker *tracker = _tracker;
557 577
558 tracker->drop_outstanding--; 578 tracker->drop_outstanding--;
567 587
568 static void 588 static void
569 purple_keyring_drop_passwords(PurpleKeyring *keyring, 589 purple_keyring_drop_passwords(PurpleKeyring *keyring,
570 PurpleKeyringDropCallback cb, gpointer data) 590 PurpleKeyringDropCallback cb, gpointer data)
571 { 591 {
572 GList *cur; 592 GList *it;
573 PurpleKeyringSave save_cb; 593 PurpleKeyringSave save_cb;
574 PurpleKeyringDropTracker *tracker; 594 PurpleKeyringDropTracker *tracker;
575 595
576 g_return_if_fail(keyring != NULL); 596 g_return_if_fail(keyring != NULL);
577 597
578 save_cb = purple_keyring_get_save_password(keyring); 598 save_cb = purple_keyring_get_save_password(keyring);
579 g_return_if_fail(save_cb != NULL); 599 g_assert(save_cb != NULL);
580 600
581 tracker = g_new0(PurpleKeyringDropTracker, 1); 601 tracker = g_new0(PurpleKeyringDropTracker, 1);
582 tracker->cb = cb; 602 tracker->cb = cb;
583 tracker->cb_data = data; 603 tracker->cb_data = data;
584 604
585 for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) { 605 for (it = purple_accounts_get_all(); it != NULL; it = it->next) {
606 PurpleAccount *account = it->data;
607
586 tracker->drop_outstanding++; 608 tracker->drop_outstanding++;
587 if (cur->next == NULL) 609 if (it->next == NULL)
588 tracker->finished = TRUE; 610 tracker->finished = TRUE;
589 611
590 save_cb(cur->data, NULL, purple_keyring_drop_passwords_cb, 612 save_cb(account, NULL, purple_keyring_drop_passwords_save_cb,
591 tracker); 613 tracker);
592 } 614 }
593 } 615 }
594 616
595 gboolean 617 gboolean
596 purple_keyring_import_password(PurpleAccount *account, 618 purple_keyring_import_password(PurpleAccount *account, const gchar *keyring_id,
597 const gchar *keyring_id, 619 const gchar *mode, const gchar *data, GError **error)
598 const gchar *mode, 620 {
599 const gchar *data, 621 PurpleKeyring *keyring;
600 GError **error)
601 {
602 PurpleKeyring *inuse; 622 PurpleKeyring *inuse;
603 PurpleKeyringImportPassword import; 623 PurpleKeyringImportPassword import;
604 const gchar *realid; 624
605 625 g_return_val_if_fail(account != NULL, FALSE);
606 purple_debug_misc("keyring", "Importing password for account %s (%s) to keyring %s.\n", 626
607 purple_account_get_username(account), 627 if (keyring_id == NULL)
608 purple_account_get_protocol_id(account), 628 keyring_id = PURPLE_DEFAULT_KEYRING;
629
630 purple_debug_misc("keyring", "Importing password for account %s to "
631 "keyring %s.\n", purple_keyring_print_account(account),
609 keyring_id); 632 keyring_id);
610 633
634 keyring = purple_keyring_find_keyring_by_id(keyring_id);
635 if (keyring == NULL) {
636 if (error != NULL) {
637 *error = g_error_new(PURPLE_KEYRING_ERROR,
638 PURPLE_KEYRING_ERROR_BACKENDFAIL,
639 "Specified keyring is not registered.");
640 }
641 purple_debug_warning("Keyring", "Specified keyring is not "
642 "registered, cannot import password info for account "
643 "%s.\n", purple_keyring_print_account(account));
644 return FALSE;
645 }
646
611 inuse = purple_keyring_get_inuse(); 647 inuse = purple_keyring_get_inuse();
612
613 if (inuse == NULL) { 648 if (inuse == NULL) {
614 PurpleKeyringFailedImport *import; 649 PurpleKeyringFailedImport *import;
615 if (error != NULL) { 650 if (error != NULL) {
616 *error = g_error_new(PURPLE_KEYRING_ERROR, 651 *error = g_error_new(PURPLE_KEYRING_ERROR,
617 PURPLE_KEYRING_ERROR_NOKEYRING, 652 PURPLE_KEYRING_ERROR_NOKEYRING,
618 "No keyring configured, cannot import password " 653 "No keyring loaded, cannot import password "
619 "info"); 654 "info");
620 } 655 }
621 purple_debug_warning("Keyring", 656 purple_debug_warning("Keyring",
622 "No keyring configured, cannot import password info for account %s (%s).\n", 657 "No keyring loaded, cannot import password info for "
623 purple_account_get_username(account), purple_account_get_protocol_id(account)); 658 "account %s.\n", purple_keyring_print_account(account));
624 659
625 import = g_new0(PurpleKeyringFailedImport, 1); 660 import = g_new0(PurpleKeyringFailedImport, 1);
626 import->keyring_id = g_strdup(keyring_id); 661 import->keyring_id = g_strdup(keyring_id);
627 import->mode = g_strdup(mode); 662 import->mode = g_strdup(mode);
628 import->data = g_strdup(data); 663 import->data = g_strdup(data);
629 g_hash_table_insert(purple_keyring_failed_imports, account, import); 664 g_hash_table_insert(purple_keyring_failed_imports, account,
665 import);
630 return FALSE; 666 return FALSE;
631 } 667 }
632 668
633 realid = purple_keyring_get_id(inuse); 669 if (inuse != keyring) {
634 /*
635 * we want to be sure that either :
636 * - there is a keyring_id specified and it matches the one configured
637 * - or the configured keyring is the fallback, compatible one.
638 */
639 if ((keyring_id != NULL && g_strcmp0(realid, keyring_id) != 0) ||
640 (keyring_id == NULL && g_strcmp0(PURPLE_DEFAULT_KEYRING, realid))) {
641 if (error != NULL) { 670 if (error != NULL) {
642 *error = g_error_new(PURPLE_KEYRING_ERROR, 671 *error = g_error_new(PURPLE_KEYRING_ERROR,
643 PURPLE_KEYRING_ERROR_INTERNAL, 672 PURPLE_KEYRING_ERROR_INTERNAL,
644 "Specified keyring id does not match the " 673 "Specified keyring id does not match the "
645 "configured one."); 674 "loaded one.");
646 } 675 }
647 purple_debug_info("keyring", 676 purple_debug_error("keyring",
648 "Specified keyring id does not match the configured one (%s vs. %s). Data will be lost.\n", 677 "Specified keyring %s is not currently used (%s). "
649 keyring_id, realid); 678 "Data will be lost.\n", keyring_id,
679 purple_keyring_get_id(inuse));
650 return FALSE; 680 return FALSE;
651 } 681 }
652 682
653 import = purple_keyring_get_import_password(inuse); 683 import = purple_keyring_get_import_password(inuse);
654 if (import == NULL) { 684 if (import == NULL) {
662 692
663 return import(account, mode, data, error); 693 return import(account, mode, data, error);
664 } 694 }
665 695
666 gboolean 696 gboolean
667 purple_keyring_export_password(PurpleAccount *account, 697 purple_keyring_export_password(PurpleAccount *account, const gchar **keyring_id,
668 const gchar **keyring_id, 698 const gchar **mode, gchar **data, GError **error,
669 const gchar **mode, 699 GDestroyNotify *destroy)
670 gchar **data,
671 GError **error,
672 GDestroyNotify *destroy)
673 { 700 {
674 PurpleKeyring *inuse; 701 PurpleKeyring *inuse;
675 PurpleKeyringExportPassword export; 702 PurpleKeyringExportPassword export;
703
704 g_return_val_if_fail(account != NULL, FALSE);
705 g_return_val_if_fail(keyring_id != NULL, FALSE);
706 g_return_val_if_fail(mode != NULL, FALSE);
707 g_return_val_if_fail(data != NULL, FALSE);
708 g_return_val_if_fail(error != NULL, FALSE);
676 709
677 inuse = purple_keyring_get_inuse(); 710 inuse = purple_keyring_get_inuse();
678 711
679 if (inuse == NULL) { 712 if (inuse == NULL) {
680 PurpleKeyringFailedImport *import = g_hash_table_lookup( 713 PurpleKeyringFailedImport *import = g_hash_table_lookup(
681 purple_keyring_failed_imports, account); 714 purple_keyring_failed_imports, account);
682 715
683 if (import == NULL) { 716 if (import == NULL) {
684 *error = g_error_new(PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_NOKEYRING, 717 *error = g_error_new(PURPLE_KEYRING_ERROR,
685 "No keyring configured, cannot export password info"); 718 PURPLE_KEYRING_ERROR_NOKEYRING,
719 "No keyring configured, cannot export password "
720 "info");
686 purple_debug_warning("keyring", 721 purple_debug_warning("keyring",
687 "No keyring configured, cannot export password info.\n"); 722 "No keyring configured, cannot export password "
723 "info.\n");
688 return FALSE; 724 return FALSE;
689 } else { 725 } else {
690 purple_debug_info("keyring", "No keyring configured, getting fallback export data for %s (%s).\n", 726 purple_debug_info("keyring", "No keyring configured, "
691 purple_account_get_username(account), 727 "getting fallback export data for %s.\n",
692 purple_account_get_protocol_id(account)); 728 purple_keyring_print_account(account));
693 729
694 *keyring_id = import->keyring_id; 730 *keyring_id = import->keyring_id;
695 *mode = import->mode; 731 *mode = import->mode;
696 *data = g_strdup(import->data); 732 *data = g_strdup(import->data);
697 *destroy = g_free; 733 *destroy = g_free;
698 return TRUE; 734 return TRUE;
699 } 735 }
700 } 736 }
701 737
702 *keyring_id = purple_keyring_get_id(inuse);
703
704 if (purple_debug_is_verbose()) { 738 if (purple_debug_is_verbose()) {
705 purple_debug_misc("keyring", 739 purple_debug_misc("keyring",
706 "Exporting password for account %s (%s) from keyring " 740 "Exporting password for account %s from keyring %s\n",
707 "%s...\n", 741 purple_keyring_print_account(account),
708 purple_account_get_username(account), 742 purple_keyring_get_id(inuse));
709 purple_account_get_protocol_id(account), *keyring_id); 743 }
710 } 744
711 745 *keyring_id = purple_keyring_get_id(inuse);
712 if (*keyring_id == NULL) {
713 *error = g_error_new(PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_INTERNAL,
714 "Plugin does not have a keyring id");
715 purple_debug_info("keyring",
716 "Configured keyring does not have a keyring id, cannot export password.\n");
717 return FALSE;
718 }
719 746
720 export = purple_keyring_get_export_password(inuse); 747 export = purple_keyring_get_export_password(inuse);
721
722 if (export == NULL) { 748 if (export == NULL) {
723 if (purple_debug_is_verbose()) { 749 if (purple_debug_is_verbose()) {
724 purple_debug_misc("Keyring", "Configured keyring " 750 purple_debug_misc("Keyring", "Configured keyring "
725 "cannot export password info. This might be " 751 "cannot export password info. This might be "
726 "normal.\n"); 752 "normal.\n");

mercurial