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