|
@@ -2,6 +2,13 @@ package org.cryptomator.ui.recoverykey;
|
|
|
|
|
|
import dagger.Lazy;
|
|
|
import org.cryptomator.common.vaults.Vault;
|
|
|
+import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
|
|
+import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
|
|
+import org.cryptomator.cryptolib.api.CryptoException;
|
|
|
+import org.cryptomator.cryptolib.api.CryptorProvider;
|
|
|
+import org.cryptomator.cryptolib.api.Masterkey;
|
|
|
+import org.cryptomator.cryptolib.api.MasterkeyLoader;
|
|
|
+import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
|
|
|
import org.cryptomator.ui.common.FxController;
|
|
|
import org.cryptomator.ui.common.FxmlFile;
|
|
|
import org.cryptomator.ui.common.FxmlScene;
|
|
@@ -18,8 +25,17 @@ import javafx.fxml.FXML;
|
|
|
import javafx.scene.Scene;
|
|
|
import javafx.stage.Stage;
|
|
|
import java.io.IOException;
|
|
|
+import java.nio.file.CopyOption;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.StandardCopyOption;
|
|
|
+import java.util.Comparator;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
|
|
+import static org.cryptomator.common.Constants.DEFAULT_KEY_ID;
|
|
|
+import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
|
|
+import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
|
|
+
|
|
|
@RecoveryKeyScoped
|
|
|
public class RecoveryKeyResetPasswordController implements FxController {
|
|
|
|
|
@@ -32,11 +48,12 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
|
|
private final StringProperty recoveryKey;
|
|
|
private final Lazy<Scene> recoverResetPasswordSuccessScene;
|
|
|
private final FxApplicationWindows appWindows;
|
|
|
+ private final MasterkeyFileAccess masterkeyFileAccess;
|
|
|
|
|
|
public NewPasswordController newPasswordController;
|
|
|
|
|
|
@Inject
|
|
|
- public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, @FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD_SUCCESS) Lazy<Scene> recoverResetPasswordSuccessScene, FxApplicationWindows appWindows) {
|
|
|
+ public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, @FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD_SUCCESS) Lazy<Scene> recoverResetPasswordSuccessScene, FxApplicationWindows appWindows, MasterkeyFileAccess masterkeyFileAccess) {
|
|
|
this.window = window;
|
|
|
this.vault = vault;
|
|
|
this.recoveryKeyFactory = recoveryKeyFactory;
|
|
@@ -44,6 +61,7 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
|
|
this.recoveryKey = recoveryKey;
|
|
|
this.recoverResetPasswordSuccessScene = recoverResetPasswordSuccessScene;
|
|
|
this.appWindows = appWindows;
|
|
|
+ this.masterkeyFileAccess = masterkeyFileAccess;
|
|
|
}
|
|
|
|
|
|
@FXML
|
|
@@ -53,19 +71,60 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
|
|
|
|
|
@FXML
|
|
|
public void resetPassword() {
|
|
|
- Task<Void> task = new ResetPasswordTask();
|
|
|
- task.setOnScheduled(event -> {
|
|
|
- LOG.debug("Using recovery key to reset password for {}.", vault.getDisplayablePath());
|
|
|
- });
|
|
|
- task.setOnSucceeded(event -> {
|
|
|
- LOG.info("Used recovery key to reset password for {}.", vault.getDisplayablePath());
|
|
|
- window.setScene(recoverResetPasswordSuccessScene.get());
|
|
|
- });
|
|
|
- task.setOnFailed(event -> {
|
|
|
- LOG.error("Resetting password failed.", task.getException());
|
|
|
- appWindows.showErrorWindow(task.getException(), window, null);
|
|
|
- });
|
|
|
- executor.submit(task);
|
|
|
+ if(vault.isMissingVaultConfig()){
|
|
|
+ Path vaultPath = vault.getPath();
|
|
|
+ Path recoveryPath = vaultPath.resolve("r");
|
|
|
+ try {
|
|
|
+ Files.createDirectory(recoveryPath);
|
|
|
+ recoveryKeyFactory.newMasterkeyFileWithPassphrase(recoveryPath, recoveryKey.get(), newPasswordController.passwordField.getCharacters());
|
|
|
+ } catch (IOException e) {
|
|
|
+ LOG.error("Creating directory or recovering masterkey failed", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ Path masterkeyFilePath = recoveryPath.resolve(MASTERKEY_FILENAME);
|
|
|
+ try (Masterkey masterkey = masterkeyFileAccess.load(masterkeyFilePath, newPasswordController.passwordField.getCharacters())) {
|
|
|
+ try {
|
|
|
+ MasterkeyLoader loader = ignored -> masterkey.copy();
|
|
|
+ CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() //
|
|
|
+ .withCipherCombo(CryptorProvider.Scheme.SIV_CTRMAC) //
|
|
|
+ .withKeyLoader(loader) //
|
|
|
+ .withShorteningThreshold(220) //
|
|
|
+ .build();
|
|
|
+ CryptoFileSystemProvider.initialize(recoveryPath, fsProps, DEFAULT_KEY_ID);
|
|
|
+ } catch (CryptoException | IOException e) {
|
|
|
+ LOG.error("Recovering vault failed", e);
|
|
|
+ }
|
|
|
+ Files.move(masterkeyFilePath, vaultPath.resolve(MASTERKEY_FILENAME), StandardCopyOption.REPLACE_EXISTING);
|
|
|
+ Files.move(recoveryPath.resolve(VAULTCONFIG_FILENAME), vaultPath.resolve(VAULTCONFIG_FILENAME));
|
|
|
+ try (var paths = Files.walk(recoveryPath)) {
|
|
|
+ paths.sorted(Comparator.reverseOrder()).forEach(p -> {
|
|
|
+ try {
|
|
|
+ Files.delete(p);
|
|
|
+ } catch (IOException e) {
|
|
|
+ LOG.info("Unable to delete {}. Please delete it manually.", p);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ window.setScene(recoverResetPasswordSuccessScene.get());
|
|
|
+ } catch (IOException e) {
|
|
|
+ LOG.error("Moving recovered files failed", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ Task<Void> task = new ResetPasswordTask();
|
|
|
+ task.setOnScheduled(event -> {
|
|
|
+ LOG.debug("Using recovery key to reset password for {}.", vault.getDisplayablePath());
|
|
|
+ });
|
|
|
+ task.setOnSucceeded(event -> {
|
|
|
+ LOG.info("Used recovery key to reset password for {}.", vault.getDisplayablePath());
|
|
|
+ window.setScene(recoverResetPasswordSuccessScene.get());
|
|
|
+ });
|
|
|
+ task.setOnFailed(event -> {
|
|
|
+ LOG.error("Resetting password failed.", task.getException());
|
|
|
+ appWindows.showErrorWindow(task.getException(), window, null);
|
|
|
+ });
|
|
|
+ executor.submit(task);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private class ResetPasswordTask extends Task<Void> {
|