239 lines
8.2 KiB
C#
239 lines
8.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Security.Cryptography;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.IO;
|
|
using System.Xml;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Security;
|
|
|
|
namespace Intel.Management.Wsman
|
|
{
|
|
class ClientRequest : IDisposable
|
|
{
|
|
private readonly HttpTransport _transport; //message transport
|
|
|
|
public ClientRequest(Uri address, AddressFamily addressType)
|
|
{
|
|
_transport = string.Compare(address.Scheme, "https", true) == 0
|
|
? new TlsTransport(addressType, address)
|
|
: new PlainTextTransport(addressType, address);
|
|
}
|
|
|
|
public Uri Address => _transport.Address;
|
|
|
|
/// <summary>
|
|
/// Sends the XML to Amt and returns the response XML
|
|
/// </summary>
|
|
/// <param name="reqDoc">The XML to send</param>
|
|
/// <param name="soapCmd">Optional Soap Action to send</param>
|
|
/// <returns></returns>
|
|
public ServerResponse Send(XmlDocument reqDoc, string soapCmd)
|
|
{
|
|
ServerResponse result = null;
|
|
string proxyToken = null;
|
|
string authToken = null;
|
|
|
|
// make sure there is authorization
|
|
GetAuthorization();
|
|
int retry = _transport.Authorization.MaxAttempts;
|
|
|
|
// _transport.Proxy = new HttpProxy("http://localhost:8080","randy","P@ssw0rd");
|
|
|
|
while (retry >0)
|
|
{
|
|
if (authToken == null)
|
|
{
|
|
switch (_transport.Authorization.State)
|
|
{
|
|
case HandshakeState.CredentialsAquired:
|
|
// get the initial token (this message will be sent with it)
|
|
authToken = _transport.Authorization.GetInitialToken();
|
|
break;
|
|
case HandshakeState.ResponseNeeded:
|
|
// get the next token (this message will be sent with it)
|
|
authToken = _transport.Authorization.GetNextToken();
|
|
break;
|
|
case HandshakeState.Failed:
|
|
break; // result may null
|
|
}
|
|
}
|
|
|
|
int contentLength = -1;
|
|
if (reqDoc != null)
|
|
{
|
|
byte[] data = Encoding.UTF8.GetBytes(reqDoc.OuterXml);
|
|
contentLength = data.Length;
|
|
}
|
|
|
|
using (StringWriter writer = new StringWriter())
|
|
{
|
|
writer.Write("POST ");
|
|
writer.Write(_transport.GetRequestUri());
|
|
writer.Write(" HTTP/1.1");
|
|
writer.WriteLine();
|
|
writer.Write("Host: ");
|
|
writer.Write(_transport.Address.Authority);
|
|
writer.WriteLine();
|
|
writer.Write("User-Agent: AmtClient/1.0");
|
|
writer.WriteLine();
|
|
writer.Write("Content-Type: text/xml; charset=utf-8");
|
|
writer.WriteLine();
|
|
writer.Write("Content-Length: ");
|
|
writer.Write(contentLength.ToString());
|
|
writer.WriteLine();
|
|
writer.Write("Connection: keep-alive");
|
|
writer.WriteLine();
|
|
|
|
if (authToken != null && !authToken.Equals(string.Empty))
|
|
{
|
|
writer.Write("Authorization: ");
|
|
writer.Write(authToken);
|
|
writer.WriteLine();
|
|
}
|
|
|
|
if (proxyToken != null)
|
|
{
|
|
writer.Write("Proxy-Authorization: ");
|
|
writer.Write(proxyToken);
|
|
writer.WriteLine();
|
|
}
|
|
|
|
// add optional SoapAction
|
|
if (soapCmd != null)
|
|
{
|
|
writer.Write("SOAPAction: ");
|
|
if (!soapCmd.StartsWith("\""))
|
|
writer.Write("\"");
|
|
writer.Write(soapCmd);
|
|
if (!soapCmd.StartsWith("\""))
|
|
writer.Write("\"");
|
|
writer.WriteLine();
|
|
}
|
|
|
|
writer.WriteLine();
|
|
|
|
_transport.InitializeRequest();
|
|
|
|
//send headers first
|
|
_transport.SendMessageHeaders(writer.ToString());
|
|
}
|
|
|
|
//next send body (if any)
|
|
if (reqDoc != null)
|
|
_transport.SendMessageBody(reqDoc.OuterXml);
|
|
result=_transport.GetResponse("POST");
|
|
proxyToken = null;
|
|
|
|
if (result.StatusCode == 401 || result.StatusCode==407 )
|
|
{
|
|
|
|
if (result.StatusCode == 401)
|
|
{
|
|
if (_transport.Authorization.State != HandshakeState.ResponseNeeded)
|
|
retry = 0;
|
|
retry--;
|
|
if (retry > 0)
|
|
_transport.Authorization.SetReturnToken(result.Challange);
|
|
}
|
|
|
|
// if we have a proxy challange then get the proxy authorization
|
|
if (!string.IsNullOrEmpty(result.ProxyChallange))
|
|
{
|
|
proxyToken = _transport.GetProxyAuthorization("POST", _transport.Address.LocalPath, result);
|
|
retry = 3;
|
|
}
|
|
else
|
|
{
|
|
authToken = null; // only keep the authToken if we have a proxy challenge
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retry = 0;
|
|
authToken = null;
|
|
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends the XML to Amt and returns the response XML
|
|
/// </summary>
|
|
/// <param name="reqDoc">The XML to send</param>
|
|
/// <returns></returns>
|
|
public ServerResponse Send(XmlDocument reqDoc)
|
|
{
|
|
return Send(reqDoc, null);
|
|
}
|
|
|
|
public ISecurityHandshake GetAuthorization()
|
|
{
|
|
if (_transport.Authorization == null)
|
|
_transport.Authorization = new AnonymousAuthorization();
|
|
return _transport.Authorization;
|
|
}
|
|
|
|
public void SetProxy(HttpProxy proxy)
|
|
{
|
|
_transport.Proxy = proxy;
|
|
}
|
|
|
|
public void SetWindowsAuthorization(string user, string domain, SecureString password, string spn)
|
|
{
|
|
if (string.IsNullOrEmpty(spn))
|
|
spn = "HTTP/" + Address?.Authority.ToUpper();
|
|
_transport.Authorization = new WindowsAuthorization(user, domain, password, spn);
|
|
}
|
|
|
|
public void SetDigestAuthorization(string user, SecureString password)
|
|
{
|
|
_transport.Authorization = new DigestAuthorization(user, password, _transport.Address.LocalPath, "POST");
|
|
}
|
|
|
|
public void SetAnonymousAuthorization()
|
|
{
|
|
_transport.Authorization = new AnonymousAuthorization();
|
|
}
|
|
|
|
public void SetCertificate(X509Certificate2 cert)
|
|
{
|
|
_transport.SetCredentials(cert);
|
|
}
|
|
|
|
public void SetCertificateOptions(bool verifyCa,bool verifyCN, bool sendRoot)
|
|
{
|
|
_transport.SetCertificateValidationOptions(verifyCa, verifyCN, sendRoot);
|
|
}
|
|
|
|
#region IDisposable Members
|
|
|
|
private bool _disposed = false;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
if (disposing)
|
|
{
|
|
_transport?.Dispose();
|
|
}
|
|
_disposed = true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}//end namespace
|
|
|