diff --git a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemCache.java b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemCache.java index 83ebb703..1c3172da 100644 --- a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemCache.java +++ b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemCache.java @@ -14,7 +14,6 @@ public class OpenFileSystemCache { private final OpenFileSystemModel model; private final Map installedApplications = new HashMap<>(); private String username; - private boolean canElevate; public OpenFileSystemCache(OpenFileSystemModel model) { this.model = model; @@ -24,7 +23,6 @@ public class OpenFileSystemCache { ShellControl sc = model.getFileSystem().getShell().get(); ShellDialect d = sc.getShellDialect(); username = sc.executeSimpleStringCommand(d.getPrintVariableCommand(d.getUsernameVariableName())); - canElevate = sc.checkCanElevate(); } public boolean isRoot() { diff --git a/app/src/main/java/io/xpipe/app/util/AskpassAlert.java b/app/src/main/java/io/xpipe/app/util/AskpassAlert.java index 0242de04..5fe5b504 100644 --- a/app/src/main/java/io/xpipe/app/util/AskpassAlert.java +++ b/app/src/main/java/io/xpipe/app/util/AskpassAlert.java @@ -8,7 +8,6 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.scene.control.Alert; import javafx.scene.layout.StackPane; -import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -16,22 +15,16 @@ import java.util.UUID; public class AskpassAlert { private static final Map requestToId = new HashMap<>(); - private static final Map passwords = new HashMap<>(); - - public static SecretValue query(String prompt, Object key) { - var rid = UUID.randomUUID(); - var secretId = UUID.nameUUIDFromBytes(ByteBuffer.allocate(4).putInt(key.hashCode()).array()); - return query(prompt, rid, secretId); - } public static SecretValue query(String prompt, UUID requestId, UUID secretId) { if (requestToId.containsKey(requestId)) { var id = requestToId.remove(requestId); - passwords.remove(id); + SecretCache.clear(id); } - if (passwords.containsKey(secretId)) { - return passwords.get(secretId); + var found = SecretCache.get(secretId); + if (found.isPresent()) { + return found.get(); } var prop = new SimpleObjectProperty(); @@ -54,8 +47,8 @@ public class AskpassAlert { // If the result is null, assume that the operation was aborted by the user if (r != null) { - passwords.put(secretId, r); requestToId.put(requestId, secretId); + SecretCache.set(secretId, r); } return r; diff --git a/app/src/main/java/io/xpipe/app/util/SecretCache.java b/app/src/main/java/io/xpipe/app/util/SecretCache.java new file mode 100644 index 00000000..53b22d9c --- /dev/null +++ b/app/src/main/java/io/xpipe/app/util/SecretCache.java @@ -0,0 +1,41 @@ +package io.xpipe.app.util; + +import io.xpipe.core.util.SecretValue; +import io.xpipe.core.util.UuidHelper; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class SecretCache { + + private static final Map passwords = new HashMap<>(); + + public static SecretValue retrieve(SecretRetrievalStrategy strategy, String prompt, Object key) throws Exception { + var id = UuidHelper.generateFromObject(key); + if (passwords.containsKey(id)) { + return passwords.get(id); + } + + if (strategy == null) { + return null; + } + + var pass = strategy.retrieve(prompt, id); + passwords.put(id, pass); + return pass; + } + + public static void clear(UUID id) { + passwords.remove(id); + } + + public static void set(UUID id, SecretValue value) { + passwords.put(id, value); + } + + public static Optional get(UUID id) { + return Optional.ofNullable(passwords.get(id)); + } +} diff --git a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java index 0b8fd762..0cfb37aa 100644 --- a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java +++ b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java @@ -6,13 +6,13 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.core.impl.LocalStore; -import io.xpipe.core.store.DataStore; import io.xpipe.core.util.SecretValue; import lombok.Builder; import lombok.Getter; import lombok.Value; import lombok.extern.jackson.Jacksonized; +import java.util.UUID; import java.util.function.Supplier; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @@ -26,20 +26,20 @@ import java.util.function.Supplier; }) public interface SecretRetrievalStrategy { - SecretValue retrieve(String displayName, DataStore store) throws Exception; + SecretValue retrieve(String displayName, UUID id) throws Exception; - boolean supportsLocalAskpass(); + boolean isLocalAskpassCompatible(); @JsonTypeName("none") public static class None implements SecretRetrievalStrategy { @Override - public SecretValue retrieve(String displayName, DataStore store) { + public SecretValue retrieve(String displayName, UUID id) { return null; } @Override - public boolean supportsLocalAskpass() { + public boolean isLocalAskpassCompatible() { return true; } } @@ -55,12 +55,12 @@ public interface SecretRetrievalStrategy { } @Override - public SecretValue retrieve(String displayName, DataStore store) { + public SecretValue retrieve(String displayName, UUID id) { return supplier.get(); } @Override - public boolean supportsLocalAskpass() { + public boolean isLocalAskpassCompatible() { return false; } } @@ -79,12 +79,12 @@ public interface SecretRetrievalStrategy { } @Override - public SecretValue retrieve(String displayName, DataStore store) { + public SecretValue retrieve(String displayName, UUID id) { return value; } @Override - public boolean supportsLocalAskpass() { + public boolean isLocalAskpassCompatible() { return false; } } @@ -93,12 +93,12 @@ public interface SecretRetrievalStrategy { public static class Prompt implements SecretRetrievalStrategy { @Override - public SecretValue retrieve(String displayName, DataStore store) { - return AskpassAlert.query(displayName, store); + public SecretValue retrieve(String displayName, UUID id) { + return AskpassAlert.query(displayName, UUID.randomUUID(), id); } @Override - public boolean supportsLocalAskpass() { + public boolean isLocalAskpassCompatible() { return true; } } @@ -112,7 +112,7 @@ public interface SecretRetrievalStrategy { String key; @Override - public SecretValue retrieve(String displayName, DataStore store) throws Exception { + public SecretValue retrieve(String displayName, UUID id) throws Exception { var cmd = AppPrefs.get().passwordManagerString(key); if (cmd == null) { return null; @@ -124,7 +124,7 @@ public interface SecretRetrievalStrategy { } @Override - public boolean supportsLocalAskpass() { + public boolean isLocalAskpassCompatible() { return false; } } @@ -138,14 +138,14 @@ public interface SecretRetrievalStrategy { String command; @Override - public SecretValue retrieve(String displayName, DataStore store) throws Exception { + public SecretValue retrieve(String displayName, UUID id) throws Exception { try (var cc = new LocalStore().createBasicControl().command(command).start()) { return SecretHelper.encrypt(cc.readStdoutOrThrow()); } } @Override - public boolean supportsLocalAskpass() { + public boolean isLocalAskpassCompatible() { return false; } } diff --git a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java index 8a8a39d0..450dd97f 100644 --- a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java +++ b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java @@ -42,7 +42,7 @@ public class SecretRetrievalStrategyHelper { .grow(false, true))) .apply(struc -> struc.get().setSpacing(10)); return new OptionsBuilder() - .name("command") + .name("passwordKey") .addComp(content, keyProperty) .bind( () -> { diff --git a/app/src/main/resources/io/xpipe/app/resources/lang/preferences_en.properties b/app/src/main/resources/io/xpipe/app/resources/lang/preferences_en.properties index 875a03dd..5d5a7f1e 100644 --- a/app/src/main/resources/io/xpipe/app/resources/lang/preferences_en.properties +++ b/app/src/main/resources/io/xpipe/app/resources/lang/preferences_en.properties @@ -6,6 +6,8 @@ editorProgram=Default Program editorProgramDescription=The default text editor to use when editing any kind of text data. useSystemFont=Use system font updates=Updates +passwordKey=Password key +command=Command advanced=Advanced thirdParty=Open source notices thirdPartyDescription=View the open source licenses of third-party libraries diff --git a/core/src/main/java/io/xpipe/core/process/ProcessControlProvider.java b/core/src/main/java/io/xpipe/core/process/ProcessControlProvider.java index 61b8dd76..e82221af 100644 --- a/core/src/main/java/io/xpipe/core/process/ProcessControlProvider.java +++ b/core/src/main/java/io/xpipe/core/process/ProcessControlProvider.java @@ -49,22 +49,6 @@ public abstract class ProcessControlProvider { .orElse(null); } - public static ShellControl createSsh(Object sshStore) { - return INSTANCES.stream() - .map(localProcessControlProvider -> localProcessControlProvider.createSshControl(sshStore)) - .filter(Objects::nonNull) - .findFirst() - .orElseThrow(); - } - - public static String createSshPreview(Object sshStore) { - return INSTANCES.stream() - .map(localProcessControlProvider -> localProcessControlProvider.createSshControlPreview(sshStore)) - .filter(Objects::nonNull) - .findFirst() - .orElseThrow(); - } - public abstract ShellControl sub( ShellControl parent, @NonNull FailableFunction commandFunction, @@ -77,7 +61,4 @@ public abstract class ProcessControlProvider { public abstract ShellControl createLocalProcessControl(boolean stoppable); - public abstract ShellControl createSshControl(Object sshStore); - - public abstract String createSshControlPreview(Object sshStore); } diff --git a/core/src/main/java/io/xpipe/core/process/ShellControl.java b/core/src/main/java/io/xpipe/core/process/ShellControl.java index 3e06be8c..507c5404 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellControl.java +++ b/core/src/main/java/io/xpipe/core/process/ShellControl.java @@ -94,8 +94,6 @@ public interface ShellControl extends ProcessControl { OsType getOsType(); - boolean checkCanElevate() throws Exception; - ShellControl elevated(String message, FailableFunction elevationFunction); default ShellControl elevationPassword(SecretValue value) {