def __init__(self, bus, item_path, session=None): self.item_path = item_path item_obj = bus_get_object(bus, item_path) self.session = session self.bus = bus self.item_iface = InterfaceWrapper(item_obj, ITEM_IFACE) self.item_props_iface = InterfaceWrapper(item_obj, dbus.PROPERTIES_IFACE) self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss')
def __init__(self, bus, collection_path=DEFAULT_COLLECTION, session=None): collection_obj = bus_get_object(bus, SECRETS, collection_path) self.bus = bus self.session = session self.collection_path = collection_path self.collection_iface = InterfaceWrapper(collection_obj, COLLECTION_IFACE) self.collection_props_iface = InterfaceWrapper(collection_obj, dbus.PROPERTIES_IFACE) self.collection_props_iface.Get(COLLECTION_IFACE, 'Label', signature='ss')
def __init__(self, bus, item_path, session=None): if isinstance(item_path, int): # An item id was specified instead of the path item_path = '%s/%d' % (DEFAULT_COLLECTION, item_path) self.item_path = item_path item_obj = bus_get_object(bus, SECRETS, item_path) self.session = session self.bus = bus self.item_iface = InterfaceWrapper(item_obj, ITEM_IFACE) self.item_props_iface = InterfaceWrapper(item_obj, dbus.PROPERTIES_IFACE) self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss')
def unlock(self, callback=None): """Requests unlocking the collection. If `callback` is specified, calls it when unlocking is complete (see :func:`~secretstorage.util.exec_prompt` description for details) and returns a boolean representing whether the operation was dismissed. Otherwise, uses loop from GLib API.""" service_obj = bus_get_object(self.bus, SECRETS, SS_PATH) service_iface = InterfaceWrapper(service_obj, SERVICE_IFACE) prompt = service_iface.Unlock([self.collection_path], signature='ao')[1] if len(prompt) > 1: if callback: exec_prompt(self.bus, prompt, callback) else: return exec_prompt_glib(self.bus, prompt)[0] elif callback: # We still need to call it. callback(False, [])
class Item(object): """Represents a secret item.""" def __init__(self, bus, item_path, session=None): if isinstance(item_path, int): # An item id was specified instead of the path item_path = '%s/%d' % (DEFAULT_COLLECTION, item_path) self.item_path = item_path item_obj = bus_get_object(bus, SECRETS, item_path) self.session = session self.bus = bus self.item_iface = InterfaceWrapper(item_obj, ITEM_IFACE) self.item_props_iface = InterfaceWrapper(item_obj, dbus.PROPERTIES_IFACE) self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss') def __eq__(self, other): return (self._item_id() == other._item_id()) \ and (self.get_attributes() == other.get_attributes()) def _item_id(self): return int(self.item_path.rsplit('/', 1)[1]) def is_locked(self): """Returns :const:`True` if item is locked, otherwise :const:`False`.""" return bool( self.item_props_iface.Get(ITEM_IFACE, 'Locked', signature='ss')) def ensure_not_locked(self): """If collection is locked, raises :exc:`~secretstorage.exceptions.LockedException`.""" if self.is_locked(): raise LockedException('Item is locked!') def get_attributes(self): """Returns item attributes (dictionary).""" attrs = self.item_props_iface.Get(ITEM_IFACE, 'Attributes', signature='ss') return dict([(to_unicode(key), to_unicode(value)) for key, value in attrs.items()]) def set_attributes(self, attributes): """Sets item attributes to `attributes` (dictionary).""" self.item_props_iface.Set(ITEM_IFACE, 'Attributes', attributes, signature='ssv') def get_label(self): """Returns item label (unicode string).""" label = self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss') return to_unicode(label) def set_label(self, label): """Sets item label to `label`.""" self.ensure_not_locked() self.item_props_iface.Set(ITEM_IFACE, 'Label', label, signature='ssv') def delete(self): """Deletes the item.""" self.ensure_not_locked() return self.item_iface.Delete(signature='') def get_secret(self): """Returns item secret (bytestring).""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = self.item_iface.GetSecret(self.session.object_path, signature='o') if not self.session.encrypted: return bytes(bytearray(secret[2])) aes_cipher = AESCipher(self.session.aes_key, mode=MODE_CBC, IV=bytes(bytearray(secret[1]))) padded_secret = bytearray( aes_cipher.decrypt(bytes(bytearray(secret[2])))) return padded_secret[:-padded_secret[-1]] def get_secret_content_type(self): """Returns content type of item secret (string).""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = self.item_iface.GetSecret(self.session.object_path, signature='o') return str(secret[3]) def set_secret(self, secret, content_type='text/plain'): """Sets item secret to `secret`. If `content_type` is given, also sets the content type of the secret (``text/plain`` by default).""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = format_secret(self.session, secret, content_type) self.item_iface.SetSecret(secret, signature='(oayays)') def get_created(self): """Returns UNIX timestamp (integer) representing the time when the item was created.""" return int( self.item_props_iface.Get(ITEM_IFACE, 'Created', signature='ss')) def get_modified(self): """Returns UNIX timestamp (integer) representing the time when the item was last modified.""" return int( self.item_props_iface.Get(ITEM_IFACE, 'Modified', signature='ss')) def to_tuple(self): """Returns (*attributes*, *secret*) tuple representing the item.""" self.ensure_not_locked() return self.get_attributes(), self.get_secret()
class Item(object): """Represents a secret item.""" def __init__(self, bus, item_path, session=None): self.item_path = item_path item_obj = bus_get_object(bus, item_path) self.session = session self.bus = bus self.item_iface = InterfaceWrapper(item_obj, ITEM_IFACE) self.item_props_iface = InterfaceWrapper(item_obj, dbus.PROPERTIES_IFACE) self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss') def __eq__(self, other): return self.item_path == other.item_path def is_locked(self): """Returns :const:`True` if item is locked, otherwise :const:`False`.""" return bool( self.item_props_iface.Get(ITEM_IFACE, 'Locked', signature='ss')) def ensure_not_locked(self): """If collection is locked, raises :exc:`~secretstorage.exceptions.LockedException`.""" if self.is_locked(): raise LockedException('Item is locked!') def unlock(self, callback=None): """Requests unlocking the item. Usually, this will mean that the whole collection containing this item will be unlocked. If `callback` is specified, calls it when unlocking is complete (see :func:`~secretstorage.util.exec_prompt` description for details). Otherwise, uses the loop from GLib API and returns a boolean representing whether the operation was dismissed. .. versionadded:: 2.1.2""" return unlock_objects(self.bus, [self.item_path], callback) def get_attributes(self): """Returns item attributes (dictionary).""" attrs = self.item_props_iface.Get(ITEM_IFACE, 'Attributes', signature='ss') return { to_unicode(key): to_unicode(value) for key, value in attrs.items() } def set_attributes(self, attributes): """Sets item attributes to `attributes` (dictionary).""" self.item_props_iface.Set(ITEM_IFACE, 'Attributes', attributes, signature='ssv') def get_label(self): """Returns item label (unicode string).""" label = self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss') return to_unicode(label) def set_label(self, label): """Sets item label to `label`.""" self.ensure_not_locked() self.item_props_iface.Set(ITEM_IFACE, 'Label', label, signature='ssv') def delete(self): """Deletes the item.""" self.ensure_not_locked() return self.item_iface.Delete(signature='') def get_secret(self): """Returns item secret (bytestring).""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = self.item_iface.GetSecret(self.session.object_path, signature='o') if not self.session.encrypted: return bytes(bytearray(secret[2])) aes_iv = bytes(bytearray(secret[1])) aes = Cipher.AES.new(self.session.aes_key, Cipher.AES.MODE_CBC, aes_iv) encrypted_secret = bytes(bytearray(secret[2])) padded_secret = aes.decrypt(encrypted_secret) padded_secret = bytearray(padded_secret) return bytes(padded_secret[:-padded_secret[-1]]) def get_secret_content_type(self): """Returns content type of item secret (string).""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = self.item_iface.GetSecret(self.session.object_path, signature='o') return str(secret[3]) def set_secret(self, secret, content_type='text/plain'): """Sets item secret to `secret`. If `content_type` is given, also sets the content type of the secret (``text/plain`` by default).""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = format_secret(self.session, secret, content_type) self.item_iface.SetSecret(secret, signature='(oayays)') def get_created(self): """Returns UNIX timestamp (integer) representing the time when the item was created. .. versionadded:: 1.1""" return int( self.item_props_iface.Get(ITEM_IFACE, 'Created', signature='ss')) def get_modified(self): """Returns UNIX timestamp (integer) representing the time when the item was last modified.""" return int( self.item_props_iface.Get(ITEM_IFACE, 'Modified', signature='ss')) def to_tuple(self): """Returns (*attributes*, *secret*) tuple representing the item.""" self.ensure_not_locked() return self.get_attributes(), self.get_secret()
def lock(self): """Locks the collection.""" service_obj = bus_get_object(self.bus, SECRETS, SS_PATH) service_iface = InterfaceWrapper(service_obj, SERVICE_IFACE) service_iface.Lock([self.collection_path], signature='ao')
class Collection(object): """Represents a collection.""" def __init__(self, bus, collection_path=DEFAULT_COLLECTION, session=None): collection_obj = bus_get_object(bus, SECRETS, collection_path) self.bus = bus self.session = session self.collection_path = collection_path self.collection_iface = InterfaceWrapper(collection_obj, COLLECTION_IFACE) self.collection_props_iface = InterfaceWrapper(collection_obj, dbus.PROPERTIES_IFACE) self.collection_props_iface.Get(COLLECTION_IFACE, 'Label', signature='ss') def is_locked(self): """Returns :const:`True` if item is locked, otherwise :const:`False`.""" return bool(self.collection_props_iface.Get( COLLECTION_IFACE, 'Locked', signature='ss')) def ensure_not_locked(self): """If collection is locked, raises :exc:`~secretstorage.exceptions.LockedException`.""" if self.is_locked(): raise LockedException('Collection is locked!') def unlock(self, callback=None): """Requests unlocking the collection. If `callback` is specified, calls it when unlocking is complete (see :func:`~secretstorage.util.exec_prompt` description for details) and returns a boolean representing whether the operation was dismissed. Otherwise, uses loop from GLib API.""" service_obj = bus_get_object(self.bus, SECRETS, SS_PATH) service_iface = InterfaceWrapper(service_obj, SERVICE_IFACE) prompt = service_iface.Unlock([self.collection_path], signature='ao')[1] if len(prompt) > 1: if callback: exec_prompt(self.bus, prompt, callback) else: return exec_prompt_glib(self.bus, prompt)[0] elif callback: # We still need to call it. callback(False, []) def lock(self): """Locks the collection.""" service_obj = bus_get_object(self.bus, SECRETS, SS_PATH) service_iface = InterfaceWrapper(service_obj, SERVICE_IFACE) service_iface.Lock([self.collection_path], signature='ao') def delete(self): """Deletes the collection and all items inside it.""" self.ensure_not_locked() self.collection_iface.Delete(signature='') def get_all_items(self): """Returns a generator of all items in the collection.""" for item_path in self.collection_props_iface.Get( COLLECTION_IFACE, 'Items', signature='ss'): yield Item(self.bus, item_path, self.session) def search_items(self, attributes): """Returns a generator of items with the given attributes. `attributes` should be a dictionary.""" result = self.collection_iface.SearchItems(attributes, signature='a{ss}') if isinstance(result, tuple): # bug in GNOME Keyring <= 3.7.5 result = result[0] + result[1] for item_path in result: yield Item(self.bus, item_path, self.session) def get_label(self): """Returns the collection label.""" label = self.collection_props_iface.Get(COLLECTION_IFACE, 'Label', signature='ss') return to_unicode(label) def set_label(self, label): """Sets collection label to `label`.""" self.ensure_not_locked() self.collection_props_iface.Set(COLLECTION_IFACE, 'Label', label, signature='ssv') def create_item(self, label, attributes, secret, replace=False, content_type='text/plain'): """Creates a new :class:`~secretstorage.item.Item` with given `label` (unicode string), `attributes` (dictionary) and `secret` (bytestring). If `replace` is :const:`True`, replaces the existing item with the same attributes. If `content_type` is given, also sets the content type of the secret (``text/plain`` by default). Returns the created item.""" self.ensure_not_locked() if not self.session: self.session = open_session(self.bus) secret = format_secret(self.session, secret, content_type) attributes = dbus.Dictionary(attributes, signature='ss') properties = { SS_PREFIX+'Item.Label': label, SS_PREFIX+'Item.Attributes': attributes } new_item, prompt = self.collection_iface.CreateItem(properties, secret, replace, signature='a{sv}(oayays)b') return Item(self.bus, new_item, self.session)