From f51d675836d9279c2e5142c14d61d7ec8aed82fd Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 11 Aug 2016 17:46:33 +0200 Subject: [PATCH] =?UTF-8?q?CredentialStoreWrapper=20=E2=80=94=20fallback?= =?UTF-8?q?=20to=20memory-only=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/FileCredentialStore.kt | 16 ++++++++++---- .../src/MacOsCredentialStore.kt | 21 +++++++++++++++++++ .../src/libraries/linuxSecretLibrary.kt | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/platform/credential-store/src/FileCredentialStore.kt b/platform/credential-store/src/FileCredentialStore.kt index 7a6bdc347146..4ce3dac4440a 100644 --- a/platform/credential-store/src/FileCredentialStore.kt +++ b/platform/credential-store/src/FileCredentialStore.kt @@ -33,7 +33,15 @@ import java.util.Base64 import java.util.concurrent.atomic.AtomicBoolean import javax.crypto.spec.SecretKeySpec -class FileCredentialStore(keyToValue: Map? = null, baseDirectory: Path = Paths.get(PathManager.getConfigPath()), var memoryOnly: Boolean = false) : PasswordStorage { +class FileCredentialStore(keyToValue: Map? = null, baseDirectory: Path = Paths.get(PathManager.getConfigPath()), var memoryOnly: Boolean = false) : PasswordStorage, CredentialStore { + override fun get(key: String) = getPassword(null, key) + + override fun set(key: String, password: ByteArray?) { + val string = password?.toString(Charsets.UTF_8) + password?.fill(0) + setPassword(key, string) + } + private val db = ContainerUtil.newConcurrentMap() private val dbFile = baseDirectory.resolve("pdb") @@ -128,10 +136,10 @@ class FileCredentialStore(keyToValue: Map? = null, baseDirectory override fun getPassword(requestor: Class<*>?, key: String): String? { val rawKey = getRawKey(key, requestor) - // try old key - as hash var value = db.get(rawKey) - if (value == null) { - value = db.remove(rawKey) + if (value == null && (requestor != null || key.contains('/'))) { + // try old key - as hash + value = db.remove(toOldKey(rawKey)) if (value != null) { db.put(rawKey, value) needToSave.set(true) diff --git a/platform/credential-store/src/MacOsCredentialStore.kt b/platform/credential-store/src/MacOsCredentialStore.kt index 6ef9802708d1..87468d48150f 100644 --- a/platform/credential-store/src/MacOsCredentialStore.kt +++ b/platform/credential-store/src/MacOsCredentialStore.kt @@ -15,14 +15,20 @@ */ package com.intellij.credentialStore +import com.intellij.credentialStore.linux.SecretCredentialStore import com.intellij.credentialStore.macOs.KeyChainCredentialStore import com.intellij.credentialStore.macOs.isMacOsCredentialStoreSupported import com.intellij.ide.passwordSafe.PasswordStorage import com.intellij.openapi.diagnostic.catchAndLog +import com.intellij.openapi.util.SystemInfo import com.intellij.util.SystemProperties private class CredentialStoreWrapper(private val store: CredentialStore) : PasswordStorage { + private val fallbackStore = lazy { FileCredentialStore(memoryOnly = true) } + override fun getPassword(requestor: Class<*>?, key: String): String? { + var store = if (fallbackStore.isInitialized()) fallbackStore.value else store + val rawKey = getRawKey(key, requestor) // try old key - as hash @Suppress("CanBeVal") @@ -30,6 +36,11 @@ private class CredentialStoreWrapper(private val store: CredentialStore) : Passw try { value = store.get(rawKey) } + catch (e: UnsatisfiedLinkError) { + store = fallbackStore.value + LOG.error(e) + value = store.get(rawKey) + } catch (e: Throwable) { LOG.error(e) return null @@ -50,6 +61,7 @@ private class CredentialStoreWrapper(private val store: CredentialStore) : Passw override fun setPassword(requestor: Class<*>?, key: String, value: String?) { LOG.catchAndLog { + val store = if (fallbackStore.isInitialized()) fallbackStore.value else store store.set(getRawKey(key, requestor), value?.toByteArray()) } } @@ -62,4 +74,13 @@ private class MacOsCredentialStoreFactory : CredentialStoreFactory { } return null } +} + +private class LinuxSecretCredentialStoreFactory : CredentialStoreFactory { + override fun create(): PasswordStorage? { + if (SystemInfo.isLinux && SystemProperties.getBooleanProperty("use.linux.keychain", true)) { + return CredentialStoreWrapper(SecretCredentialStore("com.intellij.credentialStore.Credential")) + } + return null + } } \ No newline at end of file diff --git a/platform/credential-store/src/libraries/linuxSecretLibrary.kt b/platform/credential-store/src/libraries/linuxSecretLibrary.kt index 08df55dd3098..e1cb25a67186 100644 --- a/platform/credential-store/src/libraries/linuxSecretLibrary.kt +++ b/platform/credential-store/src/libraries/linuxSecretLibrary.kt @@ -21,7 +21,7 @@ internal fun stringPointer(data: ByteArray): DisposableMemory { } // we use default collection, it seems no way to use custom -class SecretCredentialStore(schemeName: String) : CredentialStore { +internal class SecretCredentialStore(schemeName: String) : CredentialStore { private val keyAttributeNamePointer by lazy { stringPointer("key".toByteArray()) } private val scheme by lazy { LIBRARY.secret_schema_new(schemeName, SECRET_SCHEMA_NONE, keyAttributeNamePointer, SECRET_SCHEMA_ATTRIBUTE_STRING, null) }