Skip to content

Commit

Permalink
Merge branch 'release/2.0.0' into release/2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
overheadhunter committed May 6, 2021
2 parents f43c2df + c7b713b commit cb6db8e
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 88 deletions.
25 changes: 15 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,24 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>16</maven.compiler.release>

<!-- dependencies -->
<cryptolib.version>2.0.0-beta7</cryptolib.version>
<jwt.version>3.12.0</jwt.version>
<dagger.version>2.31</dagger.version>
<guava.version>30.1-jre</guava.version>
<cryptolib.version>2.0.0-rc1</cryptolib.version>
<jwt.version>3.15.0</jwt.version>
<dagger.version>2.35.1</dagger.version>
<guava.version>30.1.1-jre</guava.version>
<slf4j.version>1.7.30</slf4j.version>

<!-- test dependencies -->
<junit.jupiter.version>5.7.0</junit.jupiter.version>
<mockito.version>3.7.7</mockito.version>
<junit.jupiter.version>5.7.1</junit.jupiter.version>
<mockito.version>3.9.0</mockito.version>
<hamcrest.version>2.2</hamcrest.version>

<!-- build plugin dependencies -->
<dependency-check.version>6.1.6</dependency-check.version>
<jacoco.version>0.8.6</jacoco.version>
<nexus-staging.version>1.6.8</nexus-staging.version>
</properties>

<licenses>
Expand Down Expand Up @@ -121,7 +127,6 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>16</release>
<showWarnings>true</showWarnings>
<annotationProcessorPaths>
<path>
Expand Down Expand Up @@ -219,7 +224,7 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.1.0</version>
<version>${dependency-check.version}</version>
<configuration>
<cveValidForHours>24</cveValidForHours>
<failBuildOnCVSS>0</failBuildOnCVSS>
Expand All @@ -246,7 +251,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
Expand Down Expand Up @@ -307,7 +312,7 @@
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<version>${nexus-staging.version}</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,23 +156,21 @@ public static void initialize(Path pathToVault, CryptoFileSystemProperties prope
} finally {
Arrays.fill(rawKey, (byte) 0x00);
}
assert containsVault(pathToVault, properties.vaultConfigFilename(), properties.masterkeyFilename());
assert checkDirStructureForVault(pathToVault, properties.vaultConfigFilename(), properties.masterkeyFilename()) == DirStructure.VAULT;
}

/**
* Checks if the folder represented by the given path exists and contains a valid vault structure.
* Delegate to {@link DirStructure#checkDirStructure(Path, String, String)}.
*
* @param pathToVault A directory path
* @param vaultConfigFilename Name of the vault config file
* @param masterkeyFilename Name of the masterkey file
* @return <code>true</code> if the directory seems to contain a vault.
* @param pathToAssumedVault
* @param vaultConfigFilename
* @param masterkeyFilename
* @return a {@link DirStructure} object
* @throws IOException
* @since 2.0.0
*/
public static boolean containsVault(Path pathToVault, String vaultConfigFilename, String masterkeyFilename) {
Path vaultConfigPath = pathToVault.resolve(vaultConfigFilename);
Path masterkeyPath = pathToVault.resolve(masterkeyFilename);
Path dataDirPath = pathToVault.resolve(Constants.DATA_DIR_NAME);
return (Files.isReadable(vaultConfigPath) || Files.isReadable(masterkeyPath)) && Files.isDirectory(dataDirPath);
public static DirStructure checkDirStructureForVault(Path pathToAssumedVault, String vaultConfigFilename, String masterkeyFilename) throws IOException {
return DirStructure.checkDirStructure(pathToAssumedVault, vaultConfigFilename, masterkeyFilename);
}

/**
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/DirStructure.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.cryptomator.cryptofs;

import org.cryptomator.cryptofs.common.Constants;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

/**
* Enumeration of the vault directory structure resemblances.
* <p>
* A valid vault must contain a `d` directory.
* Beginning with vault format 8, it must also contain a vault config file.
* If the vault format is lower than 8, it must instead contain a masterkey file.
* <p>
* In the latter case, to distinguish between a damaged vault 8 directory and a legacy vault the masterkey file must be read.
* For efficiency reasons, this class only checks for existence/readability of the above elements.
* Hence, if the result of {@link #checkDirStructure(Path, String, String)} is {@link #MAYBE_LEGACY}, one needs to parse
* the masterkey file and read out the vault version to determine this case.
*
* @since 2.0.0
*/
public enum DirStructure {

/**
* Dir contains a <code>d</code> dir as well as a vault config file.
*/
VAULT,

/**
* Dir contains a <code>d</code> dir and a masterkey file, but misses a vault config file.
* Either needs migration to a newer format or damaged.
*/
MAYBE_LEGACY,

/**
* Dir does not qualify as vault.
*/
UNRELATED;


/**
* Analyzes the structure of the given directory under certain vault existence criteria.
*
* @param pathToVault A directory path
* @param vaultConfigFilename Name of the vault config file
* @param masterkeyFilename Name of the masterkey file
* @return enum indicating what this directory might be
* @throws IOException if the provided path is not a directory, does not exist or cannot be read
*/
public static DirStructure checkDirStructure(Path pathToVault, String vaultConfigFilename, String masterkeyFilename) throws IOException {
if(! Files.readAttributes(pathToVault, BasicFileAttributes.class).isDirectory()) {
throw new NotDirectoryException(pathToVault.toString());
}
Path vaultConfigPath = pathToVault.resolve(vaultConfigFilename);
Path masterkeyPath = pathToVault.resolve(masterkeyFilename);
Path dataDirPath = pathToVault.resolve(Constants.DATA_DIR_NAME);
if (Files.isDirectory(dataDirPath)) {
if (Files.isReadable(vaultConfigPath)) {
return VAULT;
} else if (Files.isReadable(masterkeyPath)) {
return MAYBE_LEGACY;
}
}
return UNRELATED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ public void initializeVaults() {
@Test
@Order(2)
@DisplayName("get filesystem with incorrect credentials")
public void testGetFsWithWrongCredentials() {
Assumptions.assumeTrue(CryptoFileSystemProvider.containsVault(pathToVault1, "vault.cryptomator", "masterkey.cryptomator"));
Assumptions.assumeTrue(CryptoFileSystemProvider.containsVault(pathToVault2, "vault.cryptomator", "masterkey.cryptomator"));
public void testGetFsWithWrongCredentials() throws IOException {
Assumptions.assumeTrue(CryptoFileSystemProvider.checkDirStructureForVault(pathToVault1, "vault.cryptomator", "masterkey.cryptomator") == DirStructure.VAULT);
Assumptions.assumeTrue(CryptoFileSystemProvider.checkDirStructureForVault(pathToVault2, "vault.cryptomator", "masterkey.cryptomator") == DirStructure.VAULT);
Assertions.assertAll(
() -> {
URI fsUri = CryptoFileSystemUri.create(pathToVault1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import static java.nio.file.StandardOpenOption.APPEND;
import static java.util.Arrays.asList;
import static org.cryptomator.cryptofs.CryptoFileSystemProperties.cryptoFileSystemProperties;
import static org.cryptomator.cryptofs.CryptoFileSystemProvider.containsVault;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -211,69 +210,6 @@ public void testNewFileSystem() throws IOException, MasterkeyLoadingFailedExcept
Mockito.verify(fileSystems).create(Mockito.same(inTest), Mockito.eq(pathToVault.toAbsolutePath()), Mockito.eq(properties));
}

@Test
public void testContainsVaultReturnsTrueIfDirectoryContainsVaultConfigFileAndDataDir() throws IOException {
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());

String vaultConfigFilename = "vaultconfig.foo.baz";
String masterkeyFilename = "masterkey.foo.baz";
Path pathToVault = fs.getPath("/vaultDir");

Path vaultConfigFile = pathToVault.resolve(vaultConfigFilename);
Path dataDir = pathToVault.resolve("d");
Files.createDirectories(dataDir);
Files.write(vaultConfigFile, new byte[0]);

Assertions.assertTrue(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
}

@Test
public void testContainsVaultReturnsTrueIfDirectoryContainsMasterkeyFileAndDataDir() throws IOException {
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());

String vaultConfigFilename = "vaultconfig.foo.baz";
String masterkeyFilename = "masterkey.foo.baz";
Path pathToVault = fs.getPath("/vaultDir");

Path masterkeyFile = pathToVault.resolve(masterkeyFilename);
Path dataDir = pathToVault.resolve("d");
Files.createDirectories(dataDir);
Files.write(masterkeyFile, new byte[0]);

Assertions.assertTrue(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
}

@Test
public void testContainsVaultReturnsFalseIfDirectoryContainsOnlyDataDir() throws IOException {
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());

String vaultConfigFilename = "vaultconfig.foo.baz";
String masterkeyFilename = "masterkey.foo.baz";
Path pathToVault = fs.getPath("/vaultDir");

Path dataDir = pathToVault.resolve("d");
Files.createDirectories(dataDir);

Assertions.assertFalse(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
}

@Test
public void testContainsVaultReturnsFalseIfDirectoryContainsNoDataDir() throws IOException {
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());

String vaultConfigFilename = "vaultconfig.foo.baz";
String masterkeyFilename = "masterkey.foo.baz";
Path pathToVault = fs.getPath("/vaultDir");

Path vaultConfigFile = pathToVault.resolve(vaultConfigFilename);
Path masterkeyFile = pathToVault.resolve(masterkeyFilename);
Files.createDirectories(pathToVault);
Files.write(vaultConfigFile, new byte[0]);
Files.write(masterkeyFile, new byte[0]);

Assertions.assertFalse(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
}

@Test
public void testGetFileSystemInvokesFileSystemsGetWithPathToVaultFromUri() {
Path pathToVault = get("a").toAbsolutePath();
Expand Down
75 changes: 75 additions & 0 deletions src/test/java/org/cryptomator/cryptofs/DirStructureTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.cryptomator.cryptofs;

import org.cryptomator.cryptofs.common.Constants;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

public class DirStructureTest {

private static final String KEY = "key";
private static final String CONFIG = "config";

@TempDir
Path vaultPath;

@Test
public void testNonExistingVaultPathThrowsIOException() {
Path vaultPath = Path.of("this/certainly/does/not/exist");
Assumptions.assumeTrue(Files.notExists(vaultPath));

Assertions.assertThrows(IOException.class, () -> DirStructure.checkDirStructure(vaultPath, CONFIG, KEY));
}

@Test
public void testNonDirectoryVaultPathThrowsIOException() throws IOException {
Path tmp = vaultPath.resolve("this");
Files.createFile(tmp);
Assumptions.assumeTrue(Files.exists(tmp));

Assertions.assertThrows(IOException.class, () -> DirStructure.checkDirStructure(tmp, CONFIG, KEY));
}

@ParameterizedTest(name = "Testing all combinations of data dir, config and masterkey file existence.")
@MethodSource("provideAllCases")
public void testAllCombosOfDataAndConfigAndKey(boolean createDataDir, boolean createConfig, boolean createKey, DirStructure expectedResult) throws IOException {
Path keyPath = vaultPath.resolve(KEY);
Path configPath = vaultPath.resolve(CONFIG);
Path dataDir = vaultPath.resolve(Constants.DATA_DIR_NAME);

if (createDataDir) {
Files.createDirectory(dataDir);
}
if (createConfig) {
Files.createFile(configPath);
}
if (createKey) {
Files.createFile(keyPath);
}

Assertions.assertEquals(expectedResult, DirStructure.checkDirStructure(vaultPath, CONFIG, KEY));
}

private static Stream<Arguments> provideAllCases() {
return Stream.of(
Arguments.of(true, true, true, DirStructure.VAULT),
Arguments.of(true, true, false, DirStructure.VAULT),
Arguments.of(true, false, true, DirStructure.MAYBE_LEGACY),
Arguments.of(true, false, false, DirStructure.UNRELATED),
Arguments.of(false, false, false, DirStructure.UNRELATED),
Arguments.of(false, false, true, DirStructure.UNRELATED),
Arguments.of(false, true, false, DirStructure.UNRELATED),
Arguments.of(false, true, true, DirStructure.UNRELATED)
);
}

}

0 comments on commit cb6db8e

Please sign in to comment.