From 009c128052766665a4363a048dc6e008e249dfcd Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Fri, 8 Oct 2021 16:32:27 +0500 Subject: [PATCH] Changed: Move termux apps properties file list to TermuxConstants and do not follow symlinks --- .../com/termux/app/TermuxOpenReceiver.java | 16 ++-- .../properties/TermuxPropertyConstants.java | 75 ++++++++++--------- .../termux/shared/termux/TermuxConstants.java | 40 +++++++--- 3 files changed, 80 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/termux/app/TermuxOpenReceiver.java b/app/src/main/java/com/termux/app/TermuxOpenReceiver.java index b5cb358e..3a85552b 100644 --- a/app/src/main/java/com/termux/app/TermuxOpenReceiver.java +++ b/app/src/main/java/com/termux/app/TermuxOpenReceiver.java @@ -184,25 +184,25 @@ public class TermuxOpenReceiver extends BroadcastReceiver { File file = new File(uri.getPath()); try { String path = file.getCanonicalPath(); - Logger.logDebug(LOG_TAG, "Open file request received for \"" + path + "\" with mode \"" + mode + "\""); + String callingPackage = getCallingPackage(); + Logger.logDebug(LOG_TAG, "Open file request received from " + callingPackage + " for \"" + path + "\" with mode \"" + mode + "\""); String storagePath = Environment.getExternalStorageDirectory().getCanonicalPath(); // See https://support.google.com/faqs/answer/7496913: if (!(path.startsWith(TermuxConstants.TERMUX_FILES_DIR_PATH) || path.startsWith(storagePath))) { throw new IllegalArgumentException("Invalid path: " + path); } - // If "allow-external-apps" property to not set to "true", then throw exception + // If TermuxConstants.PROP_ALLOW_EXTERNAL_APPS property to not set to "true", then throw exception String errmsg = PluginUtils.checkIfAllowExternalAppsPolicyIsViolated(getContext(), LOG_TAG); if (errmsg != null) { throw new IllegalArgumentException(errmsg); } - // Do not allow apps with RUN_COMMAND permission to modify termux apps properties files, - // including allow-external-apps - if (TermuxConstants.TERMUX_PROPERTIES_PRIMARY_FILE_PATH.equals(path) || - TermuxConstants.TERMUX_PROPERTIES_SECONDARY_FILE_PATH.equals(path) || - TermuxConstants.TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE_PATH.equals(path) || - TermuxConstants.TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE_PATH.equals(path)) { + // **DO NOT** allow these files to be modified by ContentProvider exposed to external + // apps, since they may silently modify the values for security properties like + // TermuxConstants.PROP_ALLOW_EXTERNAL_APPS set by users without their explicit consent. + if (TermuxConstants.TERMUX_PROPERTIES_FILE_PATHS_LIST.contains(path) || + TermuxConstants.TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST.contains(path)) { mode = "r"; } diff --git a/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java b/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java index c868450b..638ff18f 100644 --- a/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java @@ -1,8 +1,8 @@ package com.termux.shared.settings.properties; -import androidx.annotation.NonNull; - import com.google.common.collect.ImmutableBiMap; +import com.termux.shared.file.FileUtils; +import com.termux.shared.file.filesystem.FileType; import com.termux.shared.termux.TermuxConstants; import com.termux.shared.logger.Logger; import com.termux.terminal.TerminalEmulator; @@ -11,6 +11,7 @@ import com.termux.view.TerminalView; import java.io.File; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; /* @@ -81,6 +82,8 @@ import java.util.Set; */ public final class TermuxPropertyConstants { + private static final String LOG_TAG = "TermuxPropertyConstants"; + /* boolean */ /** Defines the key for whether hardware keyboard shortcuts are enabled. */ @@ -413,50 +416,54 @@ public final class TermuxPropertyConstants { - /** Returns the first {@link File} found at - * {@link TermuxConstants#TERMUX_PROPERTIES_PRIMARY_FILE_PATH} or - * {@link TermuxConstants#TERMUX_PROPERTIES_SECONDARY_FILE_PATH} - * from which termux properties can be loaded. - * If the {@link File} found is not a regular file or is not readable then null is returned. + /** Returns the first {@link File} found in + * {@link TermuxConstants#TERMUX_PROPERTIES_FILE_PATHS_LIST} via a call to + * {@link #getPropertiesFile(List)}. * - * @return Returns the {@link File} object for termux properties. + * @return Returns the {@link File} object for Termux app properties. */ public static File getTermuxPropertiesFile() { - return getPropertiesFile(new String[]{ - TermuxConstants.TERMUX_PROPERTIES_PRIMARY_FILE_PATH, - TermuxConstants.TERMUX_PROPERTIES_SECONDARY_FILE_PATH - }); + return getPropertiesFile(TermuxConstants.TERMUX_PROPERTIES_FILE_PATHS_LIST); } - /** Returns the first {@link File} found at - * {@link TermuxConstants#TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE_PATH} or - * {@link TermuxConstants#TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE_PATH} - * from which termux properties can be loaded. - * If the {@link File} found is not a regular file or is not readable then null is returned. + /** Returns the first {@link File} found in + * {@link TermuxConstants#TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST} via a call to + * {@link #getPropertiesFile(List)}. * - * @return Returns the {@link File} object for termux properties. + * @return Returns the {@link File} object for Termux:Float app properties. */ public static File getTermuxFloatPropertiesFile() { - return getPropertiesFile(new String[]{ - TermuxConstants.TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE_PATH, - TermuxConstants.TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE_PATH - }); + return getPropertiesFile(TermuxConstants.TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST); } - public static File getPropertiesFile(@NonNull String[] possiblePropertiesFileLocations) { - File propertiesFile = new File(possiblePropertiesFileLocations[0]); - int i = 0; - while (!propertiesFile.exists() && i < possiblePropertiesFileLocations.length) { - propertiesFile = new File(possiblePropertiesFileLocations[i]); - i += 1; + /** Returns the first {@link File} found in + * {@code propertiesFilePaths} from which app properties can be loaded. If the {@link File} found + * is not a regular file or is not readable, then {@code null} is returned. Symlinks **will not** + * be followed for potential security reasons. + * + * @return Returns the {@link File} object for Termux:Float app properties. + */ + public static File getPropertiesFile(List propertiesFilePaths) { + if (propertiesFilePaths == null || propertiesFilePaths.size() == 0) + return null; + + for(String propertiesFilePath : propertiesFilePaths) { + File propertiesFile = new File(propertiesFilePath); + + // Symlinks **will not** be followed. + FileType fileType = FileUtils.getFileType(propertiesFilePath, false); + if (fileType == FileType.REGULAR) { + if (propertiesFile.canRead()) + return propertiesFile; + else + Logger.logWarn(LOG_TAG, "Ignoring properties file at \"" + propertiesFilePath + "\" since it is not readable"); + } else if (fileType != FileType.NO_EXIST) { + Logger.logWarn(LOG_TAG, "Ignoring properties file at \"" + propertiesFilePath + "\" of type: \"" + fileType.getName() + "\""); + } } - if (propertiesFile.isFile() && propertiesFile.canRead()) { - return propertiesFile; - } else { - Logger.logDebug("No readable properties file found at: " + Arrays.toString(possiblePropertiesFileLocations)); - return null; - } + Logger.logDebug(LOG_TAG, "No readable properties file found at: " + propertiesFilePaths); + return null; } } diff --git a/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java b/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java index 57b619fc..65ec62f4 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java @@ -12,7 +12,7 @@ import java.util.IllegalFormatException; import java.util.List; /* - * Version: v0.32.0 + * Version: v0.33.0 * * Changelog * @@ -211,6 +211,9 @@ import java.util.List; * - 0.32.0 (2021-09-23) * - Added `TERMUX_API.TERMUX_API_ACTIVITY_NAME`, `TERMUX_TASKER.TERMUX_TASKER_ACTIVITY_NAME` * and `TERMUX_WIDGET.TERMUX_WIDGET_ACTIVITY_NAME`. + * + * - 0.33.0 (2021-10-08) + * - Added `TERMUX_PROPERTIES_FILE_PATHS_LIST` and `TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST`. */ /** @@ -653,27 +656,46 @@ public final class TermuxConstants { public static final String TERMUX_WIDGET_DEFAULT_PREFERENCES_FILE_BASENAME_WITHOUT_EXTENSION = TERMUX_WIDGET_PACKAGE_NAME + "_preferences"; // Default: "com.termux.widget_preferences" - /** Termux app termux.properties primary file path */ + + /** Termux app properties primary file path */ public static final String TERMUX_PROPERTIES_PRIMARY_FILE_PATH = TERMUX_DATA_HOME_DIR_PATH + "/termux.properties"; // Default: "/data/data/com.termux/files/home/.termux/termux.properties" - /** Termux app termux.properties primary file */ + /** Termux app properties primary file */ public static final File TERMUX_PROPERTIES_PRIMARY_FILE = new File(TERMUX_PROPERTIES_PRIMARY_FILE_PATH); - /** Termux app termux.properties secondary file path */ + /** Termux app properties secondary file path */ public static final String TERMUX_PROPERTIES_SECONDARY_FILE_PATH = TERMUX_CONFIG_HOME_DIR_PATH + "/termux.properties"; // Default: "/data/data/com.termux/files/home/.config/termux/termux.properties" - /** Termux app termux.properties secondary file */ + /** Termux app properties secondary file */ public static final File TERMUX_PROPERTIES_SECONDARY_FILE = new File(TERMUX_PROPERTIES_SECONDARY_FILE_PATH); + /** Termux app properties file paths list. **DO NOT** allow these files to be modified by + * {@link android.content.ContentProvider} exposed to external apps, since they may silently + * modify the values for security properties like {@link #PROP_ALLOW_EXTERNAL_APPS} set by users + * without their explicit consent. */ + public static final List TERMUX_PROPERTIES_FILE_PATHS_LIST = Arrays.asList( + TERMUX_PROPERTIES_PRIMARY_FILE_PATH, + TERMUX_PROPERTIES_SECONDARY_FILE_PATH); - /** Termux:Float app termux.properties primary file path */ + + + /** Termux:Float app properties primary file path */ public static final String TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE_PATH = TERMUX_DATA_HOME_DIR_PATH + "/termux.float.properties"; // Default: "/data/data/com.termux/files/home/.termux/termux.float.properties" - /** Termux:Float app termux.properties primary file */ + /** Termux:Float app properties primary file */ public static final File TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE = new File(TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE_PATH); - /** Termux:Float app termux.properties secondary file path */ + /** Termux:Float app properties secondary file path */ public static final String TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE_PATH = TERMUX_CONFIG_HOME_DIR_PATH + "/termux.float.properties"; // Default: "/data/data/com.termux/files/home/.config/termux/termux.float.properties" - /** Termux:Float app termux.properties secondary file */ + /** Termux:Float app properties secondary file */ public static final File TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE = new File(TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE_PATH); + /** Termux:Float app properties file paths list. **DO NOT** allow these files to be modified by + * {@link android.content.ContentProvider} exposed to external apps, since they may silently + * modify the values for security properties like {@link #PROP_ALLOW_EXTERNAL_APPS} set by users + * without their explicit consent. */ + public static final List TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST = Arrays.asList( + TERMUX_FLOAT_PROPERTIES_PRIMARY_FILE_PATH, + TERMUX_FLOAT_PROPERTIES_SECONDARY_FILE_PATH); + + /** Termux app and Termux:Styling colors.properties file path */ public static final String TERMUX_COLOR_PROPERTIES_FILE_PATH = TERMUX_DATA_HOME_DIR_PATH + "/colors.properties"; // Default: "/data/data/com.termux/files/home/.termux/colors.properties"