diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccess.java new file mode 100644 index 000000000..998fdfab7 --- /dev/null +++ b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccess.java @@ -0,0 +1,9 @@ +package org.cryptomator.keychain; + +public interface GnomeKeyringAccess { + public void storePassword(String key, CharSequence passphrase); + + public char[] loadPassword(String key); + + public void deletePassword(String key); +} diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccessImpl.java b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccessImpl.java new file mode 100644 index 000000000..34dcdb5fa --- /dev/null +++ b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccessImpl.java @@ -0,0 +1,52 @@ +package org.cryptomator.keychain; + +import org.freedesktop.secret.simple.SimpleCollection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GnomeKeyringAccessImpl implements GnomeKeyringAccess { + private static final Logger LOG = LoggerFactory.getLogger(GnomeKeyringAccessImpl.class); + private SimpleCollection keyring; + + public GnomeKeyringAccessImpl() { + try { + keyring = new SimpleCollection(); + } catch (IOException e) { + LOG.error("D-Bus reports a problem.", e); + } + } + + public void storePassword(String key, CharSequence passphrase) { + List list = keyring.getItems(createAttributes(key)); + if (list == null) { + keyring.createItem("Cryptomator", passphrase, createAttributes(key)); + } + } + + public char[] loadPassword(String key) { + List list = keyring.getItems(createAttributes(key)); + if (list != null) { + return keyring.getSecret(list.get(0)); + } else { + return null; + } + } + + public void deletePassword(String key) { + List list = keyring.getItems(createAttributes(key)); + if (list != null) { + keyring.deleteItem(list.get(0)); + } + } + + private Map createAttributes(String key) { + Map attributes = new HashMap(); + attributes.put("Vault", key); + return attributes; + } +} diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/LinuxKeychainTester.java b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxKeychainTester.java new file mode 100644 index 000000000..1466e895c --- /dev/null +++ b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxKeychainTester.java @@ -0,0 +1,25 @@ +package org.cryptomator.keychain; + +import java.util.Optional; + +public class LinuxKeychainTester { + public static boolean secretServiceIsAvailable() { + try { + Class.forName("org.freedesktop.secret.simple.SimpleCollection"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + public static Optional getSecretService() { + if (!secretServiceIsAvailable()) return Optional.empty(); + try { + Class clazz = Class.forName("org.cryptomator.keychain.GnomeKeyringAccessImpl"); + GnomeKeyringAccess keyring = (GnomeKeyringAccess) clazz.getDeclaredConstructor().newInstance(); + return Optional.of(keyring); + } catch (Exception e) { + return Optional.empty(); + } + } +} diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java index 70781fd39..ef8dcb092 100644 --- a/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java +++ b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java @@ -2,66 +2,38 @@ package org.cryptomator.keychain; import com.google.common.base.Preconditions; import org.apache.commons.lang3.SystemUtils; -import org.freedesktop.secret.simple.SimpleCollection; import javax.inject.Inject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.Optional; public class LinuxSecretServiceAccess implements KeychainAccessStrategy { - private final Optional gnomeLoginKeyring; + private final Optional gnomeLoginKeyring; @Inject public LinuxSecretServiceAccess() { - SimpleCollection keyring = null; - try { - keyring = new SimpleCollection(); - } catch (Exception e) { - // Accessing secret-service DBus API failed - } finally { - gnomeLoginKeyring = Optional.ofNullable(keyring); - } + gnomeLoginKeyring = LinuxKeychainTester.getSecretService(); } @Override public boolean isSupported() { - return SystemUtils.IS_OS_LINUX && gnomeLoginKeyring.isPresent(); + return SystemUtils.IS_OS_LINUX && LinuxKeychainTester.getSecretService().isPresent(); } @Override public void storePassphrase(String key, CharSequence passphrase) { Preconditions.checkState(gnomeLoginKeyring.isPresent()); - List list = gnomeLoginKeyring.get().getItems(createAttributes(key)); - if (list == null) { - gnomeLoginKeyring.get().createItem("Cryptomator", passphrase, createAttributes(key)); - } + gnomeLoginKeyring.get().storePassword(key, passphrase); } @Override public char[] loadPassphrase(String key) { Preconditions.checkState(gnomeLoginKeyring.isPresent()); - List list = gnomeLoginKeyring.get().getItems(createAttributes(key)); - if (list != null) { - return gnomeLoginKeyring.get().getSecret(list.get(0)); - } else { - return null; - } + return gnomeLoginKeyring.get().loadPassword(key); } @Override public void deletePassphrase(String key) { Preconditions.checkState(gnomeLoginKeyring.isPresent()); - List list = gnomeLoginKeyring.get().getItems(createAttributes(key)); - if (list != null) { - gnomeLoginKeyring.get().deleteItem(list.get(0)); - } - } - - private Map createAttributes(String key) { - Map attributes = new HashMap(); - attributes.put("Vault", key); - return attributes; + gnomeLoginKeyring.get().deletePassword(key); } }