From c46eeb04015af43d922b7c0fc21f827ffc89823c Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 15 Jun 2023 10:38:19 +0200 Subject: [PATCH 01/44] first impl draft --- .../common/PropertiesPreprocessor.java | 66 +++++++++++++++++++ .../org/cryptomator/launcher/Cryptomator.java | 3 +- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/cryptomator/common/PropertiesPreprocessor.java diff --git a/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java b/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java new file mode 100644 index 000000000..d28fdd2ed --- /dev/null +++ b/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java @@ -0,0 +1,66 @@ +package org.cryptomator.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.regex.Pattern; + +public class PropertiesPreprocessor { + + private static final Logger LOG = LoggerFactory.getLogger(PropertiesPreprocessor.class); + private static final Pattern TEMPLATE = Pattern.compile("@\\((.+)\\)"); + private static final LoggingEnvironment ENV = new LoggingEnvironment(System.getenv(), LOG); + + public static void run() { + var properties = System.getProperties(); + properties.stringPropertyNames().stream() // + .filter(s -> s.startsWith("cryptomator.")) // + .forEach(key -> { + var value = properties.getProperty(key); + var newValue = process(value); + if(! value.equals(newValue)) { + LOG.info("Changed property {} from {} to {}.", key, value, newValue); + } + properties.setProperty(key, newValue); + }); + LOG.info("Preprocessed cryptomator properties."); + } + + private static String process(String value) { + return TEMPLATE.matcher(value).replaceAll(match -> // + switch (match.group().substring(2, match.group().length() - 1)) { + case "appdir" -> ENV.get("APPDIR"); + case "appdata" -> ENV.get("APPDATA"); + case "userhome" -> System.getProperty("user.home"); + default -> { + LOG.warn("Found unknown keyword {} in property value {}. Keyword is not replaced.", match.group(), value); + yield match.group(); + } + }); + } + + private static class LoggingEnvironment { + + private final Map env; + private final Logger logger; + + LoggingEnvironment(Map env, Logger logger) { + this.env = env; + this.logger = logger; + } + + String get(String key) { + var val = env.get(key); + if (val == null) { + logger.warn("Variable {} used for substitution not found in environment", key); + return ""; + } else { + return val; + } + } + + } + + +} diff --git a/src/main/java/org/cryptomator/launcher/Cryptomator.java b/src/main/java/org/cryptomator/launcher/Cryptomator.java index 2b066c730..f08d70c37 100644 --- a/src/main/java/org/cryptomator/launcher/Cryptomator.java +++ b/src/main/java/org/cryptomator/launcher/Cryptomator.java @@ -9,6 +9,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import dagger.Lazy; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.Environment; +import org.cryptomator.common.PropertiesPreprocessor; import org.cryptomator.common.ShutdownHook; import org.cryptomator.ipc.IpcCommunicator; import org.cryptomator.logging.DebugMode; @@ -63,7 +64,7 @@ public class Cryptomator { System.out.printf("Cryptomator version %s (build %s)%n", appVer, buildNumber); return; } - + PropertiesPreprocessor.run(); int exitCode = CRYPTOMATOR_COMPONENT.application().run(args); LOG.info("Exit {}", exitCode); System.exit(exitCode); // end remaining non-daemon threads. From 4065e15aa1f0b099a900b056ae26c5b3d143d03b Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 16 Jun 2023 13:09:41 +0200 Subject: [PATCH 02/44] Apply code suggestion from review Co-authored-by: Sebastian Stenzel --- .../java/org/cryptomator/common/PropertiesPreprocessor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java b/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java index d28fdd2ed..342ad3e9d 100644 --- a/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java +++ b/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java @@ -9,7 +9,7 @@ import java.util.regex.Pattern; public class PropertiesPreprocessor { private static final Logger LOG = LoggerFactory.getLogger(PropertiesPreprocessor.class); - private static final Pattern TEMPLATE = Pattern.compile("@\\((.+)\\)"); + private static final Pattern TEMPLATE = Pattern.compile("@\\{(\\w+)}"); private static final LoggingEnvironment ENV = new LoggingEnvironment(System.getenv(), LOG); public static void run() { @@ -29,12 +29,12 @@ public class PropertiesPreprocessor { private static String process(String value) { return TEMPLATE.matcher(value).replaceAll(match -> // - switch (match.group().substring(2, match.group().length() - 1)) { + switch (match.group(1)) { case "appdir" -> ENV.get("APPDIR"); case "appdata" -> ENV.get("APPDATA"); case "userhome" -> System.getProperty("user.home"); default -> { - LOG.warn("Found unknown keyword {} in property value {}. Keyword is not replaced.", match.group(), value); + LOG.warn("Found unknown variable @{{}} in property value {}.", match.group(), value); yield match.group(); } }); From 173b1e83861ec878edc1235a9ac0d2dc9d6d134b Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Fri, 16 Jun 2023 11:38:07 +0200 Subject: [PATCH 03/44] Show a dedicated message when mounting to an occupied Windows drive The error message was restored from 6395f17. Fixes #2309. --- .../common/mount/MountPointInUseException.java | 8 ++++++++ src/main/java/org/cryptomator/common/mount/Mounter.java | 6 +++++- .../ui/unlock/UnlockInvalidMountPointController.java | 2 ++ src/main/resources/i18n/strings.properties | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/cryptomator/common/mount/MountPointInUseException.java diff --git a/src/main/java/org/cryptomator/common/mount/MountPointInUseException.java b/src/main/java/org/cryptomator/common/mount/MountPointInUseException.java new file mode 100644 index 000000000..9f7f11174 --- /dev/null +++ b/src/main/java/org/cryptomator/common/mount/MountPointInUseException.java @@ -0,0 +1,8 @@ +package org.cryptomator.common.mount; + +public class MountPointInUseException extends IllegalMountPointException { + + public MountPointInUseException(String msg) { + super(msg); + } +} diff --git a/src/main/java/org/cryptomator/common/mount/Mounter.java b/src/main/java/org/cryptomator/common/mount/Mounter.java index 0161268f3..a56f2b01b 100644 --- a/src/main/java/org/cryptomator/common/mount/Mounter.java +++ b/src/main/java/org/cryptomator/common/mount/Mounter.java @@ -97,7 +97,11 @@ public class Mounter { } } else { var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\"); - if (!mpIsDriveLetter && canMountToParent && !canMountToDir) { + if (mpIsDriveLetter) { + if (driveLetters.getOccupied().contains(userChosenMountPoint)) { + throw new MountPointInUseException(userChosenMountPoint.toString()); + } + } else if (canMountToParent && !canMountToDir) { MountWithinParentUtil.prepareParentNoMountPoint(userChosenMountPoint); cleanup = () -> { MountWithinParentUtil.cleanup(userChosenMountPoint); diff --git a/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java b/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java index 7bc0cbccd..b07e3ffde 100644 --- a/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java +++ b/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java @@ -1,5 +1,6 @@ package org.cryptomator.ui.unlock; +import org.cryptomator.common.mount.MountPointInUseException; import org.cryptomator.common.mount.MountPointNotExistsException; import org.cryptomator.common.mount.MountPointNotSupportedException; import org.cryptomator.common.vaults.Vault; @@ -41,6 +42,7 @@ public class UnlockInvalidMountPointController implements FxController { var translationKey = switch (e) { case MountPointNotSupportedException x -> "unlock.error.customPath.description.notSupported"; case MountPointNotExistsException x -> "unlock.error.customPath.description.notExists"; + case MountPointInUseException x -> "unlock.error.customPath.description.inUse"; default -> "unlock.error.customPath.description.generic"; }; dialogDescription.setFormat(resourceBundle.getString(translationKey)); diff --git a/src/main/resources/i18n/strings.properties b/src/main/resources/i18n/strings.properties index 43060b7c1..0d9d1bfd5 100644 --- a/src/main/resources/i18n/strings.properties +++ b/src/main/resources/i18n/strings.properties @@ -127,6 +127,7 @@ unlock.success.revealBtn=Reveal Drive unlock.error.customPath.message=Unable to mount vault to custom path unlock.error.customPath.description.notSupported=If you wish to keep using the custom path, please go to the preferences and select a volume type that supports it. Otherwise, go to the vault options and choose a supported mount point. unlock.error.customPath.description.notExists=The custom mount path does not exist. Either create it in your local filesystem or change it in the vault options. +unlock.error.customPath.description.inUse=Drive letter "%s" is already in use. unlock.error.customPath.description.generic=You have selected a custom mount path for this vault, but using it failed with the message: %s ## Hub hub.noKeychain.message=Unable to access device key From 4d09728880b5226ea7f5d03719f176b269389ddb Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 19 Jun 2023 22:31:50 +0200 Subject: [PATCH 04/44] Suppress a CVE false-positive for jackson-databind 2.14.2 Also see https://github.com/cryptomator/cryptomator/pull/2961#issuecomment-1597652134. --- suppression.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/suppression.xml b/suppression.xml index e7cc4ea65..36b795480 100644 --- a/suppression.xml +++ b/suppression.xml @@ -55,4 +55,12 @@ CVE-2022-45688 - \ No newline at end of file + + + ^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$ + CVE-2023-35116 + + + From 2c0474ec46f77649adb01fb93f46160ee5e57546 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 20 Jun 2023 12:37:07 +0200 Subject: [PATCH 05/44] add test --- .../common/PropertiesPreprocessor.java | 4 +++- .../common/PropertiesPreprocessorTest.java | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/cryptomator/common/PropertiesPreprocessorTest.java diff --git a/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java b/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java index 342ad3e9d..785b249bf 100644 --- a/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java +++ b/src/main/java/org/cryptomator/common/PropertiesPreprocessor.java @@ -1,5 +1,6 @@ package org.cryptomator.common; +import org.jetbrains.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,7 +28,8 @@ public class PropertiesPreprocessor { LOG.info("Preprocessed cryptomator properties."); } - private static String process(String value) { + @VisibleForTesting + static String process(String value) { return TEMPLATE.matcher(value).replaceAll(match -> // switch (match.group(1)) { case "appdir" -> ENV.get("APPDIR"); diff --git a/src/test/java/org/cryptomator/common/PropertiesPreprocessorTest.java b/src/test/java/org/cryptomator/common/PropertiesPreprocessorTest.java new file mode 100644 index 000000000..eee900f9c --- /dev/null +++ b/src/test/java/org/cryptomator/common/PropertiesPreprocessorTest.java @@ -0,0 +1,24 @@ +package org.cryptomator.common; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.Mockito; + +public class PropertiesPreprocessorTest { + + @ParameterizedTest + @CsvSource(value = """ + org.example.@{mytest1}.test, org.example.@{mytest1}.test + @{only*word*digits*under_score\\},@{only*words*digits*under_score\\} + C:\\Users\\@{appdir}\\dir, C:\\Users\\\\dir + @{@{appdir}},@{} + Longer @{appdir} text with @{appdir}., Longer text with . + """) + public void test(String propertyValue, String expected) { + var result = PropertiesPreprocessor.process(propertyValue); + Assertions.assertEquals(result, expected); + } + +} From ec645a4bb952b2fa5a7d104a748e3081d31ffbba Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 20 Jun 2023 16:37:32 +0200 Subject: [PATCH 06/44] replace ~ by @{userhome} on unix systems --- .github/workflows/appimage.yml | 12 ++-- .github/workflows/mac-dmg.yml | 12 ++-- .idea/runConfigurations/Cryptomator_Linux.xml | 2 +- .../Cryptomator_Linux_Dev.xml | 2 +- .idea/runConfigurations/Cryptomator_macOS.xml | 2 +- .../Cryptomator_macOS_Dev.xml | 2 +- dist/linux/appimage/build.sh | 12 ++-- dist/linux/debian/rules | 12 ++-- dist/mac/dmg/build.sh | 12 ++-- .../org/cryptomator/common/Environment.java | 22 ++---- .../cryptomator/common/EnvironmentTest.java | 67 ------------------- 11 files changed, 38 insertions(+), 119 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index f966f6b22..44ca02028 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -85,12 +85,12 @@ jobs: --java-options "-Xmx256m" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dfile.encoding=\"utf-8\"" - --java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\"" - --java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\"" - --java-options "-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" - --java-options "-Dcryptomator.p12Path=\"~/.config/Cryptomator/key.p12\"" - --java-options "-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\"" - --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" + --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" + --java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" + --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" + --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" + --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" + --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" --java-options "-Dcryptomator.showTrayIcon=false" --java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.get-version.outputs.revNum }}\"" --add-launcher Cryptomator-gtk2=launcher-gtk2.properties diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index bad80138b..1190444d3 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -98,13 +98,13 @@ jobs: --java-options "-Dapple.awt.enableTemplateImages=true" --java-options "-Dsun.java2d.metal=true" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" - --java-options "-Dcryptomator.logDir=\"~/Library/Logs/Cryptomator\"" - --java-options "-Dcryptomator.pluginDir=\"~/Library/Application Support/Cryptomator/Plugins\"" - --java-options "-Dcryptomator.settingsPath=\"~/Library/Application Support/Cryptomator/settings.json\"" - --java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/Cryptomator/key.p12\"" - --java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\"" + --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\"" + --java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\"" + --java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\"" + --java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\"" + --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\"" - --java-options "-Dcryptomator.mountPointsDir=\"~/Cryptomator\"" + --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Cryptomator\"" --java-options "-Dcryptomator.showTrayIcon=true" --java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\"" --mac-package-identifier org.cryptomator diff --git a/.idea/runConfigurations/Cryptomator_Linux.xml b/.idea/runConfigurations/Cryptomator_Linux.xml index 887a5044e..3206f553a 100644 --- a/.idea/runConfigurations/Cryptomator_Linux.xml +++ b/.idea/runConfigurations/Cryptomator_Linux.xml @@ -2,7 +2,7 @@