mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-161674 Native "Deny" answer is not respected — IDEA continues to ask access
first quick solution — keep decision for 1 minute
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.credentialStore
|
||||
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import com.intellij.ide.passwordSafe.PasswordStorage
|
||||
import com.intellij.notification.NotificationGroup
|
||||
import com.intellij.notification.NotificationType
|
||||
@@ -11,6 +12,7 @@ import com.intellij.openapi.diagnostic.runAndLogException
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.util.SystemProperties
|
||||
import com.intellij.util.concurrency.QueueProcessor
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
private val nullCredentials = Credentials("\u0000", OneTimeString("\u0000"))
|
||||
|
||||
@@ -22,20 +24,30 @@ internal val NOTIFICATION_MANAGER by lazy {
|
||||
private class CredentialStoreWrapper(private val store: CredentialStore) : PasswordStorage {
|
||||
private val fallbackStore = lazy { KeePassCredentialStore(memoryOnly = true) }
|
||||
|
||||
private val queueProcessor = QueueProcessor<() -> Unit>({ it() })
|
||||
private val queueProcessor = QueueProcessor<() -> Unit> { it() }
|
||||
|
||||
private val postponedCredentials = KeePassCredentialStore(memoryOnly = true)
|
||||
private val deniedItems = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.MINUTES).build<CredentialAttributes, Boolean>()
|
||||
|
||||
override fun get(attributes: CredentialAttributes): Credentials? {
|
||||
postponedCredentials.get(attributes)?.let {
|
||||
return if (it == nullCredentials) null else it
|
||||
}
|
||||
|
||||
if (deniedItems.getIfPresent(attributes) != null) {
|
||||
LOG.warn("User denied access to $attributes")
|
||||
return null
|
||||
}
|
||||
|
||||
var store = if (fallbackStore.isInitialized()) fallbackStore.value else store
|
||||
val requestor = attributes.requestor
|
||||
val userName = attributes.userName
|
||||
try {
|
||||
val value = store.get(attributes)
|
||||
if (value === ACCESS_TO_KEY_CHAIN_DENIED) {
|
||||
deniedItems.put(attributes, true)
|
||||
return null
|
||||
}
|
||||
if (value != null || requestor == null || userName == null) {
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.credentialStore
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
@@ -100,9 +86,10 @@ private fun parseString(data: String, delimiter: Char): List<String> {
|
||||
@JvmOverloads
|
||||
fun Credentials.serialize(storePassword: Boolean = true): ByteArray = joinData(userName, if (storePassword) password else null)!!
|
||||
|
||||
fun SecureString(value: CharSequence): SecureString = SecureString(Charsets.UTF_8.encode(CharBuffer.wrap(value)).toByteArray())
|
||||
@Suppress("FunctionName")
|
||||
internal fun SecureString(value: CharSequence): SecureString = SecureString(Charsets.UTF_8.encode(CharBuffer.wrap(value)).toByteArray())
|
||||
|
||||
class SecureString(value: ByteArray) {
|
||||
internal class SecureString(value: ByteArray) {
|
||||
companion object {
|
||||
private val encryptionSupport = EncryptionSupport(SecretKeySpec(generateAesKey(), "AES"))
|
||||
}
|
||||
@@ -110,4 +97,6 @@ class SecureString(value: ByteArray) {
|
||||
private val data = encryptionSupport.encrypt(value)
|
||||
|
||||
fun get(clearable: Boolean = true): OneTimeString = OneTimeString(encryptionSupport.decrypt(data), clearable = clearable)
|
||||
}
|
||||
}
|
||||
|
||||
internal val ACCESS_TO_KEY_CHAIN_DENIED = Credentials(null, null as OneTimeString?)
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jdom.Element
|
||||
|
||||
private const val VALUE_ELEMENT_NAME = "Value"
|
||||
|
||||
class KdbxEntry(private val element: Element, private val database: KeePassDatabase, internal @Volatile var group: KdbxGroup?) {
|
||||
internal class KdbxEntry(private val element: Element, private val database: KeePassDatabase, internal @Volatile var group: KdbxGroup?) {
|
||||
@Volatile var title: String? = element.removeProperty("Title")
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.credentialStore.kdbx
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
@@ -10,7 +11,7 @@ import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
class KdbxGroup(private val element: Element, private val database: KeePassDatabase, private @Volatile var parent: KdbxGroup?) {
|
||||
internal class KdbxGroup(private val element: Element, private val database: KeePassDatabase, private @Volatile var parent: KdbxGroup?) {
|
||||
@Volatile var name: String = element.getChildText(NAME_ELEMENT_NAME) ?: "Unnamed"
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
|
||||
@@ -29,7 +29,7 @@ private const val ROOT_ELEMENT_NAME = "Root"
|
||||
|
||||
internal var dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||
|
||||
class KeePassDatabase(private val rootElement: Element = createEmptyDatabase()) {
|
||||
internal class KeePassDatabase(private val rootElement: Element = createEmptyDatabase()) {
|
||||
private val dbMeta: Element
|
||||
get() = rootElement.getChild("Meta") ?: throw IllegalStateException("no meta")
|
||||
|
||||
|
||||
@@ -79,12 +79,15 @@ internal class KeyChainCredentialStore : CredentialStore {
|
||||
}
|
||||
}
|
||||
|
||||
fun findGenericPassword(serviceName: ByteArray, accountName: String?): Credentials? {
|
||||
private fun findGenericPassword(serviceName: ByteArray, accountName: String?): Credentials? {
|
||||
val accountNameBytes = accountName?.toByteArray()
|
||||
val passwordSize = IntArray(1)
|
||||
val passwordRef = PointerByReference()
|
||||
val itemRef = PointerByReference()
|
||||
checkForError("find", LIBRARY.SecKeychainFindGenericPassword(null, serviceName.size, serviceName, accountNameBytes?.size ?: 0, accountNameBytes, passwordSize, passwordRef, itemRef))
|
||||
val errorCode = checkForError("find", LIBRARY.SecKeychainFindGenericPassword(null, serviceName.size, serviceName, accountNameBytes?.size ?: 0, accountNameBytes, passwordSize, passwordRef, itemRef))
|
||||
if (errorCode == errSecUserCanceled) {
|
||||
return ACCESS_TO_KEY_CHAIN_DENIED
|
||||
}
|
||||
|
||||
val pointer = passwordRef.value ?: return null
|
||||
val password = OneTimeString(pointer.getByteArray(0, passwordSize.get(0)))
|
||||
@@ -158,9 +161,9 @@ internal class SecKeychainAttributeInfo : Structure() {
|
||||
override fun getFieldOrder() = listOf("count", "tag", "format")
|
||||
}
|
||||
|
||||
private fun checkForError(message: String, code: Int) {
|
||||
private fun checkForError(message: String, code: Int): Int {
|
||||
if (code == errSecSuccess || code == errSecItemNotFound) {
|
||||
return
|
||||
return code
|
||||
}
|
||||
|
||||
val translated = LIBRARY.SecCopyErrorMessageString(code, null)
|
||||
@@ -183,6 +186,8 @@ private fun checkForError(message: String, code: Int) {
|
||||
else {
|
||||
LOG.error(builder.toString())
|
||||
}
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
|
||||
+2
-16
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.ide.passwordSafe.impl.providers.memory;
|
||||
|
||||
import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed;
|
||||
@@ -46,7 +32,7 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider {
|
||||
private final transient PasswordSafeTimed<Map<ByteArrayWrapper, byte[]>> database = new PasswordSafeTimed<Map<ByteArrayWrapper, byte[]>>() {
|
||||
@Override
|
||||
protected Map<ByteArrayWrapper, byte[]> compute() {
|
||||
return Collections.synchronizedMap(ContainerUtil.<ByteArrayWrapper, byte[]>newHashMap());
|
||||
return Collections.synchronizedMap(ContainerUtil.newHashMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user