Bladeren bron

unlock for health check

Sebastian Stenzel 4 jaren geleden
bovenliggende
commit
d2cd2c923d

+ 11 - 1
main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java

@@ -4,6 +4,7 @@ import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
 import dagger.multibindings.IntoMap;
+import org.cryptomator.common.vaults.Vault;
 import org.cryptomator.ui.common.DefaultSceneFactory;
 import org.cryptomator.ui.common.FxController;
 import org.cryptomator.ui.common.FxControllerKey;
@@ -11,6 +12,8 @@ import org.cryptomator.ui.common.FxmlFile;
 import org.cryptomator.ui.common.FxmlLoaderFactory;
 import org.cryptomator.ui.common.FxmlScene;
 import org.cryptomator.ui.common.StageFactory;
+import org.cryptomator.ui.keyloading.KeyLoadingComponent;
+import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
 import org.cryptomator.ui.mainwindow.MainWindow;
 
 import javax.inject.Provider;
@@ -20,9 +23,16 @@ import javafx.stage.Stage;
 import java.util.Map;
 import java.util.ResourceBundle;
 
-@Module
+@Module(subcomponents = {KeyLoadingComponent.class})
 abstract class HealthCheckModule {
 
+	@Provides
+	@HealthCheckWindow
+	@HealthCheckScoped
+	static KeyLoadingStrategy provideKeyLoadingStrategy(KeyLoadingComponent.Builder compBuilder, @HealthCheckWindow Vault vault, @HealthCheckWindow Stage window) {
+		return compBuilder.vault(vault).window(window).build().keyloadingStrategy();
+	}
+
 	@Provides
 	@HealthCheckWindow
 	@HealthCheckScoped

+ 76 - 5
main/ui/src/main/java/org/cryptomator/ui/health/StartController.java

@@ -1,26 +1,42 @@
 package org.cryptomator.ui.health;
 
 import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.cryptofs.VaultConfig;
+import org.cryptomator.cryptofs.VaultConfigLoadException;
+import org.cryptomator.cryptofs.VaultKeyInvalidException;
+import org.cryptomator.cryptolib.api.Masterkey;
+import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
 import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.fxapp.FxApplication;
+import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
+import org.cryptomator.ui.unlock.UnlockCancelledException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.inject.Inject;
+import javafx.application.Platform;
 import javafx.fxml.FXML;
 import javafx.stage.Stage;
+import java.net.URI;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
 
 @HealthCheckScoped
 public class StartController implements FxController {
 
 	private static final Logger LOG = LoggerFactory.getLogger(StartController.class);
 
-	private final Vault vault;
 	private final Stage window;
+	private final Optional<VaultConfig.UnverifiedVaultConfig> unverifiedVaultConfig;
+	private final KeyLoadingStrategy keyLoadingStrategy;
+	private final ExecutorService executor;
 
 	@Inject
-	public StartController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window) {
-		this.vault = vault;
+	public StartController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor) {
 		this.window = window;
+		this.unverifiedVaultConfig = vault.getUnverifiedVaultConfig();
+		this.keyLoadingStrategy = keyLoadingStrategy;
+		this.executor = executor;
 	}
 
 	@FXML
@@ -32,9 +48,64 @@ public class StartController implements FxController {
 	@FXML
 	public void next() {
 		LOG.trace("StartController.next()");
+		executor.submit(this::loadKey);
 	}
 
-	public Vault getVault() {
-		return vault;
+	private void loadKey() {
+		assert !Platform.isFxApplicationThread();
+		try (var masterkey = keyLoadingStrategy.masterkeyLoader().loadKey(unverifiedVaultConfig.orElseThrow().getKeyId())) {
+			var clone = masterkey.clone(); // original key will get destroyed
+			Platform.runLater(() -> loadedKey(clone));
+		} catch (MasterkeyLoadingFailedException e) {
+			if (keyLoadingStrategy.recoverFromException(e)) {
+				// retry
+				loadKey();
+			} else {
+				Platform.runLater(() -> loadingKeyFailed(e));
+			}
+		}
+	}
+
+	private void loadedKey(Masterkey masterkey) {
+		assert unverifiedVaultConfig.isPresent();
+		var unverifiedCfg = unverifiedVaultConfig.get();
+		try {
+			var verifiedCfg = unverifiedCfg.verify(masterkey.getEncoded(), unverifiedCfg.allegedVaultVersion());
+			LOG.info("Verified vault config with cipher {}", verifiedCfg.getCipherCombo());
+		} catch (VaultKeyInvalidException e) {
+			LOG.error("Invalid key");
+			// TODO show error screen
+		} catch (VaultConfigLoadException e) {
+			LOG.error("Failed to verify vault config", e);
+			// TODO show error screen
+		} finally {
+			masterkey.destroy();
+		}
+	}
+
+	private void loadingKeyFailed(MasterkeyLoadingFailedException e) {
+		if (e instanceof UnlockCancelledException) {
+			// ok
+		} else {
+			LOG.error("Failed to load key.", e);
+			// TODO show error screen
+		}
+	}
+
+	public boolean isInvalidConfig() {
+		return unverifiedVaultConfig.isEmpty();
+	}
+
+	public int getVaultVersion() {
+		return unverifiedVaultConfig
+				.map(VaultConfig.UnverifiedVaultConfig::allegedVaultVersion)
+				.orElse(-1);
+	}
+
+	public String getKeyId() {
+		return unverifiedVaultConfig
+				.map(VaultConfig.UnverifiedVaultConfig::getKeyId)
+				.map(URI::toString)
+				.orElse(null);
 	}
 }

+ 6 - 2
main/ui/src/main/resources/fxml/health_start.fxml

@@ -16,12 +16,16 @@
 		<Insets topRightBottomLeft="12"/>
 	</padding>
 	<children>
-		<Label text="${controller.vault.displayablePath}"/>
+		<Label text="${controller.keyId}"/>
+
+		<Label text="${controller.vaultVersion}"/>
+
+		<Label text="TODO: Invalid vault config" visible="${controller.invalidConfig}" managed="${controller.invalidConfig}"/>
 
 		<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
 			<buttons>
 				<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
-				<Button text="%unlock.unlockBtn" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#next"/>
+				<Button text="%unlock.unlockBtn" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.invalidConfig}" defaultButton="true" onAction="#next"/>
 			</buttons>
 		</ButtonBar>
 	</children>