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