mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Change Read-Host -MaskInput to use existing SecureString path, but return as plain text (#13256)
This commit is contained in:
@@ -130,9 +130,9 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
|
||||
FieldDescription fd = new FieldDescription(promptString);
|
||||
if (AsSecureString)
|
||||
if (AsSecureString || MaskInput)
|
||||
{
|
||||
fd.SetParameterType(typeof(System.Security.SecureString));
|
||||
fd.SetParameterType(typeof(SecureString));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,27 +149,37 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
foreach (PSObject o in result.Values)
|
||||
{
|
||||
WriteObject(o);
|
||||
if (MaskInput && o?.BaseObject is SecureString secureString)
|
||||
{
|
||||
WriteObject(Utils.GetStringFromSecureString(secureString));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object result;
|
||||
if (AsSecureString)
|
||||
if (AsSecureString || MaskInput)
|
||||
{
|
||||
result = Host.UI.ReadLineAsSecureString();
|
||||
}
|
||||
else if (MaskInput)
|
||||
{
|
||||
result = Host.UI.ReadLineMaskedAsString();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Host.UI.ReadLine();
|
||||
}
|
||||
|
||||
WriteObject(result);
|
||||
if (MaskInput)
|
||||
{
|
||||
WriteObject(Utils.GetStringFromSecureString((SecureString)result));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,17 +112,6 @@ namespace Microsoft.PowerShell
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Null implementation of ReadLineMaskedAsString.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// It throws an exception.
|
||||
/// </returns>
|
||||
public override string ReadLineMaskedAsString()
|
||||
{
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ReadLineAsSecureString.
|
||||
/// </summary>
|
||||
|
||||
@@ -179,39 +179,6 @@ namespace Microsoft.PowerShell
|
||||
return ReadLine(false, string.Empty, out unused, true, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See base class.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The characters typed by the user.
|
||||
/// </returns>
|
||||
/// <exception cref="HostException">
|
||||
/// If obtaining a handle to the active screen buffer failed
|
||||
/// OR
|
||||
/// Win32's setting input buffer mode to disregard window and mouse input failed.
|
||||
/// OR
|
||||
/// Win32's ReadConsole failed.
|
||||
/// </exception>
|
||||
/// <exception cref="PipelineStoppedException">
|
||||
/// If Ctrl-C is entered by user.
|
||||
/// </exception>
|
||||
public override string ReadLineMaskedAsString()
|
||||
{
|
||||
HandleThrowOnReadAndPrompt();
|
||||
|
||||
// we lock here so that multiple threads won't interleave the various reads and writes here.
|
||||
object result = null;
|
||||
lock (_instanceLock)
|
||||
{
|
||||
result = ReadLineSafe(false, PrintToken);
|
||||
}
|
||||
|
||||
StringBuilder resultSb = result as StringBuilder;
|
||||
Dbg.Assert(resultSb != null, "ReadLineMaskedAsString did not return a stringBuilder");
|
||||
|
||||
return resultSb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See base class.
|
||||
/// </summary>
|
||||
|
||||
@@ -120,47 +120,6 @@ namespace System.Management.Automation.Internal.Host
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See base class.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The characters typed by the user.
|
||||
/// </returns>
|
||||
/// <exception cref="HostException">
|
||||
/// If the UI property of the external host is null, possibly because the PSHostUserInterface is not
|
||||
/// implemented by the external host.
|
||||
/// </exception>
|
||||
public override
|
||||
string
|
||||
ReadLineMaskedAsString()
|
||||
{
|
||||
if (_externalUI == null)
|
||||
{
|
||||
ThrowNotInteractive();
|
||||
}
|
||||
|
||||
string result = null;
|
||||
|
||||
try
|
||||
{
|
||||
result = _externalUI.ReadLineMaskedAsString();
|
||||
}
|
||||
catch (PipelineStoppedException)
|
||||
{
|
||||
// PipelineStoppedException is thrown by host when it wants
|
||||
// to stop the pipeline.
|
||||
LocalPipeline lpl = (LocalPipeline)((RunspaceBase)_parent.Context.CurrentRunspace).GetCurrentlyRunningPipeline();
|
||||
if (lpl == null)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
lpl.Stopper.Stop();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See base class.
|
||||
/// </summary>
|
||||
|
||||
@@ -61,29 +61,6 @@ namespace System.Management.Automation.Host
|
||||
/// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.Prompt"/>
|
||||
public abstract string ReadLine();
|
||||
|
||||
/// <summary>
|
||||
/// Same as ReadLine except that the input is not echoed to the user while it is collected
|
||||
/// or is echoed in some obfuscated way, such as showing a dot for each character.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The characters typed by the user.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Note that credentials (a user name and password) should be gathered with
|
||||
/// <see cref="System.Management.Automation.Host.PSHostUserInterface.PromptForCredential(string, string, string, string)"/>
|
||||
/// <see cref="System.Management.Automation.Host.PSHostUserInterface.PromptForCredential(string, string, string, string, System.Management.Automation.PSCredentialTypes, System.Management.Automation.PSCredentialUIOptions)"/>
|
||||
/// </remarks>
|
||||
/// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.ReadLine"/>
|
||||
/// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.PromptForCredential(string, string, string, string)"/>
|
||||
/// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.PromptForCredential(string, string, string, string, System.Management.Automation.PSCredentialTypes, System.Management.Automation.PSCredentialUIOptions)"/>
|
||||
/// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.PromptForChoice"/>
|
||||
/// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.Prompt"/>
|
||||
public virtual string ReadLineMaskedAsString()
|
||||
{
|
||||
// Default implementation of the function to maintain backwards compatibility of the base class.
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same as ReadLine, except that the result is a SecureString, and that the input is not echoed to the user while it is
|
||||
/// collected (or is echoed in some obfuscated way, such as showing a dot for each character).
|
||||
|
||||
-11
@@ -197,17 +197,6 @@ namespace System.Management.Automation.Remoting
|
||||
_serverMethodExecutor.ExecuteVoidMethod(RemoteHostMethodId.WriteWarningLine, new object[] { message });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read line as string masked.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Not implemented. It throws an exception.
|
||||
/// </returns>
|
||||
public override string ReadLineMaskedAsString()
|
||||
{
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read line as secure string.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,6 +12,7 @@ Describe "Read-Host Test" -Tag "CI" {
|
||||
|
||||
AfterEach {
|
||||
$ps.Commands.Clear()
|
||||
$th.UI.Streams.Clear()
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
@@ -30,17 +31,26 @@ Describe "Read-Host Test" -Tag "CI" {
|
||||
$prompt = $th.ui.streams.prompt[0]
|
||||
$prompt | Should -Not -BeNullOrEmpty
|
||||
$prompt.split(":")[-1] | Should -Be myprompt
|
||||
$result | Should -BeExactly 'this is a prompt response'
|
||||
}
|
||||
|
||||
It "Read-Host returns a secure string when using -AsSecureString parameter" {
|
||||
$result = $ps.AddScript("Read-Host -AsSecureString").Invoke() | Select-Object -First 1
|
||||
$result | Should -BeOfType SecureString
|
||||
[pscredential]::New("foo",$result).GetNetworkCredential().Password | Should -BeExactly TEST
|
||||
$result | ConvertFrom-SecureString -AsPlainText | Should -BeExactly 'TEST'
|
||||
}
|
||||
|
||||
It "Read-Host returns a string when using -MaskInput parameter" {
|
||||
$result = $ps.AddScript("Read-Host -MaskInput").Invoke()
|
||||
$result | Should -Be $th.UI.ReadLineData
|
||||
$result | Should -BeExactly 'TEST'
|
||||
}
|
||||
|
||||
It "Read-Host returns a string when using -MaskInput parameter used with -Prompt" {
|
||||
$result = $ps.AddScript("Read-Host -MaskInput -Prompt Test").Invoke()
|
||||
$prompt = $th.ui.streams.prompt[0]
|
||||
$prompt | Should -Not -BeNullOrEmpty
|
||||
$prompt.split(":")[-1] | Should -BeExactly 'Test'
|
||||
$result | Should -BeExactly 'this is a prompt response'
|
||||
}
|
||||
|
||||
It "Read-Host throws an error when both -AsSecureString parameter and -MaskInput parameter are used" {
|
||||
|
||||
@@ -183,11 +183,6 @@ namespace TestHost
|
||||
return ReadLineData;
|
||||
}
|
||||
|
||||
public override string ReadLineMaskedAsString()
|
||||
{
|
||||
return ReadLineData;
|
||||
}
|
||||
|
||||
public override SecureString ReadLineAsSecureString()
|
||||
{
|
||||
SecureString ss = new SecureString();
|
||||
|
||||
Reference in New Issue
Block a user