This file is indexed.

/usr/share/mopidy/mopidy/config/keyring.py is in mopidy 0.17.0-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from __future__ import unicode_literals

import logging

logger = logging.getLogger('mopidy.config.keyring')

try:
    import dbus
except ImportError:
    dbus = None


# XXX: Hack to workaround introspection bug caused by gnome-keyring, should be
# fixed by version 3.5 per:
# https://git.gnome.org/browse/gnome-keyring/commit/?id=5dccbe88eb94eea9934e2b7
if dbus:
    EMPTY_STRING = dbus.String('', variant_level=1)
else:
    EMPTY_STRING = ''


def fetch():
    if not dbus:
        logger.debug('Fetching from keyring failed: dbus not installed.')
        return []

    try:
        bus = dbus.SessionBus()
    except dbus.exceptions.DBusException as e:
        logger.debug('Fetching from keyring failed: %s', e)
        return []

    if not bus.name_has_owner('org.freedesktop.secrets'):
        logger.debug(
            'Fetching from keyring failed: secrets service not running.')
        return []

    service = _service(bus)
    session = service.OpenSession('plain', EMPTY_STRING)[1]
    items, locked = service.SearchItems({'service': 'mopidy'})

    if not locked and not items:
        return []

    if locked:
        # There is a chance we can unlock without prompting the users...
        items, prompt = service.Unlock(locked)
        if prompt != '/':
            _prompt(bus, prompt).Dismiss()
            logger.debug('Fetching from keyring failed: keyring is locked.')
            return []

    result = []
    secrets = service.GetSecrets(items, session, byte_arrays=True)
    for item_path, values in secrets.iteritems():
        session_path, parameters, value, content_type = values
        attrs = _item_attributes(bus, item_path)
        result.append((attrs['section'], attrs['key'], bytes(value)))
    return result


def set(section, key, value):
    """Store a secret config value for a given section/key.

    Indicates if storage failed or succeeded.
    """
    if not dbus:
        logger.debug('Saving %s/%s to keyring failed: dbus not installed.',
                     section, key)
        return False

    try:
        bus = dbus.SessionBus()
    except dbus.exceptions.DBusException as e:
        logger.debug('Saving %s/%s to keyring failed: %s', section, key, e)
        return False

    if not bus.name_has_owner('org.freedesktop.secrets'):
        logger.debug(
            'Saving %s/%s to keyring failed: secrets service not running.',
            section, key)
        return False

    service = _service(bus)
    collection = _collection(bus)
    if not collection:
        return False

    if isinstance(value, unicode):
        value = value.encode('utf-8')

    session = service.OpenSession('plain', EMPTY_STRING)[1]
    secret = dbus.Struct((session, '', dbus.ByteArray(value),
                          'plain/text; charset=utf8'))
    label = 'mopidy: %s/%s' % (section, key)
    attributes = {'service': 'mopidy', 'section': section, 'key': key}
    properties = {'org.freedesktop.Secret.Item.Label': label,
                  'org.freedesktop.Secret.Item.Attributes': attributes}

    try:
        item, prompt = collection.CreateItem(properties, secret, True)
    except dbus.exceptions.DBusException as e:
        # TODO: catch IsLocked errors etc.
        logger.debug('Saving %s/%s to keyring failed: %s', section, key, e)
        return False

    if prompt == '/':
        return True

    _prompt(bus, prompt).Dismiss()
    logger.debug('Saving secret %s/%s failed: Keyring is locked',
                 section, key)
    return False


def _service(bus):
    return _interface(bus, '/org/freedesktop/secrets',
                      'org.freedesktop.Secret.Service')


# NOTE: depending on versions and setup 'default' might not exists, so try and
# use it but fall back to the 'login' collection, and finally the 'session' one
# if all else fails. We should probably create a keyring/collection setting
# that allows users to set this so they have control over where their secrets
# get stored.
def _collection(bus):
    for name in 'aliases/default', 'collection/login', 'collection/session':
        path = '/org/freedesktop/secrets/' + name
        if _collection_exists(bus, path):
            break
    else:
        return None
    return _interface(bus, path, 'org.freedesktop.Secret.Collection')


# NOTE: Hack to probe if a given collection actually exists. Needed to work
# around an introspection bug in setting passwords for non-existant aliases.
def _collection_exists(bus, path):
    try:
        item = _interface(bus, path, 'org.freedesktop.DBus.Properties')
        item.Get('org.freedesktop.Secret.Collection', 'Label')
        return True
    except dbus.exceptions.DBusException:
        return False


# NOTE: We could call prompt.Prompt('') to unlock the keyring when it is not
# '/', but we would then also have to arrange to setup signals to wait until
# this has been completed. So for now we just dismiss the prompt and expect
# keyrings to be unlocked.
def _prompt(bus, path):
    return _interface(bus, path, 'Prompt')


def _item_attributes(bus, path):
    item = _interface(bus, path, 'org.freedesktop.DBus.Properties')
    result = item.Get('org.freedesktop.Secret.Item', 'Attributes')
    return dict((bytes(k), bytes(v)) for k, v in result.iteritems())


def _interface(bus, path, interface):
    obj = bus.get_object('org.freedesktop.secrets', path)
    return dbus.Interface(obj, interface)