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