1458 lines
56 KiB
C#
1458 lines
56 KiB
C#
//----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Intel Corporation, 2006 - 2010 All Rights Reserved.
|
|
//
|
|
// File: DotNetWSManClient.cs
|
|
//
|
|
// Contents: An implementation of a WS-Management client
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
using System.Net.Http.Headers;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Intel.Manageability.WSManagement
|
|
{
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net; //.Sockets
|
|
using System.Net.Http;
|
|
using System.Security.Cryptography;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using Cim;
|
|
using System.Net.Security;
|
|
using System.Security;
|
|
using Common.Utils;
|
|
|
|
/// <summary>
|
|
/// Implementation for wsman client.
|
|
/// </summary>
|
|
public class DotNetWSManClient : IWSManClient
|
|
{
|
|
#region CONSTS
|
|
|
|
#region CERTIFICATES_ISSUES
|
|
|
|
private const string HOSTNAME_MISMATCH_HEADER = "Hostname Mismatch";
|
|
private const string HOSTNAME_MISMATCH_ERROR = "Mismatched Address.\nThe certificate you are using to connect is issued to a different address.";
|
|
|
|
#endregion
|
|
|
|
//default header values
|
|
private const string DEFAULT_REPLY_TO = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
|
|
private const string DEFAULT_OPERATION_TIMEOUT = "PT60.000S";
|
|
private const string DEFAULT_WSMAN_SERVICE = "/wsman";
|
|
private const string WSMAN_FAULT = "fault";
|
|
|
|
//WSMan basic functions
|
|
private const string ENUMERATE = "http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate";
|
|
private const string PULL = "http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull";
|
|
private const string GET = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get";
|
|
private const string PUT = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Put";
|
|
private const string DELETE = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete";
|
|
private const string CREATE = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Create";
|
|
private const string RELEASE = "http://schemas.xmlsoap.org/ws/2004/09/enumeration/Release";
|
|
private const string IDENTITY = "http://schemas.xmlsoap.org/ws/2005/05/identity";
|
|
private const string SUBSCRIBE = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe";
|
|
private const string UNSUBSCRIBE = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe";
|
|
|
|
// WS-Management namespace URI
|
|
private const string WSMAN_NAMESPACE_URI = "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd";
|
|
private const string WSMAN = "wsman";
|
|
private const string WSMAN_URI_FIELD = "ResourceURI";
|
|
private const string WSMAN_SELECTOR_SET_FIELD = "SelectorSet";
|
|
private const string WSMAN_SELECTOR_FIELD = "Selector";
|
|
private const string WSMAN_SELECTOR_NAME = "Name";
|
|
private const string WSMAN_ACTION = "Action";
|
|
private const string WSMAN_BODY = "Body";
|
|
|
|
private const string WSMAN_ENUMERATE = "Enumerate";
|
|
private const string WSMAN_ENUMERATE_PREFIX = "wsen";
|
|
private const string WSMAN_ENUMERATE_NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2004/09/enumeration";
|
|
private const string WSMAN_ENUM_CONTEXT = "EnumerationContext";
|
|
private const string WSMAN_ENUM_MODE = "EnumerationMode";
|
|
private const string WSMAN_ENUM_EPR = "EnumerateEPR";
|
|
private const string WSMAN_ENUM_OBJ_N_EPR = "EnumerateObjectAndEPR";
|
|
private const string MAX_ELEMENTS = "101";
|
|
|
|
private const string OID_LOCAL = "2.16.840.1.113741.1.2.2";
|
|
private const string OID_REMOTE = "2.16.840.1.113741.1.2.1";
|
|
|
|
#endregion CONSTS
|
|
|
|
#region DATA_MEMBERS
|
|
|
|
private bool FirstCall, AllowCertErrors;
|
|
bool? allowCertificateError = null;
|
|
private HttpClient httpClient;
|
|
|
|
public delegate bool ServerCertificateValidationCallback(X509Certificate certificate,
|
|
SslPolicyErrors errors);
|
|
private ServerCertificateValidationCallback _serverCertificateValidationCallback;
|
|
|
|
/// <summary>
|
|
/// Event that raised once we get the server certificate
|
|
/// </summary>
|
|
public static event Action<X509Certificate2> ServerCertRaised;
|
|
|
|
public X509Certificate2 Certificate
|
|
{
|
|
get
|
|
{
|
|
return CertError.Certificate; ;
|
|
}
|
|
}
|
|
|
|
public CertificateError CertError { set; get; }
|
|
|
|
//Connection Info
|
|
private ConnectionInfo _connection;
|
|
|
|
/// <summary>
|
|
/// A class that represents the connection information.
|
|
/// </summary>
|
|
public ConnectionInfo Connection
|
|
{
|
|
get { return _connection; }
|
|
set
|
|
{
|
|
Connection?.Dispose();
|
|
_connection = value;
|
|
_X509CertificateCollection = null;
|
|
_credentials = null;
|
|
if (!string.IsNullOrEmpty(value.Certificate))
|
|
{
|
|
_X509CertificateCollection = getCertFromStore(value.Certificate);
|
|
if (_X509CertificateCollection.Count == 0)
|
|
throw new ArgumentException(("Cannot find appropriate certificate in the certificate store."));
|
|
}
|
|
if (!setConnectionInfo())
|
|
{
|
|
//throw missing password or user name;
|
|
throw new ArgumentException("Problem with credentials");
|
|
}
|
|
}
|
|
}
|
|
|
|
// user credentials
|
|
private X509CertificateCollection _X509CertificateCollection = null;
|
|
private CredentialCache _credentials = null;
|
|
|
|
#endregion DATA_MEMBERS
|
|
|
|
#region CONSTRUCTOR_FUNCTIONS
|
|
|
|
/// <summary>
|
|
/// Constructor of the WSMan client using ConnectionInfo
|
|
/// </summary>
|
|
/// <param name="connection">A class that represents the connection information.</param>
|
|
public DotNetWSManClient(ConnectionInfo connection) : this(connection, false) { }
|
|
|
|
/// <summary>
|
|
/// Constructor of the WSMan client using ConnectionInfo
|
|
/// </summary>
|
|
/// <param name="connection">A class that represents the connection information.</param>
|
|
/// /// <param name="AllowCertificateErrors">true, to allow certificate errors</param>
|
|
public DotNetWSManClient(ConnectionInfo connection, bool AllowCertificateErrors)
|
|
{
|
|
FirstCall = true;
|
|
AllowCertErrors = AllowCertificateErrors;
|
|
if (connection == null)
|
|
throw new ArgumentNullException("connection");
|
|
_connection = connection;
|
|
init();
|
|
}
|
|
/// <summary>
|
|
/// Constructor of the WSMan client using ConnectionInfo
|
|
/// </summary>
|
|
/// <param name="connection">A class that represents the connection information.</param>
|
|
/// <param name="certificateValidationCallback">callback for custom validation by the client of the server certificate.</param>
|
|
public DotNetWSManClient(ConnectionInfo connection, ServerCertificateValidationCallback certificateValidationCallback)
|
|
{
|
|
_serverCertificateValidationCallback = certificateValidationCallback;
|
|
FirstCall = true;
|
|
if (connection == null)
|
|
throw new ArgumentNullException("connection");
|
|
_connection = connection;
|
|
init();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor of the WSMan client based on .net components
|
|
/// </summary>
|
|
/// <param name="target">Hostname / IP of the machine to connect.</param>
|
|
/// <param name="username">User name of the machine to connect.</param>
|
|
/// <param name="password">Password of the machine to connect.</param>
|
|
/// <param name="secure">Indicates whether or not to use TLS in the connection.</param>
|
|
/// <param name="clientCert">Certificate name (as it appears in the subject field of the certificate)</param>
|
|
/// <param name="kerberos">Indicate whether to use kerberos in the connection.</param>
|
|
/// <param name="HttpProxy">Indicates whether or not to use a proxy in the connection.</param>
|
|
public DotNetWSManClient(String target, String username, SecureString password, bool secure, bool kerberos, String clientCert, IWebProxy HttpProxy)
|
|
: this(target, username, password, secure, kerberos, clientCert, HttpProxy, false)
|
|
{ }
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Constructor of the WSMan client based on .net components
|
|
/// </summary>
|
|
/// <param name="target">Hostname / IP of the machine to connect.</param>
|
|
/// <param name="username">User name of the machine to connect.</param>
|
|
/// <param name="password">Password of the machine to connect.</param>
|
|
/// <param name="secure">Indicates whether or not to use TLS in the connection.</param>
|
|
/// <param name="clientCert">Certificate name (as it appears in the subject field of the certificate)</param>
|
|
/// <param name="kerberos">Indicate whether to use kerberos in the connection.</param>
|
|
/// <param name="HttpProxy">Indicates whether or not to use a proxy in the connection.</param>
|
|
public DotNetWSManClient(String target, String username, SecureString password, bool secure, bool kerberos, String clientCert, IWebProxy HttpProxy, bool AllowCertificateErrors)
|
|
{
|
|
AllowCertErrors = AllowCertificateErrors;
|
|
FirstCall = true;
|
|
_connection = new ConnectionInfo(target, username, password, secure, clientCert, (kerberos ? ConnectionInfo.AuthMethod.Kerberos : ConnectionInfo.AuthMethod.Digest), HttpProxy, null);
|
|
init();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common init stuff
|
|
/// </summary>
|
|
private void init()
|
|
{
|
|
if (_connection.Secure)
|
|
{
|
|
_X509CertificateCollection = getCertFromStore(_connection.Certificate);
|
|
|
|
if (_X509CertificateCollection.Count == 0 && !String.IsNullOrEmpty(_connection.Certificate))
|
|
throw new ArgumentException(("Cannot find appropriate certificate in certificate store."));
|
|
}
|
|
if (!setConnectionInfo())
|
|
{
|
|
//throw missing password or user name;
|
|
throw new ArgumentException("Problem with credentials");
|
|
}
|
|
}
|
|
|
|
private X509CertificateCollection getCertFromStore(String clientCert)
|
|
{
|
|
X509CertificateCollection certificatesCollection = new X509CertificateCollection();
|
|
|
|
// Open CurrentUser cert store
|
|
using (X509Store currentUserStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
|
|
{
|
|
currentUserStore.Open(OpenFlags.ReadOnly);
|
|
foreach (X509Certificate2 certificate in currentUserStore.Certificates)
|
|
{
|
|
if (certificate.Subject.Contains(clientCert))
|
|
{
|
|
// Checking that the Enhanced Key Usage in the certificate is the one for AMT
|
|
foreach (X509Extension extension in certificate.Extensions)
|
|
{
|
|
if (extension is X509EnhancedKeyUsageExtension)
|
|
{
|
|
X509EnhancedKeyUsageExtension ex = (X509EnhancedKeyUsageExtension)extension;
|
|
foreach (Oid OID in ex.EnhancedKeyUsages)
|
|
{
|
|
if (OID.Value == OID_REMOTE || OID.Value == OID_LOCAL)
|
|
certificatesCollection.Add(certificate);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//currentUserStore.Close();
|
|
}
|
|
|
|
// Open LocalMachine cert store
|
|
using (X509Store localMachineStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))
|
|
{
|
|
localMachineStore.Open(OpenFlags.ReadOnly);
|
|
foreach (X509Certificate2 certificate in localMachineStore.Certificates)
|
|
{
|
|
if (certificate.Subject.Contains(clientCert))
|
|
{
|
|
// Checking that the Enhanced Key Usage in the certificate is the one for AMT
|
|
foreach (X509Extension extension in certificate.Extensions)
|
|
{
|
|
if (extension is X509EnhancedKeyUsageExtension)
|
|
{
|
|
X509EnhancedKeyUsageExtension ex = (X509EnhancedKeyUsageExtension)extension;
|
|
foreach (Oid OID in ex.EnhancedKeyUsages)
|
|
{
|
|
if (OID.Value == OID_REMOTE || OID.Value == OID_LOCAL)
|
|
certificatesCollection.Add(certificate);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//localMachineStore.Close();
|
|
}
|
|
return certificatesCollection;
|
|
}
|
|
|
|
private bool setConnectionInfo()
|
|
{
|
|
bool set = false;
|
|
if (_connection.Auth == ConnectionInfo.AuthMethod.Kerberos)
|
|
{
|
|
SetupAuthManager();
|
|
CredentialCache myCache = new CredentialCache();
|
|
|
|
// Use Kerberos with local credentials
|
|
if (_connection.Password == null || _connection.Password.Length == 0)
|
|
{
|
|
if (!string.IsNullOrEmpty(_connection.UserName))
|
|
{
|
|
throw new ArgumentException("Missing argument for user credentials: password. ");
|
|
}
|
|
myCache.Add(_connection.HostUri, "Negotiate", CredentialCache.DefaultNetworkCredentials);
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrEmpty(_connection.UserName))
|
|
{
|
|
throw new ArgumentException("Missing argument for user credentials: userName. ");
|
|
}
|
|
|
|
int i = _connection.UserName.IndexOf("\\");
|
|
if (i > 0)
|
|
{
|
|
string t_username = _connection.UserName.Substring(i + 1);
|
|
string t_domain = _connection.UserName.Substring(0, i);
|
|
myCache.Add(_connection.HostUri, "Negotiate", new NetworkCredential(t_username, _connection.Password.Copy(), t_domain));
|
|
}
|
|
else
|
|
{
|
|
myCache.Add(_connection.HostUri, "Negotiate", new NetworkCredential(_connection.UserName, _connection.Password.Copy()));
|
|
}
|
|
}
|
|
_credentials = myCache;
|
|
set = true;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(_connection.UserName) && (_connection.Password != null && _connection.Password.Length > 0))
|
|
{
|
|
CredentialCache myCache = new CredentialCache
|
|
{
|
|
{ _connection.HostUri, "Digest", new NetworkCredential(_connection.UserName, _connection.Password.Copy()) }
|
|
};
|
|
_credentials = myCache;
|
|
set = true;
|
|
}
|
|
|
|
_changed = _changed || set;
|
|
return set;
|
|
}
|
|
|
|
private void SetupAuthManager()
|
|
{
|
|
string hostName;
|
|
IPAddress IpAddress;
|
|
//checking if we need to find the host
|
|
if (IPAddress.TryParse(_connection.HostUri.Host, out IpAddress))
|
|
{
|
|
IPHostEntry hostInfo = Dns.GetHostEntry(IpAddress);
|
|
hostName = hostInfo.HostName;
|
|
|
|
if (hostName == null || hostName.Length == 0)
|
|
{
|
|
throw new ArgumentException("Problem with credentials.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hostName = _connection.Host;
|
|
}
|
|
|
|
if (AuthenticationManager.CustomTargetNameDictionary.ContainsKey(_connection.HostUri.AbsoluteUri) == false)
|
|
{
|
|
string SPN = "HTTP/" + hostName + ":16992";
|
|
if (_connection.HostUri.AbsoluteUri.StartsWith("https", StringComparison.CurrentCultureIgnoreCase) == true)
|
|
{
|
|
SPN = "HTTP/" + hostName + ":16993";
|
|
}
|
|
AuthenticationManager.CustomTargetNameDictionary.Add(_connection.HostUri.AbsoluteUri, SPN);
|
|
}
|
|
}
|
|
|
|
#endregion CONSTRUCTOR_FUNCTIONS
|
|
|
|
#region TRNASPORT_LAYER_OPERATION
|
|
// Create a WS-Management call, send it and return the WS-Management body response
|
|
// Note: In case of identify action, "header.Action" should be equal to constant IDENTIFY
|
|
private void WSManSendReceive(Header header, XmlElement[] bodyIn, ref XmlElement[] bodyOut)
|
|
{
|
|
if (header.Action == IDENTITY)
|
|
{
|
|
header.Action = null;
|
|
}
|
|
else
|
|
{
|
|
if ((header.Action == PUT || header.Action == CREATE) &&
|
|
(bodyIn == null || bodyIn.Equals("")))
|
|
{
|
|
throw new ArgumentException("The required body for the WSMan call is missing.");
|
|
}
|
|
//fill missing WSMan header values
|
|
header.ReplyTo = new ReplyTo();
|
|
header.MessageID = Guid.NewGuid().ToString();
|
|
header.ReplyTo.Address = DEFAULT_REPLY_TO;
|
|
header.OperationTimeout = DEFAULT_OPERATION_TIMEOUT;
|
|
header.To = _connection.HostUri.AbsoluteUri;
|
|
}
|
|
|
|
//Create WSMan call including envelope, header and body
|
|
WSManCall xmlPostData = new WSManCall
|
|
{
|
|
Header = header
|
|
};
|
|
if (null != bodyIn)
|
|
{
|
|
xmlPostData.Body.Any = bodyIn;
|
|
}
|
|
|
|
byte[] xml;
|
|
using (MemoryStream streamPostData = new MemoryStream())
|
|
{
|
|
//in order to avoid leading bytes:
|
|
Encoding utf8Enc = new UTF8Encoding(false);
|
|
//serialize all the data
|
|
XmlSerializer mySerializer = new XmlSerializer(xmlPostData.GetType());
|
|
XmlTextWriter xmlTextWriter = new XmlTextWriter(streamPostData, utf8Enc);
|
|
mySerializer.Serialize(xmlTextWriter, xmlPostData);
|
|
xml = streamPostData.ToArray();
|
|
}
|
|
|
|
try
|
|
{
|
|
//send the data and get the response
|
|
XmlDocument xmlResp = Task.Run(()=>HttpSendReceive(xml)).GetAwaiter().GetResult();
|
|
//extricate the WSMan body from the entire response
|
|
XmlNodeList nodesList = xmlResp.GetElementsByTagName(WSMAN_BODY, "*");
|
|
XmlElement innerBody = (XmlElement)nodesList.Item(0);
|
|
|
|
bodyOut = new XmlElement[innerBody.ChildNodes.Count];
|
|
int i = 0;
|
|
IEnumerator ienum = innerBody.GetEnumerator();
|
|
while (ienum.MoveNext())
|
|
{
|
|
bodyOut[i] = (XmlElement)ienum.Current;// InnerXml;
|
|
i++;
|
|
}
|
|
|
|
//checking if the action succeeded
|
|
nodesList = xmlResp.GetElementsByTagName(WSMAN_ACTION, "*");
|
|
if (nodesList.Count > 0 && nodesList[0].InnerText != null && nodesList[0].InnerText.EndsWith(WSMAN_FAULT))
|
|
{
|
|
throw new WSManException(DeserializeWSManFault(bodyOut[0]));
|
|
}
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
catch (WebException ex)
|
|
{
|
|
throw new WSManException(ex);
|
|
}
|
|
}
|
|
|
|
private bool _changed = false;
|
|
|
|
/// <summary>
|
|
/// Initiate HTTPClient Handler
|
|
/// </summary>
|
|
/// <returns> HTTPClient Handler </returns>
|
|
private HttpClientHandler CreateHttpHandler()
|
|
{
|
|
var handler = new HttpClientHandler();
|
|
try
|
|
{
|
|
handler.PreAuthenticate = true;
|
|
handler.Credentials = _credentials;
|
|
handler.Proxy = _connection.Proxy;
|
|
if (null != _X509CertificateCollection)
|
|
{
|
|
foreach (var cert in _X509CertificateCollection)
|
|
{
|
|
handler.ClientCertificates.Add(cert);
|
|
}
|
|
}
|
|
|
|
handler.ServerCertificateCustomValidationCallback = ValidationCallback;
|
|
}
|
|
catch
|
|
{
|
|
handler.Dispose();
|
|
}
|
|
|
|
return handler;
|
|
}
|
|
|
|
private bool ValidationCallback(HttpRequestMessage message, X509Certificate2 certificate, X509Chain certificateChain, SslPolicyErrors errors)
|
|
{
|
|
// We want to validate the certificate just on the first time we try to connect to the machine
|
|
if (FirstCall && (AllowCertErrors || _serverCertificateValidationCallback != null))
|
|
{
|
|
// Set the certificate policy in order to allow certificates problems
|
|
if (!CertificateValidationCallback(message, certificate, certificateChain, errors))
|
|
return false;
|
|
}
|
|
|
|
// Allow self signed certificate only if set to true in the connection, and the other options are not selected
|
|
if (_connection.AcceptSelfSignedCertificate && !AllowCertErrors &&
|
|
_serverCertificateValidationCallback == null)
|
|
{
|
|
if (!SelfSignedCertificateCallback(message, certificate, certificateChain, errors))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initiate HttpClient
|
|
/// </summary>
|
|
/// <returns>Initiated HTTP Client</returns>
|
|
private void CreateHttpClient()
|
|
{
|
|
httpClient = new HttpClient(CreateHttpHandler());
|
|
httpClient.BaseAddress = Connection.HostUri;
|
|
}
|
|
|
|
private async Task<XmlDocument> HttpSendReceive(byte[] postData)
|
|
{
|
|
if (postData == null)
|
|
{
|
|
throw new ArgumentException("Invalid post data");
|
|
}
|
|
|
|
if (_changed && httpClient != null)
|
|
{
|
|
httpClient.Dispose();
|
|
httpClient = null;
|
|
_changed = false;
|
|
}
|
|
if (httpClient == null)
|
|
{
|
|
CreateHttpClient();
|
|
}
|
|
string response = string.Empty;
|
|
try
|
|
{
|
|
XmlDocument resDoc;
|
|
using (var content = new ByteArrayContent(postData))
|
|
{
|
|
content.Headers.Remove("Content-Type");
|
|
content.Headers.Add("Content-Type", "application/soap+xml");
|
|
using (var responseMessage =
|
|
await httpClient.PostAsync(_connection.HostUri, content).ConfigureAwait(false))
|
|
{
|
|
response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
responseMessage.EnsureSuccessStatusCode();
|
|
resDoc = new XmlDocument();
|
|
resDoc.LoadXml(response);
|
|
}
|
|
}
|
|
|
|
return resDoc;
|
|
}
|
|
catch (XmlException)
|
|
{
|
|
throw;
|
|
}
|
|
catch (HttpRequestException httpReqExp)
|
|
{
|
|
if (httpReqExp.InnerException is WebException webExp)
|
|
{
|
|
throw webExp;
|
|
}
|
|
if (string.IsNullOrEmpty(response))
|
|
{
|
|
throw new WebException("Invalid HttpResponse");
|
|
}
|
|
|
|
throw new WebException(httpReqExp.Message);
|
|
}
|
|
}
|
|
|
|
#endregion TRNASPORT_LAYER_OPERATION
|
|
|
|
#region WSMAN_CALLS
|
|
|
|
/// <summary>
|
|
/// Creates a new instance of a resource and returns the URI of the new object.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, the identifier of the resource to be created</param>
|
|
/// <param name="resource">XmlElement, the instance data</param>
|
|
/// <returns></returns>
|
|
public CimReference Create(Uri resourceUri, XmlElement resource)
|
|
{
|
|
if (resourceUri == null)
|
|
throw new ArgumentNullException("resourceUri");
|
|
if (resource == null)
|
|
throw new ArgumentNullException("resource");
|
|
|
|
//define WSMan HEADER call
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = CREATE;
|
|
WSManHeader.ResourceURI = resourceUri.AbsoluteUri;
|
|
|
|
//define WSMan BODY call
|
|
|
|
XmlElement[] bodyIn = { resource };
|
|
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
CimReference retValue = null;
|
|
if (bodyOut != null)
|
|
{
|
|
retValue = new CimReference("ResourceCreated", bodyOut[0].NamespaceURI, bodyOut[0].InnerXml);
|
|
}
|
|
|
|
//ResourceCreatedType retValue = new ResourceCreatedType();
|
|
return retValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete the resource specified in the resource URI
|
|
/// (Only if one instance of the object exists)
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, the identifier of the resource to be deleted</param>
|
|
/// <param name="selectors">Selectors to id the object to delete</param>
|
|
public void Delete(Uri resourceUri, IEnumerable<Key> selectors)
|
|
{
|
|
if (resourceUri == null)
|
|
throw new ArgumentNullException("resourceUri");
|
|
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = DELETE;
|
|
WSManHeader.ResourceURI = resourceUri.AbsoluteUri;
|
|
WSManHeader.Any = AddSelectors(selectors);
|
|
|
|
XmlElement[] bodyIn = null;
|
|
XmlElement[] bodyOut = null;
|
|
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete the resource specified in the resource URI
|
|
/// (Only if one instance of the object exists)
|
|
/// </summary>
|
|
/// <param name="reference">CimReference to delete</param>
|
|
public void Delete(CimReference reference)
|
|
{
|
|
if (reference == null)
|
|
throw new ArgumentNullException("reference");
|
|
|
|
Delete(reference.GetResourceUri(), reference.GetKeys());
|
|
}
|
|
/// <summary>
|
|
/// Retrieves the resource specified by 'resource' and returns an XML representation
|
|
/// of the current instance of the resource.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, the identifier of the resource to be retrieved</param>
|
|
/// <param name="selectors">Selectors to id the object to be retrieved</param>
|
|
/// <returns>XmlElement, an XML of the current instance of the resource. </returns>
|
|
public XmlElement Get(Uri resourceUri, IEnumerable<Key> selectors)
|
|
{
|
|
if (resourceUri == null)
|
|
throw new ArgumentNullException("resourceUri");
|
|
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = GET;
|
|
WSManHeader.ResourceURI = resourceUri.AbsoluteUri;
|
|
WSManHeader.Any = AddSelectors(selectors);
|
|
|
|
XmlElement[] bodyIn = null;
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
if (bodyOut == null)
|
|
{
|
|
return null;
|
|
}
|
|
return bodyOut[0];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the resource specified by 'resource' and returns an XML representation
|
|
/// of the current instance of the resource.
|
|
/// </summary>
|
|
/// <param name="resource">EndpointReference to delete</param>
|
|
/// <returns>XmlElement, an XML of the current instance of the resource. </returns>
|
|
public XmlElement Get(CimReference resource)
|
|
{
|
|
if (resource == null)
|
|
throw new ArgumentNullException("resource");
|
|
|
|
return Get(resource.GetResourceUri(), resource.GetKeys());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update a resource.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, the identifier of the resource to update</param>
|
|
/// <param name="content"></param>
|
|
/// <param name="selectors">Selectors to id the object to update</param>
|
|
public void Put(Uri resourceUri, XmlElement content, IEnumerable<Key> selectors)
|
|
{
|
|
if (resourceUri == null)
|
|
throw new ArgumentNullException("resourceUri");
|
|
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = PUT;
|
|
WSManHeader.ResourceURI = resourceUri.AbsoluteUri;
|
|
WSManHeader.Any = AddSelectors(selectors);
|
|
|
|
//define WSMan BODY call
|
|
|
|
XmlElement[] bodyIn = { content };
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method to Identify a machine.
|
|
/// </summary>
|
|
/// <returns>XML which represent the machine</returns>
|
|
public XmlElement Identify()
|
|
{
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = IDENTITY;
|
|
XmlDocument xDoc = new XmlDocument();
|
|
String identify = "<Identify xmlns = \"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\"/>";
|
|
xDoc.LoadXml(identify);
|
|
XmlElement elem = xDoc.DocumentElement;
|
|
XmlElement[] bodyIn = { elem };
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
if (bodyOut == null)
|
|
{
|
|
return null;
|
|
}
|
|
return bodyOut[0];
|
|
}
|
|
private EnumerateRequest getEnumerateRequest(EnumerationOptions options, IEnumerable<Key> selectors)
|
|
{
|
|
XmlElement retValue = null;
|
|
EnumerateRequest enumerate = new EnumerateRequest();
|
|
enumerate.EnumerationMode = null;
|
|
enumerate.filter = null;
|
|
|
|
if (selectors != null)
|
|
{
|
|
|
|
SelectorFilter filter = new SelectorFilter();
|
|
filter.Any = AddSelectors(selectors);
|
|
filter.Dialect = "http://schemas.dmtf.org/wbem/wsman/1/wsman/SelectorFilter";
|
|
//Serialize the filter to XmlElement
|
|
XmlDocument xDoc = new XmlDocument();
|
|
XmlSerializer filterSerializer = new XmlSerializer(typeof(SelectorFilter));
|
|
using (StringWriter filterWriter = new StringWriter())
|
|
{
|
|
filterSerializer.Serialize(filterWriter, filter);
|
|
xDoc.LoadXml(filterWriter.ToString());
|
|
}
|
|
retValue = xDoc.DocumentElement;
|
|
}
|
|
|
|
if (options != null)
|
|
{
|
|
if (options.EnumMode == EnumerationOptions.EnumerationMode.NONE)
|
|
{
|
|
enumerate.EnumerationMode = null;
|
|
}
|
|
else if (options.EnumMode == EnumerationOptions.EnumerationMode.ENUMERATION_REFERENCE)
|
|
{
|
|
enumerate.EnumerationMode = WSMAN_ENUM_EPR;
|
|
}
|
|
else if (options.EnumMode == EnumerationOptions.EnumerationMode.ENUMERATION_OBJ_AND_REFERENCE)
|
|
{
|
|
enumerate.EnumerationMode = WSMAN_ENUM_OBJ_N_EPR;
|
|
}
|
|
|
|
if (options.Filter != null)
|
|
{
|
|
XmlDocument xDoc = new XmlDocument();
|
|
XmlSerializer filterSerializer = new XmlSerializer(options.Filter.GetType());
|
|
using (StringWriter filterWriter = new StringWriter())
|
|
{
|
|
Type ttt = options.Filter.GetType();
|
|
filterSerializer.Serialize(filterWriter, options.Filter);
|
|
xDoc.LoadXml(filterWriter.ToString());
|
|
}
|
|
retValue = xDoc.DocumentElement;
|
|
}
|
|
}
|
|
|
|
enumerate.filter = retValue;
|
|
return enumerate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerate resource.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, The identifier of the resource to be retrived</param>
|
|
/// <param name="selectors">Selectors to id the object to enumerate</param>
|
|
/// <param name="options">EnumerateOptions, a struct holds special enum options. Case of a NULL regular enumerate will be execute</param>
|
|
/// <returns>XmlElement array containing the xml response</returns>
|
|
public XmlElement[] Enumerate(Uri resourceUri, IEnumerable<Key> selectors, EnumerationOptions options)
|
|
{
|
|
if (resourceUri == null)
|
|
throw new ArgumentNullException("resourceUri");
|
|
|
|
//will be used later for the pull operation
|
|
PullResponse pullResp = new PullResponse();
|
|
//will contain the enumeration results
|
|
ArrayList container = new ArrayList();
|
|
|
|
//define the Header of the Enum call
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = ENUMERATE;
|
|
WSManHeader.ResourceURI = resourceUri.AbsoluteUri;
|
|
|
|
//define the BODY of the Enum call
|
|
XmlDocument xDoc = new XmlDocument();
|
|
EnumerateRequest enumerateReq = getEnumerateRequest(options, selectors);
|
|
//serialize the data
|
|
XmlSerializer enumerateSerializer = new XmlSerializer(enumerateReq.GetType());
|
|
using (StringWriter enumerateWriter = new StringWriter())
|
|
{
|
|
enumerateSerializer.Serialize(enumerateWriter, enumerateReq);
|
|
xDoc.LoadXml(enumerateWriter.ToString());
|
|
}
|
|
XmlElement[] bodyIn = { xDoc.DocumentElement };
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
//Get the EnumerationContext
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
|
|
//after getting the EnumerationContext we can call Pull to get the Enumeration elements
|
|
//create the HEADER for the pull request
|
|
WSManHeader.Action = PULL;
|
|
|
|
//update the BODY for the pull request
|
|
Pull pull = new Pull();
|
|
if (bodyOut != null)
|
|
{
|
|
pull.EnumerationContext = bodyOut[0].GetElementsByTagName(WSMAN_ENUM_CONTEXT, "*")[0].InnerText; //node[0].InnerText; //enumResp.EnumerationContext;
|
|
pull.MaxElements = MAX_ELEMENTS;
|
|
}
|
|
//serialize the data
|
|
XmlSerializer pullSerializer = new XmlSerializer(pull.GetType());
|
|
using (StringWriter pullWriter = new StringWriter())
|
|
{
|
|
pullSerializer.Serialize(pullWriter, pull);
|
|
xDoc.LoadXml(pullWriter.ToString());
|
|
}
|
|
bodyIn[0] = xDoc.DocumentElement;
|
|
bodyOut = null;
|
|
XmlSerializer myPullResSerializer = new XmlSerializer(pullResp.GetType());
|
|
do
|
|
{
|
|
//Pull the Enumeration elements
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
|
|
//get the results from the body
|
|
if (bodyOut != null)
|
|
{
|
|
pullResp = (PullResponse)myPullResSerializer.Deserialize(new StringReader(bodyOut[0].OuterXml));
|
|
}
|
|
|
|
foreach (XmlElement xmlElement in pullResp.Items)
|
|
{
|
|
// get all the xml elements from the each item nodes
|
|
foreach (XmlNode node in xmlElement.ChildNodes)
|
|
{
|
|
//In case of EndOfSequence InnerXml = ""
|
|
if (node.InnerText != "")
|
|
{
|
|
container.Add(node);
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (pullResp.EnumerationContext != null);
|
|
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
//Release the EnumerationContext
|
|
if (pullResp.EnumerationContext != null)
|
|
{
|
|
//update the HEADER for the Release request
|
|
WSManHeader.Action = RELEASE;
|
|
//update the BODY for the Release request
|
|
Release release = new Release();
|
|
release.EnumerationContext = pullResp.EnumerationContext;
|
|
//serialize the data
|
|
XmlSerializer releaseSerializer = new XmlSerializer(release.GetType());
|
|
using (StringWriter releaseWriter = new StringWriter())
|
|
{
|
|
releaseSerializer.Serialize(releaseWriter, release);
|
|
xDoc.LoadXml(releaseWriter.ToString());
|
|
}
|
|
bodyIn[0] = xDoc.DocumentElement;
|
|
|
|
//send the Release EnumerationContext WSMan call
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
return (XmlElement[])container.ToArray(typeof(XmlElement));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerate resource.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, The identifier of the resource to be retrived</param>
|
|
/// <param name="selectors"></param>
|
|
/// <returns>XmlElement array containing the xml response</returns>
|
|
public XmlElement[] Enumerate(Uri resourceUri, IEnumerable<Key> selectors)
|
|
{
|
|
return Enumerate(resourceUri, selectors, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes a method and returns the results of the method call.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, The identifier of the resource to be retrived</param>
|
|
/// <param name="actionUri">Uri, the action to run</param>
|
|
/// <param name="request">The input object for the method </param>
|
|
/// <param name="selectors">The selectors of the object to invoke method</param>
|
|
/// <returns>Method output</returns>
|
|
public XmlElement Invoke(Uri resourceUri, Uri actionUri, XmlElement request, IEnumerable<Key> selectors)
|
|
{
|
|
if (resourceUri == null)
|
|
throw new ArgumentNullException("resourceUri");
|
|
|
|
if (actionUri == null)
|
|
throw new ArgumentNullException("actionUri");
|
|
|
|
if (request == null)
|
|
throw new ArgumentNullException("request");
|
|
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = actionUri.AbsoluteUri;
|
|
WSManHeader.ResourceURI = resourceUri.AbsoluteUri;
|
|
WSManHeader.Any = AddSelectors(selectors);
|
|
|
|
//define WSMan BODY call
|
|
|
|
XmlElement[] bodyIn = { request };
|
|
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
if (bodyOut == null)
|
|
{
|
|
return null;
|
|
}
|
|
return bodyOut[0];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Subscribe to specified event.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, The identifier of the resource to be retrived</param>
|
|
/// <param name="info">Class which contains all data regarding the subscription</param>
|
|
/// <returns></returns>
|
|
public XmlElement Subscribe(SubscribeInfo info)
|
|
{
|
|
return Subscribe(info, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Subscribe to specified event.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, The identifier of the resource to be retrived</param>
|
|
/// <param name="info">Class which contains all data regarding the subscription</param>
|
|
/// <param name="issuedTokens">for digest authentication</param>
|
|
/// <returns></returns>
|
|
public XmlElement Subscribe(SubscribeInfo info, IssuedTokens issuedTokens)
|
|
{
|
|
if (info == null)
|
|
throw new ArgumentNullException("info");
|
|
|
|
//define WSMan HEADER call
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = SUBSCRIBE;
|
|
WSManHeader.ResourceURI = new Uri("http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_FilterCollection").AbsoluteUri;
|
|
WSManHeader.Any = AddSelectors(info.Keys);
|
|
|
|
//when digestAuthentication is required it needed to add the IssuedTokens to the header of the request ant the Auth to the body
|
|
//the IssuedTokens are sent as parameter to the function if digestAuthentication is required
|
|
//this class will sent with the username and password in it.
|
|
//if no it will be null
|
|
WSManHeader.IssuedTokens = issuedTokens;
|
|
if (issuedTokens != null)
|
|
info.Delivery.Auth = new Auth();
|
|
|
|
XmlDocument xDoc = new XmlDocument();
|
|
XmlSerializer SubscribeInfoSerializer = new XmlSerializer(typeof(SubscribeInfo));
|
|
using (StringWriter SubscribeWriter = new StringWriter())
|
|
{
|
|
SubscribeInfoSerializer.Serialize(SubscribeWriter, info);
|
|
xDoc.LoadXml(SubscribeWriter.ToString());
|
|
}
|
|
|
|
XmlElement[] bodyIn = { xDoc.DocumentElement };
|
|
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
if (bodyOut == null)
|
|
{
|
|
return null;
|
|
}
|
|
return bodyOut[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Unsubscribe to specified event.
|
|
/// </summary>
|
|
/// <param name="resourceUri">Uri, The identifier of the resource to be retrived</param>
|
|
/// <param name="selectors">The selectors of the object to Unsubscribe method</param>
|
|
public void Unsubscribe(IEnumerable<Key> selectors)
|
|
{
|
|
|
|
//define WSMan HEADER call
|
|
Header WSManHeader = new Header();
|
|
WSManHeader.Action = UNSUBSCRIBE;
|
|
WSManHeader.ResourceURI = new Uri("http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_FilterCollectionSubscription").AbsoluteUri;
|
|
|
|
WSManHeader.Any = AddSelectors(selectors);
|
|
|
|
//WSManHeader.Identifier = identifier;
|
|
|
|
XmlElement[] bodyIn = null;
|
|
XmlElement[] bodyOut = null;
|
|
try
|
|
{
|
|
WSManSendReceive(WSManHeader, bodyIn, ref bodyOut);
|
|
}
|
|
catch (WSManException)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This call back is used to allow the connection even if the certificate has erros (like hostname mismatch etc)
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="certificate"></param>
|
|
/// <param name="chain"></param>
|
|
/// <param name="errors"></param>
|
|
/// <returns></returns>
|
|
private bool CertificateValidationCallback(object sender, X509Certificate certificate,
|
|
X509Chain chain, SslPolicyErrors errors)
|
|
{
|
|
if (_serverCertificateValidationCallback != null)
|
|
{
|
|
if (allowCertificateError == null)
|
|
{
|
|
allowCertificateError = _serverCertificateValidationCallback(certificate, errors);
|
|
}
|
|
return allowCertificateError.Value;
|
|
}
|
|
|
|
if (AllowCertErrors)
|
|
{
|
|
if (FirstCall)
|
|
{
|
|
if (ServerCertRaised != null)
|
|
ServerCertRaised(certificate as X509Certificate2);
|
|
FirstCall = false;
|
|
}
|
|
|
|
if (errors == SslPolicyErrors.None)
|
|
{
|
|
CertError = new CertificateError();
|
|
return true;
|
|
}
|
|
|
|
if (errors == SslPolicyErrors.RemoteCertificateNameMismatch)
|
|
{
|
|
CertError = new CertificateError();
|
|
CertError.Error = errors;
|
|
CertError.Header = HOSTNAME_MISMATCH_HEADER;
|
|
CertError.Description = HOSTNAME_MISMATCH_ERROR;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool SelfSignedCertificateCallback(object sender, X509Certificate certificate,
|
|
X509Chain chain, SslPolicyErrors errors)
|
|
{
|
|
//If certificate is self signed, ignore all errors
|
|
if (certificate.Subject.Equals(certificate.Issuer))
|
|
{
|
|
return true;
|
|
}
|
|
if (errors == SslPolicyErrors.None)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endregion WSMAN_CALLS
|
|
|
|
#region WSMAN_UTILITIES
|
|
|
|
/// <summary>
|
|
/// Get the URI (the identifier) of the resource object
|
|
/// </summary>
|
|
/// <param name="type">Type, the type of the resource object</param>
|
|
/// <returns>The identifier of the resource object</returns>
|
|
public static string GetResourceUri(Type type)
|
|
{
|
|
if (type == null)
|
|
throw new ArgumentNullException("type");
|
|
|
|
foreach (object at in type.GetCustomAttributes(false))
|
|
{
|
|
if (at.GetType() == typeof(XmlRootAttribute))
|
|
{
|
|
return ((XmlRootAttribute)at).Namespace;
|
|
}
|
|
}
|
|
return "";
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// create selectors XML element with the key and values.
|
|
/// </summary>
|
|
/// <param name="selectors">selectors to be added</param>
|
|
/// <returns>XmlElement which represent the selectors</returns>
|
|
protected XmlElement[] AddSelectors(IEnumerable<Key> selectors)
|
|
{
|
|
XmlElement[] Any = null;
|
|
if (selectors != null)
|
|
{
|
|
XmlDocument paramsDoc = null;
|
|
bool firstSelector = true;
|
|
IEnumerator<Key> enumerator = selectors.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
//Create the outer tag only in the first loop
|
|
if (firstSelector)
|
|
{
|
|
Any = new XmlElement[2];
|
|
paramsDoc = new XmlDocument();
|
|
Any[1] = paramsDoc.CreateElement(WSMAN, WSMAN_SELECTOR_SET_FIELD, WSMAN_NAMESPACE_URI);
|
|
firstSelector = false;
|
|
}
|
|
|
|
Key selector = enumerator.Current;
|
|
XmlElement newChild = paramsDoc.CreateElement(WSMAN, WSMAN_SELECTOR_FIELD, WSMAN_NAMESPACE_URI);
|
|
newChild.SetAttribute(WSMAN_SELECTOR_NAME, selector.Name);
|
|
|
|
if (selector.cimReference != null)
|
|
{
|
|
newChild.InnerXml = selector.cimReference.ToString();
|
|
}
|
|
else if (selector.Value != null)
|
|
{
|
|
|
|
// if Byte Array
|
|
if (selector.Value.GetType().FullName == "System.Byte[]")
|
|
{
|
|
Object temp = selector.Value;
|
|
newChild.InnerText = Convert.ToBase64String((Byte[])temp);
|
|
}
|
|
else
|
|
{
|
|
newChild.InnerXml = selector.Value;
|
|
}
|
|
}
|
|
Any[1].AppendChild(newChild);
|
|
|
|
}
|
|
}
|
|
|
|
return Any;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Return the Type of the resource.
|
|
/// </summary>
|
|
/// <param name="resource">string, an XML representation of the resource</param>
|
|
/// <returns>Type, resource Type</returns>
|
|
public static Type GetType(string resource)
|
|
{
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.LoadXml(resource);
|
|
Type type = Type.GetType(doc.DocumentElement.LocalName);
|
|
if (type == null)
|
|
{
|
|
string className = doc.DocumentElement.NamespaceURI;
|
|
int classNameIndex = className.LastIndexOf("/");
|
|
className = className.Substring(classNameIndex + 1) + "Type+";
|
|
string typeName = "MOF_CLASSES." + className + doc.DocumentElement.LocalName;
|
|
type = Type.GetType(typeName);
|
|
if (type == null)
|
|
type = Type.GetType("MOF_CLASSES." + doc.DocumentElement.LocalName + "Type", true);
|
|
}
|
|
return type;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transforming (e.g. Deserialize) the WSMan Fault XML, to a WSMan Fault class
|
|
/// </summary>
|
|
/// <param name="XmlFault">The WSMan Fault in XML format</param>
|
|
/// <returns>The WSMan Fault in the Fault class format</returns>
|
|
private static Fault DeserializeWSManFault(XmlElement XmlFault)
|
|
{
|
|
Fault WSManFault = new Fault();
|
|
XmlSerializer mySerializer = new XmlSerializer(WSManFault.GetType());
|
|
WSManFault = (Fault)mySerializer.Deserialize(new StringReader(XmlFault.OuterXml));
|
|
return WSManFault;
|
|
}
|
|
|
|
#endregion WSMAN_UTILITIES
|
|
|
|
#region PROPERTIES
|
|
|
|
|
|
#endregion PROPERTIES
|
|
|
|
#region IDisposable Implementation
|
|
private bool _disposed = false;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
if (disposing)
|
|
{
|
|
Connection?.Dispose();
|
|
httpClient?.Dispose();
|
|
}
|
|
|
|
_disposed = true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
~DotNetWSManClient()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#region WSMAN_SOAP_STRUCT
|
|
/// <summary>
|
|
/// The WS-Management call include 2 elemtns:
|
|
/// 1. Header
|
|
/// 2. Body
|
|
/// each of them contains aditional fields, this class include all the needed fields to
|
|
/// creat a WS-Management call.
|
|
/// After filling all the data, this class will serialize to a XML format and send to the server
|
|
/// </summary>
|
|
[XmlRootAttribute("Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope", IsNullable = false)]
|
|
public class WSManCall
|
|
{
|
|
/// <summary>
|
|
/// Header of the wsman call.
|
|
/// </summary>
|
|
[XmlElement(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
|
|
public Header Header;
|
|
|
|
/// <summary>
|
|
/// Body of the wsman call.
|
|
/// </summary>
|
|
[XmlElement(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
|
|
public Body Body;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Class which represent the header of the wsman call.
|
|
/// </summary>
|
|
public class Header
|
|
{
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
|
|
public string Action;
|
|
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
|
|
public string To;
|
|
|
|
[XmlElement(Namespace = "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd")]
|
|
public string ResourceURI;
|
|
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
|
|
public string MessageID;
|
|
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
|
|
public ReplyTo ReplyTo;
|
|
|
|
[XmlElement(Namespace = "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd")]
|
|
public string MaxEnvelopeSize;
|
|
|
|
[XmlElement(Namespace = "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd")]
|
|
public string OperationTimeout;
|
|
|
|
[XmlAnyElementAttribute()]
|
|
public XmlElement[] Any;
|
|
|
|
//Optional: To request digest authentication when alerts are sent
|
|
//if digest authentication are requested this class is allocated in the subscribe function
|
|
//if not this class will be null and will not send as part of the request
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/trust")]
|
|
public IssuedTokens IssuedTokens;
|
|
|
|
public Header()
|
|
{
|
|
IssuedTokens = null;
|
|
ReplyTo = null;
|
|
}
|
|
}
|
|
|
|
public class ReplyTo
|
|
{
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
|
|
public string Address;
|
|
}
|
|
|
|
public struct Body
|
|
{
|
|
[XmlAnyElementAttribute()]
|
|
public XmlElement[] Any;
|
|
}
|
|
|
|
//Additional WS-Management sub structures (e.g. WS-Management XML elemets)
|
|
public struct EnumerateResponse
|
|
{
|
|
public string EnumerationContext;
|
|
}
|
|
|
|
[XmlRoot("Enumerate", Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public struct EnumerateRequest
|
|
{
|
|
[XmlElement(Namespace = "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd")]
|
|
public string EnumerationMode;
|
|
[XmlAnyElementAttribute()]
|
|
public XmlElement filter;
|
|
}
|
|
|
|
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public struct Pull
|
|
{
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public string EnumerationContext;
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public string MaxElements;
|
|
}
|
|
|
|
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public struct PullResponse
|
|
{
|
|
public string EnumerationContext;
|
|
|
|
[XmlAnyElementAttribute()]
|
|
public XmlElement[] Items;
|
|
}
|
|
|
|
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public struct Release
|
|
{
|
|
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/09/enumeration")]
|
|
public string EnumerationContext;
|
|
}
|
|
|
|
#endregion WSMAN_SOAP_STRUCT
|
|
|
|
#region CLASSES
|
|
|
|
public class CertificateError
|
|
{
|
|
public string Description { set; get; }
|
|
public string Header { set; get; }
|
|
public SslPolicyErrors Error { set; get; }
|
|
public X509Certificate2 Certificate { set; get; }
|
|
}
|
|
public struct CerftificateCallback
|
|
{
|
|
public bool IgnoreError { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
}
|