From 69445bffe7a17055ac47a41df5d33fe09b9aff3c Mon Sep 17 00:00:00 2001 From: pacien Date: Tue, 8 Dec 2020 16:04:48 +0100 Subject: context: read configuration from and write logs and temp files to private app storage The external app public storage directory is no longer reliably accessible on Android 11 and above. This makes editing the configuration and accessing the log files impossible in some cases. Let's move to the app private storage, to be made accessible to the user by some other mean. This has the benefit of also protecting the private keys that need to be stored encrypted otherwise. We also split the configuration and cache directory into specialised sub-directories. GitHub: related to #103 --- .../activities/start/NetworkListFragment.kt | 10 ++------- .../java/org/pacien/tincapp/context/AppPaths.kt | 24 ++++++++++++---------- .../org/pacien/tincapp/service/TincVpnService.kt | 3 --- .../java/org/pacien/tincapp/utils/TincKeyring.kt | 2 +- 4 files changed, 16 insertions(+), 23 deletions(-) (limited to 'app/src/main/java/org') diff --git a/app/src/main/java/org/pacien/tincapp/activities/start/NetworkListFragment.kt b/app/src/main/java/org/pacien/tincapp/activities/start/NetworkListFragment.kt index d3cc803..b0bbddf 100644 --- a/app/src/main/java/org/pacien/tincapp/activities/start/NetworkListFragment.kt +++ b/app/src/main/java/org/pacien/tincapp/activities/start/NetworkListFragment.kt @@ -1,6 +1,6 @@ /* * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon - * Copyright (C) 2017-2019 Pacien TRAN-GIRARD + * Copyright (C) 2017-2020 Pacien TRAN-GIRARD * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,7 +37,6 @@ import org.pacien.tincapp.extensions.setElements * @author pacien */ class NetworkListFragment : BaseFragment() { - private val appPaths = AppPaths private val networkListViewModel by lazy { NetworkListViewModel() } private val networkListAdapter by lazy { ArrayAdapter(requireContext(), R.layout.start_network_list_item) } var connectToNetworkAction = { _: String -> Unit } @@ -72,13 +71,8 @@ class NetworkListFragment : BaseFragment() { } private fun updatePlaceholder() { - val placeholderTextResource = when (appPaths.storageAvailable()) { - true -> R.string.start_network_list_empty_none_found - false -> R.string.start_network_list_empty_storage_not_available - } - start_network_list_placeholder.post { - start_network_list_placeholder_text?.text = getString(placeholderTextResource) + start_network_list_placeholder_text?.text = getString(R.string.start_network_list_empty_none_found) } } } diff --git a/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt b/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt index bd8316a..9aa2037 100644 --- a/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt +++ b/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt @@ -18,7 +18,6 @@ package org.pacien.tincapp.context -import android.os.Environment import java.io.File import java.io.FileNotFoundException @@ -28,6 +27,10 @@ import java.io.FileNotFoundException * @implNote Logs and PID files are stored in the cache directory for automatic collection. */ object AppPaths { + private const val APP_LOG_DIR = "log" + private const val APP_TINC_RUNTIME_DIR = "run" + private const val APP_TINC_NETWORKS_DIR = "networks" + private const val TINCD_BIN = "libtincd.so" private const val TINC_BIN = "libtinc.so" @@ -46,25 +49,24 @@ object AppPaths { private val context by lazy { App.getContext() } - fun storageAvailable() = - Environment.getExternalStorageState().let { it == Environment.MEDIA_MOUNTED && it != Environment.MEDIA_MOUNTED_READ_ONLY } - - fun internalCacheDir() = context.cacheDir!! - fun cacheDir() = context.externalCacheDir ?: internalCacheDir() - fun confDir() = context.getExternalFilesDir(null)!! + private fun cacheDir() = context.cacheDir!! private fun binDir() = File(context.applicationInfo.nativeLibraryDir) + fun runtimeDir() = withDir(File(cacheDir(), APP_TINC_RUNTIME_DIR)) + fun logDir() = withDir(File(cacheDir(), APP_LOG_DIR)) + fun confDir() = withDir(File(context.filesDir!!, APP_TINC_NETWORKS_DIR)) fun confDir(netName: String) = File(confDir(), netName) fun hostsDir(netName: String) = File(confDir(netName), NET_HOSTS_DIR) fun netConfFile(netName: String) = File(confDir(netName), NET_CONF_FILE) fun tincConfFile(netName: String) = File(confDir(netName), NET_TINC_CONF_FILE) fun invitationFile(netName: String) = File(confDir(netName), NET_INVITATION_FILE) - fun logFile(netName: String) = File(cacheDir(), String.format(LOGFILE_FORMAT, netName)) - fun pidFile(netName: String) = File(context.cacheDir, String.format(PIDFILE_FORMAT, netName)) - fun appLogFile() = File(cacheDir(), APPLOG_FILE) - fun crashFlagFile() = File(internalCacheDir(), CRASHFLAG_FILE) + fun logFile(netName: String) = File(logDir(), String.format(LOGFILE_FORMAT, netName)) + fun pidFile(netName: String) = File(runtimeDir(), String.format(PIDFILE_FORMAT, netName)) + fun appLogFile() = File(logDir(), APPLOG_FILE) + fun crashFlagFile() = File(cacheDir(), CRASHFLAG_FILE) fun existing(f: File) = f.apply { if (!exists()) throw FileNotFoundException(f.absolutePath) } + fun withDir(f: File) = f.apply { if (!exists()) mkdirs() } fun defaultEd25519PrivateKeyFile(netName: String) = File(confDir(netName), NET_DEFAULT_ED25519_PRIVATE_KEY_FILE) fun defaultRsaPrivateKeyFile(netName: String) = File(confDir(netName), NET_DEFAULT_RSA_PRIVATE_KEY_FILE) diff --git a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt index c688742..ac68c9f 100644 --- a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt +++ b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt @@ -93,9 +93,6 @@ class TincVpnService : VpnService() { if (TincKeyring.needsPassphrase(netName) && passphrase == null) return reportError(resources.getString(R.string.notification_error_message_passphrase_not_provided)) - if (!AppPaths.storageAvailable()) - return reportError(resources.getString(R.string.start_network_list_empty_storage_not_available)) - if (!AppPaths.confDir(netName).exists()) return reportError(resources.getString(R.string.notification_error_message_no_configuration_for_network_format, netName), docTopic = "configuration") diff --git a/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt b/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt index 89bb246..7d534e6 100644 --- a/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt +++ b/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt @@ -43,7 +43,7 @@ object TincKeyring { } private fun tempKey(name: String): File { - val file = File(AppPaths.internalCacheDir(), name) + val file = File(AppPaths.runtimeDir(), name) file.createNewFile() file.deleteOnExit() file.makePrivate() -- cgit v1.2.3