Home | History | Annotate | Download | only in dbus
      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 (&timestamp, 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, &timestamp, &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