00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "dbus-keyring.h"
00025 #include "dbus-userdb.h"
00026 #include "dbus-protocol.h"
00027 #include <dbus/dbus-string.h>
00028 #include <dbus/dbus-list.h>
00029 #include <dbus/dbus-sysdeps.h>
00030
00067 #define NEW_KEY_TIMEOUT_SECONDS (60*5)
00068
00073 #define EXPIRE_KEYS_TIMEOUT_SECONDS (NEW_KEY_TIMEOUT_SECONDS + (60*2))
00074
00077 #define MAX_TIME_TRAVEL_SECONDS (60*5)
00078
00083 #ifdef DBUS_BUILD_TESTS
00084 #define MAX_KEYS_IN_FILE 10
00085 #else
00086 #define MAX_KEYS_IN_FILE 256
00087 #endif
00088
00092 typedef struct
00093 {
00094 dbus_int32_t id;
00096 long creation_time;
00101 DBusString secret;
00103 } DBusKey;
00104
00111 struct DBusKeyring
00112 {
00113 int refcount;
00114 DBusString username;
00115 DBusString directory;
00116 DBusString filename;
00117 DBusString filename_lock;
00118 DBusKey *keys;
00119 int n_keys;
00120 };
00121
00122 static DBusKeyring*
00123 _dbus_keyring_new (void)
00124 {
00125 DBusKeyring *keyring;
00126
00127 keyring = dbus_new0 (DBusKeyring, 1);
00128 if (keyring == NULL)
00129 goto out_0;
00130
00131 if (!_dbus_string_init (&keyring->directory))
00132 goto out_1;
00133
00134 if (!_dbus_string_init (&keyring->filename))
00135 goto out_2;
00136
00137 if (!_dbus_string_init (&keyring->filename_lock))
00138 goto out_3;
00139
00140 if (!_dbus_string_init (&keyring->username))
00141 goto out_4;
00142
00143 keyring->refcount = 1;
00144 keyring->keys = NULL;
00145 keyring->n_keys = 0;
00146
00147 return keyring;
00148
00149 out_4:
00150 _dbus_string_free (&keyring->filename_lock);
00151 out_3:
00152 _dbus_string_free (&keyring->filename);
00153 out_2:
00154 _dbus_string_free (&keyring->directory);
00155 out_1:
00156 dbus_free (keyring);
00157 out_0:
00158 return NULL;
00159 }
00160
00161 static void
00162 free_keys (DBusKey *keys,
00163 int n_keys)
00164 {
00165 int i;
00166
00167
00168
00169 i = 0;
00170 while (i < n_keys)
00171 {
00172 _dbus_string_free (&keys[i].secret);
00173 ++i;
00174 }
00175
00176 dbus_free (keys);
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00196 #define MAX_LOCK_TIMEOUTS 32
00197
00198 #define LOCK_TIMEOUT_MILLISECONDS 250
00199
00200 static dbus_bool_t
00201 _dbus_keyring_lock (DBusKeyring *keyring)
00202 {
00203 int n_timeouts;
00204
00205 n_timeouts = 0;
00206 while (n_timeouts < MAX_LOCK_TIMEOUTS)
00207 {
00208 DBusError error;
00209
00210 dbus_error_init (&error);
00211 if (_dbus_create_file_exclusively (&keyring->filename_lock,
00212 &error))
00213 break;
00214
00215 _dbus_verbose ("Did not get lock file, sleeping %d milliseconds (%s)\n",
00216 LOCK_TIMEOUT_MILLISECONDS, error.message);
00217 dbus_error_free (&error);
00218
00219 _dbus_sleep_milliseconds (LOCK_TIMEOUT_MILLISECONDS);
00220
00221 ++n_timeouts;
00222 }
00223
00224 if (n_timeouts == MAX_LOCK_TIMEOUTS)
00225 {
00226 DBusError error;
00227
00228 _dbus_verbose ("Lock file timed out %d times, assuming stale\n",
00229 n_timeouts);
00230
00231 dbus_error_init (&error);
00232
00233 if (!_dbus_delete_file (&keyring->filename_lock, &error))
00234 {
00235 _dbus_verbose ("Couldn't delete old lock file: %s\n",
00236 error.message);
00237 dbus_error_free (&error);
00238 return FALSE;
00239 }
00240
00241 if (!_dbus_create_file_exclusively (&keyring->filename_lock,
00242 &error))
00243 {
00244 _dbus_verbose ("Couldn't create lock file after deleting stale one: %s\n",
00245 error.message);
00246 dbus_error_free (&error);
00247 return FALSE;
00248 }
00249 }
00250
00251 return TRUE;
00252 }
00253
00254 static void
00255 _dbus_keyring_unlock (DBusKeyring *keyring)
00256 {
00257 DBusError error;
00258 dbus_error_init (&error);
00259 if (!_dbus_delete_file (&keyring->filename_lock, &error))
00260 {
00261 _dbus_warn ("Failed to delete lock file: %s\n",
00262 error.message);
00263 dbus_error_free (&error);
00264 }
00265 }
00266
00267 static DBusKey*
00268 find_key_by_id (DBusKey *keys,
00269 int n_keys,
00270 int id)
00271 {
00272 int i;
00273
00274 i = 0;
00275 while (i < n_keys)
00276 {
00277 if (keys[i].id == id)
00278 return &keys[i];
00279
00280 ++i;
00281 }
00282
00283 return NULL;
00284 }
00285
00286 static dbus_bool_t
00287 add_new_key (DBusKey **keys_p,
00288 int *n_keys_p,
00289 DBusError *error)
00290 {
00291 DBusKey *new;
00292 DBusString bytes;
00293 int id;
00294 long timestamp;
00295 const unsigned char *s;
00296 dbus_bool_t retval;
00297 DBusKey *keys;
00298 int n_keys;
00299
00300 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00301
00302 if (!_dbus_string_init (&bytes))
00303 {
00304 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00305 return FALSE;
00306 }
00307
00308 keys = *keys_p;
00309 n_keys = *n_keys_p;
00310 retval = FALSE;
00311
00312
00313 retry:
00314
00315 if (!_dbus_generate_random_bytes (&bytes, 4))
00316 {
00317 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00318 goto out;
00319 }
00320
00321 s = (const unsigned char*) _dbus_string_get_const_data (&bytes);
00322
00323 id = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
00324 if (id < 0)
00325 id = - id;
00326 _dbus_assert (id >= 0);
00327
00328 if (find_key_by_id (keys, n_keys, id) != NULL)
00329 {
00330 _dbus_string_set_length (&bytes, 0);
00331 _dbus_verbose ("Key ID %d already existed, trying another one\n",
00332 id);
00333 goto retry;
00334 }
00335
00336 _dbus_verbose ("Creating key with ID %d\n", id);
00337
00338 #define KEY_LENGTH_BYTES 24
00339 _dbus_string_set_length (&bytes, 0);
00340 if (!_dbus_generate_random_bytes (&bytes, KEY_LENGTH_BYTES))
00341 {
00342 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00343 goto out;
00344 }
00345
00346 new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1));
00347 if (new == NULL)
00348 {
00349 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00350 goto out;
00351 }
00352
00353 keys = new;
00354 *keys_p = keys;
00355 n_keys += 1;
00356
00357 if (!_dbus_string_init (&keys[n_keys-1].secret))
00358 {
00359 n_keys -= 1;
00360 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00361 goto out;
00362 }
00363
00364 _dbus_get_current_time (×tamp, NULL);
00365
00366 keys[n_keys-1].id = id;
00367 keys[n_keys-1].creation_time = timestamp;
00368 if (!_dbus_string_move (&bytes, 0,
00369 &keys[n_keys-1].secret,
00370 0))
00371 {
00372 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00373 _dbus_string_free (&keys[n_keys-1].secret);
00374 n_keys -= 1;
00375 goto out;
00376 }
00377
00378 retval = TRUE;
00379
00380 out:
00381 *n_keys_p = n_keys;
00382
00383 _dbus_string_free (&bytes);
00384 return retval;
00385 }
00386
00401 static dbus_bool_t
00402 _dbus_keyring_reload (DBusKeyring *keyring,
00403 dbus_bool_t add_new,
00404 DBusError *error)
00405 {
00406 DBusString contents;
00407 DBusString line;
00408 dbus_bool_t retval;
00409 dbus_bool_t have_lock;
00410 DBusKey *keys;
00411 int n_keys;
00412 int i;
00413 long now;
00414 DBusError tmp_error;
00415
00416 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00417
00418 if (!_dbus_check_dir_is_private_to_user (&keyring->directory, error))
00419 return FALSE;
00420
00421 if (!_dbus_string_init (&contents))
00422 {
00423 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00424 return FALSE;
00425 }
00426
00427 if (!_dbus_string_init (&line))
00428 {
00429 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00430 _dbus_string_free (&contents);
00431 return FALSE;
00432 }
00433
00434 keys = NULL;
00435 n_keys = 0;
00436 retval = FALSE;
00437 have_lock = FALSE;
00438
00439 _dbus_get_current_time (&now, NULL);
00440
00441 if (add_new)
00442 {
00443 if (!_dbus_keyring_lock (keyring))
00444 {
00445 dbus_set_error (error, DBUS_ERROR_FAILED,
00446 "Could not lock keyring file to add to it");
00447 goto out;
00448 }
00449
00450 have_lock = TRUE;
00451 }
00452
00453 dbus_error_init (&tmp_error);
00454 if (!_dbus_file_get_contents (&contents,
00455 &keyring->filename,
00456 &tmp_error))
00457 {
00458 _dbus_verbose ("Failed to load keyring file: %s\n",
00459 tmp_error.message);
00460
00461 dbus_error_free (&tmp_error);
00462 }
00463
00464 if (!_dbus_string_validate_ascii (&contents, 0,
00465 _dbus_string_get_length (&contents)))
00466 {
00467 _dbus_warn ("Secret keyring file contains non-ASCII! Ignoring existing contents\n");
00468 _dbus_string_set_length (&contents, 0);
00469 }
00470
00471
00472
00473
00474 while (_dbus_string_pop_line (&contents, &line))
00475 {
00476 int next;
00477 long val;
00478 int id;
00479 long timestamp;
00480 int len;
00481 int end;
00482 DBusKey *new;
00483
00484
00485 if (n_keys >= (add_new ? MAX_KEYS_IN_FILE - 1 : MAX_KEYS_IN_FILE))
00486 break;
00487
00488 next = 0;
00489 if (!_dbus_string_parse_int (&line, 0, &val, &next))
00490 {
00491 _dbus_verbose ("could not parse secret key ID at start of line\n");
00492 continue;
00493 }
00494
00495 if (val > _DBUS_INT32_MAX || val < 0)
00496 {
00497 _dbus_verbose ("invalid secret key ID at start of line\n");
00498 continue;
00499 }
00500
00501 id = val;
00502
00503 _dbus_string_skip_blank (&line, next, &next);
00504
00505 if (!_dbus_string_parse_int (&line, next, ×tamp, &next))
00506 {
00507 _dbus_verbose ("could not parse secret key timestamp\n");
00508 continue;
00509 }
00510
00511 if (timestamp < 0 ||
00512 (now + MAX_TIME_TRAVEL_SECONDS) < timestamp ||
00513 (now - EXPIRE_KEYS_TIMEOUT_SECONDS) > timestamp)
00514 {
00515 _dbus_verbose ("dropping/ignoring %ld-seconds old key with timestamp %ld as current time is %ld\n",
00516 now - timestamp, timestamp, now);
00517 continue;
00518 }
00519
00520 _dbus_string_skip_blank (&line, next, &next);
00521
00522 len = _dbus_string_get_length (&line);
00523
00524 if ((len - next) == 0)
00525 {
00526 _dbus_verbose ("no secret key after ID and timestamp\n");
00527 continue;
00528 }
00529
00530
00531 new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1));
00532 if (new == NULL)
00533 {
00534 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00535 goto out;
00536 }
00537
00538 keys = new;
00539 n_keys += 1;
00540
00541 if (!_dbus_string_init (&keys[n_keys-1].secret))
00542 {
00543 n_keys -= 1;
00544 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00545 goto out;
00546 }
00547
00548 keys[n_keys-1].id = id;
00549 keys[n_keys-1].creation_time = timestamp;
00550 if (!_dbus_string_hex_decode (&line, next, &end,
00551 &keys[n_keys-1].secret, 0))
00552 {
00553 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00554 goto out;
00555 }
00556
00557 if (_dbus_string_get_length (&line) != end)
00558 {
00559 _dbus_verbose ("invalid hex encoding in keyring file\n");
00560 _dbus_string_free (&keys[n_keys - 1].secret);
00561 n_keys -= 1;
00562 continue;
00563 }
00564 }
00565
00566 _dbus_verbose ("Successfully loaded %d existing keys\n",
00567 n_keys);
00568
00569 if (add_new)
00570 {
00571 if (!add_new_key (&keys, &n_keys, error))
00572 {
00573 _dbus_verbose ("Failed to generate new key: %s\n",
00574 error ? error->message : "(unknown)");
00575 goto out;
00576 }
00577
00578 _dbus_string_set_length (&contents, 0);
00579
00580 i = 0;
00581 while (i < n_keys)
00582 {
00583 if (!_dbus_string_append_int (&contents,
00584 keys[i].id))
00585 goto nomem;
00586
00587 if (!_dbus_string_append_byte (&contents, ' '))
00588 goto nomem;
00589
00590 if (!_dbus_string_append_int (&contents,
00591 keys[i].creation_time))
00592 goto nomem;
00593
00594 if (!_dbus_string_append_byte (&contents, ' '))
00595 goto nomem;
00596
00597 if (!_dbus_string_hex_encode (&keys[i].secret, 0,
00598 &contents,
00599 _dbus_string_get_length (&contents)))
00600 goto nomem;
00601
00602 if (!_dbus_string_append_byte (&contents, '\n'))
00603 goto nomem;
00604
00605 ++i;
00606 continue;
00607
00608 nomem:
00609 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00610 goto out;
00611 }
00612
00613 if (!_dbus_string_save_to_file (&contents, &keyring->filename,
00614 error))
00615 goto out;
00616 }
00617
00618 if (keyring->keys)
00619 free_keys (keyring->keys, keyring->n_keys);
00620 keyring->keys = keys;
00621 keyring->n_keys = n_keys;
00622 keys = NULL;
00623 n_keys = 0;
00624
00625 retval = TRUE;
00626
00627 out:
00628 if (have_lock)
00629 _dbus_keyring_unlock (keyring);
00630
00631 if (! ((retval == TRUE && (error == NULL || error->name == NULL)) ||
00632 (retval == FALSE && (error == NULL || error->name != NULL))))
00633 {
00634 if (error && error->name)
00635 _dbus_verbose ("error is %s: %s\n", error->name, error->message);
00636 _dbus_warn ("returning %d but error pointer %p name %s\n",
00637 retval, error, error->name ? error->name : "(none)");
00638 _dbus_assert_not_reached ("didn't handle errors properly");
00639 }
00640
00641 if (keys != NULL)
00642 {
00643 i = 0;
00644 while (i < n_keys)
00645 {
00646 _dbus_string_zero (&keys[i].secret);
00647 _dbus_string_free (&keys[i].secret);
00648 ++i;
00649 }
00650
00651 dbus_free (keys);
00652 }
00653
00654 _dbus_string_free (&contents);
00655 _dbus_string_free (&line);
00656
00657 return retval;
00658 }
00659
00661
00674 DBusKeyring *
00675 _dbus_keyring_ref (DBusKeyring *keyring)
00676 {
00677 keyring->refcount += 1;
00678
00679 return keyring;
00680 }
00681
00688 void
00689 _dbus_keyring_unref (DBusKeyring *keyring)
00690 {
00691 keyring->refcount -= 1;
00692
00693 if (keyring->refcount == 0)
00694 {
00695 _dbus_string_free (&keyring->username);
00696 _dbus_string_free (&keyring->filename);
00697 _dbus_string_free (&keyring->filename_lock);
00698 _dbus_string_free (&keyring->directory);
00699 free_keys (keyring->keys, keyring->n_keys);
00700 dbus_free (keyring);
00701 }
00702 }
00703
00714 DBusKeyring*
00715 _dbus_keyring_new_homedir (const DBusString *username,
00716 const DBusString *context,
00717 DBusError *error)
00718 {
00719 DBusString homedir;
00720 DBusKeyring *keyring;
00721 dbus_bool_t error_set;
00722 DBusString dotdir;
00723 DBusError tmp_error;
00724
00725 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00726
00727 keyring = NULL;
00728 error_set = FALSE;
00729
00730 if (!_dbus_string_init (&homedir))
00731 {
00732 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00733 return NULL;
00734 }
00735
00736 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
00737
00738 if (username == NULL)
00739 {
00740 const DBusString *const_homedir;
00741
00742 if (!_dbus_username_from_current_process (&username) ||
00743 !_dbus_homedir_from_current_process (&const_homedir))
00744 goto failed;
00745
00746 if (!_dbus_string_copy (const_homedir, 0,
00747 &homedir, 0))
00748 goto failed;
00749 }
00750 else
00751 {
00752 if (!_dbus_homedir_from_username (username, &homedir))
00753 goto failed;
00754 }
00755
00756 #ifdef DBUS_BUILD_TESTS
00757 {
00758 const char *override;
00759
00760 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
00761 if (override != NULL && *override != '\0')
00762 {
00763 _dbus_string_set_length (&homedir, 0);
00764 if (!_dbus_string_append (&homedir, override))
00765 goto failed;
00766
00767 _dbus_verbose ("Using fake homedir for testing: %s\n",
00768 _dbus_string_get_const_data (&homedir));
00769 }
00770 else
00771 {
00772 static dbus_bool_t already_warned = FALSE;
00773 if (!already_warned)
00774 {
00775 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
00776 already_warned = TRUE;
00777 }
00778 }
00779 }
00780 #endif
00781
00782 _dbus_assert (username != NULL);
00783
00784 keyring = _dbus_keyring_new ();
00785 if (keyring == NULL)
00786 goto failed;
00787
00788
00789 if (!_dbus_keyring_validate_context (context))
00790 {
00791 error_set = TRUE;
00792 dbus_set_error_const (error,
00793 DBUS_ERROR_FAILED,
00794 "Invalid context in keyring creation");
00795 goto failed;
00796 }
00797
00798 if (!_dbus_string_copy (username, 0,
00799 &keyring->username, 0))
00800 goto failed;
00801
00802 if (!_dbus_string_copy (&homedir, 0,
00803 &keyring->directory, 0))
00804 goto failed;
00805
00806 if (!_dbus_concat_dir_and_file (&keyring->directory,
00807 &dotdir))
00808 goto failed;
00809
00810 if (!_dbus_string_copy (&keyring->directory, 0,
00811 &keyring->filename, 0))
00812 goto failed;
00813
00814 if (!_dbus_concat_dir_and_file (&keyring->filename,
00815 context))
00816 goto failed;
00817
00818 if (!_dbus_string_copy (&keyring->filename, 0,
00819 &keyring->filename_lock, 0))
00820 goto failed;
00821
00822 if (!_dbus_string_append (&keyring->filename_lock, ".lock"))
00823 goto failed;
00824
00825 dbus_error_init (&tmp_error);
00826 if (!_dbus_keyring_reload (keyring, FALSE, &tmp_error))
00827 {
00828 _dbus_verbose ("didn't load an existing keyring: %s\n",
00829 tmp_error.message);
00830 dbus_error_free (&tmp_error);
00831 }
00832
00833
00834
00835
00836
00837 dbus_error_init (&tmp_error);
00838 if (!_dbus_create_directory (&keyring->directory,
00839 &tmp_error))
00840 {
00841 _dbus_verbose ("Creating keyring directory: %s\n",
00842 tmp_error.message);
00843 dbus_error_free (&tmp_error);
00844 }
00845
00846 _dbus_string_free (&homedir);
00847
00848 return keyring;
00849
00850 failed:
00851 if (!error_set)
00852 dbus_set_error_const (error,
00853 DBUS_ERROR_NO_MEMORY,
00854 NULL);
00855 if (keyring)
00856 _dbus_keyring_unref (keyring);
00857 _dbus_string_free (&homedir);
00858 return NULL;
00859
00860 }
00861
00874 dbus_bool_t
00875 _dbus_keyring_validate_context (const DBusString *context)
00876 {
00877 if (_dbus_string_get_length (context) == 0)
00878 {
00879 _dbus_verbose ("context is zero-length\n");
00880 return FALSE;
00881 }
00882
00883 if (!_dbus_string_validate_ascii (context, 0,
00884 _dbus_string_get_length (context)))
00885 {
00886 _dbus_verbose ("context not valid ascii\n");
00887 return FALSE;
00888 }
00889
00890
00891 if (_dbus_string_find (context, 0, "/", NULL))
00892 {
00893 _dbus_verbose ("context contains a slash\n");
00894 return FALSE;
00895 }
00896
00897 if (_dbus_string_find (context, 0, "\\", NULL))
00898 {
00899 _dbus_verbose ("context contains a backslash\n");
00900 return FALSE;
00901 }
00902
00903
00904
00905
00906 if (_dbus_string_find (context, 0, ".", NULL))
00907 {
00908 _dbus_verbose ("context contains a dot\n");
00909 return FALSE;
00910 }
00911
00912
00913 if (_dbus_string_find_blank (context, 0, NULL))
00914 {
00915 _dbus_verbose ("context contains a blank\n");
00916 return FALSE;
00917 }
00918
00919 if (_dbus_string_find (context, 0, "\n", NULL))
00920 {
00921 _dbus_verbose ("context contains a newline\n");
00922 return FALSE;
00923 }
00924
00925 if (_dbus_string_find (context, 0, "\r", NULL))
00926 {
00927 _dbus_verbose ("context contains a carriage return\n");
00928 return FALSE;
00929 }
00930
00931 return TRUE;
00932 }
00933
00934 static DBusKey*
00935 find_recent_key (DBusKeyring *keyring)
00936 {
00937 int i;
00938 long tv_sec, tv_usec;
00939
00940 _dbus_get_current_time (&tv_sec, &tv_usec);
00941
00942 i = 0;
00943 while (i < keyring->n_keys)
00944 {
00945 DBusKey *key = &keyring->keys[i];
00946
00947 _dbus_verbose ("Key %d is %ld seconds old\n",
00948 i, tv_sec - key->creation_time);
00949
00950 if ((tv_sec - NEW_KEY_TIMEOUT_SECONDS) < key->creation_time)
00951 return key;
00952
00953 ++i;
00954 }
00955
00956 return NULL;
00957 }
00958
00970 int
00971 _dbus_keyring_get_best_key (DBusKeyring *keyring,
00972 DBusError *error)
00973 {
00974 DBusKey *key;
00975
00976 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00977
00978 key = find_recent_key (keyring);
00979 if (key)
00980 return key->id;
00981
00982
00983
00984
00985 if (!_dbus_keyring_reload (keyring, TRUE,
00986 error))
00987 return -1;
00988
00989 key = find_recent_key (keyring);
00990 if (key)
00991 return key->id;
00992 else
00993 {
00994 dbus_set_error_const (error,
00995 DBUS_ERROR_FAILED,
00996 "No recent-enough key found in keyring, and unable to create a new key");
00997 return -1;
00998 }
00999 }
01000
01009 dbus_bool_t
01010 _dbus_keyring_is_for_user (DBusKeyring *keyring,
01011 const DBusString *username)
01012 {
01013 return _dbus_string_equal (&keyring->username,
01014 username);
01015 }
01016
01028 dbus_bool_t
01029 _dbus_keyring_get_hex_key (DBusKeyring *keyring,
01030 int key_id,
01031 DBusString *hex_key)
01032 {
01033 DBusKey *key;
01034
01035 key = find_key_by_id (keyring->keys,
01036 keyring->n_keys,
01037 key_id);
01038 if (key == NULL)
01039 return TRUE;
01040
01041 return _dbus_string_hex_encode (&key->secret, 0,
01042 hex_key,
01043 _dbus_string_get_length (hex_key));
01044 }
01045
01047
01048 #ifdef DBUS_BUILD_TESTS
01049 #include "dbus-test.h"
01050 #include <stdio.h>
01051
01052 dbus_bool_t
01053 _dbus_keyring_test (void)
01054 {
01055 DBusString context;
01056 DBusKeyring *ring1;
01057 DBusKeyring *ring2;
01058 int id;
01059 DBusError error;
01060 int i;
01061
01062 ring1 = NULL;
01063 ring2 = NULL;
01064
01065
01066
01067 _dbus_string_init_const (&context, "foo");
01068 _dbus_assert (_dbus_keyring_validate_context (&context));
01069 _dbus_string_init_const (&context, "org_freedesktop_blah");
01070 _dbus_assert (_dbus_keyring_validate_context (&context));
01071
01072 _dbus_string_init_const (&context, "");
01073 _dbus_assert (!_dbus_keyring_validate_context (&context));
01074 _dbus_string_init_const (&context, ".foo");
01075 _dbus_assert (!_dbus_keyring_validate_context (&context));
01076 _dbus_string_init_const (&context, "bar.foo");
01077 _dbus_assert (!_dbus_keyring_validate_context (&context));
01078 _dbus_string_init_const (&context, "bar/foo");
01079 _dbus_assert (!_dbus_keyring_validate_context (&context));
01080 _dbus_string_init_const (&context, "bar\\foo");
01081 _dbus_assert (!_dbus_keyring_validate_context (&context));
01082 _dbus_string_init_const (&context, "foo\xfa\xf0");
01083 _dbus_assert (!_dbus_keyring_validate_context (&context));
01084 _dbus_string_init_const (&context, "foo\x80");
01085 _dbus_assert (!_dbus_keyring_validate_context (&context));
01086 _dbus_string_init_const (&context, "foo\x7f");
01087 _dbus_assert (_dbus_keyring_validate_context (&context));
01088 _dbus_string_init_const (&context, "foo bar");
01089 _dbus_assert (!_dbus_keyring_validate_context (&context));
01090
01091 if (!_dbus_string_init (&context))
01092 _dbus_assert_not_reached ("no memory");
01093 if (!_dbus_string_append_byte (&context, '\0'))
01094 _dbus_assert_not_reached ("no memory");
01095 _dbus_assert (!_dbus_keyring_validate_context (&context));
01096 _dbus_string_free (&context);
01097
01098
01099
01100
01101
01102 _dbus_string_init_const (&context, "org_freedesktop_dbus_testsuite");
01103 dbus_error_init (&error);
01104 ring1 = _dbus_keyring_new_homedir (NULL, &context,
01105 &error);
01106 _dbus_assert (ring1);
01107 _dbus_assert (error.name == NULL);
01108
01109 id = _dbus_keyring_get_best_key (ring1, &error);
01110 if (id < 0)
01111 {
01112 fprintf (stderr, "Could not load keyring: %s\n", error.message);
01113 dbus_error_free (&error);
01114 goto failure;
01115 }
01116
01117 ring2 = _dbus_keyring_new_homedir (NULL, &context, &error);
01118 _dbus_assert (ring2);
01119 _dbus_assert (error.name == NULL);
01120
01121 if (ring1->n_keys != ring2->n_keys)
01122 {
01123 fprintf (stderr, "Different number of keys in keyrings\n");
01124 goto failure;
01125 }
01126
01127
01128
01129
01130 i = 0;
01131 while (i < ring1->n_keys)
01132 {
01133 if (ring1->keys[i].id != ring2->keys[i].id)
01134 {
01135 fprintf (stderr, "Keyring 1 has first key ID %d and keyring 2 has %d\n",
01136 ring1->keys[i].id, ring2->keys[i].id);
01137 goto failure;
01138 }
01139
01140 if (ring1->keys[i].creation_time != ring2->keys[i].creation_time)
01141 {
01142 fprintf (stderr, "Keyring 1 has first key time %ld and keyring 2 has %ld\n",
01143 ring1->keys[i].creation_time, ring2->keys[i].creation_time);
01144 goto failure;
01145 }
01146
01147 if (!_dbus_string_equal (&ring1->keys[i].secret,
01148 &ring2->keys[i].secret))
01149 {
01150 fprintf (stderr, "Keyrings 1 and 2 have different secrets for same ID/timestamp\n");
01151 goto failure;
01152 }
01153
01154 ++i;
01155 }
01156
01157 printf (" %d keys in test\n", ring1->n_keys);
01158
01159
01160 _dbus_keyring_ref (ring1);
01161 _dbus_keyring_ref (ring2);
01162 _dbus_keyring_unref (ring1);
01163 _dbus_keyring_unref (ring2);
01164
01165
01166
01167 _dbus_keyring_unref (ring1);
01168 _dbus_keyring_unref (ring2);
01169
01170 return TRUE;
01171
01172 failure:
01173 if (ring1)
01174 _dbus_keyring_unref (ring1);
01175 if (ring2)
01176 _dbus_keyring_unref (ring2);
01177
01178 return FALSE;
01179 }
01180
01181 #endif
01182