MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.ComponentModel; // Win32Exception7using System.Diagnostics;8using System.Diagnostics.CodeAnalysis;9using System.Globalization;10using System.IO;11using System.IO.Pipes;12using System.Management.Automation.Internal;13using System.Management.Automation.Remoting;14using System.Management.Automation.Remoting.Client;15using System.Management.Automation.Tracing;16using System.Net;17using System.Net.Sockets;18using System.Reflection;19using System.Runtime.InteropServices;20using System.Security.AccessControl;21using System.Text;22using System.Threading;23 24using Microsoft.Win32.SafeHandles;25 26using Dbg = System.Management.Automation.Diagnostics;27using WSManAuthenticationMechanism = System.Management.Automation.Remoting.Client.WSManNativeApi.WSManAuthenticationMechanism;28 29// ReSharper disable CheckNamespace30 31namespace System.Management.Automation.Runspaces32// ReSharper restore CheckNamespace33{34 /// <summary>35 /// Different Authentication Mechanisms supported by New-Runspace command to connect36 /// to remote server.37 /// </summary>38 [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")]39 [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]40 public enum AuthenticationMechanism41 {42 /// <summary>43 /// Use the default authentication (as defined by the underlying protocol)44 /// for establishing a remote connection.45 /// </summary>46 Default = 0x0,47 /// <summary>48 /// Use Basic authentication for establishing a remote connection.49 /// </summary>50 Basic = 0x1,51 /// <summary>52 /// Use Negotiate authentication for establishing a remote connection.53 /// </summary>54 Negotiate = 0x2,55 /// <summary>56 /// Use Negotiate authentication for establishing a remote connection.57 /// Allow implicit credentials for Negotiate.58 /// </summary>59 NegotiateWithImplicitCredential = 0x3,60 /// <summary>61 /// Use CredSSP authentication for establishing a remote connection.62 /// </summary>63 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Credssp")]64 Credssp = 0x4,65 /// <summary>66 /// Use Digest authentication mechanism. Digest authentication operates much67 /// like Basic authentication. However, unlike Basic authentication, Digest authentication68 /// transmits credentials across the network as a hash value, also known as a message digest.69 /// The user name and password cannot be deciphered from the hash value. Conversely, Basic70 /// authentication sends a Base 64 encoded password, essentially in clear text, across the71 /// network.72 /// </summary>73 Digest = 0x5,74 /// <summary>75 /// Use Kerberos authentication for establishing a remote connection.76 /// </summary>77 Kerberos = 0x6,78 }79 80 /// <summary>81 /// Specify the type of access mode that should be82 /// used when creating a session configuration.83 /// </summary>84 public enum PSSessionConfigurationAccessMode85 {86 /// <summary>87 /// Disable the configuration.88 /// </summary>89 Disabled = 0,90 91 /// <summary>92 /// Allow local access.93 /// </summary>94 Local = 1,95 96 /// <summary>97 /// Default allow remote access.98 /// </summary>99 Remote = 2,100 }101 102 /// <summary>103 /// WSManTransportManager supports disconnected PowerShell sessions.104 /// When a remote PS session server is in disconnected state, output105 /// from the running command pipeline is cached on the server. This106 /// enum determines what the server does when the cache is full.107 /// </summary>108 public enum OutputBufferingMode109 {110 /// <summary>111 /// No output buffering mode specified. Output buffering mode on server will112 /// default to Block if a new session is created, or will retain its current113 /// mode for non-creation scenarios (e.g., disconnect/connect operations).114 /// </summary>115 None = 0,116 117 /// <summary>118 /// Command pipeline execution continues, excess output is dropped in FIFO manner.119 /// </summary>120 Drop = 1,121 122 /// <summary>123 /// Command pipeline execution on server is blocked until session is reconnected.124 /// </summary>125 Block = 2126 }127 128 /// <summary>129 /// Class which defines connection path to a remote runspace130 /// that needs to be created. Transport specific connection131 /// paths will be derived from this.132 /// </summary>133 public abstract class RunspaceConnectionInfo134 {135 #region Public Properties136 137 /// <summary>138 /// Name of the computer.139 /// </summary>140 public abstract string ComputerName { get; set; }141 142 /// <summary>143 /// Credential used for the connection.144 /// </summary>145 public abstract PSCredential Credential { get; set; }146 147 /// <summary>148 /// Authentication mechanism to use while connecting to the server.149 /// </summary>150 public abstract AuthenticationMechanism AuthenticationMechanism { get; set; }151 152 /// <summary>153 /// ThumbPrint of a certificate used for connecting to a remote machine.154 /// When this is specified, you dont need to supply credential and authentication155 /// mechanism.156 /// </summary>157 public abstract string CertificateThumbprint { get; set; }158 159 /// <summary>160 /// Culture that the remote session should use.161 /// </summary>162 public CultureInfo Culture163 {164 get165 {166 return _culture;167 }168 169 set170 {171 ArgumentNullException.ThrowIfNull(value);172 173 _culture = value;174 }175 }176 177 private CultureInfo _culture = CultureInfo.CurrentCulture;178 179 /// <summary>180 /// UI culture that the remote session should use.181 /// </summary>182 public CultureInfo UICulture183 {184 get185 {186 return _uiCulture;187 }188 189 set190 {191 ArgumentNullException.ThrowIfNull(value);192 193 _uiCulture = value;194 }195 }196 197 private CultureInfo _uiCulture = CultureInfo.CurrentUICulture;198 199 /// <summary>200 /// The duration (in ms) for which PowerShell remoting waits before timing out on a connection to a remote machine.201 /// Simply put, the timeout for a remote runspace creation.202 /// The administrator would like to tweak this timeout depending on whether203 /// he/she is connecting to a machine in the data center or across a slow WAN.204 /// </summary>205 public int OpenTimeout206 {207 get208 {209 return _openTimeout;210 }211 212 set213 {214 _openTimeout = value;215 216 if (this is WSManConnectionInfo && _openTimeout == DefaultTimeout)217 {218 _openTimeout = DefaultOpenTimeout;219 }220 else if (this is WSManConnectionInfo && _openTimeout == InfiniteTimeout)221 {222 // this timeout value gets passed to a223 // timer associated with the session224 // data structure handler state machine.225 // The timer constructor will throw an exception226 // for any value greater than Int32.MaxValue227 // hence this is the maximum possible limit228 _openTimeout = Int32.MaxValue;229 }230 }231 }232 233 private int _openTimeout = DefaultOpenTimeout;234 235 internal const int DefaultOpenTimeout = 3 * 60 * 1000; // 3 minutes236 internal const int DefaultTimeout = -1;237 internal const int InfiniteTimeout = 0;238 239 /// <summary>240 /// The duration (in ms) for which PowerShell should wait before it times out on cancel operations241 /// (close runspace or stop powershell). For instance, when the user hits ctrl-C,242 /// New-PSSession cmdlet tries to call a stop on all remote runspaces which are in the Opening state.243 /// The administrator wouldn't mind waiting for 15 seconds, but this should be time bound and of a shorter duration.244 /// A high timeout here like 3 minutes will give the administrator a feeling that the PowerShell client is not responding.245 /// </summary>246 public int CancelTimeout { get; set; } = defaultCancelTimeout;247 248 internal const int defaultCancelTimeout = BaseTransportManager.ClientCloseTimeoutMs;249 250 /// <summary>251 /// The duration for which PowerShell remoting waits before timing out252 /// for any operation. The user would like to tweak this timeout253 /// depending on whether he/she is connecting to a machine in the data254 /// center or across a slow WAN.255 ///256 /// Default: 3*60*1000 == 3minutes.257 /// </summary>258 public int OperationTimeout { get; set; } = BaseTransportManager.ClientDefaultOperationTimeoutMs;259 260 /// <summary>261 /// The duration (in ms) for which a Runspace on server needs to wait before it declares the client dead and closes itself down.262 /// This is especially important as these values may have to be configured differently for enterprise administration263 /// and exchange scenarios.264 /// </summary>265 public int IdleTimeout { get; set; } = DefaultIdleTimeout;266 267 internal const int DefaultIdleTimeout = BaseTransportManager.UseServerDefaultIdleTimeout;268 269 /// <summary>270 /// The maximum allowed idle timeout duration (in ms) that can be set on a Runspace. This is a read-only property271 /// that is set once the Runspace is successfully created and opened.272 /// </summary>273 public int MaxIdleTimeout { get; internal set; } = Int32.MaxValue;274 275 /// <summary>276 /// Populates session options from a PSSessionOption instance.277 /// </summary>278 /// <param name="options"></param>279 public virtual void SetSessionOptions(PSSessionOption options)280 {281 ArgumentNullException.ThrowIfNull(options);282 283 if (options.Culture != null)284 {285 this.Culture = options.Culture;286 }287 288 if (options.UICulture != null)289 {290 this.UICulture = options.UICulture;291 }292 293 _openTimeout = TimeSpanToTimeOutMs(options.OpenTimeout);294 CancelTimeout = TimeSpanToTimeOutMs(options.CancelTimeout);295 OperationTimeout = TimeSpanToTimeOutMs(options.OperationTimeout);296 297 // Special case for idle timeout. A value of milliseconds == -1298 // (BaseTransportManager.UseServerDefaultIdleTimeout) is allowed for299 // specifying the default value on the server.300 IdleTimeout = (options.IdleTimeout.TotalMilliseconds >= BaseTransportManager.UseServerDefaultIdleTimeout &&301 options.IdleTimeout.TotalMilliseconds < int.MaxValue)302 ? (int)(options.IdleTimeout.TotalMilliseconds) : int.MaxValue;303 }304 305 #endregion Public Properties306 307 #region Internal Methods308 309 internal int TimeSpanToTimeOutMs(TimeSpan t)310 {311 if ((t.TotalMilliseconds > int.MaxValue) || (t == TimeSpan.MaxValue) || (t.TotalMilliseconds < 0))312 {313 return int.MaxValue;314 }315 else316 {317 return (int)(t.TotalMilliseconds);318 }319 }320 321 /// <summary>322 /// Validates port number is in range.323 /// </summary>324 /// <param name="port">Port number to validate.</param>325 internal virtual void ValidatePortInRange(int port)326 {327 if ((port < MinPort || port > MaxPort))328 {329 string message =330 PSRemotingErrorInvariants.FormatResourceString(331 RemotingErrorIdStrings.PortIsOutOfRange, port);332 ArgumentException e = new ArgumentException(message);333 throw e;334 }335 }336 337 #endregion338 339 #region Public methods340 341 /// <summary>342 /// Creates the appropriate client session transportmanager.343 /// </summary>344 /// <param name="instanceId">Runspace/Pool instance Id.</param>345 /// <param name="sessionName">Session name.</param>346 /// <param name="cryptoHelper">PSRemotingCryptoHelper.</param>347 public virtual BaseClientSessionTransportManager CreateClientSessionTransportManager(348 Guid instanceId,349 string sessionName,350 PSRemotingCryptoHelper cryptoHelper)351 {352 throw new PSNotImplementedException();353 }354 355 /// <summary>356 /// Create a copy of the connection info object.357 /// </summary>358 /// <returns>Copy of the connection info object.</returns>359 public virtual RunspaceConnectionInfo Clone()360 {361 throw new PSNotImplementedException();362 }363 364 #endregion365 366 #region Constants367 368 /// <summary>369 /// Maximum value for port.370 /// </summary>371 protected const int MaxPort = 0xFFFF;372 373 /// <summary>374 /// Minimum value for port.375 /// </summary>376 protected const int MinPort = 0;377 378 #endregion379 }380 381 /// <summary>382 /// Class which defines path to a remote runspace that383 /// need to be created.384 /// </summary>385 public sealed class WSManConnectionInfo : RunspaceConnectionInfo386 {387 #region Public Properties388 389 /// <summary>390 /// Uri associated with this connection path.391 /// </summary>392 public Uri ConnectionUri393 {394 get395 {396 return _connectionUri;397 }398 399 set400 {401 if (value == null)402 {403 throw PSTraceSource.NewArgumentNullException("value");404 }405 406 UpdateUri(value);407 }408 }409 410 /// <summary>411 /// Name of the computer.412 /// </summary>413 public override string ComputerName414 {415 get416 {417 return _computerName;418 }419 420 set421 {422 // null or empty value allowed423 ConstructUri(_scheme, value, null, _appName);424 }425 }426 427 /// <summary>428 /// Scheme used for connection.429 /// </summary>430 public string Scheme431 {432 get433 {434 return _scheme;435 }436 437 set438 {439 // null or empty value allowed440 ConstructUri(value, _computerName, null, _appName);441 }442 }443 444 /// <summary>445 /// Port in which to connect.446 /// </summary>447 public int Port448 {449 get450 {451 return ConnectionUri.Port;452 }453 454 set455 {456 ConstructUri(_scheme, _computerName, value, _appName);457 }458 }459 460 /// <summary>461 /// AppName which identifies the connection462 /// end point in the machine.463 /// </summary>464 public string AppName465 {466 get467 {468 return _appName;469 }470 471 set472 {473 // null or empty value allowed474 ConstructUri(_scheme, _computerName, null, value);475 }476 }477 478 /// <summary>479 /// Credential used for the connection.480 /// </summary>481 public override PSCredential Credential482 {483 get484 {485 return _credential;486 }487 488 set489 {490 // null or empty value allowed491 _credential = value;492 }493 }494 495 /// <summary>496 /// </summary>497 [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Scope = "member", Target = "System.Management.Automation.Runspaces.WSManConnectionInfo.#ShellUri")]498 public string ShellUri499 {500 get501 {502 return _shellUri;503 }504 505 set506 {507 _shellUri = ResolveShellUri(value);508 }509 }510 511 /// <summary>512 /// Authentication mechanism to use while connecting to the server.513 /// </summary>514 public override AuthenticationMechanism AuthenticationMechanism515 {516 get517 {518 switch (WSManAuthenticationMechanism)519 {520 case WSManAuthenticationMechanism.WSMAN_FLAG_DEFAULT_AUTHENTICATION:521 return AuthenticationMechanism.Default;522 case WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_BASIC:523 return AuthenticationMechanism.Basic;524 case WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_CREDSSP:525 return AuthenticationMechanism.Credssp;526 case WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_NEGOTIATE:527 if (AllowImplicitCredentialForNegotiate)528 {529 return AuthenticationMechanism.NegotiateWithImplicitCredential;530 }531 532 return AuthenticationMechanism.Negotiate;533 case WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_DIGEST:534 return AuthenticationMechanism.Digest;535 case WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_KERBEROS:536 return AuthenticationMechanism.Kerberos;537 default:538 Dbg.Assert(false, "Invalid authentication mechanism detected.");539 return AuthenticationMechanism.Default;540 }541 }542 543 set544 {545 switch (value)546 {547 case AuthenticationMechanism.Default:548 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_DEFAULT_AUTHENTICATION;549 break;550 case AuthenticationMechanism.Basic:551 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_BASIC;552 break;553 case AuthenticationMechanism.Negotiate:554 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_NEGOTIATE;555 break;556 case AuthenticationMechanism.NegotiateWithImplicitCredential:557 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_NEGOTIATE;558 AllowImplicitCredentialForNegotiate = true;559 break;560 case AuthenticationMechanism.Credssp:561 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_CREDSSP;562 break;563 case AuthenticationMechanism.Digest:564 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_DIGEST;565 break;566 case AuthenticationMechanism.Kerberos:567 WSManAuthenticationMechanism = WSManAuthenticationMechanism.WSMAN_FLAG_AUTH_KERBEROS;568 break;569 default:570 throw new PSNotSupportedException();571 }572 573 ValidateSpecifiedAuthentication();574 }575 }576 577 /// <summary>578 /// AuthenticationMechanism converted to WSManAuthenticationMechanism type.579 /// This is internal.580 /// </summary>581 internal WSManAuthenticationMechanism WSManAuthenticationMechanism { get; private set; } = WSManAuthenticationMechanism.WSMAN_FLAG_DEFAULT_AUTHENTICATION;582 583 /// <summary>584 /// Allow default credentials for Negotiate.585 /// </summary>586 internal bool AllowImplicitCredentialForNegotiate { get; private set; }587 588 /// <summary>589 /// Returns the actual port property value and not the ConnectionUri port.590 /// Internal only.591 /// </summary>592 internal int PortSetting { get; private set; } = -1;593 594 /// <summary>595 /// ThumbPrint of a certificate used for connecting to a remote machine.596 /// When this is specified, you dont need to supply credential and authentication597 /// mechanism.598 /// </summary>599 public override string CertificateThumbprint600 {601 get602 {603 return _thumbPrint;604 }605 606 set607 {608 if (value == null)609 {610 throw PSTraceSource.NewArgumentNullException("value");611 }612 613 _thumbPrint = value;614 }615 }616 617 /// <summary>618 /// Maximum uri redirection count.619 /// </summary>620 public int MaximumConnectionRedirectionCount { get; set; }621 622 internal const int defaultMaximumConnectionRedirectionCount = 5;623 624 /// <summary>625 /// Total data (in bytes) that can be received from a remote machine626 /// targeted towards a command. If null, then the size is unlimited.627 /// Default is unlimited data.628 /// </summary>629 public int? MaximumReceivedDataSizePerCommand { get; set; }630 631 /// <summary>632 /// Maximum size (in bytes) of a deserialized object received from a remote machine.633 /// If null, then the size is unlimited. Default is unlimited object size.634 /// </summary>635 public int? MaximumReceivedObjectSize { get; set; }636 637 /// <summary>638 /// If true, underlying WSMan infrastructure will compress data sent on the network.639 /// If false, data will not be compressed. Compression improves performance by640 /// reducing the amount of data sent on the network. Compression my require extra641 /// memory consumption and CPU usage. In cases where available memory / CPU is less,642 /// set this property to false.643 /// By default the value of this property is "true".644 /// </summary>645 public bool UseCompression { get; set; } = true;646 647 /// <summary>648 /// If <see langword="true"/> then Operating System won't load the user profile (i.e. registry keys under HKCU) on the remote server649 /// which can result in a faster session creation time. This option won't have any effect if the remote machine has650 /// already loaded the profile (i.e. in another session).651 /// </summary>652 public bool NoMachineProfile { get; set; }653 654 // BEGIN: Session Options655 656 /// <summary>657 /// By default, wsman uses IEConfig - the current user658 /// Internet Explorer proxy settings for the current active network connection.659 /// This option requires the user profile to be loaded, so the option can660 /// be directly used when called within a process that is running under661 /// an interactive user account identity; if the client application is running662 /// under a user context different then the interactive user, the client663 /// application has to explicitly load the user profile prior to using this option.664 ///665 /// IMPORTANT: proxy configuration is supported for HTTPS only; for HTTP, the direct666 /// connection to the server is used.667 /// </summary>668 public ProxyAccessType ProxyAccessType { get; set; } = ProxyAccessType.None;669 670 /// <summary>671 /// The following is the definition of the input parameter "ProxyAuthentication".672 /// This parameter takes a set of authentication methods the user can select673 /// from. The available options should be as follows:674 /// - Negotiate: Use the default authentication (ad defined by the underlying675 /// protocol) for establishing a remote connection.676 /// - Basic: Use basic authentication for establishing a remote connection677 /// - Digest: Use Digest authentication for establishing a remote connection.678 /// </summary>679 public AuthenticationMechanism ProxyAuthentication680 {681 get682 {683 return _proxyAuthentication;684 }685 686 set687 {688 switch (value)689 {690 case AuthenticationMechanism.Basic:691 case AuthenticationMechanism.Negotiate:692 case AuthenticationMechanism.Digest:693 _proxyAuthentication = value;694 break;695 default:696 string message = PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.ProxyAmbiguousAuthentication,697 value,698 nameof(AuthenticationMechanism.Basic),699 nameof(AuthenticationMechanism.Negotiate),700 nameof(AuthenticationMechanism.Digest));701 throw new ArgumentException(message);702 }703 }704 }705 706 /// <summary>707 /// The following is the definition of the input parameter "ProxyCredential".708 /// </summary>709 public PSCredential ProxyCredential710 {711 get712 {713 return _proxyCredential;714 }715 716 set717 {718 if (ProxyAccessType == ProxyAccessType.None)719 {720 string message = PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.ProxyCredentialWithoutAccess,721 ProxyAccessType.None);722 throw new ArgumentException(message);723 }724 725 _proxyCredential = value;726 }727 }728 729 /// <summary>730 /// When connecting over HTTPS, the client does not validate that the server731 /// certificate is signed by a trusted certificate authority (CA). Use only when732 /// the remote computer is trusted by other means, for example, if the remote733 /// computer is part of a network that is physically secure and isolated or the734 /// remote computer is listed as a trusted host in WinRM configuration.735 /// </summary>736 public bool SkipCACheck { get; set; }737 738 /// <summary>739 /// Indicates that certificate common name (CN) of the server need not match the740 /// hostname of the server. Used only in remote operations using https. This741 /// option should only be used for trusted machines.742 /// </summary>743 public bool SkipCNCheck { get; set; }744 745 /// <summary>746 /// Indicates that certificate common name (CN) of the server need not match the747 /// hostname of the server. Used only in remote operations using https. This748 /// option should only be used for trusted machines.749 /// </summary>750 public bool SkipRevocationCheck { get; set; }751 752 /// <summary>753 /// Specifies that no encryption will be used when doing remote operations over754 /// http. Unencrypted traffic is not allowed by default and must be enabled in755 /// the local configuration.756 /// </summary>757 public bool NoEncryption { get; set; }758 759 /// <summary>760 /// Indicates the request is encoded in UTF16 format rather than UTF8 format;761 /// UTF8 is the default.762 /// </summary>763 [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "UTF")]764 public bool UseUTF16 { get; set; }765 766 // END: Session Options767 768 /// <summary>769 /// Determines how server in disconnected state deals with cached output770 /// data when the cache becomes filled.771 /// </summary>772 public OutputBufferingMode OutputBufferingMode { get; set; } = DefaultOutputBufferingMode;773 774 /// <summary>775 /// Uses Service Principal Name (SPN) along with the Port number during authentication.776 /// </summary>777 [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SPN")]778 public bool IncludePortInSPN { get; set; }779 780 /// <summary>781 /// When true and in loopback scenario (localhost) this enables creation of WSMan782 /// host process with the user interactive token, allowing PowerShell script network access,783 /// i.e., allows going off box. When this property is true and a PSSession is disconnected,784 /// reconnection is allowed only if reconnecting from a PowerShell session on the same box.785 /// </summary>786 public bool EnableNetworkAccess { get; set; }787 788 /// <summary>789 /// Specifies the maximum number of connection retries if previous connection attempts fail790 /// due to network issues.791 /// </summary>792 public int MaxConnectionRetryCount { get; set; } = DefaultMaxConnectionRetryCount;793 794 #endregion Public Properties795 796 #region Constructors797 798 /// <summary>799 /// Constructor used to create a WSManConnectionInfo.800 /// </summary>801 /// <param name="computerName">Computer to connect to.</param>802 /// <param name="scheme">Scheme to be used for connection.</param>803 /// <param name="port">Port to connect to.</param>804 /// <param name="appName">Application end point to connect to.</param>805 /// <param name="shellUri">remote shell to launch806 /// on connection</param>807 /// <param name="credential">credential to be used808 /// for connection</param>809 /// <param name="openTimeout">Timeout in milliseconds for open810 /// call on Runspace to finish</param>811 /// <exception cref="ArgumentException">Invalid812 /// scheme or invalid port is specified</exception>813 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Scope = "member", Target = "System.Management.Automation.Runspaces.WSManConnectionInfo.#.ctor(System.String,System.String,System.Int32,System.String,System.String,System.Management.Automation.PSCredential,System.Int64,System.Int64)", MessageId = "4#")]814 public WSManConnectionInfo(string scheme, string computerName, int port, string appName, string shellUri, PSCredential credential, int openTimeout)815 {816 Scheme = scheme;817 ComputerName = computerName;818 Port = port;819 AppName = appName;820 ShellUri = shellUri;821 Credential = credential;822 OpenTimeout = openTimeout;823 }824 825 /// <summary>826 /// Constructor used to create a WSManConnectionInfo.827 /// </summary>828 /// <param name="computerName">Computer to connect to.</param>829 /// <param name="scheme">Scheme to be used for connection.</param>830 /// <param name="port">Port to connect to.</param>831 /// <param name="appName">Application end point to connect to.</param>832 /// <param name="shellUri">remote shell to launch833 /// on connection</param>834 /// <param name="credential">credential to be used835 /// for connection</param>836 /// <exception cref="ArgumentException">Invalid837 /// scheme or invalid port is specified</exception>838 /// <remarks>max server life timeout and open timeout are839 /// default in this case</remarks>840 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Scope = "member", Target = "System.Management.Automation.Runspaces.WSManConnectionInfo.#.ctor(System.String,System.String,System.Int32,System.String,System.String,System.Management.Automation.PSCredential)", MessageId = "4#")]841 public WSManConnectionInfo(842 string scheme,843 string computerName,844 int port,845 string appName,846 string shellUri,847 PSCredential credential)848 : this(849 scheme,850 computerName,851 port,852 appName,853 shellUri,854 credential,855 DefaultOpenTimeout)856 {857 }858 859 /// <summary>860 /// Constructor used to create a WSManConnectionInfo.861 /// </summary>862 /// <param name="useSsl"></param>863 /// <param name="computerName"></param>864 /// <param name="port"></param>865 /// <param name="appName"></param>866 /// <param name="shellUri"></param>867 /// <param name="credential"></param>868 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "4#")]869 public WSManConnectionInfo(870 bool useSsl,871 string computerName,872 int port,873 string appName,874 string shellUri,875 PSCredential credential)876 : this(877 useSsl ? DefaultSslScheme : DefaultScheme,878 computerName,879 port,880 appName,881 shellUri,882 credential)883 {884 }885 886 /// <summary>887 /// </summary>888 /// <param name="useSsl"></param>889 /// <param name="computerName"></param>890 /// <param name="port"></param>891 /// <param name="appName"></param>892 /// <param name="shellUri"></param>893 /// <param name="credential"></param>894 /// <param name="openTimeout"></param>895 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "4#")]896 public WSManConnectionInfo(897 bool useSsl,898 string computerName,899 int port,900 string appName,901 string shellUri,902 PSCredential credential,903 int openTimeout)904 : this(905 useSsl ? DefaultSslScheme : DefaultScheme,906 computerName,907 port,908 appName,909 shellUri,910 credential,911 openTimeout)912 {913 }914 915 /// <summary>916 /// Creates a WSManConnectionInfo for the following URI917 /// and with the default credentials, default server918 /// life time and default open timeout919 /// http://localhost/920 /// The default shellname Microsoft.PowerShell will be921 /// used.922 /// </summary>923 public WSManConnectionInfo()924 {925 // ConstructUri(DefaultScheme, DefaultComputerName, DefaultPort, DefaultAppName);926 UseDefaultWSManPort = true;927 }928 929 /// <summary>930 /// Constructor to create a WSManConnectionInfo with a uri931 /// and explicit credentials - server life time is932 /// default and open timeout is default.933 /// </summary>934 /// <param name="uri">Uri of remote runspace.</param>935 /// <param name="shellUri"></param>936 /// <param name="credential">credentials to use to937 /// connect to the remote runspace</param>938 /// <exception cref="ArgumentException">When an939 /// uri representing an invalid path is specified</exception>940 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Scope = "member", Target = "System.Management.Automation.Runspaces.WSManConnectionInfo.#.ctor(System.Uri,System.String,System.Management.Automation.PSCredential)", MessageId = "1#")]941 public WSManConnectionInfo(Uri uri, string shellUri, PSCredential credential)942 {943 if (uri == null)944 {945 // if the uri is null..apply wsman default logic for port946 // resolution..BUG 542726947 ShellUri = shellUri;948 Credential = credential;949 UseDefaultWSManPort = true;950 return;951 }952 953 if (!uri.IsAbsoluteUri)954 {955 throw new NotSupportedException(PSRemotingErrorInvariants.FormatResourceString956 (RemotingErrorIdStrings.RelativeUriForRunspacePathNotSupported));957 }958 959 // This check is needed to make sure we connect to WSMan app in the960 // default case (when user did not specify any appname) like961 // http://localhost , http://127.0.0.1 etc.962 if (uri.AbsolutePath.Equals("/", StringComparison.OrdinalIgnoreCase) &&963 string.IsNullOrEmpty(uri.Query) && string.IsNullOrEmpty(uri.Fragment))964 {965 ConstructUri(uri.Scheme,966 uri.Host,967 uri.Port,968 s_defaultAppName);969 }970 else971 {972 ConnectionUri = uri;973 }974 975 ShellUri = shellUri;976 Credential = credential;977 }978 979 /// <summary>980 /// Constructor used to create a WSManConnectionInfo. This constructor supports a certificate thumbprint to981 /// be used while connecting to a remote machine instead of credential.982 /// </summary>983 /// <param name="uri">Uri of remote runspace.</param>984 /// <param name="shellUri"></param>985 /// <param name="certificateThumbprint">986 /// A thumb print of the certificate to use while connecting to the remote machine.987 /// </param>988 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#")]989 public WSManConnectionInfo(Uri uri, string shellUri, string certificateThumbprint)990 : this(uri, shellUri, (PSCredential)null)991 {992 _thumbPrint = certificateThumbprint;993 }994 995 /// <summary>996 /// Constructor to create a WSManConnectionInfo with a997 /// uri specified and the default credentials,998 /// default server life time and default open999 /// timeout.1000 /// </summary>1001 /// <param name="uri">Uri of remote runspace.</param>1002 /// <exception cref="ArgumentException">When an1003 /// uri representing an invalid path is specified</exception>1004 public WSManConnectionInfo(Uri uri)1005 : this(uri, DefaultShellUri, DefaultCredential)1006 {1007 }1008 1009 #endregion Constructors1010 1011 #region Public Methods1012 1013 /// <summary>1014 /// Populates session options from a PSSessionOption instance.1015 /// </summary>1016 /// <param name="options"></param>1017 /// <exception cref="ArgumentException">1018 /// 1. Proxy credential cannot be specified when proxy accesstype is None.1019 /// Either specify a valid proxy accesstype other than None or do not specify proxy credential.1020 /// </exception>1021 public override void SetSessionOptions(PSSessionOption options)1022 {1023 ArgumentNullException.ThrowIfNull(options);1024 1025 if ((options.ProxyAccessType == ProxyAccessType.None) && (options.ProxyCredential != null))1026 {1027 string message = PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.ProxyCredentialWithoutAccess,1028 ProxyAccessType.None);1029 throw new ArgumentException(message);1030 }1031 1032 base.SetSessionOptions(options);1033 1034 this.MaximumConnectionRedirectionCount =1035 options.MaximumConnectionRedirectionCount >= 01036 ? options.MaximumConnectionRedirectionCount : int.MaxValue;1037 1038 this.MaximumReceivedDataSizePerCommand = options.MaximumReceivedDataSizePerCommand;1039 this.MaximumReceivedObjectSize = options.MaximumReceivedObjectSize;1040 1041 this.UseCompression = !(options.NoCompression);1042 this.NoMachineProfile = options.NoMachineProfile;1043 1044 ProxyAccessType = options.ProxyAccessType;1045 _proxyAuthentication = options.ProxyAuthentication;1046 _proxyCredential = options.ProxyCredential;1047 SkipCACheck = options.SkipCACheck;1048 SkipCNCheck = options.SkipCNCheck;1049 SkipRevocationCheck = options.SkipRevocationCheck;1050 NoEncryption = options.NoEncryption;1051 UseUTF16 = options.UseUTF16;1052 IncludePortInSPN = options.IncludePortInSPN;1053 1054 OutputBufferingMode = options.OutputBufferingMode;1055 MaxConnectionRetryCount = options.MaxConnectionRetryCount;1056 }1057 1058 /// <summary>1059 /// Create a copy of the connection info object.1060 /// </summary>1061 /// <returns>Copy of the connection info object.</returns>1062 public override RunspaceConnectionInfo Clone()1063 {1064 return Copy();1065 }1066 1067 /// <summary>1068 /// Does a shallow copy of the current instance.1069 /// </summary>1070 /// <returns></returns>1071 public WSManConnectionInfo Copy()1072 {1073 WSManConnectionInfo result = new WSManConnectionInfo();1074 result._connectionUri = _connectionUri;1075 result._computerName = _computerName;1076 result._scheme = _scheme;1077 result.PortSetting = PortSetting;1078 result._appName = _appName;1079 result._shellUri = _shellUri;1080 result._credential = _credential;1081 result.UseDefaultWSManPort = UseDefaultWSManPort;1082 result.WSManAuthenticationMechanism = WSManAuthenticationMechanism;1083 result.MaximumConnectionRedirectionCount = MaximumConnectionRedirectionCount;1084 result.MaximumReceivedDataSizePerCommand = MaximumReceivedDataSizePerCommand;1085 result.MaximumReceivedObjectSize = MaximumReceivedObjectSize;1086 result.OpenTimeout = this.OpenTimeout;1087 result.IdleTimeout = this.IdleTimeout;1088 result.MaxIdleTimeout = this.MaxIdleTimeout;1089 result.CancelTimeout = this.CancelTimeout;1090 result.OperationTimeout = base.OperationTimeout;1091 result.Culture = this.Culture;1092 result.UICulture = this.UICulture;1093 result._thumbPrint = _thumbPrint;1094 result.AllowImplicitCredentialForNegotiate = AllowImplicitCredentialForNegotiate;1095 result.UseCompression = UseCompression;1096 result.NoMachineProfile = NoMachineProfile;1097 result.ProxyAccessType = this.ProxyAccessType;1098 result._proxyAuthentication = this.ProxyAuthentication;1099 result._proxyCredential = this.ProxyCredential;1100 result.SkipCACheck = this.SkipCACheck;1101 result.SkipCNCheck = this.SkipCNCheck;1102 result.SkipRevocationCheck = this.SkipRevocationCheck;1103 result.NoEncryption = this.NoEncryption;1104 result.UseUTF16 = this.UseUTF16;1105 result.IncludePortInSPN = this.IncludePortInSPN;1106 result.EnableNetworkAccess = this.EnableNetworkAccess;1107 result.UseDefaultWSManPort = this.UseDefaultWSManPort;1108 result.OutputBufferingMode = OutputBufferingMode;1109 result.DisconnectedOn = this.DisconnectedOn;1110 result.ExpiresOn = this.ExpiresOn;1111 result.MaxConnectionRetryCount = this.MaxConnectionRetryCount;1112 1113 return result;1114 }1115 1116 /// <summary>1117 /// String for http scheme.1118 /// </summary>1119 public const string HttpScheme = "http";1120 1121 /// <summary>1122 /// String for https scheme.1123 /// </summary>1124 public const string HttpsScheme = "https";1125 1126 #endregion1127 1128 #region Internal Methods1129 1130 /// <summary>1131 /// Creates the appropriate client session transportmanager.1132 /// </summary>1133 /// <param name="instanceId">Runspace/Pool instance Id.</param>1134 /// <param name="sessionName">Session name.</param>1135 /// <param name="cryptoHelper">PSRemotingCryptoHelper instance.</param>1136 /// <returns>Instance of WSManClientSessionTransportManager</returns>1137 public override BaseClientSessionTransportManager CreateClientSessionTransportManager(Guid instanceId, string sessionName, PSRemotingCryptoHelper cryptoHelper)1138 {1139 return new WSManClientSessionTransportManager(1140 instanceId,1141 this,1142 cryptoHelper,1143 sessionName);1144 }1145 1146 #endregion1147 1148 #region Private Methods1149 1150 private static string ResolveShellUri(string shell)1151 {1152 string resolvedShellUri = shell;1153 if (string.IsNullOrEmpty(resolvedShellUri))1154 {1155 resolvedShellUri = DefaultShellUri;1156 }1157 1158 if (!resolvedShellUri.Contains(WSManNativeApi.ResourceURIPrefix, StringComparison.OrdinalIgnoreCase))1159 {1160 resolvedShellUri = WSManNativeApi.ResourceURIPrefix + resolvedShellUri;1161 }1162 1163 return resolvedShellUri;1164 }1165 1166 /// <summary>1167 /// Converts <paramref name="rsCI"/> to a WSManConnectionInfo. If conversion succeeds extracts1168 /// the property..otherwise returns default value.1169 /// </summary>1170 /// <param name="rsCI"></param>1171 /// <param name="property"></param>1172 /// <param name="defaultValue"></param>1173 /// <returns></returns>1174 internal static T ExtractPropertyAsWsManConnectionInfo<T>(RunspaceConnectionInfo rsCI,1175 string property, T defaultValue)1176 {1177 if (rsCI is not WSManConnectionInfo wsCI)1178 {1179 return defaultValue;1180 }1181 1182 return (T)typeof(WSManConnectionInfo).GetProperty(property, typeof(T)).GetValue(wsCI, null);1183 }1184 1185 internal void SetConnectionUri(Uri newUri)1186 {1187 Dbg.Assert(newUri != null, "newUri cannot be null.");1188 _connectionUri = newUri;1189 }1190 1191 /// <summary>1192 /// Constructs a Uri from the supplied parameters.1193 /// </summary>1194 /// <param name="scheme"></param>1195 /// <param name="computerName"></param>1196 /// <param name="port">1197 /// Making the port nullable to make sure the UseDefaultWSManPort variable is protected and updated1198 /// only when Port is updated. Usages that dont update port, should use null for this parameter.1199 /// </param>1200 /// <param name="appName"></param>