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