Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1705,7 +1705,7 @@ private void HandleHostCallReceived(object sender, RemoteDataEventArgs<RemoteHos
internal List<CommandMetadata> GetRemoteCommandMetadata(out Dictionary<string, string> alias2resolvedCommandName)
{
bool isReleaseCandidateBackcompatibilityMode =
this.Session.Runspace.GetRemoteProtocolVersion() == RemotingConstants.ProtocolVersionWin7RC;
this.Session.Runspace.GetRemoteProtocolVersion() == RemotingConstants.ProtocolVersion_2_0;

alias2resolvedCommandName = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if ((this.CommandName == null) || (this.CommandName.Length == 0) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ internal PSObject ToPSObjectForRemoting(Version psRPVersion)
commandAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.MergeUnclaimedPreviousCommandResults, this.MergeUnclaimedPreviousCommandResults));

if (psRPVersion != null &&
psRPVersion >= RemotingConstants.ProtocolVersionWin10RTM)
psRPVersion >= RemotingConstants.ProtocolVersion_2_3)
{
// V5 merge instructions
commandAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.MergeError, MergeInstructions[(int)MergeType.Error]));
Expand All @@ -672,7 +672,7 @@ internal PSObject ToPSObjectForRemoting(Version psRPVersion)
commandAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.MergeInformation, MergeInstructions[(int)MergeType.Information]));
}
else if (psRPVersion != null &&
psRPVersion >= RemotingConstants.ProtocolVersionWin8RTM)
psRPVersion >= RemotingConstants.ProtocolVersion_2_2)
{
// V3 merge instructions.
commandAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.MergeError, MergeInstructions[(int)MergeType.Error]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5271,7 +5271,7 @@ private bool ServerSupportsBatchInvocation()
if (_runspace != null)
{
return _runspace.RunspaceStateInfo.State != RunspaceState.BeforeOpen &&
_runspace.GetRemoteProtocolVersion() >= RemotingConstants.ProtocolVersionWin8RTM;
_runspace.GetRemoteProtocolVersion() >= RemotingConstants.ProtocolVersion_2_2;
}

RemoteRunspacePoolInternal remoteRunspacePoolInternal = null;
Expand All @@ -5285,7 +5285,7 @@ private bool ServerSupportsBatchInvocation()
}

return remoteRunspacePoolInternal != null &&
remoteRunspacePoolInternal.PSRemotingProtocolVersion >= RemotingConstants.ProtocolVersionWin8RTM;
remoteRunspacePoolInternal.PSRemotingProtocolVersion >= RemotingConstants.ProtocolVersion_2_2;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ internal override bool ResetRunspaceState()
// version 2.3 or greater.
Version remoteProtocolVersionDeclaredByServer = PSRemotingProtocolVersion;
if ((remoteProtocolVersionDeclaredByServer == null) ||
(remoteProtocolVersionDeclaredByServer < RemotingConstants.ProtocolVersionWin10RTM))
(remoteProtocolVersionDeclaredByServer < RemotingConstants.ProtocolVersion_2_3))
{
throw PSTraceSource.NewInvalidOperationException(RunspacePoolStrings.ResetRunspaceStateNotSupportedOnServer);
}
Expand Down Expand Up @@ -733,7 +733,7 @@ internal bool CanDisconnect
{
// Disconnect/Connect support is currently only provided by the WSMan transport
// that is running PSRP protocol version 2.2 and greater.
return (remoteProtocolVersionDeclaredByServer >= RemotingConstants.ProtocolVersionWin8RTM &&
return (remoteProtocolVersionDeclaredByServer >= RemotingConstants.ProtocolVersion_2_2 &&
DataStructureHandler.EndpointSupportsDisconnect);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ internal void Override(RemoteRunspace remoteRunspace, object syncObject, out boo
powerShell.AddParameter("Name", new string[] { "Out-Default", "Exit-PSSession" });
powerShell.Runspace = _runspaceRef.Value;

bool isReleaseCandidateBackcompatibilityMode = _runspaceRef.Value.GetRemoteProtocolVersion() == RemotingConstants.ProtocolVersionWin7RC;
bool isReleaseCandidateBackcompatibilityMode = _runspaceRef.Value.GetRemoteProtocolVersion() == RemotingConstants.ProtocolVersion_2_0;
powerShell.IsGetCommandMetadataSpecialPipeline = !isReleaseCandidateBackcompatibilityMode;
int expectedNumberOfResults = isReleaseCandidateBackcompatibilityMode ? 2 : 3;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,20 +505,11 @@ private bool RunClientNegotiationAlgorithm(RemoteSessionCapability serverRemoteS
_serverProtocolVersion = serverProtocolVersion;
Version clientProtocolVersion = Context.ClientCapability.ProtocolVersion;

if (
clientProtocolVersion.Equals(serverProtocolVersion)
|| (clientProtocolVersion == RemotingConstants.ProtocolVersionWin7RTM &&
serverProtocolVersion == RemotingConstants.ProtocolVersionWin7RC)
|| (clientProtocolVersion == RemotingConstants.ProtocolVersionWin8RTM &&
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin7RC ||
serverProtocolVersion == RemotingConstants.ProtocolVersionWin7RTM
))
|| (clientProtocolVersion == RemotingConstants.ProtocolVersionWin10RTM &&
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin7RC ||
serverProtocolVersion == RemotingConstants.ProtocolVersionWin7RTM ||
serverProtocolVersion == RemotingConstants.ProtocolVersionWin8RTM
))
)
if (clientProtocolVersion == serverProtocolVersion ||
serverProtocolVersion == RemotingConstants.ProtocolVersion_2_0 ||
serverProtocolVersion == RemotingConstants.ProtocolVersion_2_1 ||
serverProtocolVersion == RemotingConstants.ProtocolVersion_2_2 ||
serverProtocolVersion == RemotingConstants.ProtocolVersion_2_3)
{
// passed negotiation check
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ protected override void BeginProcessing()
{
// In order to support foreach remoting properly ( icm | % { icm } ), the server must
// be using protocol version 2.2. Otherwise, we skip this and assume the old behavior.
if (version >= RemotingConstants.ProtocolVersionWin8RTM)
if (version >= RemotingConstants.ProtocolVersion_2_2)
{
// Suppress collection behavior
_needToCollect = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ private static NamedPipeServerStream CreateNamedPipe(
SafePipeHandle pipeHandle = NamedPipeNative.CreateNamedPipe(
fullPipeName,
NamedPipeNative.PIPE_ACCESS_DUPLEX | NamedPipeNative.FILE_FLAG_FIRST_PIPE_INSTANCE | NamedPipeNative.FILE_FLAG_OVERLAPPED,
NamedPipeNative.PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_READMODE_MESSAGE,
NamedPipeNative.PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_READMODE_MESSAGE | NamedPipeNative.PIPE_REJECT_REMOTE_CLIENTS,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it would be better off as a separate commit or at a minimum pointed out that this has changed here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually related to this protocol change. PowerShell has built-in support for 3 non-network transports:

  • Standard I/O
  • Named pipe
  • HyperV direct

For HyperV direct, we've confirmed with the HyperV team that the man-in-the-middle attacks are not possible with HyperV sockets.

For standard I/O, both client and server are local, so we should be good.

For named pipe, it's possible for a remote client to connect to named pipe, which 1) may not be intended from the beginning of this feature 2) could be problematic after SecureString is no longer encrypted with a session key. So, it's better off to disable remote client for it.

  1. Updated the pipe_option for creating the named pipe (used for Enter-PSHostProcess) in PowerShell to reject remote client.

I called it out in the PR description above. I will add more about it in the description.

1,
_namedPipeBufferSizeForRemoting,
_namedPipeBufferSizeForRemoting,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,27 @@ internal static class RemotingConstants
{
internal static readonly Version HostVersion = PSVersionInfo.PSVersion;

internal static readonly Version ProtocolVersionWin7RC = new Version(2, 0);
internal static readonly Version ProtocolVersionWin7RTM = new Version(2, 1);
internal static readonly Version ProtocolVersionWin8RTM = new Version(2, 2);
internal static readonly Version ProtocolVersionWin10RTM = new Version(2, 3);
internal static readonly Version ProtocolVersion_2_0 = new(2, 0); // Window 7 RC
internal static readonly Version ProtocolVersion_2_1 = new(2, 1); // Window 7 RTM
internal static readonly Version ProtocolVersion_2_2 = new(2, 2); // Window 8 RTM
internal static readonly Version ProtocolVersion_2_3 = new(2, 3); // Window 10 RTM
internal static readonly Version ProtocolVersion_2_4 = new(2, 4); // PowerShell 7.6
Comment on lines -79 to +83
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the variable names because:

  1. It's hard to map the original names to the true protocol versions when reading code
  2. The change to v2.4 doesn't map to a Windows RTM.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes perfect sense


// Minor will be incremented for each change in PSRP client/server stack and new versions will be
// forked on early major release/drop changes history.
// 2.101 to 2.102 - Disconnect support as of M2
// 2.102 to 2.103 - Key exchange protocol changes in M3
// 2.103 to 2.2 - Final ship protocol version value, no change to protocol
// 2.2 to 2.3 - Enabling informational stream
internal static readonly Version ProtocolVersionCurrent = new Version(2, 3);
// 2.3 to 2.4 - Deprecate the 'Session_Key' exchange. The following messages are obsolete when both server and client are v2.4+:
// - PUBLIC_KEY
// - PUBLIC_KEY_REQUEST
// - ENCRYPTED_SESSION_KEY
// The padding algorithm 'RSAEncryptionPadding.Pkcs1' used in the 'Session_Key' exchange is NOT secure, and therefore,
// PSRP needs to be used on top of a secure transport and the 'Session_Key' doesn't add any extra security.
// So, we decided to deprecate the 'Session_Key' exchange in PSRP and skip encryption and decryption for 'SecureString'
// objects. Instead, we require the transport to be secure for secure data transfer between PSRP clients and servers.
internal static readonly Version ProtocolVersionCurrent = new(2, 4);
internal static readonly Version ProtocolVersion = ProtocolVersionCurrent;
// Used by remoting commands to add remoting specific note properties.
internal static readonly string ComputerNameNoteProperty = "PSComputerName";
Expand Down Expand Up @@ -2158,7 +2167,7 @@ internal static bool ServerSupportsBatchInvocation(Runspace runspace)
return false;
}

return (runspace.GetRemoteProtocolVersion() >= RemotingConstants.ProtocolVersionWin8RTM);
return (runspace.GetRemoteProtocolVersion() >= RemotingConstants.ProtocolVersion_2_2);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,7 @@ public override void CloseAsync()
/// <param name="serverProtocolVersion">Server negotiated protocol version.</param>
internal void AdjustForProtocolVariations(Version serverProtocolVersion)
{
if (serverProtocolVersion <= RemotingConstants.ProtocolVersionWin7RTM)
if (serverProtocolVersion <= RemotingConstants.ProtocolVersion_2_1)
{
int maxEnvSize;
WSManNativeApi.WSManGetSessionOptionAsDword(_wsManSessionHandle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ private void HandleCreateAndInvokePowerShell(object _, RemoteDataEventArgs<Remot
bool isNested = false;

// The server would've dropped the protocol version of an older client was connecting
if (_serverCapability.ProtocolVersion >= RemotingConstants.ProtocolVersionWin8RTM)
if (_serverCapability.ProtocolVersion >= RemotingConstants.ProtocolVersion_2_2)
{
isNested = RemotingDecoder.GetIsNested(data.Data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -973,35 +973,21 @@ private bool RunServerNegotiationAlgorithm(RemoteSessionCapability clientCapabil

if (onConnect)
{
bool connectSupported = false;

// Win10 server can support reconstruct/reconnect for all 2.x protocol versions
// that support reconstruct/reconnect, Protocol 2.2+
// Major protocol version differences (2.x -> 3.x) are not supported.
// A reconstruct can only be initiated by a client that understands disconnect (2.2+),
// so we only need to check major versions from client and this server for compatibility.
if (clientProtocolVersion.Major == RemotingConstants.ProtocolVersion.Major)
// PS v7.6 server can support reconstruct/reconnect for all 2.x protocol versions that support reconstruct/reconnect (v2.2+).
// Major protocol version differences (2.x -> 3.x) are not supported. A reconstruct can only be initiated by a client that understands disconnect (v2.2+).
if (clientProtocolVersion == RemotingConstants.ProtocolVersion_2_2 ||
clientProtocolVersion == RemotingConstants.ProtocolVersion_2_3)
{
if (clientProtocolVersion.Minor == RemotingConstants.ProtocolVersionWin8RTM.Minor)
{
// Report that server is Win8 version to the client
// Protocol: 2.2
connectSupported = true;
serverProtocolVersion = RemotingConstants.ProtocolVersionWin8RTM;
Context.ServerCapability.ProtocolVersion = serverProtocolVersion;
}
else if (clientProtocolVersion.Minor > RemotingConstants.ProtocolVersionWin8RTM.Minor)
{
// All other minor versions are supported and the server returns its full capability
// Protocol: 2.3, 2.4, 2.5 ...
connectSupported = true;
}
// Report the server as the same version to the client.
// Client protocol: v2.2, v2.3
serverProtocolVersion = clientProtocolVersion;
Context.ServerCapability.ProtocolVersion = serverProtocolVersion;
}

if (!connectSupported)
else if (!(clientProtocolVersion.Major == serverProtocolVersion.Major &&
clientProtocolVersion.Minor >= serverProtocolVersion.Minor))
{
// Throw for protocol versions 2.x that don't support disconnect/reconnect.
// Protocol: < 2.2
// Client protocol: < 2.2
PSRemotingDataStructureException reasonOfFailure =
new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnNegotiation,
RemoteDataNameStrings.PS_STARTUP_PROTOCOL_VERSION_NAME,
Expand All @@ -1010,47 +996,23 @@ private bool RunServerNegotiationAlgorithm(RemoteSessionCapability clientCapabil
RemotingConstants.ProtocolVersion);
throw reasonOfFailure;
}

// All other minor versions are supported and the server returns its full capability.
// Client protocol: v2.4, v2.5 ...
}
else
{
// Win10 server can support Win8 client
if (clientProtocolVersion == RemotingConstants.ProtocolVersionWin8RTM &&
(
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin10RTM)
))
{
// - report that server is Win8 version to the client
serverProtocolVersion = RemotingConstants.ProtocolVersionWin8RTM;
Context.ServerCapability.ProtocolVersion = serverProtocolVersion;
}

// Win8, Win10 server can support Win7 client
if (clientProtocolVersion == RemotingConstants.ProtocolVersionWin7RTM &&
(
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin8RTM) ||
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin10RTM)
))
{
// - report that server is Win7 version to the client
serverProtocolVersion = RemotingConstants.ProtocolVersionWin7RTM;
Context.ServerCapability.ProtocolVersion = serverProtocolVersion;
}

// Win7, Win8, Win10 server can support Win7 RC client
if (clientProtocolVersion == RemotingConstants.ProtocolVersionWin7RC &&
(
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin7RTM) ||
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin8RTM) ||
(serverProtocolVersion == RemotingConstants.ProtocolVersionWin10RTM)
))
if (clientProtocolVersion == RemotingConstants.ProtocolVersion_2_0 ||
clientProtocolVersion == RemotingConstants.ProtocolVersion_2_1 ||
clientProtocolVersion == RemotingConstants.ProtocolVersion_2_2 ||
clientProtocolVersion == RemotingConstants.ProtocolVersion_2_3)
{
// - report that server is RC version to the client
serverProtocolVersion = RemotingConstants.ProtocolVersionWin7RC;
// We support the those client versions and report the server as the same version to the client.
serverProtocolVersion = clientProtocolVersion;
Context.ServerCapability.ProtocolVersion = serverProtocolVersion;
}

if (!((clientProtocolVersion.Major == serverProtocolVersion.Major) &&
(clientProtocolVersion.Minor >= serverProtocolVersion.Minor)))
else if (!(clientProtocolVersion.Major == serverProtocolVersion.Major &&
clientProtocolVersion.Minor >= serverProtocolVersion.Minor))
{
PSRemotingDataStructureException reasonOfFailure =
new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerNegotiationFailed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal static class SecureStringHelper
/// </summary>
/// <param name="data">Input data.</param>
/// <returns>A SecureString .</returns>
private static SecureString New(byte[] data)
internal static SecureString New(byte[] data)
{
if ((data.Length % 2) != 0)
{
Expand Down
Loading
Loading