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