Handle mstsc better

This commit is contained in:
crschnick
2026-09-15 18:29:18 +00:00
parent 2a16911dac
commit 2ab0230b34
3 changed files with 51 additions and 22 deletions
@@ -25,6 +25,7 @@ import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.prefs.WorkspaceManager;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.rdp.MicrosoftRdpClient;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageMigratedDialog;
import io.xpipe.app.storage.DataStorageSyncHandler;
@@ -220,6 +221,7 @@ public class AppBaseMode extends AppOperationMode {
AppMcpServer.reset();
WorkspaceManager.reset();
RemoteDesktopWindow.reset();
MicrosoftRdpClient.reset();
AppPrefs.reset();
DataStorage.reset();
DataStorageSyncHandler.getInstance().reset();
@@ -10,6 +10,7 @@ import io.xpipe.app.platform.OptionsBuilder;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.prefs.ExternalApplicationType;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.secret.InPlaceSecretValue;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.*;
@@ -25,9 +26,7 @@ import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;
import java.time.Duration;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@SuperBuilder(toBuilder = true)
@@ -148,6 +147,16 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst
private static final int CRED_TYPE_GENERIC = 1;
private static final int CRED_TYPE_DOMAIN_PASSWORD = 2;
private static final int CRED_PERSIST_SESSION = 1;
private static final Set<String> storedCredentials = new HashSet<String>();
public static void reset() {
synchronized (storedCredentials) {
for (String s : storedCredentials) {
AuthModuleProvider.get().deleteWindowsCredential(s, CRED_PERSIST_SESSION);
}
}
}
@Override
public void launch(RdpLaunchConfig configuration) throws Exception {
@@ -185,25 +194,33 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst
disableSignatureWarning(configuration);
if (configuration.getPassword() != null) {
AuthModuleProvider.get()
.setWindowsCredential(
"TERMSRV/" + configuration.getHost(),
CRED_TYPE_GENERIC,
CRED_PERSIST_SESSION,
configuration.getUsername(),
configuration.getPassword());
}
synchronized (storedCredentials) {
if (configuration.getPassword() != null) {
String target = "TERMSRV/" + configuration.getHost();
var gateway = configuration.getGateway();
if (gateway != null && gateway.getPassword() != null) {
AuthModuleProvider.get()
.setWindowsCredential(
gateway.getHost(),
CRED_TYPE_GENERIC,
CRED_PERSIST_SESSION,
gateway.getUsername(),
gateway.getPassword());
var existing = AuthModuleProvider.get().getWindowsCredential(target, CRED_TYPE_GENERIC);
if (existing.isPresent()) {
AuthModuleProvider.get().setWindowsCredential(target, CRED_TYPE_GENERIC, CRED_PERSIST_SESSION, configuration.getUsername(),
configuration.getPassword());
storedCredentials.add(target);
}
GlobalTimer.delay(() -> {
AuthModuleProvider.get().deleteWindowsCredential(target, CRED_PERSIST_SESSION);
}, Duration.ofSeconds(120));
}
var gateway = configuration.getGateway();
if (gateway != null && gateway.getPassword() != null) {
String target = gateway.getHost();
AuthModuleProvider.get().setWindowsCredential(target, CRED_TYPE_GENERIC, CRED_PERSIST_SESSION, gateway.getUsername(),
gateway.getPassword());
storedCredentials.add(target);
GlobalTimer.delay(() -> {
AuthModuleProvider.get().deleteWindowsCredential(target, CRED_PERSIST_SESSION);
}, Duration.ofSeconds(120));
}
}
var file = writeRdpConfigFile(configuration.getTitle(), adaptedRdpConfig);
@@ -267,6 +284,16 @@ public abstract class MicrosoftRdpClient implements ExternalApplicationType.Inst
private RdpConfig getAdaptedConfig(RdpLaunchConfig configuration) {
var input = configuration.getConfig();
var pass = configuration.getPassword();
// Use existing pw if possible and needed
if (pass == null) {
String target = "TERMSRV/" + configuration.getHost();
var existing = AuthModuleProvider.get().getWindowsCredential(target, CRED_TYPE_GENERIC);
if (existing.isPresent()) {
pass = InPlaceSecretValue.of(existing.get().getPassword());
}
}
var adapted = input.overlay(Map.of(
"prompt for credentials",
new RdpConfig.TypedValue("i", pass != null ? "0" : "1"),
@@ -176,7 +176,7 @@ public class RemoteDesktopWindow {
}
public void focus() {
PlatformThread.runLaterIfNeeded(() -> {
ThreadHelper.runFailableAsync(() -> {
model.focus();
});
}