mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-22 04:31:27 +00:00
Feature: Use system certificate stores/custom pkcs12 file (#3675)
* for Windows use Windows certificate * for macOS use macOS Keychain * for Linux use a custom PKCS12 file under /etc/cryptomator/certs.p12
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import ch.qos.logback.classic.spi.Configurator;
|
||||
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
|
||||
import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider;
|
||||
@@ -13,6 +14,9 @@ import org.cryptomator.common.locationpresets.OneDriveLinuxLocationPresetsProvid
|
||||
import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
|
||||
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
|
||||
import org.cryptomator.networking.SSLContextWithMacKeychain;
|
||||
import org.cryptomator.networking.SSLContextProvider;
|
||||
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
|
||||
import org.cryptomator.integrations.tray.TrayMenuController;
|
||||
import org.cryptomator.logging.LogbackConfiguratorFactory;
|
||||
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
||||
@@ -54,9 +58,11 @@ open module org.cryptomator.desktop {
|
||||
requires com.github.benmanes.caffeine;
|
||||
|
||||
uses org.cryptomator.common.locationpresets.LocationPresetsProvider;
|
||||
uses SSLContextProvider;
|
||||
|
||||
provides TrayMenuController with AwtTrayMenuController;
|
||||
provides Configurator with LogbackConfiguratorFactory;
|
||||
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;
|
||||
provides LocationPresetsProvider with //
|
||||
DropboxWindowsLocationPresetsProvider, DropboxMacLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, //
|
||||
GoogleDriveMacLocationPresetsProvider, GoogleDriveWindowsLocationPresetsProvider, //
|
||||
|
||||
@@ -9,8 +9,9 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import dagger.Lazy;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.SubstitutingProperties;
|
||||
import org.cryptomator.common.ShutdownHook;
|
||||
import org.cryptomator.common.SubstitutingProperties;
|
||||
import org.cryptomator.networking.SSLContextProvider;
|
||||
import org.cryptomator.ipc.IpcCommunicator;
|
||||
import org.cryptomator.logging.DebugMode;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||
@@ -19,8 +20,10 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -48,14 +51,16 @@ public class Cryptomator {
|
||||
private final Environment env;
|
||||
private final Lazy<IpcMessageHandler> ipcMessageHandler;
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final SecureRandom csprng;
|
||||
|
||||
@Inject
|
||||
Cryptomator(DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy<IpcMessageHandler> ipcMessageHandler, ShutdownHook shutdownHook) {
|
||||
Cryptomator(DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy<IpcMessageHandler> ipcMessageHandler, ShutdownHook shutdownHook, SecureRandom csprng) {
|
||||
this.debugMode = debugMode;
|
||||
this.supportedLanguages = supportedLanguages;
|
||||
this.env = env;
|
||||
this.ipcMessageHandler = ipcMessageHandler;
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.csprng = csprng;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -89,7 +94,7 @@ public class Cryptomator {
|
||||
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
|
||||
debugMode.initialize();
|
||||
supportedLanguages.applyPreferred();
|
||||
|
||||
changeDefaultSSLContext();
|
||||
/*
|
||||
* Attempts to create an IPC connection to a running Cryptomator instance and sends it the given args.
|
||||
* If no external process could be reached, the args will be handled by the loopback IPC endpoint.
|
||||
@@ -115,6 +120,17 @@ public class Cryptomator {
|
||||
}
|
||||
}
|
||||
|
||||
private void changeDefaultSSLContext() {
|
||||
SSLContextProvider.loadAll().findFirst().ifPresent(p -> {
|
||||
try {
|
||||
var context = p.getContext(csprng);
|
||||
SSLContext.setDefault(context);
|
||||
} catch (SSLContextProvider.SSLContextBuildException e) {
|
||||
LOG.warn("Failed to change default SSL context with provider {}", p.getClass().getName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the JavaFX application, blocking the main thread until shuts down.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.cryptomator.networking;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
||||
|
||||
abstract KeyStore getTruststore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException;
|
||||
|
||||
@Override
|
||||
public SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException {
|
||||
try {
|
||||
KeyStore truststore = getTruststore();
|
||||
truststore.load(null, null);
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(truststore);
|
||||
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, tmf.getTrustManagers(), csprng);
|
||||
return context;
|
||||
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | KeyManagementException | IOException e) {
|
||||
throw new SSLContextBuildException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.cryptomator.networking;
|
||||
|
||||
import org.cryptomator.integrations.common.IntegrationsLoader;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface SSLContextProvider {
|
||||
|
||||
SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException;
|
||||
|
||||
class SSLContextBuildException extends Exception {
|
||||
|
||||
SSLContextBuildException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<SSLContextProvider> loadAll() {
|
||||
return IntegrationsLoader.loadAll(ServiceLoader.load(SSLContextProvider.class), SSLContextProvider.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.cryptomator.networking;
|
||||
|
||||
import org.cryptomator.integrations.common.OperatingSystem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
/**
|
||||
* SSLContextProvider for macOS using the macOS Keychain as truststore
|
||||
*/
|
||||
@OperatingSystem(OperatingSystem.Value.MAC)
|
||||
public class SSLContextWithMacKeychain extends SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
||||
|
||||
@Override
|
||||
KeyStore getTruststore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
|
||||
return KeyStore.getInstance("KeychainStore-ROOT");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.cryptomator.networking;
|
||||
|
||||
import org.cryptomator.integrations.common.CheckAvailability;
|
||||
import org.cryptomator.integrations.common.OperatingSystem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* SSLContextProvider for Linux using a PKCS#12 file as trust store
|
||||
*/
|
||||
@OperatingSystem(OperatingSystem.Value.LINUX)
|
||||
@CheckAvailability
|
||||
public class SSLContextWithPKCS12TrustStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
||||
|
||||
private static final String CERT_FILE_LOCATION_PROPERTY = "cryptomator.networking.truststore.p12Path";
|
||||
|
||||
@Override
|
||||
KeyStore getTruststore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
|
||||
var pkcs12FilePath = Path.of(System.getProperty(CERT_FILE_LOCATION_PROPERTY));
|
||||
try {
|
||||
return KeyStore.getInstance(pkcs12FilePath.toFile(), new char[]{});
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new NoSuchFileException(pkcs12FilePath.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@CheckAvailability
|
||||
public static boolean isSupported() {
|
||||
var pkcs12Path = System.getProperty(CERT_FILE_LOCATION_PROPERTY);
|
||||
return Optional.ofNullable(pkcs12Path) //
|
||||
.map(Path::of) //
|
||||
.map(Files::exists).orElse(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.cryptomator.networking;
|
||||
|
||||
import org.cryptomator.integrations.common.OperatingSystem;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
|
||||
/**
|
||||
* SSLContextProvider for Windows using the Windows certificate store as trust store
|
||||
* <p>
|
||||
* In order to work, the jdk.crypto.mscapi jmod is needed
|
||||
*/
|
||||
@OperatingSystem(OperatingSystem.Value.WINDOWS)
|
||||
public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
||||
|
||||
@Override
|
||||
KeyStore getTruststore() throws KeyStoreException {
|
||||
return KeyStore.getInstance("WINDOWS-ROOT");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user