using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Net; using System.IO; using System.Xml; using System.Security.Cryptography.X509Certificates; using System.Net.Security; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Sockets; using System.Threading.Tasks; using System.Security; using Common.Utils; namespace Intel.Management.Wsman { /// /// Implementation of the IWsmanConnection interface /// [Guid("73131C56-E7EA-4c1d-A6E2-03B6350A9B60")] [ComVisible(true)] public class WsmanConnection : IWsmanConnection { #region Consts /// /// consts defining username and password limits /// public const int MAX_PWD_LENGTH = 32; public const int MIN_PWD_LENGTH = 8; public const int MAX_USERNAME_LENGTH = 32; private const string DIGEST_AUTH = "Digest"; private const string KERBEROS_AUTH = "Negotiate"; private const int CONNECTION_TIMEOUT = 10060; private const int CONNECTION_REFUSED = 10061; #endregion #region Fields private Uri _address = new Uri("http://localhost:16992/wsman"); private string _username = string.Empty; private SecureString _password = new SecureString(); private string _scheme = KERBEROS_AUTH; private SecureString _dmp = null; private DateTime _serverTime; private HttpClient _client; private readonly WsmanConnectionOptions _options = new WsmanConnectionOptions(); private IWsmanFault _lastError = null; private ClientRequest _reqObj = null; private bool _changed = true; private static readonly object _nsLock = new object(); private static IDictionary _nsResolver; private static readonly System.Diagnostics.TraceSource _trace = new System.Diagnostics.TraceSource("Intel.Management.Wsman"); internal bool? allowCertificateError = null; #endregion #region Events /// /// Event that raised once we get the server certificate /// public static event Action ServerCertRaised; #endregion #region Constructors /// /// Initializes a new instance of the WsmanConnection class /// public WsmanConnection() { // add default namespaces lock (_nsLock) { if (_nsResolver == null) { _nsResolver = new Dictionary { { "CIM", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/" }, { "AMT", "http://intel.com/wbem/wscim/1/amt-schema/1/" }, { "IPS", "http://intel.com/wbem/wscim/1/ips-schema/1/" }, { "Win32", "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/" }, { "Datetime", "http://schemas.dmtf.org/wbem/wscim/1/common" }, { "Interval", "http://schemas.dmtf.org/wbem/wscim/1/common" }, { "AssociatedInstances", "http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" }, { "*", "http://schemas.dmtf.org/wbem/wscim/1" } }; } } // Enforcing TLS1.2 and TLS1.1 - This is a W\A when debugging with Visual Studio (.NET doesn't add these protocols when debugging) // Issue does not occur when running with CLI. ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; } #endregion #region Finalizer /// /// Disposes Client and Handler /// ~WsmanConnection() { Dispose(false); } #endregion #region Properties /// /// Gets or sets the username the connection will use to authenticate /// public string Username { get { return _username; } set { int pos = -1; if (value == null) value = string.Empty; else pos = value.IndexOf('\\'); if (pos > 0 || value == string.Empty) //Kerberos { AuthenticationScheme = KERBEROS_AUTH; //Accepting null value for Kerberos connection var newName = value; _changed = _changed || _username != newName; _username = newName; if (_username.Length > MAX_USERNAME_LENGTH) throw new WsmanConnectionException("Username can contain up to 32 characters."); } else //Digest { AuthenticationScheme = DIGEST_AUTH; if (pos == 0) { value = value.Substring(1); } if (string.IsNullOrEmpty(value)) throw new WsmanConnectionException("Username null or an empty string."); _changed = _changed || _username != value; _username = value; if (_username.Length > MAX_USERNAME_LENGTH) throw new WsmanConnectionException("Username can contain up to 32 characters."); } _dmp = null; ReqObj = null; } } /// /// Gets or sets the password the connection will use to authenticate /// public SecureString Password { get { return _password; } set { if (string.IsNullOrEmpty(_scheme)) throw new WsmanConnectionException("Cannot initialize password, authentication scheme is null or empty."); if (value == null) { //Kerberos allows empty password if (_scheme == KERBEROS_AUTH) { _changed = _changed || _password.Length > 0 ; _password?.Dispose(); _password = new SecureString(); } else throw new WsmanConnectionException("Password is null or an empty string."); } else { if (value.Length < MIN_PWD_LENGTH || value.Length > MAX_PWD_LENGTH) throw new WsmanConnectionException("Password can contain between 8 to 32 characters."); _changed = _changed || !_password.ValueEquals(value); _password?.Dispose(); _password = value; } _dmp = null; ReqObj = null; } } /// /// Gets or sets the address that will be associated with this connection /// /// public string Address { get { return _address.ToString(); } set { if (!Uri.IsWellFormedUriString(value, 0)) throw new WsmanConnectionException("Invalid argument - Address is not a valid uri"); var newUri = new Uri(value); _changed = _changed || _address != newUri; _address = newUri; ReqObj = null; } } /// /// Gets or sets the authentication scheme the connection will use /// public string AuthenticationScheme { get { return _scheme; } set { _changed = _changed || _scheme != value; _scheme = value; ReqObj = null; } } /// /// Gets the Connection Options /// public IWsmanConnectionOptions Options => _options; private ClientRequest ReqObj { get => _reqObj; set { _reqObj?.Dispose(); _reqObj = value; } } /// /// Gets the last error that occured when using the connection /// public IWsmanFault LastError => _lastError; public DateTime ServerTime => _serverTime; #endregion #region Public Methods private bool _disposed = false; /// /// Implement IDisposable method /// /// protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _client?.Dispose(); _client = null; _dmp?.Dispose(); Password?.Dispose(); Options?.Dispose(); ReqObj?.Dispose(); } _disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Resolves a class name prefix to a full resourceUri /// /// /// The resoved resourceUri public string ResolveNamespace(string prefix) { string result = null; lock (_nsLock) { _nsResolver.TryGetValue(prefix, out result); } return result; } /// /// Registers a namespaceUri for a class name prefix /// /// /// public void RegisterNamespace(string prefix, string ns) { lock (_nsLock) { _nsResolver[prefix] = ns; } } /// /// Closes the connection /// /// Forces future request to use a new network connection public void Close() { ReqObj?.Dispose(); _dmp?.Dispose(); _client?.Dispose(); _client = null; } /// /// Tests the connection to see if the endpoint supports Wsman /// public IManagedInstance Identify() { return (IManagedInstance)SubmitRequest(WsmanResources.IDENTIFY_XML, null, null); } /// /// Creates a reference to a object supported by a Wsman Service /// /// A string describing the object reference /// A IManagedReference pointing to the object public IManagedReference NewReference(string resourceUri) { ManagedReference wsRef = new ManagedReference(this, resourceUri); return wsRef; } /// /// Creates a new representation of a CIM object that can be exchanged with the server /// /// A string describing the instance /// A IManagedInstance representing the resource public IManagedInstance NewInstance(string resourceUri) { ManagedInstance inst = new ManagedInstance(this, resourceUri); return inst; } /// /// Executes a simple SQL type query /// /// /// An IWsmanEnumeration containing resulting items public IWsmanEnumeration ExecQuery(string queryString) { IWsmanEnumeration result = null; IManagedReference objRef = GetReferenceFromSQL(queryString); try { result = objRef.Enumerate(null, null); } catch (WsmanUnreachableException) { result = new WsmanEnumeration(this, null, null); } return result; } /// /// Executes a simple SQL type query /// /// /// An IManagedReference to the object described by the SQL query string public IManagedReference GetReferenceFromSQL(string queryString) { string tableName = string.Empty; int pos = -1; IManagedReference result = null; const string SELECT_CLAUSE = "select * from "; tableName = queryString.Substring(SELECT_CLAUSE.Length).TrimStart(); queryString = tableName; pos = tableName.IndexOf(" "); if (pos > 0) { tableName = tableName.Substring(0, pos); queryString = queryString.Substring(pos).Trim(); } if (tableName.Equals(string.Empty)) { throw new WsmanQueryFormatException("Missing Resource Name"); } result = NewReference(tableName); //check where clause if (queryString.ToLower().StartsWith("where")) { string name = null; string value = null; queryString = queryString.Substring("where".Length).Trim(); while (!queryString.Equals(string.Empty)) { pos = queryString.IndexOf("="); if (pos <= 0) throw new WsmanQueryFormatException("Missing property name"); name = queryString.Substring(0, pos); value = queryString.Substring(pos + 1).TrimStart(); queryString = value; if (value.StartsWith("'")) { pos = value.IndexOf("'", 1); if (pos > 0) { value = value.Substring(1, pos - 1); queryString = queryString.Substring(pos + 1).TrimStart(); } else throw new WsmanQueryFormatException("Missing close quote"); } else if (value.StartsWith("\"")) { pos = value.IndexOf("\"", 1); if (pos > 0) { value = value.Substring(1, pos - 1); queryString = queryString.Substring(pos + 1).TrimStart(); } else throw new WsmanQueryFormatException("Missing close quote"); } else { pos = value.IndexOf(" "); if (pos > 0) { value = value.Substring(0, pos); queryString = queryString.Substring(pos).TrimStart(); } else { queryString = queryString.Substring(value.Length).TrimStart(); } } if (queryString.ToLower().StartsWith("and ")) { queryString = queryString.Substring("and ".Length).TrimStart(); } result.AddSelector(name, value); }//end while where }//end if where return result; } /// /// Submits a Wsman command to the server /// /// The string command to send /// The reference the Wsman command will use /// Message Parameters /// An object representing the results of the command public object SubmitRequest(string requestString, IManagedReference refObj, IManagedInstance input) { XmlDocument reqDoc = new XmlDocument(); reqDoc.LoadXml(requestString); return SubmitRequest(reqDoc, refObj, input); } /// /// Submits a Wsman command to the server /// /// The XML document to send /// The reference the Wsman command will use /// Message Parameters /// An object representing the results of the command public object SubmitRequest(XmlDocument reqDoc, IManagedReference refObj, IManagedInstance input) { //load the requesting namespace manager XmlNamespaceManager ns = LoadNamespaces(reqDoc); // Set the MessageID string reqUUID = "uuid:" + Guid.NewGuid().ToString().ToUpper(); XmlNode node = reqDoc.DocumentElement.SelectSingleNode("s:Header/wsa:MessageID", ns); if (node != null) node.InnerText = reqUUID; SetEpr(refObj, reqDoc, ns); //add input if (input != null) { node = reqDoc.DocumentElement.SelectSingleNode("s:Body", ns); if (node != null) node.InnerXml = input.Xml; } MergeNamespaces(reqDoc, ns); TraceDocument(reqDoc); if (ReqObj == null) { if (Options.ClientCertificate != null) { X509Certificate2 cert2 = (X509Certificate2)Options.ClientCertificate; //check provisioning cert if (_options.IsSetupCertificate(cert2)) { ReqObj = CreateRequest(); } } } return ReqObj != null ? SendObjectRequest(reqUUID, reqDoc, refObj, input) : SendWebRequest(reqUUID, reqDoc, refObj); } public void TraceDocument(XmlDocument doc) { TraceDocument(doc, System.Diagnostics.TraceEventType.Information); } public void TraceDocument(XmlDocument doc, System.Diagnostics.TraceEventType eventType) { if (_trace.Switch.ShouldTrace(eventType)) { StringBuilder builder = new StringBuilder(Environment.NewLine); XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = Encoding.Unicode; settings.ConformanceLevel = ConformanceLevel.Document; settings.Indent = true; settings.IndentChars = (" "); XmlWriter writer = XmlWriter.Create(builder, settings); doc.WriteContentTo(writer); writer.Close(); _trace.TraceInformation(builder.ToString()); } } public static System.Diagnostics.TraceSource TraceSource { get { return _trace; } } /// /// Sets the host and port used by the connection /// /// The host name or IP address of the Wsman service /// The port the Wsman service is listening on public void SetHost(string hostname, string port) { StringBuilder builder = new StringBuilder(); if (port.Equals("16993")) builder.Append("https://"); else builder.Append("http://"); builder.Append(hostname); if (!port.Equals(string.Empty)) { builder.Append(":"); builder.Append(port); } builder.Append("/wsman"); Address = builder.ToString(); } /// /// Sets the connection credentials /// /// The user name /// Secure Password object /// Use this for passing a System.Security.SecureString public void SetCredentials(string name, SecureString pass) { if (name.Equals(string.Empty) || name.IndexOf('\\') > 0) { AuthenticationScheme = KERBEROS_AUTH; } else { AuthenticationScheme = DIGEST_AUTH; } Username = name; Password = pass; } public bool Equals(WsmanConnection other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(other._username, _username) && Equals(other.Password.ValueEquals(Password)) && Equals(other._address, _address); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != typeof(WsmanConnection)) return false; return Equals((WsmanConnection)obj); } public override int GetHashCode() { unchecked { int result = (_username != null ? _username.GetHashCode() : 0); result = (result * 397) ^ (Password != null ? Password.GetHashCode() : 0); result = (result * 397) ^ (Address != null ? Address.GetHashCode() : 0); return result; } } #endregion //Public Methods #region Private Methods private object SendObjectRequest(string msgId, XmlDocument reqDoc, IManagedReference refObj, IManagedInstance input) { XmlDocument resDoc = null; Exception reqExp; TraceDocument(reqDoc); ServerResponse response = RetryLoop(reqDoc, out reqExp); if (response == null) { Close(); throw new WsmanConnectionException(reqExp.Message, reqExp); } if (response.StatusCode >= 400) { XmlDocument faultDoc = null; switch (response.StatusCode) { case 400: faultDoc = response.GetXml(); _lastError = WsmanFault.GetXmlFault(faultDoc); if (_lastError.Subcode.Equals("DestinationUnreachable")) { TraceDocument(faultDoc, System.Diagnostics.TraceEventType.Warning); throw new WsmanUnreachableException(_lastError.Reason); } TraceDocument(faultDoc, System.Diagnostics.TraceEventType.Error); throw new WsmanException(_lastError.Reason); case 500: faultDoc = response.GetXml(); _lastError = WsmanFault.GetXmlFault(faultDoc); TraceDocument(faultDoc, System.Diagnostics.TraceEventType.Error); if (response.StatusCode == 500) throw new WsmanRecieverFault(_lastError.Reason); break; case 401: throw new WsmanUnauthorizedException("Unauthorized"); default: throw new WsmanException(response.StatusText); } } _serverTime = response.Date; resDoc = response.GetXml(); TraceDocument(resDoc); return GetResponseObject(refObj, msgId, resDoc); } /// /// Initiate HTTPClient Handler /// /// HTTPClient Handler private HttpClientHandler CreateHttpHandler() { var handler = new HttpClientHandler(); handler.AllowAutoRedirect = false; handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.Proxy = _options.Proxy; //register callback to the certificate call back if (Options.ServerCertificateValidationCallback != null) handler.ServerCertificateCustomValidationCallback += CertificateValidationCallback; if (Options.AcceptSelfSignedCertificate) handler.ServerCertificateCustomValidationCallback += SelfSignedCertificateCallback; if (Options.ClientCertificate != null) { handler.ClientCertificates.Add(Options.ClientCertificate); } NetworkCredential networkCredential = null; switch (_scheme) { case KERBEROS_AUTH: int pos = _username.IndexOf('\\'); string domain = null; string user = null; if (pos > 0) { domain = _username.Substring(0, pos); user = _username.Substring(pos + 1); } if (domain != null && !domain.Equals(string.Empty)) { networkCredential = new NetworkCredential(user, Password.Copy(), domain); } if (!AuthenticationManager.CustomTargetNameDictionary.ContainsKey(_address.ToString())) { var spnPort = "HTTP/" + _address.Authority.ToUpper(); AuthenticationManager.CustomTargetNameDictionary.Add(_address.ToString(), spnPort); } handler.PreAuthenticate = true; break; case DIGEST_AUTH: networkCredential = new NetworkCredential(_username, Password.Copy()); break; } if (networkCredential != null) { handler.Credentials = new CredentialCache { { _address, _scheme, networkCredential } }; } else { handler.Credentials = CredentialCache.DefaultNetworkCredentials.GetCredential(_address, KERBEROS_AUTH); } return handler; } /// /// Initiate HTTClient /// /// Initiated HTTP Client private void CreateHttpClient() { _client = new HttpClient(CreateHttpHandler()); _client.BaseAddress = _address; _client.Timeout = TimeSpan.FromMilliseconds(Options.Timeout); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); _client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate"); _client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true }; _client.DefaultRequestHeaders.Connection.Add("keep-alive"); } /// /// Build, send HTTPClient and send request /// /// /// /// /// /// /// /// /// private async Task SendHttpClient(XmlDocument reqDoc, IManagedReference refObj, string msgId) { int retry = 2; if (_changed && _client != null) { Close(); _changed = false; } if (_client == null) { CreateHttpClient(); } while (retry > 0) //for PG use case { DateTime startTime = DateTime.Now; string response = string.Empty; HttpStatusCode statusCode = HttpStatusCode.OK; try { XmlDocument resDoc; using (var content = new StringContent(reqDoc.InnerXml, Encoding.UTF8, "application/soap+xml")) using (var responseMessage = await _client.PostAsync(_address, content).ConfigureAwait(false)) { response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); statusCode = responseMessage.StatusCode; responseMessage.EnsureSuccessStatusCode(); resDoc = new XmlDocument(); resDoc.LoadXml(response); } TraceDocument(resDoc); return GetResponseObject(refObj, msgId, resDoc); } catch (XmlException) { throw new WsmanConnectionException(response); } catch (TaskCanceledException) { TimeSpan span = DateTime.Now.Subtract(startTime); if (span.TotalMilliseconds > Options.Timeout) { return null; } retry = 1; } catch (HttpRequestException httpReqExp) { int ErrorCode = 0; if (httpReqExp.InnerException is SocketException se1) // This exception is received when compiling for .net 6 { ErrorCode = se1.ErrorCode; } else if (httpReqExp.InnerException?.InnerException is SocketException se2) // When compiling for .net framework 48, a webSocket exception is received, with SocketException as an inner exception { ErrorCode = se2.ErrorCode; } if (ErrorCode == CONNECTION_TIMEOUT || ErrorCode == CONNECTION_REFUSED) { TimeSpan span = DateTime.Now.Subtract(startTime); if (span.TotalMilliseconds > Options.Timeout) { return null; //if we exceeded time out don't wait by try one more time } System.Threading.Thread.Sleep(1000); retry--; continue; } if (string.IsNullOrEmpty(response)) { var exp = httpReqExp.InnerException ?? httpReqExp; throw new WsmanConnectionException(exp.Message, exp); } switch (statusCode) { case HttpStatusCode.BadRequest when _lastError?.Subcode != null && _lastError.Subcode.Equals("DestinationUnreachable"): throw new WsmanUnreachableException(WsmanFault.GetXmlFault(response).Reason, httpReqExp); case HttpStatusCode.BadRequest: throw new WsmanSenderException(WsmanFault.GetXmlFault(response).Reason, httpReqExp); case HttpStatusCode.InternalServerError: throw new WsmanRecieverFault(WsmanFault.GetXmlFault(response).Reason, httpReqExp); case HttpStatusCode.Unauthorized: throw new WsmanUnauthorizedException(statusCode.ToString(), httpReqExp); } throw new WsmanConnectionException(statusCode.ToString(), httpReqExp); } } return null; } private object SendWebRequest(string msgId, XmlDocument reqDoc, IManagedReference refObj) { var output = Task.Run(()=>SendHttpClient(reqDoc, refObj, msgId)).GetAwaiter().GetResult(); if (output == null) { throw new WsmanConnectionException("Unable to connect", new WebException("Max Retry attempts reached", WebExceptionStatus.RequestCanceled)); } return output; } private ServerResponse RetryLoop(XmlDocument reqDoc, out Exception resultExp) { ServerResponse result = null; resultExp = null; DateTime startTime = DateTime.Now; int retryCount = 13;//limit the retry loop by count and time while (retryCount > 0) { try { result = ReqObj.Send(reqDoc); retryCount = 0; } catch (SocketException sockExp) { //WSATIMEOUT 10060 WSACONNECTIONREFUSED 10061 if (sockExp.ErrorCode == 10060 || sockExp.ErrorCode == 10061)// { retryCount--; Close(); } else { retryCount = 0; resultExp = sockExp; } } catch (Exception nonSockExp) { retryCount = 0; resultExp = nonSockExp; } TimeSpan span = DateTime.Now.Subtract(startTime); if (span.TotalSeconds > Options.Timeout) retryCount = 0; if (retryCount > 0) System.Threading.Thread.Sleep(1000); } return result; } private ClientRequest CreateRequest() { ClientRequest reqObj = null; reqObj = Options.InternetProtocol == InternetProtocolType.Ipv6 ? new ClientRequest(_address, AddressFamily.InterNetworkV6) : new ClientRequest(_address, AddressFamily.InterNetwork); MpsManager mps = null; try { if (Options.ClientCertificate != null) { X509Certificate2 cert2 = (X509Certificate2)Options.ClientCertificate; reqObj.SetCertificate(cert2); // We are assuming setup certificate is used reqObj.SetCertificateOptions(false, false, true); } switch (_scheme) { case DIGEST_AUTH when Options.UseDigestMasterPassword: GetDmp(); break; case DIGEST_AUTH: _dmp = null; reqObj.SetDigestAuthorization(_username, Password.Copy()); break; case KERBEROS_AUTH when Password == null || Password.Length == 0: { reqObj.SetWindowsAuthorization(null, null, new SecureString(), Options.ServiceName); break; } case KERBEROS_AUTH: { string[] cred = _username.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); reqObj.SetWindowsAuthorization(cred[1], cred[0], Password.Copy(), Options.ServiceName); break; } default: { if (_scheme.EndsWith("Anonymous")) { reqObj.SetAnonymousAuthorization(); } break; } } mps = new MpsManager(); HttpProxy proxy = null; if (!string.IsNullOrEmpty(Options.ProxyAddress)) { proxy = new HttpProxy(Options.ProxyAddress, Options.ProxyUser, Options.ProxyPassword); reqObj.SetProxy(proxy); } else if (mps.IsConnected(_address.Host)) { proxy = new HttpProxy(mps.HttpProxy, mps.HttpUser, mps.HttpPassword); reqObj.SetProxy(proxy); } } catch (Exception) { reqObj.Dispose(); } finally { mps?.Dispose(); } return reqObj; } private void GetDmp() { ClientRequest reqObj = CreateRequest(); XmlDocument reqDoc = new XmlDocument(); reqDoc.LoadXml(WsmanResources.IDENTIFY_XML); ServerResponse response = null; try { response = ReqObj.Send(reqDoc); } catch (Exception exp) { throw new WsmanConnectionException(exp.Message, exp); } if (response != null && response.StatusCode >= 400) { switch (response.StatusCode) { case 400: _lastError = WsmanFault.GetXmlFault(response.GetXml()); if (_lastError.Subcode.Equals("DestinationUnreachable")) throw new WsmanUnreachableException(_lastError.Reason); throw new WsmanException(_lastError.Reason); case 401: break; case 500: _lastError = WsmanFault.GetXmlFault(response.GetXml()); if (response.StatusCode == 500) throw new WsmanRecieverFault(_lastError.Reason); break; default: throw new WsmanException(response.StatusText); } } string[] list = ((AnonymousAuthorization)reqObj.GetAuthorization()).GetAuthorizations(); foreach (string item in list) { if (item.StartsWith("WWW-Authenticate: Digest")) { string token = "realm=\""; int pos1 = item.IndexOf(token); if (pos1 > 0) { byte[] key = Password.ConvertToByteArray(); pos1 += token.Length; int pos2 = item.IndexOf("\"", pos1); string realm = item.Substring(pos1, pos2 - pos1); if (string.IsNullOrEmpty(_username) || key == null) { throw new WsmanConnectionException("Username or password are null or empty."); } using (HMACSHA256 sha2 = new HMACSHA256(key)) { byte[] hash = sha2.ComputeHash(Encoding.ASCII.GetBytes(realm + _username)); _dmp = hash.ConvertByteArrayToSecureString(); ; reqObj.SetDigestAuthorization(_username, _dmp); ReqObj = reqObj; Array.Clear(hash, 0, hash.Length); } Array.Clear(key,0,key.Length); } } } if (ReqObj != reqObj) reqObj.Dispose(); } private void SetEpr(IManagedReference refObj, XmlDocument document, XmlNamespaceManager ns) { XmlNode node = document.DocumentElement.SelectSingleNode("s:Header/wsa:To", ns); if (node != null) node.InnerText = _address.ToString(); if (refObj != null) { node = document.DocumentElement.SelectSingleNode("s:Header/wsman:ResourceURI", ns); if (node != null) node.InnerText = refObj.ResourceUri; node = document.DocumentElement.SelectSingleNode("s:Body/n:Enumerate", ns); if (node == null) { node = document.DocumentElement.SelectSingleNode("s:Header/wsman:SelectorSet", ns); if (node != null) { //add namespaces to parent node.InnerXml = refObj.Xml; // fix embedding XmlNode setNode = node.SelectSingleNode("wsa:EndpointReference/wsa:ReferenceParameters/wsman:SelectorSet", ns); node.InnerXml = setNode != null ? setNode.InnerXml : string.Empty; } } } } private void MergeNamespaces(XmlDocument document, XmlNamespaceManager ns) { XmlNode addrNode = document.DocumentElement.SelectSingleNode("s:Header/wsa:To", ns); XmlNode uriNode = document.DocumentElement.SelectSingleNode("s:Header/wsman:ResourceURI", ns); //Merge Addressing Namespaces if (addrNode != null && uriNode != null) { XmlNodeList list = document.DocumentElement.GetElementsByTagName("*"); foreach (XmlNode listNode in list) { if (listNode.NamespaceURI.Equals(addrNode.NamespaceURI)) listNode.Prefix = addrNode.Prefix; else if (listNode.NamespaceURI.Equals(uriNode.NamespaceURI)) listNode.Prefix = uriNode.Prefix; } } } private object GetResponseObject(IManagedReference refObj, string reqId, XmlDocument document) { object result = null; XmlNamespaceManager ns = LoadNamespaces(document); // check request ID XmlNode node = document.DocumentElement.SelectSingleNode("s:Header/wsa:RelatesTo", ns); if (node != null) if (node.InnerText != null && !node.InnerText.Equals(reqId)) throw new IOException(WsmanResources.ID_MISMATCH); node = document.DocumentElement.SelectSingleNode("s:Header/wsa:Action", ns); // process a Get response if (node == null) { ns.AddNamespace("wsmid", "http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"); node = document.DocumentElement.SelectSingleNode("s:Body/wsmid:IdentifyResponse", ns); if (node != null) result = new ManagedInstance(this, node.OuterXml); } else if (node.InnerText != null && node.InnerText.Equals(WsmanResources.GET_RESPONSE)) { node = document.DocumentElement.SelectSingleNode("s:Body", ns); if (node != null) { node = node.FirstChild; if (node != null) { while (node != null && node.NodeType != XmlNodeType.Element) node = node.NextSibling; result = new ManagedInstance(this, node.OuterXml); } } } else if (node.InnerText != null && node.InnerText.Equals(WsmanResources.ENUM_RESPONSE)) { // create a Wsman Pull document XmlDocument pullDoc = new XmlDocument(); pullDoc.LoadXml(WsmanResources.PULL_XML); XmlNamespaceManager pullNs = LoadNamespaces(pullDoc); pullNs.AddNamespace("n", WsmanResources.ENUM_NS); ns.AddNamespace("n", WsmanResources.ENUM_NS); // set the EPR SetEpr(refObj, pullDoc, pullNs); // Set the enumeration context node = document.DocumentElement.SelectSingleNode("s:Body/n:EnumerateResponse/n:EnumerationContext", ns); XmlNode pullNode = pullDoc.DocumentElement.SelectSingleNode("s:Body/n:Pull/n:EnumerationContext", pullNs); if (pullNode != null && node != null) pullNode.InnerText = node.InnerText; //set Max elements pullNode = pullDoc.DocumentElement.SelectSingleNode("s:Body/n:Pull/n:MaxElements", pullNs); if (pullNode != null) pullNode.InnerText = Options.MaxElements.ToString(); result = new WsmanEnumeration(this, pullDoc, pullNs); } else if (node.InnerText != null && node.InnerText.Equals(WsmanResources.PULL_RESPONSE)) { result = document; } else if (node.InnerText != null && node.InnerText.Equals(WsmanResources.CREATE_RESPONSE)) { node = document.DocumentElement.SelectSingleNode("s:Body/wxf:ResourceCreated", ns); if (node != null) result = ManagedReference.GetEmbeddedRef(this, node, ns); } else if (node.InnerText != null && node.InnerText.Equals(WsmanResources.SUBSCRIBE_RESPONSE)) { node = document.DocumentElement.SelectSingleNode("s:Body/wse:SubscribeResponse/wse:SubscriptionManager", ns); if (node != null) result = ManagedReference.GetEmbeddedRef(this, node, ns); } else { node = document.DocumentElement.SelectSingleNode("s:Body", ns); if (node != null) result = new ManagedInstance(this, node.InnerXml); } return result; } private static XmlNamespaceManager LoadNamespaces(XmlDocument document) { XmlNamespaceManager ns = new XmlNamespaceManager(document.NameTable); ns.AddNamespace("wsa", WsmanResources.ADDRESSING_NS); ns.AddNamespace("wsman", WsmanResources.WSMAN_NS); ns.AddNamespace("s", WsmanResources.SOAP_NS); ns.AddNamespace("n", WsmanResources.ENUM_NS); ns.AddNamespace("wxf", WsmanResources.WSTRANSFER_NS); ns.AddNamespace("wse", WsmanResources.WSEVENTING_NS); return ns; } /// /// This callback is used to allow the connection even if the certificate has errors (like hostname mismatch etc) /// /// /// /// /// /// private bool CertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { //raise the event only once if (allowCertificateError == null) { allowCertificateError = Options.ServerCertificateValidationCallback(certificate, errors); } return allowCertificateError.Value; } private bool SelfSignedCertificateCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors error) { //If certificate is self signed, ignore all errors if (certificate.Subject.Equals(certificate.Issuer) && Options.AcceptSelfSignedCertificate) { return true; } if (error == SslPolicyErrors.None) { return true; } return false; } #endregion //Private Methods } // end WsmanConnection Object }//end Intel.Management.Wsman namespace