Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
PSRemotingCmdlet.cs4545 linesDownload Raw Back to commands
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Collections.ObjectModel;8using System.Diagnostics.CodeAnalysis;9using System.Globalization;10using System.Linq;11using System.Management.Automation;12using System.Management.Automation.Host;13using System.Management.Automation.Internal;14using System.Management.Automation.Language;15using System.Management.Automation.Remoting;16using System.Management.Automation.Remoting.Client;17using System.Management.Automation.Runspaces;18using System.Threading;19 20using Dbg = System.Management.Automation.Diagnostics;21 22namespace Microsoft.PowerShell.Commands23{24    /// <summary>25    /// This class defines most of the common functionality used26    /// across remoting cmdlets.27    ///28    /// It contains tons of utility functions which are used all29    /// across the remoting cmdlets.30    /// </summary>31    public abstract class PSRemotingCmdlet : PSCmdlet32    {33        #region Overrides34 35        /// <summary>36        /// Verifies if remoting cmdlets can be used.37        /// </summary>38        protected override void BeginProcessing()39        {40            if (!SkipWinRMCheck)41            {42                RemotingCommandUtil.CheckRemotingCmdletPrerequisites();43            }44        }45 46        #endregion Overrides47 48        #region Utility functions49 50        /// <summary>51        /// Handle the object obtained from an ObjectStream's reader52        /// based on its type.53        /// </summary>54        internal void WriteStreamObject(Action<Cmdlet> action)55        {56            action(this);57        }58 59        /// <summary>60        /// Resolve all the machine names provided. Basically, if a machine61        /// name is '.' assume localhost.62        /// </summary>63        /// <param name="computerNames">Array of computer names to resolve.</param>64        /// <param name="resolvedComputerNames">Resolved array of machine names.</param>65        protected void ResolveComputerNames(string[] computerNames, out string[] resolvedComputerNames)66        {67            if (computerNames == null)68            {69                resolvedComputerNames = new string[1];70 71                resolvedComputerNames[0] = ResolveComputerName(".");72            }73            else if (computerNames.Length == 0)74            {75                resolvedComputerNames = Array.Empty<string>();76            }77            else78            {79                resolvedComputerNames = new string[computerNames.Length];80 81                for (int i = 0; i < resolvedComputerNames.Length; i++)82                {83                    resolvedComputerNames[i] = ResolveComputerName(computerNames[i]);84                }85            }86        }87 88        /// <summary>89        /// Resolves a computer name. If its null or empty90        /// its assumed to be localhost.91        /// </summary>92        /// <param name="computerName">Computer name to resolve.</param>93        /// <returns>Resolved computer name.</returns>94        protected string ResolveComputerName(string computerName)95        {96            Diagnostics.Assert(computerName != null, "Null ComputerName");97 98            if (string.Equals(computerName, ".", StringComparison.OrdinalIgnoreCase))99            {100                // tracer.WriteEvent(ref PSEventDescriptors.PS_EVENT_HOSTNAMERESOLVE);101                // tracer.Dispose();102                // tracer.OperationalChannel.WriteVerbose(PSEventId.HostNameResolve, PSOpcode.Method, PSTask.CreateRunspace);103                return s_LOCALHOST;104            }105            else106            {107                return computerName;108            }109        }110 111        /// <summary>112        /// Load the resource corresponding to the specified errorId and113        /// return the message as a string.114        /// </summary>115        /// <param name="resourceString">resource String which holds the message116        /// </param>117        /// <returns>Error message loaded from appropriate resource cache.</returns>118        internal string GetMessage(string resourceString)119        {120            string message = GetMessage(resourceString, null);121 122            return message;123        }124 125        /// <summary>126        /// </summary>127        /// <param name="resourceString"></param>128        /// <param name="args"></param>129        /// <returns></returns>130        internal string GetMessage(string resourceString, params object[] args)131        {132            string message;133 134            if (args != null)135            {136                message = StringUtil.Format(resourceString, args);137            }138            else139            {140                message = resourceString;141            }142 143            return message;144        }145 146        #endregion Utility functions147 148        #region Private Members149 150        private static readonly string s_LOCALHOST = "localhost";151 152        // private PSETWTracer tracer = PSETWTracer.GetETWTracer(PSKeyword.Cmdlets);153 154        #endregion Private Members155 156        #region Protected Members157 158        /// <summary>159        /// Computername parameter set.160        /// </summary>161        protected const string ComputerNameParameterSet = "ComputerName";162 163        /// <summary>164        /// Computername with session instance ID parameter set.165        /// </summary>166        protected const string ComputerInstanceIdParameterSet = "ComputerInstanceId";167 168        /// <summary>169        /// Container ID parameter set.170        /// </summary>171        protected const string ContainerIdParameterSet = "ContainerId";172 173        /// <summary>174        /// VM guid parameter set.175        /// </summary>176        protected const string VMIdParameterSet = "VMId";177 178        /// <summary>179        /// VM name parameter set.180        /// </summary>181        protected const string VMNameParameterSet = "VMName";182 183        /// <summary>184        /// SSH host parameter set.185        /// </summary>186        protected const string SSHHostParameterSet = "SSHHost";187 188        /// <summary>189        /// SSH host parmeter set supporting hash connection parameters.190        /// </summary>191        protected const string SSHHostHashParameterSet = "SSHHostHashParam";192 193        /// <summary>194        /// Runspace parameter set.195        /// </summary>196        protected const string SessionParameterSet = "Session";197 198        /// <summary>199        /// Parameter set to use Windows PowerShell.200        /// </summary>201        protected const string UseWindowsPowerShellParameterSet = "UseWindowsPowerShellParameterSet";202 203        /// <summary>204        /// Default shellname.205        /// </summary>206        protected const string DefaultPowerShellRemoteShellName = WSManNativeApi.ResourceURIPrefix + "Microsoft.PowerShell";207 208        /// <summary>209        /// Default application name for the connection uri.210        /// </summary>211        protected const string DefaultPowerShellRemoteShellAppName = "WSMan";212 213        #endregion Protected Members214 215        #region Internal Members216 217        /// <summary>218        /// Skip checking for WinRM.219        /// </summary>220        internal bool SkipWinRMCheck { get; set; } = false;221 222        #endregion Internal Members223 224        #region Protected Methods225 226        /// <summary>227        /// Determines the shellname to use based on the following order:228        ///     1. ShellName parameter specified229        ///     2. DEFAULTREMOTESHELLNAME variable set230        ///     3. PowerShell.231        /// </summary>232        /// <returns>The shell to launch in the remote machine.</returns>233        protected string ResolveShell(string shell)234        {235            string resolvedShell;236 237            if (!string.IsNullOrEmpty(shell))238            {239                resolvedShell = shell;240            }241            else242            {243                resolvedShell = (string)SessionState.Internal.ExecutionContext.GetVariableValue(244                    SpecialVariables.PSSessionConfigurationNameVarPath, DefaultPowerShellRemoteShellName);245            }246 247            return resolvedShell;248        }249 250        /// <summary>251        /// Determines the appname to be used based on the following order:252        ///     1. AppName parameter specified253        ///     2. DEFAULTREMOTEAPPNAME variable set254        ///     3. WSMan.255        /// </summary>256        /// <param name="appName">Application name to resolve.</param>257        /// <returns>Resolved appname.</returns>258        protected string ResolveAppName(string appName)259        {260            string resolvedAppName;261 262            if (!string.IsNullOrEmpty(appName))263            {264                resolvedAppName = appName;265            }266            else267            {268                resolvedAppName = (string)SessionState.Internal.ExecutionContext.GetVariableValue(269                    SpecialVariables.PSSessionApplicationNameVarPath,270                    DefaultPowerShellRemoteShellAppName);271            }272 273            return resolvedAppName;274        }275 276        #endregion277    }278 279    /// <summary>280    /// Contains SSH connection information.281    /// </summary>282    internal struct SSHConnection283    {284        public string ComputerName;285        public string UserName;286        public string KeyFilePath;287        public int Port;288        public string Subsystem;289        public int ConnectingTimeout;290        public Hashtable Options;291    }292 293    /// <summary>294    /// Base class for any cmdlet which takes a -Session parameter295    /// or a -ComputerName parameter (along with its other associated296    /// parameters). The following cmdlets currently fall under this297    /// category:298    ///     1. New-PSSession299    ///     2. Invoke-Expression300    ///     3. Start-PSJob.301    /// </summary>302    public abstract class PSRemotingBaseCmdlet : PSRemotingCmdlet303    {304        #region Enums305 306        /// <summary>307        /// State of virtual machine. This is the same as VMState in308        /// \vm\ux\powershell\objects\common\Types.cs.309        /// </summary>310        internal enum VMState311        {312            /// <summary>313            /// Other. Corresponds to CIM_EnabledLogicalElement.EnabledState = Other.314            /// </summary>315            Other = 1,316 317            /// <summary>318            /// Running. Corresponds to CIM_EnabledLogicalElement.EnabledState = Enabled.319            /// </summary>320            Running = 2,321 322            /// <summary>323            /// Off. Corresponds to CIM_EnabledLogicalElement.EnabledState = Disabled.324            /// </summary>325            Off = 3,326 327            /// <summary>328            /// Stopping. Corresponds to CIM_EnabledLogicalElement.EnabledState = ShuttingDown.329            /// </summary>330            Stopping = 4,331 332            /// <summary>333            /// Saved. Corresponds to CIM_EnabledLogicalElement.EnabledState = Enabled but offline.334            /// </summary>335            Saved = 6,336 337            /// <summary>338            /// Paused. Corresponds to CIM_EnabledLogicalElement.EnabledState = Quiesce.339            /// </summary>340            Paused = 9,341 342            /// <summary>343            /// Starting. EnabledStateStarting. State transition from PowerOff or Saved to Running.344            /// </summary>345            Starting = 10,346 347            /// <summary>348            /// Reset. Corresponds to CIM_EnabledLogicalElement.EnabledState = Reset.349            /// </summary>350            Reset = 11,351 352            /// <summary>353            /// Saving. Corresponds to EnabledStateSaving.354            /// </summary>355            Saving = 32773,356 357            /// <summary>358            /// Pausing. Corresponds to EnabledStatePausing.359            /// </summary>360            Pausing = 32776,361 362            /// <summary>363            /// Resuming. Corresponds to EnabledStateResuming.364            /// </summary>365            Resuming = 32777,366 367            /// <summary>368            /// FastSaved. EnabledStateFastSuspend.369            /// </summary>370            FastSaved = 32779,371 372            /// <summary>373            /// FastSaving. EnabledStateFastSuspending.374            /// </summary>375            FastSaving = 32780,376 377            /// <summary>378            /// ForceShutdown. Used to force a graceful shutdown of the virtual machine.379            /// </summary>380            ForceShutdown = 32781,381 382            /// <summary>383            /// ForceReboot. Used to force a graceful reboot of the virtual machine.384            /// </summary>385            ForceReboot = 32782,386 387            /// <summary>388            /// RunningCritical. Critical states.389            /// </summary>390            RunningCritical,391 392            /// <summary>393            /// OffCritical. Critical states.394            /// </summary>395            OffCritical,396 397            /// <summary>398            /// StoppingCritical. Critical states.399            /// </summary>400            StoppingCritical,401 402            /// <summary>403            /// SavedCritical. Critical states.404            /// </summary>405            SavedCritical,406 407            /// <summary>408            /// PausedCritical. Critical states.409            /// </summary>410            PausedCritical,411 412            /// <summary>413            /// StartingCritical. Critical states.414            /// </summary>415            StartingCritical,416 417            /// <summary>418            /// ResetCritical. Critical states.419            /// </summary>420            ResetCritical,421 422            /// <summary>423            /// SavingCritical. Critical states.424            /// </summary>425            SavingCritical,426 427            /// <summary>428            /// PausingCritical. Critical states.429            /// </summary>430            PausingCritical,431 432            /// <summary>433            /// ResumingCritical. Critical states.434            /// </summary>435            ResumingCritical,436 437            /// <summary>438            /// FastSavedCritical. Critical states.439            /// </summary>440            FastSavedCritical,441 442            /// <summary>443            /// FastSavingCritical. Critical states.444            /// </summary>445            FastSavingCritical,446        }447 448#nullable enable449        /// <summary>450        /// Get the State property from Get-VM result.451        /// </summary>452        /// <param name="value">The raw PSObject as returned by Get-VM.</param>453        /// <returns>The VMState value of the State property if present and parsable, otherwise null.</returns>454        internal VMState? GetVMStateProperty(PSObject value)455        {456            object? rawState = value.Properties["State"].Value;457            if (rawState is Enum enumState)458            {459                // If the Hyper-V module was directly importable we have the VMState enum460                // value which we can just cast to our VMState type.461                return (VMState)enumState;462            }463            else if (rawState is string stringState && Enum.TryParse(stringState, true, out VMState result))464            {465                // If the Hyper-V module was imported through implicit remoting on old466                // Windows versions we get a string back which we will try and parse467                // as the enum label.468                return result;469            }470 471            // Unknown scenario, this should not happen.472            string message = PSRemotingErrorInvariants.FormatResourceString(473                RemotingErrorIdStrings.HyperVFailedToGetStateUnknownType,474                rawState?.GetType()?.FullName ?? "null");475            throw new InvalidOperationException(message);476        }477#nullable disable478 479        #endregion480 481        #region Tracer482 483        // PSETWTracer tracer = PSETWTracer.GetETWTracer(PSKeyword.Runspace);484 485        #endregion Tracer486 487        #region Properties488 489        /// <summary>490        /// The PSSession object describing the remote runspace491        /// using which the specified cmdlet operation will be performed.492        /// </summary>493        [Parameter(Position = 0,494                   ValueFromPipelineByPropertyName = true,495                   ParameterSetName = PSRemotingBaseCmdlet.SessionParameterSet)]496        [ValidateNotNullOrEmpty]497        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]498        public virtual PSSession[] Session { get; set; }499 500        /// <summary>501        /// This parameter represents the address(es) of the remote502        /// computer(s). The following formats are supported:503        ///      (a) Computer name504        ///      (b) IPv4 address : 132.3.4.5505        ///      (c) IPv6 address: 3ffe:8311:ffff:f70f:0:5efe:172.30.162.18.506        /// </summary>507        [Parameter(Position = 0,508                   ValueFromPipelineByPropertyName = true,509                   ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]510        [Alias("Cn")]511        public virtual string[] ComputerName { get; set; }512 513        /// <summary>514        /// Computer names after they have been resolved515        /// (null, empty string, "." resolves to localhost)516        /// </summary>517        /// <remarks>If Null or empty string is specified, then localhost is assumed.518        /// The ResolveComputerNames will include this.519        /// </remarks>520        protected string[] ResolvedComputerNames { get; set; }521 522        /// <summary>523        /// Guid of target virtual machine.524        /// </summary>525        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",526            Justification = "This is by spec.")]527        [Parameter(Position = 0,528                   Mandatory = true,529                   ValueFromPipelineByPropertyName = true,530                   ParameterSetName = PSRemotingBaseCmdlet.VMIdParameterSet)]531        [ValidateNotNullOrEmpty]532        [Alias("VMGuid")]533        public virtual Guid[] VMId { get; set; }534 535        /// <summary>536        /// Name of target virtual machine.537        /// </summary>538        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",539            Justification = "This is by spec.")]540        [Parameter(Mandatory = true,541                   ValueFromPipelineByPropertyName = true,542                   ParameterSetName = PSRemotingBaseCmdlet.VMNameParameterSet)]543        [ValidateNotNullOrEmpty]544        public virtual string[] VMName { get; set; }545 546        /// <summary>547        /// Specifies the credentials of the user to impersonate in the548        /// remote machine. If this parameter is not specified then the549        /// credentials of the current user process will be assumed.550        /// </summary>551        [Parameter(ValueFromPipelineByPropertyName = true,552                   ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]553        [Parameter(ValueFromPipelineByPropertyName = true,554                   ParameterSetName = PSRemotingBaseCmdlet.UriParameterSet)]555        [Parameter(ValueFromPipelineByPropertyName = true,556                   ParameterSetName = PSRemotingBaseCmdlet.VMIdParameterSet)]557        [Parameter(ValueFromPipelineByPropertyName = true,558                   ParameterSetName = PSRemotingBaseCmdlet.VMNameParameterSet)]559        [Credential()]560        public virtual PSCredential Credential561        {562            get563            {564                return _pscredential;565            }566 567            set568            {569                _pscredential = value;570                ValidateSpecifiedAuthentication(Credential, CertificateThumbprint, Authentication);571            }572        }573 574        private PSCredential _pscredential;575 576        /// <summary>577        /// ID of target container.578        /// </summary>579        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",580            Justification = "This is by spec.")]581        [Parameter(Mandatory = true,582                   ValueFromPipelineByPropertyName = true,583                   ParameterSetName = PSRemotingBaseCmdlet.ContainerIdParameterSet)]584        [ValidateNotNullOrEmpty]585        public virtual string[] ContainerId { get; set; }586 587        /// <summary>588        /// When set, PowerShell process inside container will be launched with589        /// high privileged account.590        /// Otherwise (default case), PowerShell process inside container will be launched591        /// with low privileged account.592        /// </summary>593        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ContainerIdParameterSet)]594        public virtual SwitchParameter RunAsAdministrator { get; set; }595 596        /// <summary>597        /// Port specifies the alternate port to be used in case the598        /// default ports are not used for the transport mechanism599        /// (port 80 for http and port 443 for useSSL)600        /// </summary>601        /// <remarks>602        /// Currently this is being accepted as a parameter. But in future603        /// support will be added to make this a part of a policy setting.604        /// When a policy setting is in place this parameter can be used605        /// to override the policy setting606        /// </remarks>607        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]608        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]609        [ValidateRange((int)1, (int)UInt16.MaxValue)]610        public virtual int Port { get; set; }611 612        /// <summary>613        /// This parameter suggests that the transport scheme to be used for614        /// remote connections is useSSL instead of the default http.Since615        /// there are only two possible transport schemes that are possible616        /// at this point, a SwitchParameter is being used to switch between617        /// the two.618        /// </summary>619        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]620        [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")]621        public virtual SwitchParameter UseSSL { get; set; }622 623        /// <summary>624        /// This parameters specifies the appname which identifies the connection625        /// end point on the remote machine. If this parameter is not specified626        /// then the value specified in DEFAULTREMOTEAPPNAME will be used. If that's627        /// not specified as well, then "WSMAN" will be used.628        /// </summary>629        [Parameter(ValueFromPipelineByPropertyName = true,630                   ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]631        public virtual string ApplicationName632        {633            get634            {635                return _appName;636            }637 638            set639            {640                _appName = ResolveAppName(value);641            }642        }643 644        private string _appName;645 646        /// <summary>647        /// Allows the user of the cmdlet to specify a throttling value648        /// for throttling the number of remote operations that can649        /// be executed simultaneously.650        /// </summary>651        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]652        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SessionParameterSet)]653        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.UriParameterSet)]654        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ContainerIdParameterSet)]655        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.VMIdParameterSet)]656        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.VMNameParameterSet)]657        public virtual int ThrottleLimit { get; set; } = 0;658 659        /// <summary>660        /// A complete URI(s) specified for the remote computer and shell to661        /// connect to and create runspace for.662        /// </summary>663        [Parameter(Position = 0, Mandatory = true,664                   ValueFromPipelineByPropertyName = true,665                   ParameterSetName = PSRemotingBaseCmdlet.UriParameterSet)]666        [ValidateNotNullOrEmpty]667        [Alias("URI", "CU")]668        public virtual Uri[] ConnectionUri { get; set; }669 670        /// <summary>671        /// The AllowRedirection parameter enables the implicit redirection functionality.672        /// </summary>673        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.UriParameterSet)]674        public virtual SwitchParameter AllowRedirection675        {676            get { return _allowRedirection; }677 678            set { _allowRedirection = value; }679        }680 681        private bool _allowRedirection = false;682 683        /// <summary>684        /// Extended Session Options for controlling the session creation. Use685        /// "New-WSManSessionOption" cmdlet to supply value for this parameter.686        /// </summary>687        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]688        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.UriParameterSet)]689        [ValidateNotNull]690        public virtual PSSessionOption SessionOption691        {692            get693            {694                if (_sessionOption == null)695                {696                    object tmp = this.SessionState.PSVariable.GetValue(DEFAULT_SESSION_OPTION);697                    if (tmp == null || !LanguagePrimitives.TryConvertTo<PSSessionOption>(tmp, out _sessionOption))698                    {699                        _sessionOption = new PSSessionOption();700                    }701                }702 703                return _sessionOption;704            }705 706            set707            {708                _sessionOption = value;709            }710        }711 712        private PSSessionOption _sessionOption;713 714        internal const string DEFAULT_SESSION_OPTION = "PSSessionOption";715 716        // Quota related variables.717        /// <summary>718        /// Use basic authentication to authenticate the user.719        /// </summary>720        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.ComputerNameParameterSet)]721        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.UriParameterSet)]722        public virtual AuthenticationMechanism Authentication723        {724            get725            {726                return _authMechanism;727            }728 729            set730            {731                _authMechanism = value;732                // Validate if a user can specify this authentication.733                ValidateSpecifiedAuthentication(Credential, CertificateThumbprint, Authentication);734            }735        }736 737        private AuthenticationMechanism _authMechanism = AuthenticationMechanism.Default;738 739        /// <summary>740        /// Specifies the certificate thumbprint to be used to impersonate the user on the741        /// remote machine.742        /// </summary>743        [Parameter(ParameterSetName = NewPSSessionCommand.ComputerNameParameterSet)]744        [Parameter(ParameterSetName = NewPSSessionCommand.UriParameterSet)]745        public virtual string CertificateThumbprint746        {747            get748            {749                return _thumbPrint;750            }751 752            set753            {754                _thumbPrint = value;755                ValidateSpecifiedAuthentication(Credential, CertificateThumbprint, Authentication);756            }757        }758 759        private string _thumbPrint = null;760 761        #region SSHHostParameters762 763        /// <summary>764        /// Host name for an SSH remote connection.765        /// </summary>766        [Parameter(Position = 0, Mandatory = true,767            ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]768        [ValidateNotNullOrEmpty()]769        public virtual string[] HostName770        {771            get;772            set;773        }774 775        /// <summary>776        /// SSH User Name.777        /// </summary>778        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]779        [ValidateNotNullOrEmpty()]780        public virtual string UserName781        {782            get;783            set;784        }785 786        /// <summary>787        /// SSH Key File Path.788        /// </summary>789        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]790        [ValidateNotNullOrEmpty()]791        [Alias("IdentityFilePath")]792        public virtual string KeyFilePath793        {794            get;795            set;796        }797 798        /// <summary>799        /// Gets or sets a value for the SSH subsystem to use for the remote connection.800        /// </summary>801        [Parameter(ValueFromPipelineByPropertyName = true,802                   ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]803        public virtual string Subsystem { get; set; }804 805        /// <summary>806        /// Gets or sets a value in milliseconds that limits the time allowed for an SSH connection to be established.807        /// Default timeout value is infinite.808        /// </summary>809        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]810        public virtual int ConnectingTimeout { get; set; } = Timeout.Infinite;811 812        /// <summary>813        /// This parameter specifies that SSH is used to establish the remote814        /// connection and act as the remoting transport.  By default WinRM is used815        /// as the remoting transport.  Using the SSH transport requires that SSH is816        /// installed and PowerShell remoting is enabled on both client and remote machines.817        /// </summary>818        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]819        [ValidateSet("true")]820        public virtual SwitchParameter SSHTransport821        {822            get;823            set;824        }825 826        /// <summary>827        /// Hashtable array containing SSH connection parameters for each remote target828        ///   ComputerName  (Alias: HostName)           (required)829        ///   UserName                                  (optional)830        ///   KeyFilePath   (Alias: IdentityFilePath)   (optional)831        /// </summary>832        [Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostHashParameterSet, Mandatory = true)]833        [ValidateNotNullOrEmpty()]834        public virtual Hashtable[] SSHConnection835        {836            get;837            set;838        }839 840        /// <summary>841        /// Gets or sets the Hashtable containing options to be passed to OpenSSH.842        /// </summary>843        [Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]844        [ValidateNotNullOrEmpty]845        public virtual Hashtable Options { get; set; }846 847        #endregion848 849        #endregion Properties850 851        #region Internal Static Methods852 853        /// <summary>854        /// Used to resolve authentication from the parameters chosen by the user.855        /// User has the following options:856        /// 1. AuthMechanism + Credential857        /// 2. CertificateThumbPrint858        ///859        /// All the above are mutually exclusive.860        /// </summary>861        /// <exception cref="InvalidOperationException">862        /// If there is ambiguity as specified above.863        /// </exception>864        internal static void ValidateSpecifiedAuthentication(PSCredential credential, string thumbprint, AuthenticationMechanism authentication)865        {866            if ((credential != null) && (thumbprint != null))867            {868                string message = PSRemotingErrorInvariants.FormatResourceString(869                    RemotingErrorIdStrings.NewRunspaceAmbiguousAuthentication,870                        "CertificateThumbPrint", "Credential");871 872                throw new InvalidOperationException(message);873            }874 875            if ((authentication != AuthenticationMechanism.Default) && (thumbprint != null))876            {877                string message = PSRemotingErrorInvariants.FormatResourceString(878                    RemotingErrorIdStrings.NewRunspaceAmbiguousAuthentication,879                        "CertificateThumbPrint", authentication.ToString());880 881                throw new InvalidOperationException(message);882            }883 884            if ((authentication == AuthenticationMechanism.NegotiateWithImplicitCredential) &&885                (credential != null))886            {887                string message = PSRemotingErrorInvariants.FormatResourceString(888                    RemotingErrorIdStrings.NewRunspaceAmbiguousAuthentication,889                    "Credential", authentication.ToString());890                throw new InvalidOperationException(message);891            }892        }893 894        #endregion895 896        #region Internal Methods897 898        #region SSH Connection Strings899 900        private const string ComputerNameParameter = "ComputerName";901        private const string HostNameAlias = "HostName";902        private const string UserNameParameter = "UserName";903        private const string KeyFilePathParameter = "KeyFilePath";904        private const string IdentityFilePathAlias = "IdentityFilePath";905        private const string PortParameter = "Port";906        private const string SubsystemParameter = "Subsystem";907        private const string ConnectingTimeoutParameter = "ConnectingTimeout";908        private const string OptionsParameter = "Options";909 910        #endregion911 912        /// <summary>913        /// Parse a hostname used with SSH Transport to get embedded914        /// username and/or port.915        /// </summary>916        /// <param name="hostname">Host name to parse.</param>917        /// <param name="host">Resolved target host.</param>918        /// <param name="userName">Resolved target user name.</param>919        /// <param name="port">Resolved target port.</param>920        protected void ParseSshHostName(string hostname, out string host, out string userName, out int port)921        {922            host = hostname;923            userName = this.UserName;924            port = this.Port;925            try926            {927                Uri uri = new System.Uri("ssh://" + hostname);928                host = ResolveComputerName(uri.Host);929                ValidateComputerName(new string[] { host });930                if (uri.UserInfo != string.Empty)931                {932                    userName = uri.UserInfo;933                }934 935                if (uri.Port != -1)936                {937                    port = uri.Port;938                }939            }940            catch (UriFormatException)941            {942                ThrowTerminatingError(new ErrorRecord(943                    new ArgumentException(PSRemotingErrorInvariants.FormatResourceString(944                        RemotingErrorIdStrings.InvalidComputerName)), "PSSessionInvalidComputerName",945                            ErrorCategory.InvalidArgument, hostname));946            }947        }948 949        /// <summary>950        /// Parse the Connection parameter HashTable array.951        /// </summary>952        /// <returns>Array of SSHConnection objects.</returns>953        internal SSHConnection[] ParseSSHConnectionHashTable()954        {955            List<SSHConnection> connections = new();956            foreach (var item in this.SSHConnection)957            {958                if (item.ContainsKey(ComputerNameParameter) && item.ContainsKey(HostNameAlias))959                {960                    throw new PSArgumentException(RemotingErrorIdStrings.SSHConnectionDuplicateHostName);961                }962 963                if (item.ContainsKey(KeyFilePathParameter) && item.ContainsKey(IdentityFilePathAlias))964                {965                    throw new PSArgumentException(RemotingErrorIdStrings.SSHConnectionDuplicateKeyPath);966                }967 968                SSHConnection connectionInfo = new();969                foreach (var key in item.Keys)970                {971                    string paramName = key as string;972                    if (string.IsNullOrEmpty(paramName))973                    {974                        throw new PSArgumentException(RemotingErrorIdStrings.InvalidSSHConnectionParameter);975                    }976 977                    if (paramName.Equals(ComputerNameParameter, StringComparison.OrdinalIgnoreCase) || paramName.Equals(HostNameAlias, StringComparison.OrdinalIgnoreCase))978                    {979                        var resolvedComputerName = ResolveComputerName(GetSSHConnectionStringParameter(item[paramName]));980                        ParseSshHostName(resolvedComputerName, out string host, out string userName, out int port);981                        connectionInfo.ComputerName = host;982                        if (userName != string.Empty)983                        {984                            connectionInfo.UserName = userName;985                        }986 987                        if (port != -1)988                        {989                            connectionInfo.Port = port;990                        }991                    }992                    else if (paramName.Equals(UserNameParameter, StringComparison.OrdinalIgnoreCase))993                    {994                        connectionInfo.UserName = GetSSHConnectionStringParameter(item[paramName]);995                    }996                    else if (paramName.Equals(KeyFilePathParameter, StringComparison.OrdinalIgnoreCase) || paramName.Equals(IdentityFilePathAlias, StringComparison.OrdinalIgnoreCase))997                    {998                        connectionInfo.KeyFilePath = GetSSHConnectionStringParameter(item[paramName]);999                    }1000                    else if (paramName.Equals(PortParameter, StringComparison.OrdinalIgnoreCase))1001                    {1002                        connectionInfo.Port = GetSSHConnectionIntParameter(item[paramName]);1003                    }1004                    else if (paramName.Equals(SubsystemParameter, StringComparison.OrdinalIgnoreCase))1005                    {1006                        connectionInfo.Subsystem = GetSSHConnectionStringParameter(item[paramName]);1007                    }1008                    else if (paramName.Equals(ConnectingTimeoutParameter, StringComparison.OrdinalIgnoreCase))1009                    {1010                        connectionInfo.ConnectingTimeout = GetSSHConnectionIntParameter(item[paramName]);1011                    }1012                    else if (paramName.Equals(OptionsParameter, StringComparison.OrdinalIgnoreCase))1013                    {1014                        connectionInfo.Options = item[paramName] as Hashtable;1015                    }1016                    else1017                    {1018                        throw new PSArgumentException(1019                            StringUtil.Format(RemotingErrorIdStrings.UnknownSSHConnectionParameter, paramName));1020                    }1021                }1022 1023                if (string.IsNullOrEmpty(connectionInfo.ComputerName))1024                {1025                    throw new PSArgumentException(RemotingErrorIdStrings.MissingRequiredSSHParameter);1026                }1027 1028                connections.Add(connectionInfo);1029            }1030 1031            return connections.ToArray();1032        }1033 1034        #endregion1035 1036        #region Private Methods1037 1038        /// <summary>1039        /// Validate the PSSession objects specified and write1040        /// appropriate error records.1041        /// </summary>1042        /// <remarks>This function will lead in terminating errors when any of1043        /// the validations fail</remarks>1044        protected void ValidateRemoteRunspacesSpecified()1045        {1046            Dbg.Assert(Session != null && Session.Length != 0,1047                    "Remote Runspaces specified must not be null or empty");1048 1049            // Check if there are duplicates in the specified PSSession objects1050            if (RemotingCommandUtil.HasRepeatingRunspaces(Session))1051            {1052                ThrowTerminatingError(new ErrorRecord(new ArgumentException(1053                    GetMessage(RemotingErrorIdStrings.RemoteRunspaceInfoHasDuplicates)),1054                        nameof(PSRemotingErrorId.RemoteRunspaceInfoHasDuplicates),1055                            ErrorCategory.InvalidArgument, Session));1056            }1057 1058            // BUGBUG: The following is a bogus check1059            // Check if the number of PSSession objects specified is greater1060            // than the maximum allowable range1061            if (RemotingCommandUtil.ExceedMaximumAllowableRunspaces(Session))1062            {1063                ThrowTerminatingError(new ErrorRecord(new ArgumentException(1064                    GetMessage(RemotingErrorIdStrings.RemoteRunspaceInfoLimitExceeded)),1065                        nameof(PSRemotingErrorId.RemoteRunspaceInfoLimitExceeded),1066                            ErrorCategory.InvalidArgument, Session));1067            }1068        }1069 1070        /// <summary>1071        /// Updates connection info with the data read from cmdlet's parameters and1072        /// sessions variables.1073        /// The following data is updated:1074        /// 1. MaxURIRedirectionCount1075        /// 2. MaxRecvdDataSizePerSession1076        /// 3. MaxRecvdDataSizePerCommand1077        /// 4. MaxRecvdObjectSize.1078        /// </summary>1079        /// <param name="connectionInfo"></param>1080        internal void UpdateConnectionInfo(WSManConnectionInfo connectionInfo)1081        {1082            Dbg.Assert(connectionInfo != null, "connectionInfo cannot be null.");1083 1084            connectionInfo.SetSessionOptions(this.SessionOption);1085 1086            if (!ParameterSetName.Equals(PSRemotingBaseCmdlet.UriParameterSet, StringComparison.OrdinalIgnoreCase))1087            {1088                // uri redirection is supported only with URI parameter set1089                connectionInfo.MaximumConnectionRedirectionCount = 0;1090            }1091 1092            if (!_allowRedirection)1093            {1094                // uri redirection required explicit user consent1095                connectionInfo.MaximumConnectionRedirectionCount = 0;1096            }1097        }1098 1099        /// <summary>1100        /// Uri parameter set.1101        /// </summary>1102        protected const string UriParameterSet = "Uri";1103 1104        /// <summary>1105        /// Validates computer names to check if none of them1106        /// happen to be a Uri. If so this throws an error.1107        /// </summary>1108        /// <param name="computerNames">collection of computer1109        /// names to validate</param>1110        protected void ValidateComputerName(string[] computerNames)1111        {1112            foreach (string computerName in computerNames)1113            {1114                UriHostNameType nametype = Uri.CheckHostName(computerName);1115                if (!(nametype == UriHostNameType.Dns || nametype == UriHostNameType.IPv4 ||1116                    nametype == UriHostNameType.IPv6))1117                {1118                    ThrowTerminatingError(new ErrorRecord(1119                        new ArgumentException(PSRemotingErrorInvariants.FormatResourceString(1120                            RemotingErrorIdStrings.InvalidComputerName)), "PSSessionInvalidComputerName",1121                                ErrorCategory.InvalidArgument, computerNames));1122                }1123            }1124        }1125 1126        /// <summary>1127        /// Validates parameter value and returns as string.1128        /// </summary>1129        /// <param name="param">Parameter value to be validated.</param>1130        /// <returns>Parameter value as string.</returns>1131        private static string GetSSHConnectionStringParameter(object param)1132        {1133            string paramValue;1134            try1135            {1136                paramValue = LanguagePrimitives.ConvertTo<string>(param);1137            }1138            catch (PSInvalidCastException e)1139            {1140                throw new PSArgumentException(e.Message, e);1141            }1142 1143            if (!string.IsNullOrEmpty(paramValue))1144            {1145                return paramValue;1146            }1147 1148            throw new PSArgumentException(RemotingErrorIdStrings.InvalidSSHConnectionParameter);1149        }1150 1151        /// <summary>1152        /// Validates parameter value and returns as integer.1153        /// </summary>1154        /// <param name="param">Parameter value to be validated.</param>1155        /// <returns>Parameter value as integer.</returns>1156        private static int GetSSHConnectionIntParameter(object param)1157        {1158            if (param == null)1159            {1160                throw new PSArgumentException(RemotingErrorIdStrings.InvalidSSHConnectionParameter);1161            }1162 1163            try1164            {1165                return LanguagePrimitives.ConvertTo<int>(param);1166            }1167            catch (PSInvalidCastException e)1168            {1169                throw new PSArgumentException(e.Message, e);1170            }1171        }1172 1173        #endregion Private Methods1174 1175        #region Overrides1176 1177        /// <summary>1178        /// Resolves shellname and appname.1179        /// </summary>1180        protected override void BeginProcessing()1181        {1182            base.BeginProcessing();1183 1184            // Validate KeyFilePath parameter.1185            if ((ParameterSetName == PSRemotingBaseCmdlet.SSHHostParameterSet) &&1186                (this.KeyFilePath != null))1187            {1188                // Resolve the key file path when set.1189                this.KeyFilePath = PathResolver.ResolveProviderAndPath(this.KeyFilePath, true, this, false, RemotingErrorIdStrings.FilePathNotFromFileSystemProvider);1190            }1191 1192            // Validate IdleTimeout parameter.1193            int idleTimeout = (int)SessionOption.IdleTimeout.TotalMilliseconds;1194            if (idleTimeout != BaseTransportManager.UseServerDefaultIdleTimeout &&1195                idleTimeout < BaseTransportManager.MinimumIdleTimeout)1196            {1197                throw new PSArgumentException(1198                    StringUtil.Format(RemotingErrorIdStrings.InvalidIdleTimeoutOption,1199                    idleTimeout / 1000, BaseTransportManager.MinimumIdleTimeout / 1000));1200            }

Showing the first 1,200 of 4545 lines. Download the file for the rest.