mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
Merge pull request #2285 from tecxx/develop-orig
support extraction of SSH private keys from external cred prov
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
using Microsoft.Win32;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Security;
|
||||
using SecretServerAuthentication.DSS;
|
||||
using SecretServerRestClient.DSS;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace ExternalConnectors.DSS
|
||||
{
|
||||
@@ -114,25 +119,22 @@ namespace ExternalConnectors.DSS
|
||||
}
|
||||
}
|
||||
|
||||
private static void FetchSecret(int secretID, out string secretUsername, out string secretPassword, out string secretDomain)
|
||||
private static SecretsServiceClient ConstructSecretsServiceClient()
|
||||
{
|
||||
string baseURL = SSConnectionData.ssUrl;
|
||||
|
||||
SecretModel secret;
|
||||
if (SSConnectionData.ssSSO)
|
||||
{
|
||||
// REQUIRES IIS CONFIG! https://docs.thycotic.com/ss/11.0.0/api-scripting/webservice-iwa-powershell
|
||||
var handler = new HttpClientHandler() { UseDefaultCredentials = true };
|
||||
using (var httpClient = new HttpClient(handler))
|
||||
var httpClient = new HttpClient(handler);
|
||||
{
|
||||
// Call REST API:
|
||||
var client = new SecretsServiceClient($"{baseURL}/winauthwebservices/api", httpClient);
|
||||
secret = client.GetSecretAsync(false, true, secretID, null).Result;
|
||||
return new SecretsServiceClient($"{baseURL}/winauthwebservices/api", httpClient);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
var httpClient = new HttpClient();
|
||||
{
|
||||
|
||||
var token = GetToken();
|
||||
@@ -140,15 +142,22 @@ namespace ExternalConnectors.DSS
|
||||
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
// Call REST API:
|
||||
var client = new SecretsServiceClient($"{baseURL}/api", httpClient);
|
||||
secret = client.GetSecretAsync(false, true, secretID, null).Result;
|
||||
return new SecretsServiceClient($"{baseURL}/api", httpClient);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static void FetchSecret(int secretID, out string secretUsername, out string secretPassword, out string secretDomain, out string privatekey)
|
||||
{
|
||||
var client = ConstructSecretsServiceClient();
|
||||
SecretModel secret = client.GetSecretAsync(false, true, secretID, null).Result;
|
||||
|
||||
// clear return variables
|
||||
secretDomain = "";
|
||||
secretUsername = "";
|
||||
secretPassword = "";
|
||||
privatekey = "";
|
||||
string privatekeypassphrase = "";
|
||||
|
||||
// parse data and extract what we need
|
||||
foreach (var item in secret.Items)
|
||||
@@ -159,10 +168,91 @@ namespace ExternalConnectors.DSS
|
||||
secretUsername = item.ItemValue;
|
||||
else if (item.FieldName.ToLower().Equals("password"))
|
||||
secretPassword = item.ItemValue;
|
||||
else if (item.FieldName.ToLower().Equals("private key"))
|
||||
{
|
||||
client.ReadResponseNoJSONConvert = true;
|
||||
privatekey = client.GetFieldAsync(false, false, secretID, "private-key").Result;
|
||||
client.ReadResponseNoJSONConvert = false;
|
||||
}
|
||||
else if (item.FieldName.ToLower().Equals("private key passphrase"))
|
||||
privatekeypassphrase = item.ItemValue;
|
||||
}
|
||||
|
||||
// need to decode the private key?
|
||||
if (!string.IsNullOrEmpty(privatekeypassphrase))
|
||||
{
|
||||
try
|
||||
{
|
||||
var key = DecodePrivateKey(privatekey, privatekeypassphrase);
|
||||
privatekey = key;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// conversion to putty format necessary?
|
||||
if (!string.IsNullOrEmpty(privatekey) && !privatekey.StartsWith("PuTTY-User-Key-File-2"))
|
||||
{
|
||||
try
|
||||
{
|
||||
RSACryptoServiceProvider key = ImportPrivateKey(privatekey);
|
||||
privatekey = PuttyKeyFileGenerator.ToPuttyPrivateKey(key);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region PUTTY KEY HANDLING
|
||||
// decode rsa private key with encryption password
|
||||
private static string DecodePrivateKey(string encryptedPrivateKey, string password)
|
||||
{
|
||||
TextReader textReader = new StringReader(encryptedPrivateKey);
|
||||
PemReader pemReader = new PemReader(textReader, new PasswordFinder(password));
|
||||
|
||||
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
|
||||
|
||||
TextWriter textWriter = new StringWriter();
|
||||
var pemWriter = new PemWriter(textWriter);
|
||||
pemWriter.WriteObject(keyPair.Private);
|
||||
pemWriter.Writer.Flush();
|
||||
|
||||
return ""+textWriter.ToString();
|
||||
}
|
||||
private class PasswordFinder : IPasswordFinder
|
||||
{
|
||||
private string password;
|
||||
|
||||
public PasswordFinder(string password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
|
||||
public char[] GetPassword()
|
||||
{
|
||||
return password.ToCharArray();
|
||||
}
|
||||
}
|
||||
|
||||
// read private key pem string to rsacryptoserviceprovider
|
||||
public static RSACryptoServiceProvider ImportPrivateKey(string pem)
|
||||
{
|
||||
PemReader pr = new PemReader(new StringReader(pem));
|
||||
AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
|
||||
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
|
||||
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
|
||||
rsa.ImportParameters(rsaParams);
|
||||
return rsa;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region TOKEN
|
||||
private static string GetToken()
|
||||
{
|
||||
// if there is no token, fetch a fresh one
|
||||
@@ -233,11 +323,11 @@ namespace ExternalConnectors.DSS
|
||||
return tokenResult;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
// input must be the secret id to fetch
|
||||
public static void FetchSecretFromServer(string input, out string username, out string password, out string domain)
|
||||
public static void FetchSecretFromServer(string input, out string username, out string password, out string domain, out string privatekey)
|
||||
{
|
||||
// get secret id
|
||||
int secretID = Int32.Parse(input);
|
||||
@@ -246,7 +336,7 @@ namespace ExternalConnectors.DSS
|
||||
SSConnectionData.Init();
|
||||
|
||||
// get the secret
|
||||
FetchSecret(secretID, out username, out password, out domain);
|
||||
FetchSecret(secretID, out username, out password, out domain, out privatekey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72886,6 +72886,9 @@ namespace SecretServerRestClient.DSS
|
||||
}
|
||||
|
||||
public bool ReadResponseAsString { get; set; }
|
||||
// RR 2022-09-97
|
||||
public bool ReadResponseNoJSONConvert { get; set; }
|
||||
// RR END
|
||||
|
||||
protected virtual async System.Threading.Tasks.Task<ObjectResponseResult<T>> ReadObjectResponseAsync<T>(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -72894,6 +72897,14 @@ namespace SecretServerRestClient.DSS
|
||||
return new ObjectResponseResult<T>(default(T), string.Empty);
|
||||
}
|
||||
|
||||
// RR 2022-09-97
|
||||
if (ReadResponseNoJSONConvert)
|
||||
{
|
||||
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
return new ObjectResponseResult<T>((T)(object)responseText, responseText); // not sure if this is best practice, but it works.
|
||||
}
|
||||
// RR END
|
||||
|
||||
if (ReadResponseAsString)
|
||||
{
|
||||
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<PackageReference Include="AWSSDK.Core" Version="3.7.12.15" />
|
||||
<PackageReference Include="AWSSDK.EC2" Version="3.7.79.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
109
ExternalConnectors/PuttyKeyFileGenerator.cs
Normal file
109
ExternalConnectors/PuttyKeyFileGenerator.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ExternalConnectors;
|
||||
|
||||
public class PuttyKeyFileGenerator
|
||||
{
|
||||
private const int prefixSize = 4;
|
||||
private const int paddedPrefixSize = prefixSize + 1;
|
||||
private const int lineLength = 64;
|
||||
private const string keyType = "ssh-rsa";
|
||||
private const string encryptionType = "none";
|
||||
|
||||
// source from
|
||||
// https://gist.github.com/canton7/5670788?permalink_comment_id=3240331
|
||||
// https://gist.github.com/bosima/ee6630d30b533c7d7b2743a849e9b9d0
|
||||
|
||||
public static string ToPuttyPrivateKey(RSACryptoServiceProvider cryptoServiceProvider, string Comment = "imported-openssh-key")
|
||||
{
|
||||
var publicParameters = cryptoServiceProvider.ExportParameters(false);
|
||||
byte[] publicBuffer = new byte[3 + keyType.Length + GetPrefixSize(publicParameters.Exponent) + publicParameters.Exponent.Length +
|
||||
GetPrefixSize(publicParameters.Modulus) + publicParameters.Modulus.Length + 1];
|
||||
|
||||
using (var bw = new BinaryWriter(new MemoryStream(publicBuffer)))
|
||||
{
|
||||
bw.Write(new byte[] { 0x00, 0x00, 0x00 });
|
||||
bw.Write(keyType);
|
||||
PutPrefixed(bw, publicParameters.Exponent, CheckIsNeddPadding(publicParameters.Exponent));
|
||||
PutPrefixed(bw, publicParameters.Modulus, CheckIsNeddPadding(publicParameters.Modulus));
|
||||
}
|
||||
var publicBlob = System.Convert.ToBase64String(publicBuffer);
|
||||
|
||||
var privateParameters = cryptoServiceProvider.ExportParameters(true);
|
||||
byte[] privateBuffer = new byte[paddedPrefixSize + privateParameters.D.Length + paddedPrefixSize + privateParameters.P.Length + paddedPrefixSize + privateParameters.Q.Length + paddedPrefixSize + privateParameters.InverseQ.Length];
|
||||
|
||||
using (var bw = new BinaryWriter(new MemoryStream(privateBuffer)))
|
||||
{
|
||||
PutPrefixed(bw, privateParameters.D, true);
|
||||
PutPrefixed(bw, privateParameters.P, true);
|
||||
PutPrefixed(bw, privateParameters.Q, true);
|
||||
PutPrefixed(bw, privateParameters.InverseQ, true);
|
||||
}
|
||||
var privateBlob = System.Convert.ToBase64String(privateBuffer);
|
||||
|
||||
HMACSHA1 hmacsha1 = new HMACSHA1(new SHA1CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes("putty-private-key-file-mac-key")));
|
||||
//byte[] bytesToHash = new byte[4 + 7 + 4 + 4 + 4 + Comment.Length + 4 + publicBuffer.Length + 4 + privateBuffer.Length];
|
||||
byte[] bytesToHash = new byte[prefixSize + keyType.Length + prefixSize + encryptionType.Length + prefixSize + Comment.Length +
|
||||
prefixSize + publicBuffer.Length + prefixSize + privateBuffer.Length];
|
||||
|
||||
using (var bw = new BinaryWriter(new MemoryStream(bytesToHash)))
|
||||
{
|
||||
PutPrefixed(bw, Encoding.ASCII.GetBytes("ssh-rsa"));
|
||||
PutPrefixed(bw, Encoding.ASCII.GetBytes("none"));
|
||||
PutPrefixed(bw, Encoding.ASCII.GetBytes(Comment));
|
||||
PutPrefixed(bw, publicBuffer);
|
||||
PutPrefixed(bw, privateBuffer);
|
||||
}
|
||||
|
||||
var hash = string.Join("", hmacsha1.ComputeHash(bytesToHash).Select(x => string.Format("{0:x2}", x)));
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("PuTTY-User-Key-File-2: " + keyType);
|
||||
sb.AppendLine("Encryption: " + encryptionType);
|
||||
sb.AppendLine("Comment: " + Comment);
|
||||
|
||||
var publicLines = SpliceText(publicBlob, lineLength);
|
||||
sb.AppendLine("Public-Lines: " + publicLines.Length);
|
||||
foreach (var line in publicLines)
|
||||
{
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
|
||||
var privateLines = SpliceText(privateBlob, lineLength);
|
||||
sb.AppendLine("Private-Lines: " + privateLines.Length);
|
||||
foreach (var line in privateLines)
|
||||
{
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
|
||||
sb.AppendLine("Private-MAC: " + hash);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
private static void PutPrefixed(BinaryWriter bw, byte[] bytes, bool addLeadingNull = false)
|
||||
{
|
||||
bw.Write(BitConverter.GetBytes(bytes.Length + (addLeadingNull ? 1 : 0)).Reverse().ToArray());
|
||||
if (addLeadingNull)
|
||||
bw.Write(new byte[] { 0x00 });
|
||||
bw.Write(bytes);
|
||||
}
|
||||
|
||||
private static string[] SpliceText(string text, int lineLength)
|
||||
{
|
||||
return Regex.Matches(text, ".{1," + lineLength + "}").Cast<Match>().Select(m => m.Value).ToArray();
|
||||
}
|
||||
private static int GetPrefixSize(byte[] bytes)
|
||||
{
|
||||
return CheckIsNeddPadding(bytes) ? paddedPrefixSize : prefixSize;
|
||||
}
|
||||
private static bool CheckIsNeddPadding(byte[] bytes)
|
||||
{
|
||||
// 128 == 10000000
|
||||
// This means that the number of bits can be divided by 8.
|
||||
// According to the algorithm in putty, you need to add a padding.
|
||||
return bytes[0] >= 128;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using System.Windows.Forms;
|
||||
using mRemoteNG.Properties;
|
||||
using mRemoteNG.Resources.Language;
|
||||
using Connection;
|
||||
using System.IO;
|
||||
|
||||
// ReSharper disable ArrangeAccessorOwnerBody
|
||||
|
||||
@@ -57,6 +58,8 @@ namespace mRemoteNG.Connection.Protocol
|
||||
|
||||
public override bool Connect()
|
||||
{
|
||||
string optionalTemporaryPrivateKeyPath = ""; // path to ppk file instead of password. only temporary (extracted from credential vault).
|
||||
|
||||
try
|
||||
{
|
||||
_isPuttyNg = PuttyTypeDetector.GetPuttyType() == PuttyTypeDetector.PuttyType.PuttyNg;
|
||||
@@ -85,14 +88,22 @@ namespace mRemoteNG.Connection.Protocol
|
||||
var password = InterfaceControl.Info?.Password ?? "";
|
||||
var domain = InterfaceControl.Info?.Domain ?? "";
|
||||
var UserViaAPI = InterfaceControl.Info?.UserViaAPI ?? "";
|
||||
|
||||
string privatekey = "";
|
||||
|
||||
// access secret server api if necessary
|
||||
if (InterfaceControl.Info.ExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{UserViaAPI}", out username, out password, out domain);
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{UserViaAPI}", out username, out password, out domain, out privatekey);
|
||||
|
||||
if (!string.IsNullOrEmpty(privatekey))
|
||||
{
|
||||
optionalTemporaryPrivateKeyPath = Path.GetTempFileName();
|
||||
File.WriteAllText(optionalTemporaryPrivateKeyPath, privatekey);
|
||||
FileInfo fileInfo = new FileInfo(optionalTemporaryPrivateKeyPath);
|
||||
fileInfo.Attributes = FileAttributes.Temporary;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -111,22 +122,26 @@ namespace mRemoteNG.Connection.Protocol
|
||||
username = Properties.OptionsCredentialsPage.Default.DefaultUsername;
|
||||
break;
|
||||
case "custom":
|
||||
try
|
||||
|
||||
if (Properties.OptionsCredentialsPage.Default.ExternalCredentialProviderDefault == ExternalCredentialProvider.DelineaSecretServer)
|
||||
{
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer(
|
||||
"SSAPI:" + Properties.OptionsCredentialsPage.Default.UserViaAPDefault, out username, out password,
|
||||
out domain);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Event_ErrorOccured(this, "Secret Server Interface Error: " + ex.Message, 0);
|
||||
try
|
||||
{
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer(
|
||||
$"{Properties.OptionsCredentialsPage.Default.UserViaAPIDefault}", out username, out password, out domain, out privatekey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Event_ErrorOccured(this, "Secret Server Interface Error: " + ex.Message, 0);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(password))
|
||||
if (string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(optionalTemporaryPrivateKeyPath))
|
||||
{
|
||||
if (Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
|
||||
{
|
||||
@@ -149,6 +164,13 @@ namespace mRemoteNG.Connection.Protocol
|
||||
arguments.Add("-pw", password);
|
||||
}
|
||||
}
|
||||
|
||||
// use private key if specified
|
||||
if (!string.IsNullOrEmpty(optionalTemporaryPrivateKeyPath))
|
||||
{
|
||||
arguments.Add("-i", optionalTemporaryPrivateKeyPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
arguments.Add("-P", InterfaceControl.Info.Port.ToString());
|
||||
@@ -219,6 +241,15 @@ namespace mRemoteNG.Connection.Protocol
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.ConnectionFailed + Environment.NewLine + ex.Message);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// make sure to remove the private key file
|
||||
if (!string.IsNullOrEmpty(optionalTemporaryPrivateKeyPath))
|
||||
{
|
||||
System.Threading.Thread.Sleep(500);
|
||||
System.IO.File.Delete(optionalTemporaryPrivateKeyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Focus()
|
||||
|
||||
@@ -409,14 +409,15 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
string gwu = connectionInfo.RDGatewayUsername;
|
||||
string gwp = connectionInfo.RDGatewayPassword;
|
||||
string gwd = connectionInfo.RDGatewayDomain;
|
||||
string pkey = "";
|
||||
|
||||
// access secret server api if necessary
|
||||
if (InterfaceControl.Info.RDGatewayExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
string idviaapi = InterfaceControl.Info.RDGatewayUserViaAPI;
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{idviaapi}", out gwu, out gwp, out gwd);
|
||||
string RDGUserViaAPI = InterfaceControl.Info.RDGatewayUserViaAPI;
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{RDGUserViaAPI}", out gwu, out gwp, out gwd, out pkey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -494,13 +495,14 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
var password = connectionInfo?.Password ?? "";
|
||||
var domain = connectionInfo?.Domain ?? "";
|
||||
var UserViaAPI = connectionInfo?.UserViaAPI ?? "";
|
||||
string pkey = "";
|
||||
|
||||
// access secret server api if necessary
|
||||
if (InterfaceControl.Info.ExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{UserViaAPI}", out userName, out password, out domain);
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer($"{UserViaAPI}", out userName, out password, out domain, out pkey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -522,7 +524,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
case "custom":
|
||||
try
|
||||
{
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer("SSAPI:" + Properties.OptionsCredentialsPage.Default.UserViaAPDefault, out userName, out password, out domain);
|
||||
ExternalConnectors.DSS.SecretServerInterface.FetchSecretFromServer(Properties.OptionsCredentialsPage.Default.UserViaAPIDefault, out userName, out password, out domain, out pkey);
|
||||
_rdpClient.UserName = userName;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -2200,10 +2200,10 @@ Nightly Channel includes Alphas, Betas & Release Candidates.</value>
|
||||
<comment>https://docs.microsoft.com/en-us/windows/win32/termserv/imstscsecuredsettings-workdir</comment>
|
||||
</data>
|
||||
<data name="OpeningCommand" xml:space="preserve">
|
||||
<value>TODO</value>
|
||||
<value>OpeningCommand TODO</value>
|
||||
</data>
|
||||
<data name="PropertyDescriptionOpeningCommand" xml:space="preserve">
|
||||
<value>TODO</value>
|
||||
<value>Description of OpeningCommand TODO</value>
|
||||
</data>
|
||||
<data name="RedirectDrives" xml:space="preserve">
|
||||
<value>Disk Drives</value>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using Connection;
|
||||
|
||||
namespace mRemoteNG.Properties {
|
||||
|
||||
|
||||
@@ -58,16 +60,31 @@ namespace mRemoteNG.Properties {
|
||||
this["DefaultDomain"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string UserViaAPDefault {
|
||||
public ExternalCredentialProvider ExternalCredentialProviderDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((ExternalCredentialProvider)(this["ExternalCredentialProviderDefault"]));
|
||||
}
|
||||
set
|
||||
{
|
||||
this["ExternalCredentialProviderDefault"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string UserViaAPIDefault {
|
||||
get {
|
||||
return ((string)(this["UserViaAPDefault"]));
|
||||
return ((string)(this["UserViaAPIDefault"]));
|
||||
}
|
||||
set {
|
||||
this["UserViaAPDefault"] = value;
|
||||
this["UserViaAPIDefault"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
txtCredentialsPassword.Text =
|
||||
cryptographyProvider.Decrypt(Properties.OptionsCredentialsPage.Default.DefaultPassword, Runtime.EncryptionKey);
|
||||
txtCredentialsDomain.Text = Properties.OptionsCredentialsPage.Default.DefaultDomain;
|
||||
txtCredentialsUserViaAPI.Text = Properties.OptionsCredentialsPage.Default.UserViaAPDefault;
|
||||
txtCredentialsUserViaAPI.Text = Properties.OptionsCredentialsPage.Default.UserViaAPIDefault;
|
||||
}
|
||||
|
||||
public override void SaveSettings()
|
||||
@@ -77,7 +77,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
Properties.OptionsCredentialsPage.Default.DefaultPassword =
|
||||
cryptographyProvider.Encrypt(txtCredentialsPassword.Text, Runtime.EncryptionKey);
|
||||
Properties.OptionsCredentialsPage.Default.DefaultDomain = txtCredentialsDomain.Text;
|
||||
Properties.OptionsCredentialsPage.Default.UserViaAPDefault = txtCredentialsUserViaAPI.Text;
|
||||
Properties.OptionsCredentialsPage.Default.UserViaAPIDefault = txtCredentialsUserViaAPI.Text;
|
||||
}
|
||||
|
||||
private void radCredentialsCustom_CheckedChanged(object sender, EventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user