Compare commits

..

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
5b59518364 Fix RDP connections for AD Protected Users by supporting Kerberos-only modes
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2026-02-25 17:37:30 +00:00
copilot-swe-agent[bot]
ba72c1666c Initial plan 2026-02-25 17:28:12 +00:00
5 changed files with 26 additions and 41 deletions

View File

@@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AWSSDK.Core" Version="4.0.3.15" />
<PackageVersion Include="AWSSDK.EC2" Version="4.0.77" />
<PackageVersion Include="AWSSDK.EC2" Version="4.0.76.1" />
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.6.2" />
<PackageVersion Include="Castle.Core" Version="5.2.1" />
<PackageVersion Include="ConsoleControl" Version="1.3.0" />

View File

@@ -641,20 +641,27 @@ namespace mRemoteNG.Connection.Protocol.RDP
_rdpClient.UserName = userName;
}
if (string.IsNullOrEmpty(password))
// Restricted Admin and Remote Credential Guard modes use the current user's Kerberos
// credentials and do not forward explicit passwords to the remote host.
// Skipping password assignment avoids potential NTLM fallback attempts that would
// fail for accounts in the AD Protected Users security group.
if (!connectionInfo.UseRestrictedAdmin && !connectionInfo.UseRCG)
{
if (Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
if (string.IsNullOrEmpty(password))
{
if (Properties.OptionsCredentialsPage.Default.DefaultPassword != "")
if (Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
{
LegacyRijndaelCryptographyProvider cryptographyProvider = new();
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Properties.OptionsCredentialsPage.Default.DefaultPassword, Runtime.EncryptionKey);
if (Properties.OptionsCredentialsPage.Default.DefaultPassword != "")
{
LegacyRijndaelCryptographyProvider cryptographyProvider = new();
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Properties.OptionsCredentialsPage.Default.DefaultPassword, Runtime.EncryptionKey);
}
}
}
}
else
{
_rdpClient.AdvancedSettings2.ClearTextPassword = password;
else
{
_rdpClient.AdvancedSettings2.ClearTextPassword = password;
}
}
if (string.IsNullOrEmpty(domain))

View File

@@ -1114,10 +1114,10 @@ If you run into such an error, please create a new connection file!</value>
<value>Use the Credential Security Support Provider (CredSSP) for authentication if it is available.</value>
</data>
<data name="PropertyDescriptionUseRestrictedAdmin" xml:space="preserve">
<value>Use restricted admin mode on the target host (local system context).</value>
<value>Use restricted admin mode on the target host (local system context). Credentials are not forwarded to the remote host; the current user's Kerberos ticket is used instead. Recommended for AD Protected Users accounts where NTLM authentication is disabled. Requires the connecting user to have administrative rights on the target.</value>
</data>
<data name="PropertyDescriptionUseRCG" xml:space="preserve">
<value>Use Remote Credential Guard to tunnel authentication on target back to source through the RDP channel.</value>
<value>Use Remote Credential Guard to tunnel authentication on target back to source through the RDP channel. Kerberos requests are redirected back to the connecting device, so credentials are never sent to the remote host. Recommended for AD Protected Users accounts where NTLM authentication is disabled. Requires both client and server to be domain-joined.</value>
</data>
<data name="PropertyDescriptionUser1" xml:space="preserve">
<value>Feel free to enter any information you need here.</value>

View File

@@ -127,10 +127,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages
Properties.OptionsUpdatesPage.Default.UpdateProxyAuthUser = txtProxyUsername.Text;
LegacyRijndaelCryptographyProvider cryptographyProvider = new();
Properties.OptionsUpdatesPage.Default.UpdateProxyAuthPass = cryptographyProvider.Encrypt(txtProxyPassword.Text, Runtime.EncryptionKey);
// Mark that the user has explicitly configured their update preference so the
// first-run preference prompt does not appear again.
Properties.OptionsUpdatesPage.Default.CheckForUpdatesAsked = true;
}
public override void LoadRegistrySettings()

View File

@@ -416,15 +416,6 @@ namespace mRemoteNG.UI.Forms
if (!CommonRegistrySettings.AllowCheckForUpdatesAutomatical) return;
if (Properties.OptionsUpdatesPage.Default.CheckForUpdatesAsked) return;
// If the user has already explicitly disabled automatic updates via settings, don't ask again
if (!Properties.OptionsUpdatesPage.Default.CheckForUpdatesOnStartup)
{
Properties.OptionsUpdatesPage.Default.CheckForUpdatesAsked = true;
Properties.OptionsUpdatesPage.Default.Save();
return;
}
string[] commandButtons =
[
Language.AskUpdatesCommandRecommended,
@@ -434,25 +425,16 @@ namespace mRemoteNG.UI.Forms
CTaskDialog.ShowTaskDialogBox(this, GeneralAppInfo.ProductName, Language.AskUpdatesMainInstruction, string.Format(Language.AskUpdatesContent, GeneralAppInfo.ProductName), "", "", "", "", string.Join(" | ", commandButtons), ETaskDialogButtons.None, ESysIcons.Question, ESysIcons.Question);
if (CTaskDialog.CommandButtonResult == 0)
if (CTaskDialog.CommandButtonResult == 0 | CTaskDialog.CommandButtonResult == 1)
{
// Use Recommended Settings: enable automatic updates with the default frequency
Properties.OptionsUpdatesPage.Default.CheckForUpdatesOnStartup = true;
if (Properties.OptionsUpdatesPage.Default.CheckForUpdatesFrequencyDays < 1)
Properties.OptionsUpdatesPage.Default.CheckForUpdatesFrequencyDays = 14;
Properties.OptionsUpdatesPage.Default.CheckForUpdatesAsked = true;
Properties.OptionsUpdatesPage.Default.Save();
}
else if (CTaskDialog.CommandButtonResult == 1)
{
// Customize: let the user configure update settings manually, then open Options
Properties.OptionsUpdatesPage.Default.CheckForUpdatesAsked = true;
Properties.OptionsUpdatesPage.Default.Save();
AppWindows.Show(WindowType.Options);
if (AppWindows.OptionsFormWindow != null)
AppWindows.OptionsFormWindow.SetActivatedPage(Language.Updates);
}
// For "Ask Later" (button 2), CheckForUpdatesAsked remains false so the dialog will show again next startup
if (CTaskDialog.CommandButtonResult != 1) return;
AppWindows.Show(WindowType.Options);
if (AppWindows.OptionsFormWindow != null)
AppWindows.OptionsFormWindow.SetActivatedPage(Language.Updates);
}
private async Task CheckForUpdates()