Check URI permissions #626

This commit is contained in:
J-Jamet
2021-08-21 16:52:13 +02:00
parent 8d3f1fe179
commit d841c25bd3
9 changed files with 120 additions and 19 deletions

View File

@@ -1,8 +1,9 @@
KeePassDX(3.0.0)
* Add / Manage dynamic templates #191
* Manually select RecycleBin group and Templates group #191
* Small changes #1035
* Fix timeout in dialogs #716
* Check URI permissions #626
* Small changes #1035
KeePassDX(2.10.5)
* Increase the saving speed of database #1028

View File

@@ -126,6 +126,12 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
}
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryDeleteListener { fileDatabaseHistoryToDelete ->
// Remove from app database
fileDatabaseHistoryToDelete.databaseUri?.let { databaseUri ->
UriUtil.releaseUriPermission(
contentResolver,
databaseUri
)
}
databaseFilesViewModel.deleteDatabaseFile(fileDatabaseHistoryToDelete)
true
}

View File

@@ -127,17 +127,7 @@ class ExternalFileHelper {
if (data != null) {
val uri = data.data
if (uri != null) {
try {
// try to persist read and write permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity?.contentResolver?.apply {
takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
}
} catch (e: Exception) {
// nop
}
UriUtil.takeUriPermission(activity?.contentResolver, uri)
onFileSelected?.invoke(uri)
}
}

View File

@@ -23,7 +23,9 @@ import android.content.ContentResolver
import android.content.Context
import android.content.res.Resources
import android.net.Uri
import android.os.Build
import android.util.Log
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.action.node.NodeHandler
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine

View File

@@ -30,6 +30,7 @@ import android.content.IntentFilter
import android.os.Build
import android.util.Log
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
import com.kunzisoft.keepass.services.ClipboardEntryNotificationService
@@ -139,4 +140,21 @@ fun Context.closeDatabase(database: Database?) {
}
// Clear data
database?.clearAndClose(this)
// Release not useful URI permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
applicationContext?.let { appContext ->
val fileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(appContext)
fileDatabaseHistoryAction.getDatabaseFileList { databaseFileList ->
val listToNotRemove = databaseFileList.map { it.databaseUri }
// Remove URI permission for not database files
val resolver = appContext.contentResolver
resolver.persistedUriPermissions.forEach { uriPermission ->
val uri = uriPermission.uri
if (!listToNotRemove.contains(uri))
UriUtil.releaseUriPermission(resolver, uri)
}
}
}
}
}

View File

@@ -56,7 +56,7 @@ object UriUtil {
}
}
} catch (e: Exception) {
Log.e("FileData", "Unable to get document file", e)
Log.e(TAG, "Unable to get document file", e)
null
}
}
@@ -110,6 +110,83 @@ object UriUtil {
return Uri.decode(uri) ?: ""
}
private fun persistUriPermission(contentResolver: ContentResolver?,
uri: Uri,
release: Boolean,
readOnly: Boolean) {
try {
// try to persist read and write permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
contentResolver?.apply {
var readPermissionAllowed = false
var writePermissionAllowed = false
// Check current permissions allowed
persistedUriPermissions.find { uriPermission ->
uriPermission.uri == uri
}?.let { uriPermission ->
Log.d(TAG, "Check URI permission : $uriPermission")
if (uriPermission.isReadPermission) {
readPermissionAllowed = true
}
if (uriPermission.isWritePermission) {
writePermissionAllowed = true
}
}
// Release permission
if (release) {
if (writePermissionAllowed) {
Log.d(TAG, "Release write permission : $uri")
val removeFlags: Int = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
releasePersistableUriPermission(uri, removeFlags)
}
if (readPermissionAllowed) {
Log.d(TAG, "Release read permission $uri")
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION
releasePersistableUriPermission(uri, takeFlags)
}
}
// Take missing permission
if (!readPermissionAllowed) {
Log.d(TAG, "Take read permission $uri")
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION
takePersistableUriPermission(uri, takeFlags)
}
if (readOnly) {
if (writePermissionAllowed) {
Log.d(TAG, "Release write permission $uri")
val removeFlags: Int = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
releasePersistableUriPermission(uri, removeFlags)
}
} else {
if (!writePermissionAllowed) {
Log.d(TAG, "Take write permission $uri")
val takeFlags: Int = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
takePersistableUriPermission(uri, takeFlags)
}
}
}
}
} catch (e: Exception) {
if (release)
Log.e(TAG, "Unable to release persistable URI permission", e)
else
Log.e(TAG, "Unable to take persistable URI permission", e)
}
}
fun takeUriPermission(contentResolver: ContentResolver?,
uri: Uri,
readOnly: Boolean = false) {
persistUriPermission(contentResolver, uri, false, readOnly)
}
fun releaseUriPermission(contentResolver: ContentResolver?,
uri: Uri) {
persistUriPermission(contentResolver, uri, release = true, readOnly = false)
}
fun getUriFromIntent(intent: Intent, key: String): Uri? {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
@@ -156,7 +233,7 @@ object UriUtil {
context.applicationContext.packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES)
return true
} catch (e: Exception) {
Log.e(javaClass.simpleName, "App not accessible", e)
Log.e(TAG, "App not accessible", e)
}
return false
}
@@ -165,7 +242,7 @@ object UriUtil {
try {
context.startActivity(context.applicationContext.packageManager.getLaunchIntentForPackage(packageName))
} catch (e: Exception) {
Log.e(javaClass.simpleName, "App cannot be open", e)
Log.e(TAG, "App cannot be open", e)
}
}
@@ -177,4 +254,5 @@ object UriUtil {
}
}
private const val TAG = "UriUtil"
}

View File

@@ -48,6 +48,10 @@ class FileDatabaseInfo : Serializable {
}
fun init() {
// Check permission
fileUri?.let { uri ->
UriUtil.takeUriPermission(context.contentResolver, uri)
}
documentFile = UriUtil.getFileData(context, fileUri)
}

View File

@@ -1,4 +1,5 @@
* Add / Manage dynamic templates #191
* Allow to manually select RecycleBin group and Templates group #191
* Small changes #1035
* Fix timeout in dialogs #716
* Fix timeout in dialogs #716
* Check URI permissions #626
* Small changes #1035

View File

@@ -1,4 +1,5 @@
* Ajout / Gestion dynamique des templates #191
* Sélection manuelle des groupes de la corbeille et des templates #191
* Petits changements #1035
* Correction du délai d'expiration dans les dialogues #716
* Correction du délai d'expiration dans les dialogues #716
* Vérification des permissions URI #626
* Petits changements #1035