From aa2eaf51e9355edc882b03b55e723e78523ebf86 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Jul 2023 13:32:00 +0200 Subject: [PATCH 1/6] fixes #175 --- .../cryptofs/CryptoFileSystemImpl.java | 2 +- ...yptoFileSystemProviderIntegrationTest.java | 66 ++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java index bd10dc34..8bd83d2d 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java @@ -599,7 +599,7 @@ private void moveFile(CryptoPath cleartextSource, CryptoPath cleartextTarget, Co CiphertextFilePath ciphertextTarget = cryptoPathMapper.getCiphertextFilePath(cleartextTarget); try (OpenCryptoFiles.TwoPhaseMove twoPhaseMove = openCryptoFiles.prepareMove(ciphertextSource.getRawPath(), ciphertextTarget.getRawPath())) { if (ciphertextTarget.isShortened()) { - Files.createDirectory(ciphertextTarget.getRawPath()); + Files.createDirectories(ciphertextTarget.getRawPath()); ciphertextTarget.persistLongFileName(); } Files.move(ciphertextSource.getFilePath(), ciphertextTarget.getFilePath(), options); diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java index 487d683c..c9f0b4bd 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java @@ -62,7 +62,9 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributeView; import java.util.Arrays; +import java.util.Comparator; import java.util.EnumSet; +import java.util.Set; import static java.nio.file.Files.readAllBytes; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; @@ -170,7 +172,7 @@ public void testCopyExceedingPathLengthLimit(String path) { @Nested @TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - public class InMemory { + public class InMemoryOrdered { private FileSystem tmpFs; private MasterkeyLoader keyLoader1; @@ -587,6 +589,68 @@ public void testMoveFileFromOneCryptoFileSystemToAnother() throws IOException { } + + @Nested + public class InMemory { + + private static FileSystem tmpFs; + private static Path pathToVault; + + @BeforeAll + public static void beforeAll() { + tmpFs = Jimfs.newFileSystem(Configuration.unix()); + pathToVault = tmpFs.getPath("/vault"); + } + + @BeforeEach + public void beforeEach() throws IOException { + Files.createDirectory(pathToVault); + } + + @AfterEach + public void afterEach() throws IOException { + try (var paths = Files.walk(pathToVault)) { + var nodes = paths.sorted(Comparator.reverseOrder()).toList(); + for (var node : nodes) { + Files.delete(node); + } + } + } + + @AfterAll + public static void afterAll() throws IOException { + tmpFs.close(); + } + + @Test + @DisplayName("Replace an existing, shortened file") + public void testReplaceExistingShortenedFile() throws IOException { + try (var fs = setupCryptoFs(50, 100, false)) { + var fiftyCharName2 = "/50char2_50char2_50char2_50char2_50char2_50char.txt"; //since filename encryption increases filename length, 50 cleartext chars are sufficient + var source = fs.getPath("/source.txt"); + var target = fs.getPath(fiftyCharName2); + Files.createFile(source); + Files.createFile(target); + + Assertions.assertDoesNotThrow(() -> Files.move(source, target, REPLACE_EXISTING)); + Assertions.assertTrue(Files.notExists(source)); + Assertions.assertTrue(Files.exists(target)); + } + } + + private FileSystem setupCryptoFs(int ciphertextShorteningThreshold, int maxCleartextFilename, boolean readonly) throws IOException { + byte[] key = new byte[64]; + Arrays.fill(key, (byte) 0x55); + var keyLoader = Mockito.mock(MasterkeyLoader.class); + Mockito.when(keyLoader.loadKey(Mockito.any())).thenAnswer(ignored -> new Masterkey(key)); + var properties = CryptoFileSystemProperties.cryptoFileSystemProperties().withKeyLoader(keyLoader).withShorteningThreshold(ciphertextShorteningThreshold).withMaxCleartextNameLength(maxCleartextFilename).withFlags(readonly ? Set.of(CryptoFileSystemProperties.FileSystemFlags.READONLY) : Set.of()).build(); + CryptoFileSystemProvider.initialize(pathToVault, properties, URI.create("test:key")); + URI fsUri = CryptoFileSystemUri.create(pathToVault); + return FileSystems.newFileSystem(fsUri, cryptoFileSystemProperties().withKeyLoader(keyLoader).build()); + } + + } + @Nested @EnabledOnOs({OS.MAC, OS.LINUX}) @TestInstance(TestInstance.Lifecycle.PER_CLASS) From 2897396d06f4b154709d18763ae8770266f3e96a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Jul 2023 16:35:14 +0200 Subject: [PATCH 2/6] bump com.auth0:java-jwt to 4.4.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cbe30c2e..0a797544 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 2.1.2 - 4.3.0 + 4.4.0 2.44.2 32.0.0-jre 3.1.4 From db287e134c152044e62a56fb1568f0b2115799c0 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 12 Jul 2023 10:35:19 +0200 Subject: [PATCH 3/6] suppress non-vulnerability --- suppression.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/suppression.xml b/suppression.xml index ebb877b8..4c274d96 100644 --- a/suppression.xml +++ b/suppression.xml @@ -9,4 +9,13 @@ cpe:/a:cryptomator:cryptomator CVE-2022-25366 + + + + + ^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$ + CVE-2023-35116 + \ No newline at end of file From 7142f36fe7860dac1ca807ad001393b623995858 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 18 Jul 2023 10:44:23 +0200 Subject: [PATCH 4/6] correct link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 53e70212..ba6c0d31 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ### Security Architecture -For more information on the security details, visit [cryptomator.org](https://cryptomator.org/architecture/). +For more information on the security details, visit [docs.cryptomator.org](https://docs.cryptomator.org/en/latest/security/architecture/). ## Audits From b977c43c62bb3a664f4a2cfade34c6547efe6e98 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 18 Jul 2023 12:16:43 +0200 Subject: [PATCH 5/6] Update docs. fixes #157 --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ba6c0d31..6ed04e88 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,14 @@ For more information on the security details, visit [docs.cryptomator.org](https ```java Path storageLocation = Paths.get("/home/cryptobot/vault"); Files.createDirectories(storageLocation); -CryptoFileSystemProvider.initialize(storageLocation, "masterkey.cryptomator", "password"); +Masterkey masterkey = Masterkey.generate(csprng)); +MasterkeyLoader loader = ignoredUri -> masterkey.copy(); //create a copy because the key handed over to init() method will be destroyed +CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withKeyLoader(loader).build(); +CryptoFileSystemProvider.initialize(storageLocation, fsProps, "myKeyId"); ``` +The key material used for initialization and later de- & encryption is given by the [org.cryptomator.cryptolib.api.Masterkeyloader](https://github.com/cryptomator/cryptolib/blob/2.1.2/src/main/java/org/cryptomator/cryptolib/api/MasterkeyLoader.java) interface. + ### Obtaining a FileSystem Instance You have the option to use the convenience method `CryptoFileSystemProvider#newFileSystem` as follows: @@ -44,7 +49,7 @@ You have the option to use the convenience method `CryptoFileSystemProvider#newF FileSystem fileSystem = CryptoFileSystemProvider.newFileSystem( storageLocation, CryptoFileSystemProperties.cryptoFileSystemProperties() - .withPassphrase("password") + .withKeyLoader(ignoredUri -> masterkey.copy()) .withFlags(FileSystemFlags.READONLY) // readonly flag is optional of course .build()); ``` @@ -56,7 +61,7 @@ URI uri = CryptoFileSystemUri.create(storageLocation); FileSystem fileSystem = FileSystems.newFileSystem( uri, CryptoFileSystemProperties.cryptoFileSystemProperties() - .withPassphrase("password") + .withKeyLoader(ignoredUri -> masterkey.copy()) .withFlags(FileSystemFlags.READONLY) // readonly flag is optional of course .build()); ``` From 56fb7e0b8a4abb0bd39b507bb1245763a31259c9 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 18 Jul 2023 12:27:22 +0200 Subject: [PATCH 6/6] prepare 2.6.6 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0a797544..0083ba02 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.cryptomator cryptofs - 2.7.0-SNAPSHOT + 2.6.6 Cryptomator Crypto Filesystem This library provides the Java filesystem provider used by Cryptomator. https://github.com/cryptomator/cryptofs