PKcJQ((keyring_jeepney.py"""A pure Python keyring backend using the Freedesktop secret service. """ __version__ = '0.1' import os from keyring.backend import KeyringBackend from keyring.util import properties from jeepney import new_method_call, DBusObject, Properties, DBusErrorResponse from jeepney.integrate.blocking import connect_and_authenticate secret_service = DBusObject('/org/freedesktop/secrets', bus_name= 'org.freedesktop.secrets', interface='org.freedesktop.Secret.Service') class DBusMethods: """Wrappers for the subset of the secrets API we use. These methods will block while waiting for a reply. """ def __init__(self, connection, collection): self.connection = connection self.session_path = self._open_session() self.collection = collection self.collection_obj = DBusObject(collection, bus_name='org.freedesktop.secrets', interface='org.freedesktop.Secret.Collection') def search(self, attribs): msg = new_method_call(self.collection_obj, 'SearchItems', 'a{ss}', (attribs,)) return self.connection.send_and_get_reply(msg).body[0] def _open_session(self): msg = new_method_call(secret_service, 'OpenSession', 'sv', ('plain', ('s', ''))) return self.connection.send_and_get_reply(msg).body[1] # TODO: Handle unlocking. This will fail if the item is locked. def get_secret(self, item_path): item = DBusObject(item_path, bus_name='org.freedesktop.secrets', interface='org.freedesktop.Secret.Item') msg = new_method_call(item, 'GetSecret', 'o', (self.session_path,)) return self.connection.send_and_get_reply(msg).body[0] def create_item(self, label, attributes, password, replace=True): secret = (self.session_path, b'', password.encode('utf-8'), 'text/plain; charset=utf8') properties = { 'org.freedesktop.Secret.Item.Label': ('s', label), 'org.freedesktop.Secret.Item.Attributes': ('a{ss}', attributes), } msg = new_method_call(self.collection_obj, 'CreateItem', 'a{sv}(oayays)b', (properties, secret, replace)) return self.connection.send_and_get_reply(msg).body[0] def delete(self, item_path): item = DBusObject(item_path, bus_name='org.freedesktop.secrets', interface='org.freedesktop.Secret.Item') msg = new_method_call(item, 'Delete') prompt_path = self.connection.send_and_get_reply(msg).body[0] assert prompt_path == '/' DEFAULT_COLLECTION = '/org/freedesktop/secrets/aliases/default' class Keyring(KeyringBackend): """A keyring backend using the Freedesktop secret service.""" def __init__(self, collection=DEFAULT_COLLECTION): self.conn = connect_and_authenticate(bus='SESSION') self.dbus_methods = DBusMethods(self.conn, collection) @properties.ClassProperty @classmethod def priority(cls): if 'DBUS_SESSION_BUS_ADDRESS' not in os.environ: raise RuntimeError("Environment variable DBUS_SESSION_BUS_ADDRESS " "not set") conn = connect_and_authenticate(bus='SESSION') try: conn.send_and_get_reply(Properties(secret_service).get('Collections')) except DBusErrorResponse: raise RuntimeError("Could not communicate with /org/freedesktop/secrets") # The well-tested Secret Service backend has priority 5. We'll defer # to that if it's available. return 4 def _find(self, service, username): return self.dbus_methods.search({"username": username, "service": service}) def get_password(self, service, username): for obj_path in self._find(service, username): secret = self.dbus_methods.get_secret(obj_path) session, enc_params, value, content_type = secret # TODO: check encoding with content_type return bytes(value).decode('utf-8') def set_password(self, service, username, password): attributes = { "application": "python-keyring", "service": service, "username": username } label = "Password for '%s' on '%s'" % (username, service) self.dbus_methods.create_item(label, attributes, password, replace=True) def delete_password(self, service, username): for obj_path in self._find(service, username): return self.dbus_methods.delete(obj_path) PKcJ9I 8--.keyring_jeepney-0.1.dist-info/entry_points.txt[keyring.backends] jeepney = keyring_jeepney PKfbJGD99%keyring_jeepney-0.1.dist-info/LICENSEThe MIT License (MIT) Copyright (c) 2017 Thomas Kluyver Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!H;@QP#keyring_jeepney-0.1.dist-info/WHEEL1 0 RZq+D-Dv;_[*7Fp ܦpv/fݞoL(*IPK!H &keyring_jeepney-0.1.dist-info/METADATAMs@ +tġt0-m )p7o`?ߣ7iC.ZIJA+Z'${f\b vVQر}-v9L0|,y٠ koBxmaiӗ݈3v% _S{d-|˗Y 䰣k9i.lwp/QrM|9%$fa?Ox٧=rJ %M vq Sc`o.v_\[\ᚫu 1>Ѣ_Oυ{;X[a -/Yqg΍MJ[ By+^"x kruA0gmcMf *f"QXPQsZ(bx*422~r5Njb]OCοx67L]9FBoI1HL[jZ92B֢rT*Z2>.Px=tFd'i'nlD8CuyI  - ip,C^pQ$wK=QҔqCėlWVHT#O=O v(hZQwz1o!JgC~9ˮѰVKUVB^yMr im# GZ Mk#4t:A,Q[|AZ[Z$.Zq PK!H4\,$keyring_jeepney-0.1.dist-info/RECORD˚BP}ςqq[$%#r ŬWy~-aZBx+iJحcfZ)ďOREkx6u")UY0it+Ë\ۦC 07ZlGE/evRQ%&7Ԑ}@mxH:%SajaZjGV zAȚ폛I\l;CnwCPQ Qѕ2HuVȧh1OXUAt\M|GPKcJQ((keyring_jeepney.pyPKcJ9I 8--.Xkeyring_jeepney-0.1.dist-info/entry_points.txtPKfbJGD99%keyring_jeepney-0.1.dist-info/LICENSEPK!H;@QP#Mkeyring_jeepney-0.1.dist-info/WHEELPK!H &keyring_jeepney-0.1.dist-info/METADATAPK!H4\,$keyring_jeepney-0.1.dist-info/RECORDPKd