diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index a7e85a2..27b3f3e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -10,14 +10,12 @@ jobs:
#This check is case insensitive
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
outputs:
- artifact-version: ${{ steps.setversion.outputs.version }}
- env:
- BUILD_VERSION: SNAPSHOT
+ artifactVersion: ${{ steps.setversion.outputs.version }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
- java-version: 14
+ java-version: 17
- uses: actions/cache@v1
with:
path: ~/.m2/repository
@@ -27,18 +25,17 @@ jobs:
- name: Ensure to use tagged version
run: mvn versions:set --file ./pom.xml -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
if: startsWith(github.ref, 'refs/tags/')
- - name: Export the project version to the job environment and fix it as an ouput of this job
+ - name: Output project version
id: setversion
run: |
- v=$(mvn help:evaluate "-Dexpression=project.version" -q -DforceStdout)
- echo "::set-env name=BUILD_VERSION::${v}"
- echo "::set-output name=version::${v}"
+ BUILD_VERSION=$(mvn help:evaluate "-Dexpression=project.version" -q -DforceStdout)
+ echo "::set-output name=version::${BUILD_VERSION}"
- name: Build and Test
run: mvn -B install
- - name: Upload snapshot artifact cryptomator-cli-${{ env.BUILD_VERSION }}.jar
+ - name: Upload artifact cryptomator-cli-${{ steps.setversion.outputs.version }}.jar
uses: actions/upload-artifact@v2
with:
- name: cryptomator-cli-${{ env.BUILD_VERSION }}.jar
+ name: cryptomator-cli-${{ steps.setversion.outputs.version }}.jar
path: target/cryptomator-cli-*.jar
release:
@@ -50,7 +47,7 @@ jobs:
- name: Download cryptomator-cli.jar
uses: actions/download-artifact@v1
with:
- name: cryptomator-cli-${{ needs.build.outputs.artifact-version }}.jar
+ name: cryptomator-cli-${{ needs.build.outputs.artifactVersion }}.jar
path: .
- name: Create Release
id: create_release
@@ -64,12 +61,12 @@ jobs:
:construction: Work in Progress
draft: true
prerelease: false
- - name: Upload cryptomator-cli-${{ needs.build.outputs.artifact-version }}.jar to GitHub Releases
+ - name: Upload cryptomator-cli-${{ needs.build.outputs.artifactVersion }}.jar to GitHub Releases
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
- asset_path: cryptomator-cli-${{ needs.build.outputs.artifact-version }}.jar
- asset_name: cryptomator-cli-${{ needs.build.outputs.artifact-version }}.jar
+ asset_path: cryptomator-cli-${{ needs.build.outputs.artifactVersion }}.jar
+ asset_name: cryptomator-cli-${{ needs.build.outputs.artifactVersion }}.jar
asset_content_type: application/jar
diff --git a/README.md b/README.md
index e6dd37a..232ae86 100644
--- a/README.md
+++ b/README.md
@@ -15,4 +15,4 @@ This project is a fork of https://github.com/cryptomator/cli and currently, it a
lead to data loss.
5. A saner API when unlocking a single vault and the example is:
-```java -jar cryptomator-cli.jar --vault $VAULT_PATH --fusemount $MOUNT_PATH --mountFlags $FUSE_OPTIONS```
+```java -jar cryptomator-cli.jar --vault $VAULT_PATH --fusemount $MOUNT_PATH --mountFlags $FUSE_OPTIONS```
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 6b4d59e..2efc757 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,19 +2,19 @@
4.0.0
org.cryptomator
cli
- 0.5.0-SNAPSHOT
+ 0.5.1
Cryptomator CLI
Command line program to access encrypted files via WebDAV.
https://github.com/cryptomator/cli
- 1.9.10
- 1.0.11
- 1.4
- 1.2.3
- 1.2.4
+ 2.3.1
+ 1.2.6
+ 1.5.0
+ 1.2.9
+ 1.3.3
- 11
+ 17
UTF-8
diff --git a/src/main/java/org/cryptomator/cli/CryptomatorCli.java b/src/main/java/org/cryptomator/cli/CryptomatorCli.java
index 5b2df06..2e1440b 100644
--- a/src/main/java/org/cryptomator/cli/CryptomatorCli.java
+++ b/src/main/java/org/cryptomator/cli/CryptomatorCli.java
@@ -17,13 +17,17 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Optional;
import java.util.Set;
+import com.google.common.base.Preconditions;
import org.apache.commons.cli.ParseException;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
+import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,6 +59,9 @@ public class CryptomatorCli {
private static final Logger LOG = LoggerFactory.getLogger(CryptomatorCli.class);
+ private static final byte[] PEPPER = new byte[0];
+ private static final String SCHEME = "masterkeyfile";
+
public static void main(String[] rawArgs) throws IOException {
try {
if (rawArgs.length==1 && strEq(rawArgs[0], "--version")) {
@@ -102,12 +109,27 @@ private static void startup(Args args) throws IOException {
Optional server = initWebDavServer(args);
ArrayList mounts = new ArrayList<>();
ArrayList mInfo = new ArrayList<>();
+
+ SecureRandom secureRandom;
+ try {
+ secureRandom = SecureRandom.getInstanceStrong();
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalStateException("A strong algorithm must exist in every Java platform.", e);
+ }
+ MasterkeyFileAccess masterkeyFileAccess = new MasterkeyFileAccess(PEPPER, secureRandom);
+
for (String vaultName : args.getVaultNames()) {
Path vaultPath = Paths.get(args.getVaultPath(vaultName));
LOG.info("Unlocking vault \"{}\" located at {}", vaultName, vaultPath);
String vaultPassword = args.getPasswordStrategy(vaultName).password();
CryptoFileSystemProperties properties = CryptoFileSystemProperties.cryptoFileSystemProperties()
- .withPassphrase(vaultPassword).build();
+ .withKeyLoader(keyId -> {
+ Preconditions.checkArgument(SCHEME.equalsIgnoreCase(keyId.getScheme()), "Only supports keys with scheme " + SCHEME);
+ Path keyFilePath = vaultPath.resolve(keyId.getSchemeSpecificPart());
+ return masterkeyFileAccess.load(keyFilePath, vaultPassword);
+ })
+ .build();
+
Path vaultRoot = CryptoFileSystemProvider.newFileSystem(vaultPath, properties).getPath("/");
Path fuseMountPoint = args.getFuseMountPoint(vaultName);
@@ -177,16 +199,34 @@ private static boolean hasActiveMount(ArrayList localList) {
}
private static void listenForUnMountEvents(ArrayList mounts) {
- while (true){
- if (hasActiveMount(mounts)){
+ while (true) {
+ if (hasActiveMount(mounts)) {
sleep(2);
- }else{
+ } else {
LOG.info("All vaults are locked, exiting");
break;
}
}
}
+ private static void waitForShutdown(Runnable runnable) {
+ Runtime.getRuntime().addShutdownHook(new Thread(runnable));
+ LOG.info("Press Ctrl+C to terminate.");
+
+ // Block the main thread infinitely as otherwise when using
+ // Fuse mounts the application quits immediately.
+ try {
+ Object mainThreadBlockLock = new Object();
+ synchronized (mainThreadBlockLock) {
+ while (true) {
+ mainThreadBlockLock.wait();
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Main thread blocking failed.");
+ }
+ }
+
private static void sleep(int interval) {
try {
Object mainThreadBlockLock = new Object();
diff --git a/src/main/java/org/cryptomator/cli/frontend/FuseMount.java b/src/main/java/org/cryptomator/cli/frontend/FuseMount.java
index 46f10bb..34b6d8c 100644
--- a/src/main/java/org/cryptomator/cli/frontend/FuseMount.java
+++ b/src/main/java/org/cryptomator/cli/frontend/FuseMount.java
@@ -4,8 +4,8 @@
import java.util.Arrays;
import java.util.ArrayList;
-import org.cryptomator.frontend.fuse.mount.CommandFailedException;
import org.cryptomator.frontend.fuse.mount.EnvironmentVariables;
+import org.cryptomator.frontend.fuse.mount.FuseMountException;
import org.cryptomator.frontend.fuse.mount.FuseMountFactory;
import org.cryptomator.frontend.fuse.mount.Mount;
import org.cryptomator.frontend.fuse.mount.Mounter;
@@ -40,28 +40,32 @@ public boolean mount() {
try {
Mounter mounter = FuseMountFactory.getMounter();
- EnvironmentVariables envVars ;
-
+ String[] parsedMountFlags;
if (mountFlags != null) {
- ArrayList defaultMountFlags = new ArrayList(Arrays.asList(mounter.defaultMountFlags()));
+ ArrayList defaultMountFlags = new ArrayList(Arrays.asList(mounter.defaultMountFlags()));
for (String it : mountFlags.split(",")) {
- String m = it.replace(' ','=');
- m = m.replace(encodeCharacterToString('='), "=");
- defaultMountFlags.add("-o"+m);
+ defaultMountFlags.add(
+ "-o"+it
+ .replace(' ','=')
+ .replace(encodeCharacterToString('='), "=")
+ );
}
- String[] newMountFlags = defaultMountFlags.toArray(new String[defaultMountFlags.size()]);
- envVars = EnvironmentVariables.create().withFlags(newMountFlags)
- .withMountPoint(mountPoint).build();
+ parsedMountFlags = defaultMountFlags.toArray(new String[defaultMountFlags.size()]);
}else{
- envVars = EnvironmentVariables.create().withFlags(mounter.defaultMountFlags())
- .withMountPoint(mountPoint).build();
+ parsedMountFlags = mounter.defaultMountFlags();
}
+ EnvironmentVariables envVars = EnvironmentVariables.create() //
+ .withFlags(parsedMountFlags) //
+ .withFileNameTranscoder(mounter.defaultFileNameTranscoder()) //
+ .withMountPoint(mountPoint).build();
+
+
mnt = mounter.mount(vaultRoot, envVars);
LOG.info("Mounted to {}", mountPoint);
LOG.info("Run fusermount -u \"{}\" to unmount", mountPoint);
- } catch (CommandFailedException e) {
+ } catch (FuseMountException e) {
LOG.error("Can't mount: {}, error: {}", mountPoint, e.getMessage());
return false;
}
@@ -72,7 +76,7 @@ public void unmount() {
try {
mnt.unmount();
LOG.info("Unmounted {}", mountPoint);
- } catch (CommandFailedException e) {
+ } catch (FuseMountException e) {
LOG.error("Can't unmount gracefully: {}. Force unmount.", e.getMessage());
forceUnmount();
}
@@ -82,7 +86,7 @@ private void forceUnmount() {
try {
mnt.unmountForced();
LOG.info("Unmounted {}", mountPoint);
- } catch (CommandFailedException e) {
+ } catch (FuseMountException e) {
LOG.error("Force unmount failed: {}", e.getMessage());
}
}