Coverage report for dbus/dbus-keyring.c.gcov

        -:    0:Source:dbus-keyring.c
        -:    0:Graph:.libs/dbus-keyring.gcno
        -:    0:Data:.libs/dbus-keyring.gcda
        -:    0:Runs:11813
        -:    0:Programs:5
        -:    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)
function _dbus_keyring_new called 6888 returned 100% blocks executed 100%
     6888:  124:{
        -:  125:  DBusKeyring *keyring;
        -:  126:
     6888:  127:  keyring = dbus_new0 (DBusKeyring, 1);
call    0 returned 100%
     6888:  128:  if (keyring == NULL)
branch  0 taken 1% (fallthrough)
branch  1 taken 99%
        6:  129:    goto out_0;
        -:  130:  
     6882:  131:  if (!_dbus_string_init (&keyring->directory))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        6:  132:    goto out_1;
        -:  133:
     6876:  134:  if (!_dbus_string_init (&keyring->filename))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        6:  135:    goto out_2;
        -:  136:
     6870:  137:  if (!_dbus_string_init (&keyring->filename_lock))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        6:  138:    goto out_3;
        -:  139:
     6864:  140:  if (!_dbus_string_init (&keyring->username))
call    0 returned 100%
branch  1 taken 99% (fallthrough)
branch  2 taken 1%
        6:  141:    goto out_4;
        -:  142:  
     6858:  143:  keyring->refcount = 1;
     6858:  144:  keyring->keys = NULL;
     6858:  145:  keyring->n_keys = 0;
        -:  146:
     6858:  147:  return keyring;
        -:  148:
        6:  149: out_4:
        6:  150:  _dbus_string_free (&keyring->filename_lock);
call    0 returned 100%
       12:  151: out_3:
       12:  152:  _dbus_string_free (&keyring->filename);
call    0 returned 100%
       18:  153: out_2:
       18:  154:  _dbus_string_free (&keyring->directory);
call    0 returned 100%
       24:  155: out_1:
       24:  156:  dbus_free (keyring);
call    0 returned 100%
       30:  157: out_0:
       30:  158:  return NULL;
        -:  159:}
        -:  160:
        -:  161:static void
        -:  162:free_keys (DBusKey *keys,
        -:  163:           int      n_keys)
function free_keys called 6858 returned 100% blocks executed 100%
     6858:  164:{
        -:  165:  int i;
        -:  166:
        -:  167:  /* should be safe for args NULL, 0 */
        -:  168:  
     6858:  169:  i = 0;
    54189:  170:  while (i < n_keys)
branch  0 taken 86%
branch  1 taken 14% (fallthrough)
        -:  171:    {
    40473:  172:      _dbus_string_free (&keys[i].secret);
call    0 returned 100%
    40473:  173:      ++i;
        -:  174:    }
        -:  175:
     6858:  176:  dbus_free (keys);
call    0 returned 100%
     6858:  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)
function _dbus_keyring_lock called 310 returned 100% blocks executed 36%
      310:  202:{
        -:  203:  int n_timeouts;
        -:  204:  
      310:  205:  n_timeouts = 0;
      620:  206:  while (n_timeouts < MAX_LOCK_TIMEOUTS)
branch  0 taken 100%
branch  1 taken 0% (fallthrough)
        -:  207:    {
        -:  208:      DBusError error;
        -:  209:
      310:  210:      dbus_error_init (&error);
call    0 returned 100%
      310:  211:      if (_dbus_create_file_exclusively (&keyring->filename_lock,
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0%
        -:  212:                                         &error))
      310:  213:        break;
        -:  214:
    #####:  215:      _dbus_verbose ("Did not get lock file, sleeping %d milliseconds (%s)\n",
call    0 never executed
        -:  216:                     LOCK_TIMEOUT_MILLISECONDS, error.message);
    #####:  217:      dbus_error_free (&error);
call    0 never executed
        -:  218:
    #####:  219:      _dbus_sleep_milliseconds (LOCK_TIMEOUT_MILLISECONDS);
call    0 never executed
        -:  220:      
    #####:  221:      ++n_timeouts;
        -:  222:    }
        -:  223:
      310:  224:  if (n_timeouts == MAX_LOCK_TIMEOUTS)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  225:    {
        -:  226:      DBusError error;
        -:  227:      
    #####:  228:      _dbus_verbose ("Lock file timed out %d times, assuming stale\n",
call    0 never executed
        -:  229:                     n_timeouts);
        -:  230:
    #####:  231:      dbus_error_init (&error);
call    0 never executed
        -:  232:
    #####:  233:      if (!_dbus_delete_file (&keyring->filename_lock, &error))
call    0 never executed
branch  1 never executed
branch  2 never executed
        -:  234:        {
    #####:  235:          _dbus_verbose ("Couldn't delete old lock file: %s\n",
call    0 never executed
        -:  236:                         error.message);
    #####:  237:          dbus_error_free (&error);
call    0 never executed
    #####:  238:          return FALSE;
        -:  239:        }
        -:  240:
    #####:  241:      if (!_dbus_create_file_exclusively (&keyring->filename_lock,
call    0 never executed
branch  1 never executed
branch  2 never executed
        -:  242:                                          &error))
        -:  243:        {
    #####:  244:          _dbus_verbose ("Couldn't create lock file after deleting stale one: %s\n",
call    0 never executed
        -:  245:                         error.message);
    #####:  246:          dbus_error_free (&error);
call    0 never executed
    #####:  247:          return FALSE;
        -:  248:        }
        -:  249:    }
        -:  250:  
      310:  251:  return TRUE;
        -:  252:}
        -:  253:
        -:  254:static void
        -:  255:_dbus_keyring_unlock (DBusKeyring *keyring)
function _dbus_keyring_unlock called 310 returned 100% blocks executed 67%
      310:  256:{
        -:  257:  DBusError error;
      310:  258:  dbus_error_init (&error);
call    0 returned 100%
      310:  259:  if (!_dbus_delete_file (&keyring->filename_lock, &error))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  260:    {
    #####:  261:      _dbus_warn ("Failed to delete lock file: %s\n",
call    0 never executed
        -:  262:                  error.message);
    #####:  263:      dbus_error_free (&error);
call    0 never executed
        -:  264:    }
      310:  265:}
        -:  266:
        -:  267:static DBusKey*
        -:  268:find_key_by_id (DBusKey *keys,
        -:  269:                int      n_keys,
        -:  270:                int      id)
function find_key_by_id called 6504 returned 100% blocks executed 100%
     6504:  271:{
        -:  272:  int i;
        -:  273:
     6504:  274:  i = 0;
    15744:  275:  while (i < n_keys)
branch  0 taken 90%
branch  1 taken 10% (fallthrough)
        -:  276:    {
     8361:  277:      if (keys[i].id == id)
branch  0 taken 67% (fallthrough)
branch  1 taken 33%
     5625:  278:        return &keys[i];
        -:  279:      
     2736:  280:      ++i;
        -:  281:    }
        -:  282:
      879:  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)
function add_new_key called 310 returned 100% blocks executed 65%
      310:  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:
      310:  300:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  301:  
      310:  302:  if (!_dbus_string_init (&bytes))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  303:    {
    #####:  304:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 never executed
    #####:  305:      return FALSE;
        -:  306:    }
        -:  307:
      310:  308:  keys = *keys_p;
      310:  309:  n_keys = *n_keys_p;
      310:  310:  retval = FALSE;
        -:  311:      
        -:  312:  /* Generate an integer ID and then the actual key. */
      310:  313: retry:
        -:  314:      
      310:  315:  if (!_dbus_generate_random_bytes (&bytes, 4))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  316:    {
    #####:  317:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 never executed
    #####:  318:      goto out;
        -:  319:    }
        -:  320:
      310:  321:  s = (const unsigned char*) _dbus_string_get_const_data (&bytes);
call    0 returned 100%
        -:  322:      
      310:  323:  id = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
      310:  324:  if (id < 0)
branch  0 taken 50% (fallthrough)
branch  1 taken 50%
      154:  325:    id = - id;
      310:  326:  _dbus_assert (id >= 0);
call    0 returned 100%
        -:  327:
      310:  328:  if (find_key_by_id (keys, n_keys, id) != NULL)
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  329:    {
    #####:  330:      _dbus_string_set_length (&bytes, 0);
call    0 never executed
    #####:  331:      _dbus_verbose ("Key ID %d already existed, trying another one\n",
call    0 never executed
        -:  332:                     id);
    #####:  333:      goto retry;
        -:  334:    }
        -:  335:
      310:  336:  _dbus_verbose ("Creating key with ID %d\n", id);
call    0 returned 100%
        -:  337:      
        -:  338:#define KEY_LENGTH_BYTES 24
      310:  339:  _dbus_string_set_length (&bytes, 0);
call    0 returned 100%
      310:  340:  if (!_dbus_generate_random_bytes (&bytes, KEY_LENGTH_BYTES))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  341:    {
    #####:  342:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 never executed
    #####:  343:      goto out;
        -:  344:    }
        -:  345:
      310:  346:  new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1));
call    0 returned 100%
      310:  347:  if (new == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  348:    {
    #####:  349:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 never executed
    #####:  350:      goto out;
        -:  351:    }
        -:  352:
      310:  353:  keys = new;
      310:  354:  *keys_p = keys; /* otherwise *keys_p ends up invalid */
      310:  355:  n_keys += 1;
        -:  356:
      310:  357:  if (!_dbus_string_init (&keys[n_keys-1].secret))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  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);
call    0 never executed
    #####:  361:      goto out;
        -:  362:    }
        -:  363:
      310:  364:  _dbus_get_current_time (&timestamp, NULL);
call    0 returned 100%
        -:  365:      
      310:  366:  keys[n_keys-1].id = id;
      310:  367:  keys[n_keys-1].creation_time = timestamp;
      310:  368:  if (!_dbus_string_move (&bytes, 0,
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  369:                          &keys[n_keys-1].secret,
        -:  370:                          0))
        -:  371:    {
    #####:  372:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 never executed
    #####:  373:      _dbus_string_free (&keys[n_keys-1].secret);
call    0 never executed
    #####:  374:      n_keys -= 1;
    #####:  375:      goto out;
        -:  376:    }
        -:  377:  
      310:  378:  retval = TRUE;
        -:  379:  
      310:  380: out:
      310:  381:  *n_keys_p = n_keys;
        -:  382:  
      310:  383:  _dbus_string_free (&bytes);
call    0 returned 100%
      310:  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)
function _dbus_keyring_reload called 7387 returned 100% blocks executed 73%
     7387:  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:
     7387:  416:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  417:  
     7387:  418:  if (!_dbus_check_dir_is_private_to_user (&keyring->directory, error))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        1:  419:    return FALSE;
        -:  420:    
     7386:  421:  if (!_dbus_string_init (&contents))
call    0 returned 100%
branch  1 taken 4% (fallthrough)
branch  2 taken 96%
        -:  422:    {
      280:  423:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 returned 100%
      280:  424:      return FALSE;
        -:  425:    }
        -:  426:
     7106:  427:  if (!_dbus_string_init (&line))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  428:    {
        8:  429:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 returned 100%
        8:  430:      _dbus_string_free (&contents);
call    0 returned 100%
        8:  431:      return FALSE;
        -:  432:    }
        -:  433:   
     7098:  434:  keys = NULL;
     7098:  435:  n_keys = 0;
     7098:  436:  retval = FALSE;
     7098:  437:  have_lock = FALSE;
        -:  438:
     7098:  439:  _dbus_get_current_time (&now, NULL);
call    0 returned 100%
        -:  440:  
     7098:  441:  if (add_new)
branch  0 taken 4% (fallthrough)
branch  1 taken 96%
        -:  442:    {
      310:  443:      if (!_dbus_keyring_lock (keyring))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  444:        {
    #####:  445:          dbus_set_error (error, DBUS_ERROR_FAILED,
call    0 never executed
        -:  446:                          "Could not lock keyring file to add to it");
    #####:  447:          goto out;
        -:  448:        }
        -:  449:
      310:  450:      have_lock = TRUE;
        -:  451:    }
        -:  452:
     7098:  453:  dbus_error_init (&tmp_error);
call    0 returned 100%
     7098:  454:  if (!_dbus_file_get_contents (&contents, 
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  455:                                &keyring->filename,
        -:  456:                                &tmp_error))
        -:  457:    {
        8:  458:      _dbus_verbose ("Failed to load keyring file: %s\n",
call    0 returned 100%
        -:  459:                     tmp_error.message);
        -:  460:      /* continue with empty keyring file, so we recreate it */
        8:  461:      dbus_error_free (&tmp_error);
call    0 returned 100%
        -:  462:    }
        -:  463:
     7098:  464:  if (!_dbus_string_validate_ascii (&contents, 0,
call    0 returned 100%
call    1 returned 100%
branch  2 taken 0% (fallthrough)
branch  3 taken 100%
        -:  465:                                    _dbus_string_get_length (&contents)))
        -:  466:    {
    #####:  467:      _dbus_warn ("Secret keyring file contains non-ASCII! Ignoring existing contents\n");
call    0 never executed
    #####:  468:      _dbus_string_set_length (&contents, 0);
call    0 never executed
        -:  469:    }
        -:  470:
        -:  471:  /* FIXME this is badly inefficient for large keyring files
        -:  472:   * (not that large keyring files exist outside of test suites)
        -:  473:   */
    59159:  474:  while (_dbus_string_pop_line (&contents, &line))
call    0 returned 100%
branch  1 taken 89%
branch  2 taken 11% (fallthrough)
        -:  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. */
    46389:  485:      if (n_keys >= (add_new ? MAX_KEYS_IN_FILE - 1 : MAX_KEYS_IN_FILE))
branch  0 taken 7% (fallthrough)
branch  1 taken 93%
branch  2 taken 1% (fallthrough)
branch  3 taken 99%
      299:  486:        break;
        -:  487:      
    46090:  488:      next = 0;
    46090:  489:      if (!_dbus_string_parse_int (&line, 0, &val, &next))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  490:        {
    #####:  491:          _dbus_verbose ("could not parse secret key ID at start of line\n");
call    0 never executed
    #####:  492:          continue;
        -:  493:        }
        -:  494:
    46090:  495:      if (val > _DBUS_INT32_MAX || val < 0)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 0% (fallthrough)
branch  3 taken 100%
        -:  496:        {
    #####:  497:          _dbus_verbose ("invalid secret key ID at start of line\n");
call    0 never executed
    #####:  498:          continue;
        -:  499:        }
        -:  500:      
    46090:  501:      id = val;
        -:  502:
    46090:  503:      _dbus_string_skip_blank (&line, next, &next);
call    0 returned 100%
        -:  504:      
    46090:  505:      if (!_dbus_string_parse_int (&line, next, &timestamp, &next))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  506:        {
    #####:  507:          _dbus_verbose ("could not parse secret key timestamp\n");
call    0 never executed
    #####:  508:          continue;
        -:  509:        }
        -:  510:
    46090:  511:      if (timestamp < 0 ||
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 100% (fallthrough)
branch  3 taken 0%
branch  4 taken 0% (fallthrough)
branch  5 taken 100%
        -:  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",
call    0 never executed
        -:  516:                         now - timestamp, timestamp, now);
    #####:  517:          continue;
        -:  518:        }
        -:  519:      
    46090:  520:      _dbus_string_skip_blank (&line, next, &next);
call    0 returned 100%
        -:  521:
    46090:  522:      len = _dbus_string_get_length (&line);
call    0 returned 100%
        -:  523:
    46090:  524:      if ((len - next) == 0)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  525:        {
    #####:  526:          _dbus_verbose ("no secret key after ID and timestamp\n");
call    0 never executed
    #####:  527:          continue;
        -:  528:        }
        -:  529:      
        -:  530:      /* We have all three parts */
    46090:  531:      new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1));
call    0 returned 100%
    46090:  532:      if (new == NULL)
branch  0 taken 1% (fallthrough)
branch  1 taken 99%
        -:  533:        {
       44:  534:          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 returned 100%
       44:  535:          goto out;
        -:  536:        }
        -:  537:
    46046:  538:      keys = new;
    46046:  539:      n_keys += 1;
        -:  540:
    46046:  541:      if (!_dbus_string_init (&keys[n_keys-1].secret))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  542:        {
       43:  543:          n_keys -= 1; /* we don't want to free the one we didn't init */
       43:  544:          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 returned 100%
       43:  545:          goto out;
        -:  546:        }
        -:  547:      
    46003:  548:      keys[n_keys-1].id = id;
    46003:  549:      keys[n_keys-1].creation_time = timestamp;
    46003:  550:      if (!_dbus_string_hex_decode (&line, next, &end,
call    0 returned 100%
branch  1 taken 2% (fallthrough)
branch  2 taken 98%
        -:  551:                                    &keys[n_keys-1].secret, 0))
        -:  552:	{
     1040:  553:	  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 returned 100%
     1040:  554:	  goto out;
        -:  555:	}
        -:  556:
    44963:  557:      if (_dbus_string_get_length (&line) != end)
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  558:	{
    #####:  559:	  _dbus_verbose ("invalid hex encoding in keyring file\n");
call    0 never executed
    #####:  560:	  _dbus_string_free (&keys[n_keys - 1].secret);
call    0 never executed
    #####:  561:	  n_keys -= 1;
    #####:  562:	  continue;
        -:  563:	}
        -:  564:    }
        -:  565:
     5971:  566:  _dbus_verbose ("Successfully loaded %d existing keys\n",
call    0 returned 100%
        -:  567:                 n_keys);
        -:  568:
     5971:  569:  if (add_new)
branch  0 taken 5% (fallthrough)
branch  1 taken 95%
        -:  570:    {
      310:  571:      if (!add_new_key (&keys, &n_keys, error))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  572:        {
    #####:  573:          _dbus_verbose ("Failed to generate new key: %s\n",
branch  0 never executed
branch  1 never executed
call    2 never executed
        -:  574:                         error ? error->message : "(unknown)");
    #####:  575:          goto out;
        -:  576:        }
        -:  577:
      310:  578:      _dbus_string_set_length (&contents, 0);
call    0 returned 100%
        -:  579:
      310:  580:      i = 0;
     3666:  581:      while (i < n_keys)
branch  0 taken 91%
branch  1 taken 9% (fallthrough)
        -:  582:        {
     3046:  583:          if (!_dbus_string_append_int (&contents,
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0%
        -:  584:                                        keys[i].id))
    #####:  585:            goto nomem;
        -:  586:
     3046:  587:          if (!_dbus_string_append_byte (&contents, ' '))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  588:            goto nomem;
        -:  589:
     3046:  590:          if (!_dbus_string_append_int (&contents,
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  591:                                        keys[i].creation_time))
    #####:  592:            goto nomem;
        -:  593:
     3046:  594:          if (!_dbus_string_append_byte (&contents, ' '))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  595:            goto nomem;
        -:  596:
     3046:  597:          if (!_dbus_string_hex_encode (&keys[i].secret, 0,
call    0 returned 100%
call    1 returned 100%
branch  2 taken 0% (fallthrough)
branch  3 taken 100%
        -:  598:                                        &contents,
        -:  599:                                        _dbus_string_get_length (&contents)))
    #####:  600:            goto nomem;
        -:  601:
     3046:  602:          if (!_dbus_string_append_byte (&contents, '\n'))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  603:            goto nomem;          
        -:  604:          
     3046:  605:          ++i;
     3046:  606:          continue;
        -:  607:
    #####:  608:        nomem:
    #####:  609:          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 never executed
    #####:  610:          goto out;
        -:  611:        }
        -:  612:      
      310:  613:      if (!_dbus_string_save_to_file (&contents, &keyring->filename,
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  614:                                      error))
    #####:  615:        goto out;
        -:  616:    }
        -:  617:
     5971:  618:  if (keyring->keys)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  619:    free_keys (keyring->keys, keyring->n_keys);
call    0 never executed
     5971:  620:  keyring->keys = keys;
     5971:  621:  keyring->n_keys = n_keys;
     5971:  622:  keys = NULL;
     5971:  623:  n_keys = 0;
        -:  624:  
     5971:  625:  retval = TRUE;  
        -:  626:  
     7098:  627: out:
     7098:  628:  if (have_lock)
branch  0 taken 4% (fallthrough)
branch  1 taken 96%
      310:  629:    _dbus_keyring_unlock (keyring);
call    0 returned 100%
        -:  630:  
     7098:  631:  if (! ((retval == TRUE && (error == NULL || error->name == NULL)) ||
branch  0 taken 84% (fallthrough)
branch  1 taken 16%
branch  2 taken 100% (fallthrough)
branch  3 taken 0%
branch  4 taken 0% (fallthrough)
branch  5 taken 100%
branch  6 taken 100% (fallthrough)
branch  7 taken 0%
branch  8 taken 100% (fallthrough)
branch  9 taken 0%
branch 10 taken 0% (fallthrough)
branch 11 taken 100%
        -:  632:         (retval == FALSE && (error == NULL || error->name != NULL))))
        -:  633:    {
    #####:  634:      if (error && error->name)
branch  0 never executed
branch  1 never executed
branch  2 never executed
branch  3 never executed
    #####:  635:        _dbus_verbose ("error is %s: %s\n", error->name, error->message);
call    0 never executed
    #####:  636:      _dbus_warn ("returning %d but error pointer %p name %s\n",
branch  0 never executed
branch  1 never executed
call    2 never executed
        -:  637:                  retval, error, error->name ? error->name : "(none)");
    #####:  638:      _dbus_assert_not_reached ("didn't handle errors properly");
call    0 never executed
        -:  639:    }
        -:  640:  
     7098:  641:  if (keys != NULL)
branch  0 taken 16% (fallthrough)
branch  1 taken 84%
        -:  642:    {
     1120:  643:      i = 0;
     8080:  644:      while (i < n_keys)
branch  0 taken 84%
branch  1 taken 16% (fallthrough)
        -:  645:        {
     5840:  646:          _dbus_string_zero (&keys[i].secret);
call    0 returned 100%
     5840:  647:          _dbus_string_free (&keys[i].secret);
call    0 returned 100%
     5840:  648:          ++i;
        -:  649:        }
        -:  650:
     1120:  651:      dbus_free (keys);
call    0 returned 100%
        -:  652:    }
        -:  653:  
     7098:  654:  _dbus_string_free (&contents);
call    0 returned 100%
     7098:  655:  _dbus_string_free (&line);
call    0 returned 100%
        -:  656:
     7098:  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)
function _dbus_keyring_ref called 2 returned 100% blocks executed 100%
        2:  676:{
        2:  677:  keyring->refcount += 1;
        -:  678:
        2:  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)
function _dbus_keyring_unref called 6860 returned 100% blocks executed 100%
     6860:  690:{
     6860:  691:  keyring->refcount -= 1;
        -:  692:
     6860:  693:  if (keyring->refcount == 0)
branch  0 taken 99% (fallthrough)
branch  1 taken 1%
        -:  694:    {
     6858:  695:      _dbus_string_free (&keyring->username);
call    0 returned 100%
     6858:  696:      _dbus_string_free (&keyring->filename);
call    0 returned 100%
     6858:  697:      _dbus_string_free (&keyring->filename_lock);
call    0 returned 100%
     6858:  698:      _dbus_string_free (&keyring->directory);
call    0 returned 100%
     6858:  699:      free_keys (keyring->keys, keyring->n_keys);
call    0 returned 100%
     6858:  700:      dbus_free (keyring);      
call    0 returned 100%
        -:  701:    }
     6860:  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)
function _dbus_keyring_new_homedir called 6903 returned 100% blocks executed 89%
     6903:  718:{
        -:  719:  DBusString homedir;
        -:  720:  DBusKeyring *keyring;
        -:  721:  dbus_bool_t error_set;
        -:  722:  DBusString dotdir;
        -:  723:  DBusError tmp_error;
        -:  724:
     6903:  725:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  726:  
     6903:  727:  keyring = NULL;
     6903:  728:  error_set = FALSE;
        -:  729:  
     6903:  730:  if (!_dbus_string_init (&homedir))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  731:    {
        6:  732:      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
call    0 returned 100%
        6:  733:      return NULL;
        -:  734:    }
        -:  735:
     6897:  736:  _dbus_string_init_const (&dotdir, ".dbus-keyrings");
call    0 returned 100%
        -:  737:  
     6897:  738:  if (username == NULL)
branch  0 taken 44% (fallthrough)
branch  1 taken 56%
        -:  739:    {
        -:  740:      const DBusString *const_homedir;
        -:  741:
     3009:  742:      if (!_dbus_username_from_current_process (&username) ||
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0%
call    3 returned 100%
branch  4 taken 100% (fallthrough)
branch  5 taken 0%
        -:  743:          !_dbus_homedir_from_current_process (&const_homedir))
        -:  744:        goto failed;
        -:  745:
     3009:  746:      if (!_dbus_string_copy (const_homedir, 0,
call    0 returned 100%
branch  1 taken 99% (fallthrough)
branch  2 taken 1%
        -:  747:                              &homedir, 0))
        3:  748:        goto failed;
        -:  749:    }
        -:  750:  else
        -:  751:    {
     3888:  752:      if (!_dbus_homedir_from_username (username, &homedir))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        6:  753:        goto failed;
        -:  754:    }
        -:  755:
        -:  756:#ifdef DBUS_BUILD_TESTS
        -:  757: {
        -:  758:   const char *override;
        -:  759:
     6888:  760:   override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
call    0 returned 100%
    13776:  761:   if (override != NULL && *override != '\0')
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 100% (fallthrough)
branch  3 taken 0%
        -:  762:     {
     6888:  763:       _dbus_string_set_length (&homedir, 0);
call    0 returned 100%
     6888:  764:       if (!_dbus_string_append (&homedir, override))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  765:         goto failed;
        -:  766:
     6888:  767:       _dbus_verbose ("Using fake homedir for testing: %s\n",
call    0 returned 100%
call    1 returned 100%
        -:  768:                      _dbus_string_get_const_data (&homedir));
        -:  769:     }
        -:  770:   else
        -:  771:     {
        -:  772:       static dbus_bool_t already_warned = FALSE;
    #####:  773:       if (!already_warned)
branch  0 never executed
branch  1 never executed
        -:  774:         {
    #####:  775:           _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
call    0 never executed
    #####:  776:           already_warned = TRUE;
        -:  777:         }
        -:  778:     }
        -:  779: }
        -:  780:#endif
        -:  781:  
     6888:  782:  _dbus_assert (username != NULL);    
call    0 returned 100%
        -:  783:  
     6888:  784:  keyring = _dbus_keyring_new ();
call    0 returned 100%
     6888:  785:  if (keyring == NULL)
branch  0 taken 1% (fallthrough)
branch  1 taken 99%
       30:  786:    goto failed;
        -:  787:
        -:  788:  /* should have been validated already, but paranoia check here */
     6858:  789:  if (!_dbus_keyring_validate_context (context))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  790:    {
    #####:  791:      error_set = TRUE;
    #####:  792:      dbus_set_error_const (error,
call    0 never executed
        -:  793:                            DBUS_ERROR_FAILED,
        -:  794:                            "Invalid context in keyring creation");
    #####:  795:      goto failed;
        -:  796:    }
        -:  797:
     6858:  798:  if (!_dbus_string_copy (username, 0,
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  799:                          &keyring->username, 0))
        6:  800:    goto failed;
        -:  801:  
     6852:  802:  if (!_dbus_string_copy (&homedir, 0,
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  803:                          &keyring->directory, 0))
        6:  804:    goto failed;
        -:  805:  
     6846:  806:  if (!_dbus_concat_dir_and_file (&keyring->directory,
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  807:                                  &dotdir))
       11:  808:    goto failed;
        -:  809:
     6835:  810:  if (!_dbus_string_copy (&keyring->directory, 0,
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  811:                          &keyring->filename, 0))
        8:  812:    goto failed;
        -:  813:
     6827:  814:  if (!_dbus_concat_dir_and_file (&keyring->filename,
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  815:                                  context))
       13:  816:    goto failed;
        -:  817:
     6814:  818:  if (!_dbus_string_copy (&keyring->filename, 0,
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  819:                          &keyring->filename_lock, 0))
        4:  820:    goto failed;
        -:  821:
     6810:  822:  if (!_dbus_string_append (&keyring->filename_lock, ".lock"))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        8:  823:    goto failed;
        -:  824:
     6802:  825:  dbus_error_init (&tmp_error);
call    0 returned 100%
     6802:  826:  if (!_dbus_keyring_reload (keyring, FALSE, &tmp_error))
call    0 returned 100%
branch  1 taken 17% (fallthrough)
branch  2 taken 83%
        -:  827:    {
     1141:  828:      _dbus_verbose ("didn't load an existing keyring: %s\n",
call    0 returned 100%
        -:  829:                     tmp_error.message);
     1141:  830:      dbus_error_free (&tmp_error);
call    0 returned 100%
        -:  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:   */
     6802:  837:  dbus_error_init (&tmp_error);
call    0 returned 100%
     6802:  838:  if (!_dbus_create_directory (&keyring->directory,
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  839:                               &tmp_error))
        -:  840:    {
    #####:  841:      _dbus_verbose ("Creating keyring directory: %s\n",
call    0 never executed
        -:  842:                     tmp_error.message);
    #####:  843:      dbus_error_free (&tmp_error);
call    0 never executed
        -:  844:    }
        -:  845:
     6802:  846:  _dbus_string_free (&homedir);
call    0 returned 100%
        -:  847:  
     6802:  848:  return keyring;
        -:  849:  
       95:  850: failed:
       95:  851:  if (!error_set)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
       95:  852:    dbus_set_error_const (error,
call    0 returned 100%
        -:  853:                          DBUS_ERROR_NO_MEMORY,
        -:  854:                          NULL);
       95:  855:  if (keyring)
branch  0 taken 59% (fallthrough)
branch  1 taken 41%
       56:  856:    _dbus_keyring_unref (keyring);
call    0 returned 100%
       95:  857:  _dbus_string_free (&homedir);
call    0 returned 100%
       95:  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)
function _dbus_keyring_validate_context called 11016 returned 100% blocks executed 89%
    11016:  876:{
    11016:  877:  if (_dbus_string_get_length (context) == 0)
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  878:    {
        1:  879:      _dbus_verbose ("context is zero-length\n");
call    0 returned 100%
        1:  880:      return FALSE;
        -:  881:    }
        -:  882:
    11015:  883:  if (!_dbus_string_validate_ascii (context, 0,
call    0 returned 100%
call    1 returned 100%
branch  2 taken 1% (fallthrough)
branch  3 taken 99%
        -:  884:                                    _dbus_string_get_length (context)))
        -:  885:    {
        3:  886:      _dbus_verbose ("context not valid ascii\n");
call    0 returned 100%
        3:  887:      return FALSE;
        -:  888:    }
        -:  889:  
        -:  890:  /* no directory separators */  
    11012:  891:  if (_dbus_string_find (context, 0, "/", NULL))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  892:    {
        1:  893:      _dbus_verbose ("context contains a slash\n");
call    0 returned 100%
        1:  894:      return FALSE;
        -:  895:    }
        -:  896:
    11011:  897:  if (_dbus_string_find (context, 0, "\\", NULL))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  898:    {
        1:  899:      _dbus_verbose ("context contains a backslash\n");
call    0 returned 100%
        1:  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:   */
    11010:  906:  if (_dbus_string_find (context, 0, ".", NULL))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  907:    {
        2:  908:      _dbus_verbose ("context contains a dot\n");
call    0 returned 100%
        2:  909:      return FALSE;
        -:  910:    }
        -:  911:
        -:  912:  /* no spaces/tabs, those are used for separators in the protocol */
    11008:  913:  if (_dbus_string_find_blank (context, 0, NULL))
call    0 returned 100%
branch  1 taken 1% (fallthrough)
branch  2 taken 99%
        -:  914:    {
        1:  915:      _dbus_verbose ("context contains a blank\n");
call    0 returned 100%
        1:  916:      return FALSE;
        -:  917:    }
        -:  918:
    11007:  919:  if (_dbus_string_find (context, 0, "\n", NULL))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  920:    {
    #####:  921:      _dbus_verbose ("context contains a newline\n");
call    0 never executed
    #####:  922:      return FALSE;
        -:  923:    }
        -:  924:
    11007:  925:  if (_dbus_string_find (context, 0, "\r", NULL))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  926:    {
    #####:  927:      _dbus_verbose ("context contains a carriage return\n");
call    0 never executed
    #####:  928:      return FALSE;
        -:  929:    }
        -:  930:  
    11007:  931:  return TRUE;
        -:  932:}
        -:  933:
        -:  934:static DBusKey*
        -:  935:find_recent_key (DBusKeyring *keyring)
function find_recent_key called 4158 returned 100% blocks executed 89%
     4158:  936:{
        -:  937:  int i;
        -:  938:  long tv_sec, tv_usec;
        -:  939:
     4158:  940:  _dbus_get_current_time (&tv_sec, &tv_usec);
call    0 returned 100%
        -:  941:  
     4158:  942:  i = 0;
     8316:  943:  while (i < keyring->n_keys)
branch  0 taken 86%
branch  1 taken 14% (fallthrough)
        -:  944:    {
     3573:  945:      DBusKey *key = &keyring->keys[i];
        -:  946:
     3573:  947:      _dbus_verbose ("Key %d is %ld seconds old\n",
call    0 returned 100%
        -:  948:                     i, tv_sec - key->creation_time);
        -:  949:      
     3573:  950:      if ((tv_sec - NEW_KEY_TIMEOUT_SECONDS) < key->creation_time)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
     3573:  951:        return key;
        -:  952:      
    #####:  953:      ++i;
        -:  954:    }
        -:  955:
      585:  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)
function _dbus_keyring_get_best_key called 3848 returned 100% blocks executed 83%
     3848:  973:{
        -:  974:  DBusKey *key;
        -:  975:
     3848:  976:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  977:  
     3848:  978:  key = find_recent_key (keyring);
call    0 returned 100%
     3848:  979:  if (key)
branch  0 taken 85% (fallthrough)
branch  1 taken 15%
     3263:  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:   */
      585:  985:  if (!_dbus_keyring_reload (keyring, TRUE,
call    0 returned 100%
branch  1 taken 47% (fallthrough)
branch  2 taken 53%
        -:  986:                             error))
      275:  987:    return -1;
        -:  988:
      310:  989:  key = find_recent_key (keyring);
call    0 returned 100%
      310:  990:  if (key)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
      310:  991:    return key->id;
        -:  992:  else
        -:  993:    {
    #####:  994:      dbus_set_error_const (error,
call    0 never executed
        -:  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)
function _dbus_keyring_is_for_user called 0 returned 0% blocks executed 0%
    #####: 1012:{
    #####: 1013:  return _dbus_string_equal (&keyring->username,
call    0 never executed
        -: 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)
function _dbus_keyring_get_hex_key called 6194 returned 100% blocks executed 100%
     6194: 1032:{
        -: 1033:  DBusKey *key;
        -: 1034:
     6194: 1035:  key = find_key_by_id (keyring->keys,
call    0 returned 100%
        -: 1036:                        keyring->n_keys,
        -: 1037:                        key_id);
     6194: 1038:  if (key == NULL)
branch  0 taken 9% (fallthrough)
branch  1 taken 91%
      569: 1039:    return TRUE; /* had enough memory, so TRUE */
        -: 1040:
     5625: 1041:  return _dbus_string_hex_encode (&key->secret, 0,
call    0 returned 100%
call    1 returned 100%
        -: 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)
function _dbus_keyring_test called 1 returned 100% blocks executed 79%
        1: 1054:{
        -: 1055:  DBusString context;
        -: 1056:  DBusKeyring *ring1;
        -: 1057:  DBusKeyring *ring2;
        -: 1058:  int id;
        -: 1059:  DBusError error;
        -: 1060:  int i;
        -: 1061:
        1: 1062:  ring1 = NULL;
        1: 1063:  ring2 = NULL;
        -: 1064:  
        -: 1065:  /* Context validation */
        -: 1066:  
        1: 1067:  _dbus_string_init_const (&context, "foo");
call    0 returned 100%
        1: 1068:  _dbus_assert (_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1069:  _dbus_string_init_const (&context, "org_freedesktop_blah");
call    0 returned 100%
        1: 1070:  _dbus_assert (_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        -: 1071:  
        1: 1072:  _dbus_string_init_const (&context, "");
call    0 returned 100%
        1: 1073:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1074:  _dbus_string_init_const (&context, ".foo");
call    0 returned 100%
        1: 1075:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1076:  _dbus_string_init_const (&context, "bar.foo");
call    0 returned 100%
        1: 1077:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1078:  _dbus_string_init_const (&context, "bar/foo");
call    0 returned 100%
        1: 1079:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1080:  _dbus_string_init_const (&context, "bar\\foo");
call    0 returned 100%
        1: 1081:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1082:  _dbus_string_init_const (&context, "foo\xfa\xf0");
call    0 returned 100%
        1: 1083:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1084:  _dbus_string_init_const (&context, "foo\x80");
call    0 returned 100%
        1: 1085:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1086:  _dbus_string_init_const (&context, "foo\x7f");
call    0 returned 100%
        1: 1087:  _dbus_assert (_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1088:  _dbus_string_init_const (&context, "foo bar");
call    0 returned 100%
        1: 1089:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        -: 1090:  
        1: 1091:  if (!_dbus_string_init (&context))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####: 1092:    _dbus_assert_not_reached ("no memory");
call    0 never executed
        1: 1093:  if (!_dbus_string_append_byte (&context, '\0'))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####: 1094:    _dbus_assert_not_reached ("no memory");
call    0 never executed
        1: 1095:  _dbus_assert (!_dbus_keyring_validate_context (&context));
call    0 returned 100%
call    1 returned 100%
        1: 1096:  _dbus_string_free (&context);
call    0 returned 100%
        -: 1097:
        -: 1098:  /* Now verify that if we create a key in keyring 1,
        -: 1099:   * it is properly loaded in keyring 2
        -: 1100:   */
        -: 1101:
        1: 1102:  _dbus_string_init_const (&context, "org_freedesktop_dbus_testsuite");
call    0 returned 100%
        1: 1103:  dbus_error_init (&error);
call    0 returned 100%
        1: 1104:  ring1 = _dbus_keyring_new_homedir (NULL, &context,
call    0 returned 100%
        -: 1105:                                     &error);
        1: 1106:  _dbus_assert (ring1);
call    0 returned 100%
        1: 1107:  _dbus_assert (error.name == NULL);
call    0 returned 100%
        -: 1108:
        1: 1109:  id = _dbus_keyring_get_best_key (ring1, &error);
call    0 returned 100%
        1: 1110:  if (id < 0)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -: 1111:    {
    #####: 1112:      fprintf (stderr, "Could not load keyring: %s\n", error.message);
call    0 never executed
    #####: 1113:      dbus_error_free (&error);
call    0 never executed
    #####: 1114:      goto failure;
        -: 1115:    }
        -: 1116:
        1: 1117:  ring2 = _dbus_keyring_new_homedir (NULL, &context, &error);
call    0 returned 100%
        1: 1118:  _dbus_assert (ring2);
call    0 returned 100%
        1: 1119:  _dbus_assert (error.name == NULL);
call    0 returned 100%
        -: 1120:  
        1: 1121:  if (ring1->n_keys != ring2->n_keys)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -: 1122:    {
    #####: 1123:      fprintf (stderr, "Different number of keys in keyrings\n");
call    0 never executed
    #####: 1124:      goto failure;
        -: 1125:    }
        -: 1126:
        -: 1127:  /* We guarantee we load and save keeping keys in a fixed
        -: 1128:   * order
        -: 1129:   */
        1: 1130:  i = 0;
        3: 1131:  while (i < ring1->n_keys)
branch  0 taken 50%
branch  1 taken 50% (fallthrough)
        -: 1132:    {
        1: 1133:      if (ring1->keys[i].id != ring2->keys[i].id)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -: 1134:        {
    #####: 1135:          fprintf (stderr, "Keyring 1 has first key ID %d and keyring 2 has %d\n",
call    0 never executed
        -: 1136:                   ring1->keys[i].id, ring2->keys[i].id);
    #####: 1137:          goto failure;
        -: 1138:        }      
        -: 1139:
        1: 1140:      if (ring1->keys[i].creation_time != ring2->keys[i].creation_time)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -: 1141:        {
    #####: 1142:          fprintf (stderr, "Keyring 1 has first key time %ld and keyring 2 has %ld\n",
call    0 never executed
        -: 1143:                   ring1->keys[i].creation_time, ring2->keys[i].creation_time);
    #####: 1144:          goto failure;
        -: 1145:        }
        -: 1146:
        1: 1147:      if (!_dbus_string_equal (&ring1->keys[i].secret,
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -: 1148:                               &ring2->keys[i].secret))
        -: 1149:        {
    #####: 1150:          fprintf (stderr, "Keyrings 1 and 2 have different secrets for same ID/timestamp\n");
call    0 never executed
    #####: 1151:          goto failure;
        -: 1152:        }
        -: 1153:      
        1: 1154:      ++i;
        -: 1155:    }
        -: 1156:
        1: 1157:  printf (" %d keys in test\n", ring1->n_keys);
call    0 returned 100%
        -: 1158:
        -: 1159:  /* Test ref/unref */
        1: 1160:  _dbus_keyring_ref (ring1);
call    0 returned 100%
        1: 1161:  _dbus_keyring_ref (ring2);
call    0 returned 100%
        1: 1162:  _dbus_keyring_unref (ring1);
call    0 returned 100%
        1: 1163:  _dbus_keyring_unref (ring2);
call    0 returned 100%
        -: 1164:
        -: 1165:
        -: 1166:  /* really unref */
        1: 1167:  _dbus_keyring_unref (ring1);
call    0 returned 100%
        1: 1168:  _dbus_keyring_unref (ring2);
call    0 returned 100%
        -: 1169:  
        1: 1170:  return TRUE;
        -: 1171:
    #####: 1172: failure:
    #####: 1173:  if (ring1)
branch  0 never executed
branch  1 never executed
    #####: 1174:    _dbus_keyring_unref (ring1);
call    0 never executed
    #####: 1175:  if (ring2)
branch  0 never executed
branch  1 never executed
    #####: 1176:    _dbus_keyring_unref (ring2);
call    0 never executed
        -: 1177:
    #####: 1178:  return FALSE;
        -: 1179:}
        -: 1180:
        -: 1181:#endif /* DBUS_BUILD_TESTS */
        -: 1182: