Parcourir la source

- better handling of MAC auth fails, providing link to help page
- use random data as file size obfuscation padding
- fixed osx unmount error
- new attempt to close #41

Sebastian Stenzel il y a 10 ans
Parent
commit
188a13b202

+ 1 - 1
main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java

@@ -559,7 +559,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
 		// append a few blocks of fake data:
 		final int numberOfPlaintextBlocks = (int) Math.ceil(plaintextSize / AES_BLOCK_LENGTH);
 		final int upToTenPercentFakeBlocks = (int) Math.ceil(Math.random() * 0.1 * numberOfPlaintextBlocks);
-		final byte[] emptyBytes = new byte[AES_BLOCK_LENGTH];
+		final byte[] emptyBytes = this.randomData(AES_BLOCK_LENGTH);
 		for (int i = 0; i < upToTenPercentFakeBlocks; i += AES_BLOCK_LENGTH) {
 			blockSizeBufferedOut.write(emptyBytes);
 		}

+ 26 - 1
main/ui/src/main/java/org/cryptomator/ui/controllers/MacWarningsController.java

@@ -1,11 +1,16 @@
 package org.cryptomator.ui.controllers;
 
+import javafx.application.Application;
+import javafx.collections.ListChangeListener.Change;
 import javafx.collections.ObservableList;
+import javafx.collections.WeakListChangeListener;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.control.ListView;
 import javafx.stage.Stage;
 
+import javax.inject.Inject;
+
 public class MacWarningsController {
 
 	@FXML
@@ -13,13 +18,33 @@ public class MacWarningsController {
 
 	private Stage stage;
 
+	private final Application application;
+
+	@Inject
+	public MacWarningsController(Application application) {
+		this.application = application;
+	}
+
 	@FXML
-	private void hideWindow(ActionEvent event) {
+	private void didClickDismissButton(ActionEvent event) {
 		stage.hide();
 	}
 
+	@FXML
+	private void didClickMoreInformationButton(ActionEvent event) {
+		application.getHostServices().showDocument("https://cryptomator.org/help.html#macWarning");
+	}
+
 	public void setMacWarnings(ObservableList<String> macWarnings) {
 		this.warningsList.setItems(macWarnings);
+		this.warningsList.getItems().addListener(new WeakListChangeListener<String>(this::warningsDidChange));
+	}
+
+	// closes this window automatically, if all warnings disappeared (e.g. due to an unmount event)
+	private void warningsDidChange(Change<? extends String> change) {
+		if (change.getList().isEmpty()) {
+			stage.hide();
+		}
 	}
 
 	public Stage getStage() {

+ 2 - 0
main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java

@@ -51,6 +51,7 @@ import org.cryptomator.ui.controls.DirectoryListCell;
 import org.cryptomator.ui.model.Vault;
 import org.cryptomator.ui.model.VaultFactory;
 import org.cryptomator.ui.settings.Settings;
+import org.cryptomator.ui.util.ActiveWindowStyleSupport;
 import org.cryptomator.ui.util.ObservableSetAggregator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -336,6 +337,7 @@ public class MainController implements Initializable, InitializationListener, Un
 				stage.sizeToScene();
 				stage.setResizable(false);
 				stage.setOnHidden(this::onHideMacWarningsWindow);
+				ActiveWindowStyleSupport.startObservingFocus(stage);
 
 				final MacWarningsController ctrl = loader.getController();
 				ctrl.setMacWarnings(this.aggregatedMacWarnings);

+ 9 - 6
main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java

@@ -113,10 +113,7 @@ public class UnlockController implements Initializable {
 			Files.copy(masterKeyPath, masterKeyBackupPath, StandardCopyOption.REPLACE_EXISTING);
 			vault.setUnlocked(true);
 			final Future<Boolean> futureMount = exec.submit(() -> vault.mount());
-			FXThreads.runOnMainThreadWhenFinished(exec, futureMount, this::didUnlockAndMount);
-			FXThreads.runOnMainThreadWhenFinished(exec, futureMount, (result) -> {
-				setControlsDisabled(false);
-			});
+			FXThreads.runOnMainThreadWhenFinished(exec, futureMount, this::unlockAndMountFinished);
 		} catch (DecryptFailedException | IOException ex) {
 			setControlsDisabled(false);
 			progressIndicator.setVisible(false);
@@ -143,9 +140,15 @@ public class UnlockController implements Initializable {
 		unlockButton.setDisable(disable);
 	}
 
-	private void didUnlockAndMount(boolean mountSuccess) {
+	private void unlockAndMountFinished(boolean mountSuccess) {
 		progressIndicator.setVisible(false);
-		if (listener != null) {
+		setControlsDisabled(false);
+		if (vault.isUnlocked() && !mountSuccess) {
+			vault.getCryptor().swipeSensitiveData();
+			vault.stopServer();
+			vault.setUnlocked(false);
+		}
+		if (mountSuccess && listener != null) {
 			listener.didUnlock(this);
 		}
 	}

+ 2 - 0
main/ui/src/main/java/org/cryptomator/ui/controllers/WelcomeController.java

@@ -31,6 +31,7 @@ import javax.inject.Named;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.lang3.SystemUtils;
 
@@ -67,6 +68,7 @@ public class WelcomeController implements Initializable {
 	private void checkForUpdates() {
 		final HttpClient client = new HttpClient();
 		final HttpMethod method = new GetMethod("https://cryptomator.org/downloads/latestVersion.json");
+		client.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
 		client.getParams().setConnectionManagerTimeout(5000);
 		try {
 			client.executeMethod(method);

+ 1 - 1
main/ui/src/main/java/org/cryptomator/ui/util/mount/MacOsXWebDavMounter.java

@@ -38,7 +38,7 @@ final class MacOsXWebDavMounter implements WebDavMounterStrategy {
 				.addEnv("MOUNT_PATH", path)
 				.addEnv("MOUNT_NAME", name);
 		final Script unmountScript = Script.fromLines(
-				"umount $MOUNT_PATH")
+				"diskutil umount $MOUNT_PATH")
 				.addEnv("MOUNT_PATH", path);
 		mountScript.execute();
 		return new AbstractWebDavMount() {

+ 23 - 5
main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsWebDavMounter.java

@@ -30,6 +30,7 @@ import org.cryptomator.ui.util.command.Script;
 final class WindowsWebDavMounter implements WebDavMounterStrategy {
 
 	private static final Pattern WIN_MOUNT_DRIVELETTER_PATTERN = Pattern.compile("\\s*([A-Z]:)\\s*");
+	private static final int MAX_MOUNT_ATTEMPTS = 10;
 
 	@Override
 	public boolean shouldWork() {
@@ -50,11 +51,28 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
 
 	@Override
 	public WebDavMount mount(URI uri, String name) throws CommandFailedException {
-		final Script mountScript = fromLines("net use * http://0--1.ipv6-literal.net:%PORT%%DAV_PATH% /persistent:no")
-				.addEnv("PORT", String.valueOf(uri.getPort()))
-				.addEnv("DAV_PATH", uri.getRawPath());
-		final CommandResult mountResult = mountScript.execute(30, TimeUnit.SECONDS);
-		final String driveLetter = getDriveLetter(mountResult.getStdOut());
+		final Script mountScript = fromLines("net use * http://0--1.ipv6-literal.net:%PORT%%DAV_PATH% /persistent:no");
+		mountScript.addEnv("PORT", String.valueOf(uri.getPort())).addEnv("DAV_PATH", uri.getRawPath());
+		String driveLetter = null;
+		// The ugliness of the following 20 lines is solely windows' fault. Deal with it.
+		for (int i = 0; i < MAX_MOUNT_ATTEMPTS; i++) {
+			try {
+				final CommandResult mountResult = mountScript.execute(10, TimeUnit.SECONDS);
+				driveLetter = getDriveLetter(mountResult.getStdOut());
+				break;
+			} catch (CommandFailedException ex) {
+				if (i == MAX_MOUNT_ATTEMPTS - 1) {
+					throw ex;
+				} else {
+					try {
+						// retry after 500ms
+						Thread.sleep(500);
+					} catch (InterruptedException e) {
+						Thread.currentThread().interrupt();
+					}
+				}
+			}
+		}
 		final Script openExplorerScript = fromLines("start explorer.exe " + driveLetter);
 		openExplorerScript.execute();
 		final Script unmountScript = fromLines("net use " + driveLetter + " /delete").addEnv("DRIVE_LETTER", driveLetter);

+ 8 - 2
main/ui/src/main/resources/fxml/mac_warnings.fxml

@@ -13,15 +13,21 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.HBox?>
 
-<VBox alignment="CENTER" prefHeight="225.0" prefWidth="525.0" spacing="12.0" fx:controller="org.cryptomator.ui.controllers.MacWarningsController" xmlns:fx="http://javafx.com/fxml">
+<VBox styleClass="root" alignment="CENTER" prefHeight="225.0" prefWidth="525.0" spacing="12.0" fx:controller="org.cryptomator.ui.controllers.MacWarningsController" xmlns:fx="http://javafx.com/fxml">
 
 	<padding><Insets top="12.0" right="12.0" bottom="12.0" left="12.0"/></padding>
 
 	<children>
 		<Label textAlignment="CENTER" text="%macWarnings.message"/>
 		<ListView fx:id="warningsList" VBox.vgrow="ALWAYS" focusTraversable="false" />
-		<Button text="%macWarnings.okButton" defaultButton="true" prefWidth="150.0" onAction="#hideWindow" />
+		<HBox alignment="CENTER_RIGHT" spacing="12.0">
+			<children>
+				<Button text="%macWarnings.dismissButton" prefWidth="200.0" onAction="#didClickDismissButton" focusTraversable="false"/>
+				<Button text="%macWarnings.moreInformationButton" defaultButton="true" prefWidth="200.0" onAction="#didClickMoreInformationButton" focusTraversable="false"/>
+			</children>
+		</HBox>
 	</children>
 
 </VBox>

+ 3 - 2
main/ui/src/main/resources/localization.properties

@@ -49,9 +49,10 @@ unlocked.button.lock=Lock vault
 unlocked.ioGraph.yAxis.label=Throughput (MiB/s)
 
 # mac_warnings.fxml
-macWarnings.windowTitle=MAC authentication failed
+macWarnings.windowTitle=Danger - MAC authentication failed
 macWarnings.message=Cryptomator detected potentially malicious corruptions in the following files:
-macWarnings.okButton=I'll be careful
+macWarnings.moreInformationButton=Learn more
+macWarnings.dismissButton=I promise to be careful
 
 # tray icon
 tray.menu.open=Open