2019-03-06 01:37:12 +00:00
|
|
|
import asyncio
|
2021-03-01 07:25:31 +00:00
|
|
|
import os
|
2022-03-06 09:14:28 +00:00
|
|
|
|
2020-12-16 02:56:42 +00:00
|
|
|
import secretstorage
|
|
|
|
|
2019-03-06 01:37:12 +00:00
|
|
|
from vorta.keyring.abc import VortaKeyring
|
|
|
|
from vorta.log import logger
|
|
|
|
|
2022-03-06 09:14:28 +00:00
|
|
|
LABEL_TEMPLATE = "Vorta Backup Repo {repo_url}"
|
|
|
|
|
2019-03-06 01:37:12 +00:00
|
|
|
|
|
|
|
class VortaSecretStorageKeyring(VortaKeyring):
|
|
|
|
"""A wrapper for the secretstorage package to support the custom keyring backend"""
|
|
|
|
|
|
|
|
def __init__(self):
|
2019-03-24 09:21:12 +00:00
|
|
|
"""
|
2022-04-20 04:15:08 +00:00
|
|
|
Test whether DBus and a SecretStorage provider are available.
|
2019-03-24 09:21:12 +00:00
|
|
|
"""
|
2022-04-20 04:15:08 +00:00
|
|
|
try:
|
|
|
|
self.connection = secretstorage.dbus_init()
|
|
|
|
except secretstorage.exceptions.SecretServiceNotAvailableException as e:
|
|
|
|
logger.debug("SecretStorage provider or DBus daemon is not available.")
|
|
|
|
raise e
|
2019-03-24 09:21:12 +00:00
|
|
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
2022-04-20 04:15:08 +00:00
|
|
|
self.collection = secretstorage.get_default_collection(self.connection)
|
2019-03-06 01:37:12 +00:00
|
|
|
|
|
|
|
def set_password(self, service, repo_url, password):
|
2022-03-06 09:14:28 +00:00
|
|
|
"""
|
|
|
|
Writes a password to the underlying store.
|
|
|
|
"""
|
2022-04-20 04:15:08 +00:00
|
|
|
if self.is_unlocked:
|
2020-12-16 02:56:42 +00:00
|
|
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
|
|
|
attributes = {
|
|
|
|
'application': 'Vorta',
|
|
|
|
'service': service,
|
|
|
|
'repo_url': repo_url,
|
|
|
|
'xdg:schema': 'org.freedesktop.Secret.Generic'}
|
2022-04-20 04:15:08 +00:00
|
|
|
self.collection.create_item(LABEL_TEMPLATE.format(repo_url=repo_url),
|
|
|
|
attributes,
|
|
|
|
password,
|
|
|
|
replace=True)
|
2019-03-06 01:37:12 +00:00
|
|
|
|
|
|
|
def get_password(self, service, repo_url):
|
2022-03-06 09:14:28 +00:00
|
|
|
"""
|
|
|
|
Retrieve a password from the underlying store. Return None if not found.
|
|
|
|
"""
|
2020-12-16 02:56:42 +00:00
|
|
|
if self.is_unlocked:
|
|
|
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
|
|
|
attributes = {'application': 'Vorta', 'service': service, 'repo_url': repo_url}
|
2022-04-20 04:15:08 +00:00
|
|
|
items = list(self.collection.search_items(attributes))
|
2020-12-16 02:56:42 +00:00
|
|
|
logger.debug('Found %i passwords matching repo URL.', len(items))
|
|
|
|
if len(items) > 0:
|
2022-04-20 04:15:08 +00:00
|
|
|
item = items[0]
|
|
|
|
if item.is_locked() and item.unlock():
|
|
|
|
return None
|
|
|
|
return item.get_secret().decode("utf-8")
|
2019-03-06 01:37:12 +00:00
|
|
|
return None
|
2020-12-16 02:56:42 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def is_unlocked(self):
|
2022-04-20 04:15:08 +00:00
|
|
|
# unlock() will return True if the unlock prompt is dismissed
|
|
|
|
return not (self.collection.is_locked() and self.collection.unlock())
|
2021-03-01 07:25:31 +00:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_priority(cls):
|
|
|
|
return 6 if "GNOME" in os.getenv("XDG_CURRENT_DESKTOP", "") else 5
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_system(self):
|
|
|
|
return True
|