1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-keyring.c Store secret cookies in your homedir 3 * 4 * Copyright (C) 2003, 2004 Red Hat Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 #include "dbus-keyring.h" 26 #include "dbus-protocol.h" 27 #include <dbus/dbus-string.h> 28 #include <dbus/dbus-list.h> 29 #include <dbus/dbus-sysdeps.h> 30 31 /** 32 * @defgroup DBusKeyring keyring class 33 * @ingroup DBusInternals 34 * @brief DBusKeyring data structure 35 * 36 * Types and functions related to DBusKeyring. DBusKeyring is intended 37 * to manage cookies used to authenticate clients to servers. This is 38 * essentially the "verify that client can read the user's homedir" 39 * authentication mechanism. Both client and server must have access 40 * to the homedir. 41 * 42 * The secret keys are not kept in locked memory, and are written to a 43 * file in the user's homedir. However they are transient (only used 44 * by a single server instance for a fixed period of time, then 45 * discarded). Also, the keys are not sent over the wire. 46 * 47 * @todo there's a memory leak on some codepath in here, I saw it once 48 * when running make check - probably some specific initial cookies 49 * present in the cookie file, then depending on what we do with them. 50 */ 51 52 /** 53 * @defgroup DBusKeyringInternals DBusKeyring implementation details 54 * @ingroup DBusInternals 55 * @brief DBusKeyring implementation details 56 * 57 * The guts of DBusKeyring. 58 * 59 * @{ 60 */ 61 62 /** The maximum age of a key before we create a new key to use in 63 * challenges. This isn't super-reliably enforced, since system 64 * clocks can change or be wrong, but we make a best effort to only 65 * use keys for a short time. 66 */ 67 #define NEW_KEY_TIMEOUT_SECONDS (60*5) 68 /** 69 * The time after which we drop a key from the secrets file. 70 * The EXPIRE_KEYS_TIMEOUT_SECONDS - NEW_KEY_TIMEOUT_SECONDS is the minimum 71 * time window a client has to complete authentication. 72 */ 73 #define EXPIRE_KEYS_TIMEOUT_SECONDS (NEW_KEY_TIMEOUT_SECONDS + (60*2)) 74 /** 75 * The maximum amount of time a key can be in the future. 76 */ 77 #define MAX_TIME_TRAVEL_SECONDS (60*5) 78 79 /** 80 * Maximum number of keys in the keyring before 81 * we just ignore the rest 82 */ 83 #ifdef DBUS_BUILD_TESTS 84 #define MAX_KEYS_IN_FILE 10 85 #else 86 #define MAX_KEYS_IN_FILE 256 87 #endif 88 89 /** 90 * A single key from the cookie file 91 */ 92 typedef struct 93 { 94 dbus_int32_t id; /**< identifier used to refer to the key */ 95 96 long creation_time; /**< when the key was generated, 97 * as unix timestamp. signed long 98 * matches struct timeval. 99 */ 100 101 DBusString secret; /**< the actual key */ 102 103 } DBusKey; 104 105 /** 106 * @brief Internals of DBusKeyring. 107 * 108 * DBusKeyring internals. DBusKeyring is an opaque object, it must be 109 * used via accessor functions. 110 */ 111 struct DBusKeyring 112 { 113 int refcount; /**< Reference count */ 114 DBusString directory; /**< Directory the below two items are inside */ 115 DBusString filename; /**< Keyring filename */ 116 DBusString filename_lock; /**< Name of lockfile */ 117 DBusKey *keys; /**< Keys loaded from the file */ 118 int n_keys; /**< Number of keys */ 119 DBusCredentials *credentials; /**< Credentials containing user the keyring is for */ 120 }; 121 122 static DBusKeyring* 123 _dbus_keyring_new (void) 124 { 125 DBusKeyring *keyring; 126 127 keyring = dbus_new0 (DBusKeyring, 1); 128 if (keyring == NULL) 129 goto out_0; 130 131 if (!_dbus_string_init (&keyring->directory)) 132 goto out_1; 133 134 if (!_dbus_string_init (&keyring->filename)) 135 goto out_2; 136 137 if (!_dbus_string_init (&keyring->filename_lock)) 138 goto out_3; 139 140 keyring->refcount = 1; 141 keyring->keys = NULL; 142 keyring->n_keys = 0; 143 144 return keyring; 145 146 out_3: 147 _dbus_string_free (&keyring->filename); 148 out_2: 149 _dbus_string_free (&keyring->directory); 150 out_1: 151 dbus_free (keyring); 152 out_0: 153 return NULL; 154 } 155 156 static void 157 free_keys (DBusKey *keys, 158 int n_keys) 159 { 160 int i; 161 162 /* should be safe for args NULL, 0 */ 163 164 i = 0; 165 while (i < n_keys) 166 { 167 _dbus_string_free (&keys[i].secret); 168 ++i; 169 } 170 171 dbus_free (keys); 172 } 173 174 /* Our locking scheme is highly unreliable. However, there is 175 * unfortunately no reliable locking scheme in user home directories; 176 * between bugs in Linux NFS, people using Tru64 or other total crap 177 * NFS, AFS, random-file-system-of-the-week, and so forth, fcntl() in 178 * homedirs simply generates tons of bug reports. This has been 179 * learned through hard experience with GConf, unfortunately. 180 * 181 * This bad hack might work better for the kind of lock we have here, 182 * which we don't expect to hold for any length of time. Crashing 183 * while we hold it should be unlikely, and timing out such that we 184 * delete a stale lock should also be unlikely except when the 185 * filesystem is running really slowly. Stuff might break in corner 186 * cases but as long as it's not a security-level breakage it should 187 * be OK. 188 */ 189 190 /** Maximum number of timeouts waiting for lock before we decide it's stale */ 191 #define MAX_LOCK_TIMEOUTS 32 192 /** Length of each timeout while waiting for a lock */ 193 #define LOCK_TIMEOUT_MILLISECONDS 250 194 195 static dbus_bool_t 196 _dbus_keyring_lock (DBusKeyring *keyring) 197 { 198 int n_timeouts; 199 200 n_timeouts = 0; 201 while (n_timeouts < MAX_LOCK_TIMEOUTS) 202 { 203 DBusError error = DBUS_ERROR_INIT; 204 205 if (_dbus_create_file_exclusively (&keyring->filename_lock, 206 &error)) 207 break; 208 209 _dbus_verbose ("Did not get lock file, sleeping %d milliseconds (%s)\n", 210 LOCK_TIMEOUT_MILLISECONDS, error.message); 211 dbus_error_free (&error); 212 213 _dbus_sleep_milliseconds (LOCK_TIMEOUT_MILLISECONDS); 214 215 ++n_timeouts; 216 } 217 218 if (n_timeouts == MAX_LOCK_TIMEOUTS) 219 { 220 DBusError error = DBUS_ERROR_INIT; 221 222 _dbus_verbose ("Lock file timed out %d times, assuming stale\n", 223 n_timeouts); 224 225 if (!_dbus_delete_file (&keyring->filename_lock, &error)) 226 { 227 _dbus_verbose ("Couldn't delete old lock file: %s\n", 228 error.message); 229 dbus_error_free (&error); 230 return FALSE; 231 } 232 233 if (!_dbus_create_file_exclusively (&keyring->filename_lock, 234 &error)) 235 { 236 _dbus_verbose ("Couldn't create lock file after deleting stale one: %s\n", 237 error.message); 238 dbus_error_free (&error); 239 return FALSE; 240 } 241 } 242 243 return TRUE; 244 } 245 246 static void 247 _dbus_keyring_unlock (DBusKeyring *keyring) 248 { 249 DBusError error = DBUS_ERROR_INIT; 250 251 if (!_dbus_delete_file (&keyring->filename_lock, &error)) 252 { 253 _dbus_warn ("Failed to delete lock file: %s\n", 254 error.message); 255 dbus_error_free (&error); 256 } 257 } 258 259 static DBusKey* 260 find_key_by_id (DBusKey *keys, 261 int n_keys, 262 int id) 263 { 264 int i; 265 266 i = 0; 267 while (i < n_keys) 268 { 269 if (keys[i].id == id) 270 return &keys[i]; 271 272 ++i; 273 } 274 275 return NULL; 276 } 277 278 static dbus_bool_t 279 add_new_key (DBusKey **keys_p, 280 int *n_keys_p, 281 DBusError *error) 282 { 283 DBusKey *new; 284 DBusString bytes; 285 int id; 286 long timestamp; 287 const unsigned char *s; 288 dbus_bool_t retval; 289 DBusKey *keys; 290 int n_keys; 291 292 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 293 294 if (!_dbus_string_init (&bytes)) 295 { 296 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 297 return FALSE; 298 } 299 300 keys = *keys_p; 301 n_keys = *n_keys_p; 302 retval = FALSE; 303 304 /* Generate an integer ID and then the actual key. */ 305 retry: 306 307 if (!_dbus_generate_random_bytes (&bytes, 4)) 308 { 309 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 310 goto out; 311 } 312 313 s = (const unsigned char*) _dbus_string_get_const_data (&bytes); 314 315 id = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 316 if (id < 0) 317 id = - id; 318 _dbus_assert (id >= 0); 319 320 if (find_key_by_id (keys, n_keys, id) != NULL) 321 { 322 _dbus_string_set_length (&bytes, 0); 323 _dbus_verbose ("Key ID %d already existed, trying another one\n", 324 id); 325 goto retry; 326 } 327 328 _dbus_verbose ("Creating key with ID %d\n", id); 329 330 #define KEY_LENGTH_BYTES 24 331 _dbus_string_set_length (&bytes, 0); 332 if (!_dbus_generate_random_bytes (&bytes, KEY_LENGTH_BYTES)) 333 { 334 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 335 goto out; 336 } 337 338 new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1)); 339 if (new == NULL) 340 { 341 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 342 goto out; 343 } 344 345 keys = new; 346 *keys_p = keys; /* otherwise *keys_p ends up invalid */ 347 n_keys += 1; 348 349 if (!_dbus_string_init (&keys[n_keys-1].secret)) 350 { 351 n_keys -= 1; /* we don't want to free the one we didn't init */ 352 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 353 goto out; 354 } 355 356 _dbus_get_real_time (×tamp, NULL); 357 358 keys[n_keys-1].id = id; 359 keys[n_keys-1].creation_time = timestamp; 360 if (!_dbus_string_move (&bytes, 0, 361 &keys[n_keys-1].secret, 362 0)) 363 { 364 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 365 _dbus_string_free (&keys[n_keys-1].secret); 366 n_keys -= 1; 367 goto out; 368 } 369 370 retval = TRUE; 371 372 out: 373 *n_keys_p = n_keys; 374 375 _dbus_string_free (&bytes); 376 return retval; 377 } 378 379 /** 380 * Reloads the keyring file, optionally adds one new key to the file, 381 * removes all expired keys from the file iff a key was added, then 382 * resaves the file. Stores the keys from the file in keyring->keys. 383 * Note that the file is only resaved (written to) if a key is added, 384 * this means that only servers ever write to the file and need to 385 * lock it, which avoids a lot of lock contention at login time and 386 * such. 387 * 388 * @param keyring the keyring 389 * @param add_new #TRUE to add a new key to the file, expire keys, and resave 390 * @param error return location for errors 391 * @returns #FALSE on failure 392 */ 393 static dbus_bool_t 394 _dbus_keyring_reload (DBusKeyring *keyring, 395 dbus_bool_t add_new, 396 DBusError *error) 397 { 398 DBusString contents; 399 DBusString line; 400 dbus_bool_t retval; 401 dbus_bool_t have_lock; 402 DBusKey *keys; 403 int n_keys; 404 int i; 405 long now; 406 DBusError tmp_error; 407 408 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 409 410 if (!_dbus_check_dir_is_private_to_user (&keyring->directory, error)) 411 return FALSE; 412 413 if (!_dbus_string_init (&contents)) 414 { 415 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 416 return FALSE; 417 } 418 419 if (!_dbus_string_init (&line)) 420 { 421 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 422 _dbus_string_free (&contents); 423 return FALSE; 424 } 425 426 keys = NULL; 427 n_keys = 0; 428 retval = FALSE; 429 have_lock = FALSE; 430 431 _dbus_get_real_time (&now, NULL); 432 433 if (add_new) 434 { 435 if (!_dbus_keyring_lock (keyring)) 436 { 437 dbus_set_error (error, DBUS_ERROR_FAILED, 438 "Could not lock keyring file to add to it"); 439 goto out; 440 } 441 442 have_lock = TRUE; 443 } 444 445 dbus_error_init (&tmp_error); 446 if (!_dbus_file_get_contents (&contents, 447 &keyring->filename, 448 &tmp_error)) 449 { 450 _dbus_verbose ("Failed to load keyring file: %s\n", 451 tmp_error.message); 452 /* continue with empty keyring file, so we recreate it */ 453 dbus_error_free (&tmp_error); 454 } 455 456 if (!_dbus_string_validate_ascii (&contents, 0, 457 _dbus_string_get_length (&contents))) 458 { 459 _dbus_warn ("Secret keyring file contains non-ASCII! Ignoring existing contents\n"); 460 _dbus_string_set_length (&contents, 0); 461 } 462 463 /* FIXME this is badly inefficient for large keyring files 464 * (not that large keyring files exist outside of test suites) 465 */ 466 while (_dbus_string_pop_line (&contents, &line)) 467 { 468 int next; 469 long val; 470 int id; 471 long timestamp; 472 int len; 473 int end; 474 DBusKey *new; 475 476 /* Don't load more than the max. */ 477 if (n_keys >= (add_new ? MAX_KEYS_IN_FILE - 1 : MAX_KEYS_IN_FILE)) 478 break; 479 480 next = 0; 481 if (!_dbus_string_parse_int (&line, 0, &val, &next)) 482 { 483 _dbus_verbose ("could not parse secret key ID at start of line\n"); 484 continue; 485 } 486 487 if (val > _DBUS_INT32_MAX || val < 0) 488 { 489 _dbus_verbose ("invalid secret key ID at start of line\n"); 490 continue; 491 } 492 493 id = val; 494 495 _dbus_string_skip_blank (&line, next, &next); 496 497 if (!_dbus_string_parse_int (&line, next, ×tamp, &next)) 498 { 499 _dbus_verbose ("could not parse secret key timestamp\n"); 500 continue; 501 } 502 503 if (timestamp < 0 || 504 (now + MAX_TIME_TRAVEL_SECONDS) < timestamp || 505 (now - EXPIRE_KEYS_TIMEOUT_SECONDS) > timestamp) 506 { 507 _dbus_verbose ("dropping/ignoring %ld-seconds old key with timestamp %ld as current time is %ld\n", 508 now - timestamp, timestamp, now); 509 continue; 510 } 511 512 _dbus_string_skip_blank (&line, next, &next); 513 514 len = _dbus_string_get_length (&line); 515 516 if ((len - next) == 0) 517 { 518 _dbus_verbose ("no secret key after ID and timestamp\n"); 519 continue; 520 } 521 522 /* We have all three parts */ 523 new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1)); 524 if (new == NULL) 525 { 526 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 527 goto out; 528 } 529 530 keys = new; 531 n_keys += 1; 532 533 if (!_dbus_string_init (&keys[n_keys-1].secret)) 534 { 535 n_keys -= 1; /* we don't want to free the one we didn't init */ 536 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 537 goto out; 538 } 539 540 keys[n_keys-1].id = id; 541 keys[n_keys-1].creation_time = timestamp; 542 if (!_dbus_string_hex_decode (&line, next, &end, 543 &keys[n_keys-1].secret, 0)) 544 { 545 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 546 goto out; 547 } 548 549 if (_dbus_string_get_length (&line) != end) 550 { 551 _dbus_verbose ("invalid hex encoding in keyring file\n"); 552 _dbus_string_free (&keys[n_keys - 1].secret); 553 n_keys -= 1; 554 continue; 555 } 556 } 557 558 _dbus_verbose ("Successfully loaded %d existing keys\n", 559 n_keys); 560 561 if (add_new) 562 { 563 if (!add_new_key (&keys, &n_keys, error)) 564 { 565 _dbus_verbose ("Failed to generate new key: %s\n", 566 error ? error->message : "(unknown)"); 567 goto out; 568 } 569 570 _dbus_string_set_length (&contents, 0); 571 572 i = 0; 573 while (i < n_keys) 574 { 575 if (!_dbus_string_append_int (&contents, 576 keys[i].id)) 577 goto nomem; 578 579 if (!_dbus_string_append_byte (&contents, ' ')) 580 goto nomem; 581 582 if (!_dbus_string_append_int (&contents, 583 keys[i].creation_time)) 584 goto nomem; 585 586 if (!_dbus_string_append_byte (&contents, ' ')) 587 goto nomem; 588 589 if (!_dbus_string_hex_encode (&keys[i].secret, 0, 590 &contents, 591 _dbus_string_get_length (&contents))) 592 goto nomem; 593 594 if (!_dbus_string_append_byte (&contents, '\n')) 595 goto nomem; 596 597 ++i; 598 continue; 599 600 nomem: 601 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 602 goto out; 603 } 604 605 if (!_dbus_string_save_to_file (&contents, &keyring->filename, 606 FALSE, error)) 607 goto out; 608 } 609 610 if (keyring->keys) 611 free_keys (keyring->keys, keyring->n_keys); 612 keyring->keys = keys; 613 keyring->n_keys = n_keys; 614 keys = NULL; 615 n_keys = 0; 616 617 retval = TRUE; 618 619 out: 620 if (have_lock) 621 _dbus_keyring_unlock (keyring); 622 623 if (! ((retval == TRUE && (error == NULL || error->name == NULL)) || 624 (retval == FALSE && (error == NULL || error->name != NULL)))) 625 { 626 if (error && error->name) 627 _dbus_verbose ("error is %s: %s\n", error->name, error->message); 628 _dbus_warn ("returning %d but error pointer %p name %s\n", 629 retval, error, error->name ? error->name : "(none)"); 630 _dbus_assert_not_reached ("didn't handle errors properly"); 631 } 632 633 if (keys != NULL) 634 { 635 i = 0; 636 while (i < n_keys) 637 { 638 _dbus_string_zero (&keys[i].secret); 639 _dbus_string_free (&keys[i].secret); 640 ++i; 641 } 642 643 dbus_free (keys); 644 } 645 646 _dbus_string_free (&contents); 647 _dbus_string_free (&line); 648 649 return retval; 650 } 651 652 /** @} */ /* end of internals */ 653 654 /** 655 * @addtogroup DBusKeyring 656 * 657 * @{ 658 */ 659 660 /** 661 * Increments reference count of the keyring 662 * 663 * @param keyring the keyring 664 * @returns the keyring 665 */ 666 DBusKeyring * 667 _dbus_keyring_ref (DBusKeyring *keyring) 668 { 669 keyring->refcount += 1; 670 671 return keyring; 672 } 673 674 /** 675 * Decrements refcount and finalizes if it reaches 676 * zero. 677 * 678 * @param keyring the keyring 679 */ 680 void 681 _dbus_keyring_unref (DBusKeyring *keyring) 682 { 683 keyring->refcount -= 1; 684 685 if (keyring->refcount == 0) 686 { 687 if (keyring->credentials) 688 _dbus_credentials_unref (keyring->credentials); 689 690 _dbus_string_free (&keyring->filename); 691 _dbus_string_free (&keyring->filename_lock); 692 _dbus_string_free (&keyring->directory); 693 free_keys (keyring->keys, keyring->n_keys); 694 dbus_free (keyring); 695 } 696 } 697 698 /** 699 * Creates a new keyring that lives in the ~/.dbus-keyrings directory 700 * of the given user credentials. If the credentials are #NULL or 701 * empty, uses those of the current process. 702 * 703 * @param username username to get keyring for, or #NULL 704 * @param context which keyring to get 705 * @param error return location for errors 706 * @returns the keyring or #NULL on error 707 */ 708 DBusKeyring* 709 _dbus_keyring_new_for_credentials (DBusCredentials *credentials, 710 const DBusString *context, 711 DBusError *error) 712 { 713 DBusString ringdir; 714 DBusKeyring *keyring; 715 dbus_bool_t error_set; 716 DBusError tmp_error; 717 DBusCredentials *our_credentials; 718 719 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 720 721 if (_dbus_check_setuid ()) 722 { 723 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 724 "Unable to create DBus keyring when setuid"); 725 return NULL; 726 } 727 728 keyring = NULL; 729 error_set = FALSE; 730 our_credentials = NULL; 731 732 if (!_dbus_string_init (&ringdir)) 733 { 734 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 735 return NULL; 736 } 737 738 if (credentials != NULL) 739 { 740 our_credentials = _dbus_credentials_copy (credentials); 741 } 742 else 743 { 744 our_credentials = _dbus_credentials_new_from_current_process (); 745 } 746 747 if (our_credentials == NULL) 748 goto failed; 749 750 if (_dbus_credentials_are_anonymous (our_credentials)) 751 { 752 if (!_dbus_credentials_add_from_current_process (our_credentials)) 753 goto failed; 754 } 755 756 if (!_dbus_append_keyring_directory_for_credentials (&ringdir, 757 our_credentials)) 758 goto failed; 759 760 keyring = _dbus_keyring_new (); 761 if (keyring == NULL) 762 goto failed; 763 764 _dbus_assert (keyring->credentials == NULL); 765 keyring->credentials = our_credentials; 766 our_credentials = NULL; /* so we don't unref it again later */ 767 768 /* should have been validated already, but paranoia check here */ 769 if (!_dbus_keyring_validate_context (context)) 770 { 771 error_set = TRUE; 772 dbus_set_error_const (error, 773 DBUS_ERROR_FAILED, 774 "Invalid context in keyring creation"); 775 goto failed; 776 } 777 778 /* Save keyring dir in the keyring object */ 779 if (!_dbus_string_copy (&ringdir, 0, 780 &keyring->directory, 0)) 781 goto failed; 782 783 /* Create keyring->filename based on keyring dir and context */ 784 if (!_dbus_string_copy (&keyring->directory, 0, 785 &keyring->filename, 0)) 786 goto failed; 787 788 if (!_dbus_concat_dir_and_file (&keyring->filename, 789 context)) 790 goto failed; 791 792 /* Create lockfile name */ 793 if (!_dbus_string_copy (&keyring->filename, 0, 794 &keyring->filename_lock, 0)) 795 goto failed; 796 797 if (!_dbus_string_append (&keyring->filename_lock, ".lock")) 798 goto failed; 799 800 /* Reload keyring */ 801 dbus_error_init (&tmp_error); 802 if (!_dbus_keyring_reload (keyring, FALSE, &tmp_error)) 803 { 804 _dbus_verbose ("didn't load an existing keyring: %s\n", 805 tmp_error.message); 806 dbus_error_free (&tmp_error); 807 } 808 809 /* We don't fail fatally if we can't create the directory, 810 * but the keyring will probably always be empty 811 * unless someone else manages to create it 812 */ 813 dbus_error_init (&tmp_error); 814 if (!_dbus_create_directory (&keyring->directory, 815 &tmp_error)) 816 { 817 _dbus_verbose ("Creating keyring directory: %s\n", 818 tmp_error.message); 819 dbus_error_free (&tmp_error); 820 } 821 822 _dbus_string_free (&ringdir); 823 824 return keyring; 825 826 failed: 827 if (!error_set) 828 dbus_set_error_const (error, 829 DBUS_ERROR_NO_MEMORY, 830 NULL); 831 if (our_credentials) 832 _dbus_credentials_unref (our_credentials); 833 if (keyring) 834 _dbus_keyring_unref (keyring); 835 _dbus_string_free (&ringdir); 836 return NULL; 837 838 } 839 840 /** 841 * Checks whether the context is a valid context. 842 * Contexts that might cause confusion when used 843 * in filenames are not allowed (contexts can't 844 * start with a dot or contain dir separators). 845 * 846 * @todo this is the most inefficient implementation 847 * imaginable. 848 * 849 * @param context the context 850 * @returns #TRUE if valid 851 */ 852 dbus_bool_t 853 _dbus_keyring_validate_context (const DBusString *context) 854 { 855 if (_dbus_string_get_length (context) == 0) 856 { 857 _dbus_verbose ("context is zero-length\n"); 858 return FALSE; 859 } 860 861 if (!_dbus_string_validate_ascii (context, 0, 862 _dbus_string_get_length (context))) 863 { 864 _dbus_verbose ("context not valid ascii\n"); 865 return FALSE; 866 } 867 868 /* no directory separators */ 869 if (_dbus_string_find (context, 0, "/", NULL)) 870 { 871 _dbus_verbose ("context contains a slash\n"); 872 return FALSE; 873 } 874 875 if (_dbus_string_find (context, 0, "\\", NULL)) 876 { 877 _dbus_verbose ("context contains a backslash\n"); 878 return FALSE; 879 } 880 881 /* prevent attempts to use dotfiles or ".." or ".lock" 882 * all of which might allow some kind of attack 883 */ 884 if (_dbus_string_find (context, 0, ".", NULL)) 885 { 886 _dbus_verbose ("context contains a dot\n"); 887 return FALSE; 888 } 889 890 /* no spaces/tabs, those are used for separators in the protocol */ 891 if (_dbus_string_find_blank (context, 0, NULL)) 892 { 893 _dbus_verbose ("context contains a blank\n"); 894 return FALSE; 895 } 896 897 if (_dbus_string_find (context, 0, "\n", NULL)) 898 { 899 _dbus_verbose ("context contains a newline\n"); 900 return FALSE; 901 } 902 903 if (_dbus_string_find (context, 0, "\r", NULL)) 904 { 905 _dbus_verbose ("context contains a carriage return\n"); 906 return FALSE; 907 } 908 909 return TRUE; 910 } 911 912 static DBusKey* 913 find_recent_key (DBusKeyring *keyring) 914 { 915 int i; 916 long tv_sec, tv_usec; 917 918 _dbus_get_real_time (&tv_sec, &tv_usec); 919 920 i = 0; 921 while (i < keyring->n_keys) 922 { 923 DBusKey *key = &keyring->keys[i]; 924 925 _dbus_verbose ("Key %d is %ld seconds old\n", 926 i, tv_sec - key->creation_time); 927 928 if ((tv_sec - NEW_KEY_TIMEOUT_SECONDS) < key->creation_time) 929 return key; 930 931 ++i; 932 } 933 934 return NULL; 935 } 936 937 /** 938 * Gets a recent key to use for authentication. 939 * If no recent key exists, creates one. Returns 940 * the key ID. If a key can't be written to the keyring 941 * file so no recent key can be created, returns -1. 942 * All valid keys are > 0. 943 * 944 * @param keyring the keyring 945 * @param error error on failure 946 * @returns key ID to use for auth, or -1 on failure 947 */ 948 int 949 _dbus_keyring_get_best_key (DBusKeyring *keyring, 950 DBusError *error) 951 { 952 DBusKey *key; 953 954 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 955 956 key = find_recent_key (keyring); 957 if (key) 958 return key->id; 959 960 /* All our keys are too old, or we've never loaded the 961 * keyring. Create a new one. 962 */ 963 if (!_dbus_keyring_reload (keyring, TRUE, 964 error)) 965 return -1; 966 967 key = find_recent_key (keyring); 968 if (key) 969 return key->id; 970 else 971 { 972 dbus_set_error_const (error, 973 DBUS_ERROR_FAILED, 974 "No recent-enough key found in keyring, and unable to create a new key"); 975 return -1; 976 } 977 } 978 979 /** 980 * Checks whether the keyring is for the same user as the given credentials. 981 * 982 * @param keyring the keyring 983 * @param credentials the credentials to check 984 * 985 * @returns #TRUE if the keyring belongs to the given user 986 */ 987 dbus_bool_t 988 _dbus_keyring_is_for_credentials (DBusKeyring *keyring, 989 DBusCredentials *credentials) 990 { 991 return _dbus_credentials_same_user (keyring->credentials, 992 credentials); 993 } 994 995 /** 996 * Gets the hex-encoded secret key for the given ID. 997 * Returns #FALSE if not enough memory. Returns #TRUE 998 * but empty key on any other error such as unknown 999 * key ID. 1000 * 1001 * @param keyring the keyring 1002 * @param key_id the key ID 1003 * @param hex_key string to append hex-encoded key to 1004 * @returns #TRUE if we had enough memory 1005 */ 1006 dbus_bool_t 1007 _dbus_keyring_get_hex_key (DBusKeyring *keyring, 1008 int key_id, 1009 DBusString *hex_key) 1010 { 1011 DBusKey *key; 1012 1013 key = find_key_by_id (keyring->keys, 1014 keyring->n_keys, 1015 key_id); 1016 if (key == NULL) 1017 return TRUE; /* had enough memory, so TRUE */ 1018 1019 return _dbus_string_hex_encode (&key->secret, 0, 1020 hex_key, 1021 _dbus_string_get_length (hex_key)); 1022 } 1023 1024 /** @} */ /* end of exposed API */ 1025 1026 #ifdef DBUS_BUILD_TESTS 1027 #include "dbus-test.h" 1028 #include <stdio.h> 1029 1030 dbus_bool_t 1031 _dbus_keyring_test (void) 1032 { 1033 DBusString context; 1034 DBusKeyring *ring1; 1035 DBusKeyring *ring2; 1036 int id; 1037 DBusError error; 1038 int i; 1039 1040 ring1 = NULL; 1041 ring2 = NULL; 1042 1043 /* Context validation */ 1044 1045 _dbus_string_init_const (&context, "foo"); 1046 _dbus_assert (_dbus_keyring_validate_context (&context)); 1047 _dbus_string_init_const (&context, "org_freedesktop_blah"); 1048 _dbus_assert (_dbus_keyring_validate_context (&context)); 1049 1050 _dbus_string_init_const (&context, ""); 1051 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1052 _dbus_string_init_const (&context, ".foo"); 1053 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1054 _dbus_string_init_const (&context, "bar.foo"); 1055 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1056 _dbus_string_init_const (&context, "bar/foo"); 1057 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1058 _dbus_string_init_const (&context, "bar\\foo"); 1059 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1060 _dbus_string_init_const (&context, "foo\xfa\xf0"); 1061 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1062 _dbus_string_init_const (&context, "foo\x80"); 1063 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1064 _dbus_string_init_const (&context, "foo\x7f"); 1065 _dbus_assert (_dbus_keyring_validate_context (&context)); 1066 _dbus_string_init_const (&context, "foo bar"); 1067 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1068 1069 if (!_dbus_string_init (&context)) 1070 _dbus_assert_not_reached ("no memory"); 1071 if (!_dbus_string_append_byte (&context, '\0')) 1072 _dbus_assert_not_reached ("no memory"); 1073 _dbus_assert (!_dbus_keyring_validate_context (&context)); 1074 _dbus_string_free (&context); 1075 1076 /* Now verify that if we create a key in keyring 1, 1077 * it is properly loaded in keyring 2 1078 */ 1079 1080 _dbus_string_init_const (&context, "org_freedesktop_dbus_testsuite"); 1081 dbus_error_init (&error); 1082 ring1 = _dbus_keyring_new_for_credentials (NULL, &context, 1083 &error); 1084 _dbus_assert (ring1 != NULL); 1085 _dbus_assert (error.name == NULL); 1086 1087 id = _dbus_keyring_get_best_key (ring1, &error); 1088 if (id < 0) 1089 { 1090 fprintf (stderr, "Could not load keyring: %s\n", error.message); 1091 dbus_error_free (&error); 1092 goto failure; 1093 } 1094 1095 ring2 = _dbus_keyring_new_for_credentials (NULL, &context, &error); 1096 _dbus_assert (ring2 != NULL); 1097 _dbus_assert (error.name == NULL); 1098 1099 if (ring1->n_keys != ring2->n_keys) 1100 { 1101 fprintf (stderr, "Different number of keys in keyrings\n"); 1102 goto failure; 1103 } 1104 1105 /* We guarantee we load and save keeping keys in a fixed 1106 * order 1107 */ 1108 i = 0; 1109 while (i < ring1->n_keys) 1110 { 1111 if (ring1->keys[i].id != ring2->keys[i].id) 1112 { 1113 fprintf (stderr, "Keyring 1 has first key ID %d and keyring 2 has %d\n", 1114 ring1->keys[i].id, ring2->keys[i].id); 1115 goto failure; 1116 } 1117 1118 if (ring1->keys[i].creation_time != ring2->keys[i].creation_time) 1119 { 1120 fprintf (stderr, "Keyring 1 has first key time %ld and keyring 2 has %ld\n", 1121 ring1->keys[i].creation_time, ring2->keys[i].creation_time); 1122 goto failure; 1123 } 1124 1125 if (!_dbus_string_equal (&ring1->keys[i].secret, 1126 &ring2->keys[i].secret)) 1127 { 1128 fprintf (stderr, "Keyrings 1 and 2 have different secrets for same ID/timestamp\n"); 1129 goto failure; 1130 } 1131 1132 ++i; 1133 } 1134 1135 printf (" %d keys in test\n", ring1->n_keys); 1136 1137 /* Test ref/unref */ 1138 _dbus_keyring_ref (ring1); 1139 _dbus_keyring_ref (ring2); 1140 _dbus_keyring_unref (ring1); 1141 _dbus_keyring_unref (ring2); 1142 1143 1144 /* really unref */ 1145 _dbus_keyring_unref (ring1); 1146 _dbus_keyring_unref (ring2); 1147 1148 return TRUE; 1149 1150 failure: 1151 if (ring1) 1152 _dbus_keyring_unref (ring1); 1153 if (ring2) 1154 _dbus_keyring_unref (ring2); 1155 1156 return FALSE; 1157 } 1158 1159 #endif /* DBUS_BUILD_TESTS */ 1160 1161