Skip to content

Commit cb6db8e

Browse files
Merge branch 'release/2.0.0' into release/2.1.0
2 parents f43c2df + c7b713b commit cb6db8e

File tree

6 files changed

+171
-88
lines changed

6 files changed

+171
-88
lines changed

pom.xml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,24 @@
1515

1616
<properties>
1717
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
<maven.compiler.release>16</maven.compiler.release>
1819

1920
<!-- dependencies -->
20-
<cryptolib.version>2.0.0-beta7</cryptolib.version>
21-
<jwt.version>3.12.0</jwt.version>
22-
<dagger.version>2.31</dagger.version>
23-
<guava.version>30.1-jre</guava.version>
21+
<cryptolib.version>2.0.0-rc1</cryptolib.version>
22+
<jwt.version>3.15.0</jwt.version>
23+
<dagger.version>2.35.1</dagger.version>
24+
<guava.version>30.1.1-jre</guava.version>
2425
<slf4j.version>1.7.30</slf4j.version>
2526

2627
<!-- test dependencies -->
27-
<junit.jupiter.version>5.7.0</junit.jupiter.version>
28-
<mockito.version>3.7.7</mockito.version>
28+
<junit.jupiter.version>5.7.1</junit.jupiter.version>
29+
<mockito.version>3.9.0</mockito.version>
2930
<hamcrest.version>2.2</hamcrest.version>
31+
32+
<!-- build plugin dependencies -->
33+
<dependency-check.version>6.1.6</dependency-check.version>
34+
<jacoco.version>0.8.6</jacoco.version>
35+
<nexus-staging.version>1.6.8</nexus-staging.version>
3036
</properties>
3137

3238
<licenses>
@@ -121,7 +127,6 @@
121127
<artifactId>maven-compiler-plugin</artifactId>
122128
<version>3.8.1</version>
123129
<configuration>
124-
<release>16</release>
125130
<showWarnings>true</showWarnings>
126131
<annotationProcessorPaths>
127132
<path>
@@ -219,7 +224,7 @@
219224
<plugin>
220225
<groupId>org.owasp</groupId>
221226
<artifactId>dependency-check-maven</artifactId>
222-
<version>6.1.0</version>
227+
<version>${dependency-check.version}</version>
223228
<configuration>
224229
<cveValidForHours>24</cveValidForHours>
225230
<failBuildOnCVSS>0</failBuildOnCVSS>
@@ -246,7 +251,7 @@
246251
<plugin>
247252
<groupId>org.jacoco</groupId>
248253
<artifactId>jacoco-maven-plugin</artifactId>
249-
<version>0.8.6</version>
254+
<version>${jacoco.version}</version>
250255
<executions>
251256
<execution>
252257
<id>prepare-agent</id>
@@ -307,7 +312,7 @@
307312
<plugin>
308313
<groupId>org.sonatype.plugins</groupId>
309314
<artifactId>nexus-staging-maven-plugin</artifactId>
310-
<version>1.6.8</version>
315+
<version>${nexus-staging.version}</version>
311316
<extensions>true</extensions>
312317
<configuration>
313318
<serverId>ossrh</serverId>

src/main/java/org/cryptomator/cryptofs/CryptoFileSystemProvider.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,23 +156,21 @@ public static void initialize(Path pathToVault, CryptoFileSystemProperties prope
156156
} finally {
157157
Arrays.fill(rawKey, (byte) 0x00);
158158
}
159-
assert containsVault(pathToVault, properties.vaultConfigFilename(), properties.masterkeyFilename());
159+
assert checkDirStructureForVault(pathToVault, properties.vaultConfigFilename(), properties.masterkeyFilename()) == DirStructure.VAULT;
160160
}
161161

162162
/**
163-
* Checks if the folder represented by the given path exists and contains a valid vault structure.
163+
* Delegate to {@link DirStructure#checkDirStructure(Path, String, String)}.
164164
*
165-
* @param pathToVault A directory path
166-
* @param vaultConfigFilename Name of the vault config file
167-
* @param masterkeyFilename Name of the masterkey file
168-
* @return <code>true</code> if the directory seems to contain a vault.
165+
* @param pathToAssumedVault
166+
* @param vaultConfigFilename
167+
* @param masterkeyFilename
168+
* @return a {@link DirStructure} object
169+
* @throws IOException
169170
* @since 2.0.0
170171
*/
171-
public static boolean containsVault(Path pathToVault, String vaultConfigFilename, String masterkeyFilename) {
172-
Path vaultConfigPath = pathToVault.resolve(vaultConfigFilename);
173-
Path masterkeyPath = pathToVault.resolve(masterkeyFilename);
174-
Path dataDirPath = pathToVault.resolve(Constants.DATA_DIR_NAME);
175-
return (Files.isReadable(vaultConfigPath) || Files.isReadable(masterkeyPath)) && Files.isDirectory(dataDirPath);
172+
public static DirStructure checkDirStructureForVault(Path pathToAssumedVault, String vaultConfigFilename, String masterkeyFilename) throws IOException {
173+
return DirStructure.checkDirStructure(pathToAssumedVault, vaultConfigFilename, masterkeyFilename);
176174
}
177175

178176
/**
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package org.cryptomator.cryptofs;
2+
3+
import org.cryptomator.cryptofs.common.Constants;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Files;
7+
import java.nio.file.NotDirectoryException;
8+
import java.nio.file.Path;
9+
import java.nio.file.attribute.BasicFileAttributes;
10+
11+
/**
12+
* Enumeration of the vault directory structure resemblances.
13+
* <p>
14+
* A valid vault must contain a `d` directory.
15+
* Beginning with vault format 8, it must also contain a vault config file.
16+
* If the vault format is lower than 8, it must instead contain a masterkey file.
17+
* <p>
18+
* In the latter case, to distinguish between a damaged vault 8 directory and a legacy vault the masterkey file must be read.
19+
* For efficiency reasons, this class only checks for existence/readability of the above elements.
20+
* Hence, if the result of {@link #checkDirStructure(Path, String, String)} is {@link #MAYBE_LEGACY}, one needs to parse
21+
* the masterkey file and read out the vault version to determine this case.
22+
*
23+
* @since 2.0.0
24+
*/
25+
public enum DirStructure {
26+
27+
/**
28+
* Dir contains a <code>d</code> dir as well as a vault config file.
29+
*/
30+
VAULT,
31+
32+
/**
33+
* Dir contains a <code>d</code> dir and a masterkey file, but misses a vault config file.
34+
* Either needs migration to a newer format or damaged.
35+
*/
36+
MAYBE_LEGACY,
37+
38+
/**
39+
* Dir does not qualify as vault.
40+
*/
41+
UNRELATED;
42+
43+
44+
/**
45+
* Analyzes the structure of the given directory under certain vault existence criteria.
46+
*
47+
* @param pathToVault A directory path
48+
* @param vaultConfigFilename Name of the vault config file
49+
* @param masterkeyFilename Name of the masterkey file
50+
* @return enum indicating what this directory might be
51+
* @throws IOException if the provided path is not a directory, does not exist or cannot be read
52+
*/
53+
public static DirStructure checkDirStructure(Path pathToVault, String vaultConfigFilename, String masterkeyFilename) throws IOException {
54+
if(! Files.readAttributes(pathToVault, BasicFileAttributes.class).isDirectory()) {
55+
throw new NotDirectoryException(pathToVault.toString());
56+
}
57+
Path vaultConfigPath = pathToVault.resolve(vaultConfigFilename);
58+
Path masterkeyPath = pathToVault.resolve(masterkeyFilename);
59+
Path dataDirPath = pathToVault.resolve(Constants.DATA_DIR_NAME);
60+
if (Files.isDirectory(dataDirPath)) {
61+
if (Files.isReadable(vaultConfigPath)) {
62+
return VAULT;
63+
} else if (Files.isReadable(masterkeyPath)) {
64+
return MAYBE_LEGACY;
65+
}
66+
}
67+
return UNRELATED;
68+
}
69+
}

src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ public void initializeVaults() {
227227
@Test
228228
@Order(2)
229229
@DisplayName("get filesystem with incorrect credentials")
230-
public void testGetFsWithWrongCredentials() {
231-
Assumptions.assumeTrue(CryptoFileSystemProvider.containsVault(pathToVault1, "vault.cryptomator", "masterkey.cryptomator"));
232-
Assumptions.assumeTrue(CryptoFileSystemProvider.containsVault(pathToVault2, "vault.cryptomator", "masterkey.cryptomator"));
230+
public void testGetFsWithWrongCredentials() throws IOException {
231+
Assumptions.assumeTrue(CryptoFileSystemProvider.checkDirStructureForVault(pathToVault1, "vault.cryptomator", "masterkey.cryptomator") == DirStructure.VAULT);
232+
Assumptions.assumeTrue(CryptoFileSystemProvider.checkDirStructureForVault(pathToVault2, "vault.cryptomator", "masterkey.cryptomator") == DirStructure.VAULT);
233233
Assertions.assertAll(
234234
() -> {
235235
URI fsUri = CryptoFileSystemUri.create(pathToVault1);

src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderTest.java

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import static java.nio.file.StandardOpenOption.APPEND;
4747
import static java.util.Arrays.asList;
4848
import static org.cryptomator.cryptofs.CryptoFileSystemProperties.cryptoFileSystemProperties;
49-
import static org.cryptomator.cryptofs.CryptoFileSystemProvider.containsVault;
5049
import static org.hamcrest.Matchers.containsString;
5150
import static org.hamcrest.Matchers.instanceOf;
5251
import static org.mockito.Mockito.mock;
@@ -211,69 +210,6 @@ public void testNewFileSystem() throws IOException, MasterkeyLoadingFailedExcept
211210
Mockito.verify(fileSystems).create(Mockito.same(inTest), Mockito.eq(pathToVault.toAbsolutePath()), Mockito.eq(properties));
212211
}
213212

214-
@Test
215-
public void testContainsVaultReturnsTrueIfDirectoryContainsVaultConfigFileAndDataDir() throws IOException {
216-
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
217-
218-
String vaultConfigFilename = "vaultconfig.foo.baz";
219-
String masterkeyFilename = "masterkey.foo.baz";
220-
Path pathToVault = fs.getPath("/vaultDir");
221-
222-
Path vaultConfigFile = pathToVault.resolve(vaultConfigFilename);
223-
Path dataDir = pathToVault.resolve("d");
224-
Files.createDirectories(dataDir);
225-
Files.write(vaultConfigFile, new byte[0]);
226-
227-
Assertions.assertTrue(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
228-
}
229-
230-
@Test
231-
public void testContainsVaultReturnsTrueIfDirectoryContainsMasterkeyFileAndDataDir() throws IOException {
232-
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
233-
234-
String vaultConfigFilename = "vaultconfig.foo.baz";
235-
String masterkeyFilename = "masterkey.foo.baz";
236-
Path pathToVault = fs.getPath("/vaultDir");
237-
238-
Path masterkeyFile = pathToVault.resolve(masterkeyFilename);
239-
Path dataDir = pathToVault.resolve("d");
240-
Files.createDirectories(dataDir);
241-
Files.write(masterkeyFile, new byte[0]);
242-
243-
Assertions.assertTrue(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
244-
}
245-
246-
@Test
247-
public void testContainsVaultReturnsFalseIfDirectoryContainsOnlyDataDir() throws IOException {
248-
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
249-
250-
String vaultConfigFilename = "vaultconfig.foo.baz";
251-
String masterkeyFilename = "masterkey.foo.baz";
252-
Path pathToVault = fs.getPath("/vaultDir");
253-
254-
Path dataDir = pathToVault.resolve("d");
255-
Files.createDirectories(dataDir);
256-
257-
Assertions.assertFalse(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
258-
}
259-
260-
@Test
261-
public void testContainsVaultReturnsFalseIfDirectoryContainsNoDataDir() throws IOException {
262-
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
263-
264-
String vaultConfigFilename = "vaultconfig.foo.baz";
265-
String masterkeyFilename = "masterkey.foo.baz";
266-
Path pathToVault = fs.getPath("/vaultDir");
267-
268-
Path vaultConfigFile = pathToVault.resolve(vaultConfigFilename);
269-
Path masterkeyFile = pathToVault.resolve(masterkeyFilename);
270-
Files.createDirectories(pathToVault);
271-
Files.write(vaultConfigFile, new byte[0]);
272-
Files.write(masterkeyFile, new byte[0]);
273-
274-
Assertions.assertFalse(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
275-
}
276-
277213
@Test
278214
public void testGetFileSystemInvokesFileSystemsGetWithPathToVaultFromUri() {
279215
Path pathToVault = get("a").toAbsolutePath();
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.cryptomator.cryptofs;
2+
3+
import org.cryptomator.cryptofs.common.Constants;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Assumptions;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.io.TempDir;
8+
import org.junit.jupiter.params.ParameterizedTest;
9+
import org.junit.jupiter.params.provider.Arguments;
10+
import org.junit.jupiter.params.provider.MethodSource;
11+
12+
import java.io.IOException;
13+
import java.nio.file.Files;
14+
import java.nio.file.Path;
15+
import java.util.stream.Stream;
16+
17+
public class DirStructureTest {
18+
19+
private static final String KEY = "key";
20+
private static final String CONFIG = "config";
21+
22+
@TempDir
23+
Path vaultPath;
24+
25+
@Test
26+
public void testNonExistingVaultPathThrowsIOException() {
27+
Path vaultPath = Path.of("this/certainly/does/not/exist");
28+
Assumptions.assumeTrue(Files.notExists(vaultPath));
29+
30+
Assertions.assertThrows(IOException.class, () -> DirStructure.checkDirStructure(vaultPath, CONFIG, KEY));
31+
}
32+
33+
@Test
34+
public void testNonDirectoryVaultPathThrowsIOException() throws IOException {
35+
Path tmp = vaultPath.resolve("this");
36+
Files.createFile(tmp);
37+
Assumptions.assumeTrue(Files.exists(tmp));
38+
39+
Assertions.assertThrows(IOException.class, () -> DirStructure.checkDirStructure(tmp, CONFIG, KEY));
40+
}
41+
42+
@ParameterizedTest(name = "Testing all combinations of data dir, config and masterkey file existence.")
43+
@MethodSource("provideAllCases")
44+
public void testAllCombosOfDataAndConfigAndKey(boolean createDataDir, boolean createConfig, boolean createKey, DirStructure expectedResult) throws IOException {
45+
Path keyPath = vaultPath.resolve(KEY);
46+
Path configPath = vaultPath.resolve(CONFIG);
47+
Path dataDir = vaultPath.resolve(Constants.DATA_DIR_NAME);
48+
49+
if (createDataDir) {
50+
Files.createDirectory(dataDir);
51+
}
52+
if (createConfig) {
53+
Files.createFile(configPath);
54+
}
55+
if (createKey) {
56+
Files.createFile(keyPath);
57+
}
58+
59+
Assertions.assertEquals(expectedResult, DirStructure.checkDirStructure(vaultPath, CONFIG, KEY));
60+
}
61+
62+
private static Stream<Arguments> provideAllCases() {
63+
return Stream.of(
64+
Arguments.of(true, true, true, DirStructure.VAULT),
65+
Arguments.of(true, true, false, DirStructure.VAULT),
66+
Arguments.of(true, false, true, DirStructure.MAYBE_LEGACY),
67+
Arguments.of(true, false, false, DirStructure.UNRELATED),
68+
Arguments.of(false, false, false, DirStructure.UNRELATED),
69+
Arguments.of(false, false, true, DirStructure.UNRELATED),
70+
Arguments.of(false, true, false, DirStructure.UNRELATED),
71+
Arguments.of(false, true, true, DirStructure.UNRELATED)
72+
);
73+
}
74+
75+
}

0 commit comments

Comments
 (0)