CredentialStoreWrapper — fallback to memory-only store

This commit is contained in:
Vladimir Krivosheev
2016-08-11 17:48:44 +02:00
parent ae0559fe48
commit f51d675836
3 changed files with 34 additions and 5 deletions
@@ -33,7 +33,15 @@ import java.util.Base64
import java.util.concurrent.atomic.AtomicBoolean
import javax.crypto.spec.SecretKeySpec
class FileCredentialStore(keyToValue: Map<String, String>? = null, baseDirectory: Path = Paths.get(PathManager.getConfigPath()), var memoryOnly: Boolean = false) : PasswordStorage {
class FileCredentialStore(keyToValue: Map<String, String>? = 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<String, String>()
private val dbFile = baseDirectory.resolve("pdb")
@@ -128,10 +136,10 @@ class FileCredentialStore(keyToValue: Map<String, String>? = 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)
@@ -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
}
}
@@ -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) }