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; /// /// Sends the XML to Amt and returns the response XML /// /// The XML to send /// Optional Soap Action to send /// 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; } /// /// Sends the XML to Amt and returns the response XML /// /// The XML to send /// 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