// Copyright (C) Intel Corporation, 2010 All Rights Reserved. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Xml; using System.Security; using Common.Utils; namespace Intel.Management.Mei { /// /// The Setup Status of Me Device /// public enum MeSetupStatus { Unknown=-1, Unconfigured=0, RemoteStarted=1, Configured=2, } public enum InternetProtocolVersionType : int { IPv4 = 4, Ipv6 = 6, } /// /// Implements a local Intel Management Engine Device /// [Guid("8B6308C7-CB52-4db2-B0DF-63786CDE58AE")] [ComVisible(true)] public class MeDevice : IMeDevice,IDisposable { Intel.Management.Wsman.IWsmanConnection _conn = null; IDictionary _verInfo; MeSetupStatus _setupStatus; string _biosString; string _configNonce; string _realm; string[] _hashes; bool _ztcEnabled; bool _ccmSupported; bool _hostCfgSupported; /// /// Default constructor /// public MeDevice() { //_mngSelection= ManageabilitySelectionMode. _setupStatus=MeSetupStatus.Unknown; } private void GetSetupState(HECIClass heci) { HECIClass.ProvisioningState state; if (heci.GetProvisioningState(out state)) { switch (state) { case HECIClass.ProvisioningState.Pre: _setupStatus = MeSetupStatus.Unconfigured; break; case HECIClass.ProvisioningState.In: _setupStatus = MeSetupStatus.RemoteStarted; break; case HECIClass.ProvisioningState.Post: _setupStatus = MeSetupStatus.Configured; break; } } } private bool GetCodeVersions(HECIClass heci) { HECIClass.AMT_VERSION_TYPE[] versions; bool result = false; if (heci.GetCodeVersions(out _biosString, out versions)) { result = true; _verInfo = new Dictionary(); //look for AMT foreach (HECIClass.AMT_VERSION_TYPE version in versions) { _verInfo.Add(version.Description.Text, new MeVersionInfo(version.Version.Text)); } } return result; } private void GetHashes(HECIClass heci) { HECIClass.HashEntry[] hashes; _hashes = new string[0]; if (heci.GetCertHashes(out hashes)) { List list = new List(); foreach (HECIClass.HashEntry hash in hashes) { if (hash.IsActive) list.Add(hash.Thumbprint); } _hashes = list.ToArray(); } } private void GetCredentials(HECIClass heci) { string userName; SecureString password; if (heci.GetLocalAdminCredentials(out userName, out password)) { if (_conn == null) _conn = new Intel.Management.Wsman.WsmanConnection(); _conn.Username = userName; if (_conn.Password != null) _conn.Dispose(); _conn.Password = password; IMeVersionInfo coreVersion; coreVersion = GetCodeVersion("AMT"); // get the configuration Nonce if AMT core version is greater than 6.1 if ((coreVersion != null && ((coreVersion.Major > 6) || (coreVersion.Major == 6 && coreVersion.Minor > 1)))) { foreach (Intel.Management.Wsman.IWsmanItem item in _conn.ExecQuery("SELECT * FROM IPS_HostBasedSetupService")) { if (!item.Object.GetProperty("ConfigurationNonce").IsNull) _configNonce = item.Object.GetProperty("ConfigurationNonce").ToString(); foreach (Intel.Management.Wsman.IWsmanItem modeItem in item.Object.GetProperty("AllowedControlModes")) { if (modeItem.ToString().Equals("1")) _hostCfgSupported = true; if (modeItem.ToString().Equals("2")) { _hostCfgSupported = true; _ccmSupported = true; } } } foreach (Intel.Management.Wsman.IWsmanItem item in _conn.ExecQuery("SELECT * FROM AMT_GeneralSettings")) { _realm = item.Object.GetProperty("DigestRealm").ToString(); } } } } private bool PerformDisovery(HECIClass heci) { bool result = GetCodeVersions(heci); if (result) { GetSetupState(heci); heci.GetZeroTouchEnabled(out _ztcEnabled); GetCredentials(heci); GetHashes(heci); } return result; } public string BiosVersion { get { return _biosString; } } public string ConfigurationNonce { get { return _configNonce; } } public string DigestRealm { get { return _realm; } } public string[] ActiveHashes { get { if (_hashes == null) _hashes = new string[0]; return _hashes; } } public bool ClientControlSupported { get { return _ccmSupported; } } public bool HostConfigurationSupported { get { return _hostCfgSupported; } } public IMeVersionInfo GetCodeVersion(string name) { IMeVersionInfo result = null; if (_verInfo != null) _verInfo.TryGetValue(name, out result); return result; } public bool Enable() { bool result=false; HECIClass heci = new HECIClass(); heci.Init(); try { result = GetCodeVersions(heci); } finally { heci.DeInit(); } if (result == false) { heci = new HECIClass(); heci.Init(HECIClass.WatchDogGuid); try { result = heci.QueryStateIndependence(); if (result) result = heci.EnableStateIndependence(); if (result == false) throw new HECIClass.MeiException("Unable to Enabled ME State Independence"); } finally { heci.DeInit(); } } return result; } public bool Discover() { bool result = false; HECIClass heci = new HECIClass(); heci.Init(); try { result = PerformDisovery(heci); } finally { heci.DeInit(); } return result; } public IMeVersionInfo CoreVersion { get { return GetCodeVersion("AMT"); } } public MeSetupStatus SetupStatus { get { return _setupStatus; } } public bool RemoteConfigurationSupported { get { bool result = false; HECIClass heci = new HECIClass(); heci.Init(); try { heci.GetZeroTouchEnabled(out result); } finally { heci.DeInit(); } return result; } } public bool StartRemoteConfiguration(string otpValue,bool useIPv6) { bool result = false; SecureString secOTP = new SecureString(); IMeVersionInfo coreVersion; HECIClass heci = new HECIClass(); heci.Init(); try { if (_verInfo == null) PerformDisovery(heci); coreVersion = GetCodeVersion("AMT"); if (!string.IsNullOrEmpty(otpValue)) { secOTP = otpValue.ConvertToSecureString(); otpValue = string.Empty; heci.SetOTP(secOTP); } if (useIPv6) { result=heci.StartConfigurationEx(true); } if ((coreVersion != null && coreVersion.Major >= 6)) { result=heci.StartConfigurationEx(false); } else { result = heci.StartConfiguration(); } //update the state GetSetupState(heci); } finally { secOTP.Dispose(); heci.DeInit(); } return result; } public bool Unprovision() { HECIClass heci = new HECIClass(); heci.Init(); bool result = false; try { result = heci.UnProvision(); } finally { heci.DeInit(); } if (result && _conn!=null) { _conn.Close(); } return result; } public bool OpenUserInitiatedConnection() { HECIClass heci = new HECIClass(); heci.Init(); bool result = false; try { result = heci.OpenUserInitiatedConnection(); } catch (Exception exp) { throw exp; // re-throw } finally { heci.DeInit(); } return result; } public bool CloseUserInitiatedConnection() { HECIClass heci = new HECIClass(); heci.Init(); bool result = false; try { result = heci.CloseUserInitiatedConnection(); } catch (Exception exp) { throw exp; // re-throw } finally { heci.DeInit(); } if (result && _conn != null) { _conn.Close(); } return result; } public bool StopConfiguration() { HECIClass heci = new HECIClass(); heci.Init(); bool result = false; try { result = heci.StopConfiguration(); } catch (Exception exp) { throw exp; // re-throw } finally { heci.DeInit(); } if (result && _conn != null) { _conn.Close(); } return result; } /// /// Returns local $OSAdmin Wsman Connection /// public Wsman.IWsmanConnection LocalConnection { get { if (_conn == null) { HECIClass heci = new HECIClass(); heci.Init(); try { GetCredentials(heci); } finally { heci.DeInit(); } } return _conn; } } public SecureString CreateRandomPassword(int length) { SecureString secPass =new SecureString(); // generate random number from Cryptography provider byte[] data; using (System.Security.Cryptography.RandomNumberGenerator rng = System.Security.Cryptography.RandomNumberGenerator.Create()) { data = new byte[sizeof(int)]; rng.GetBytes(data); } //create a random seed generate Random rnd = new Random(BitConverter.ToInt32(data, 0)); string lowChars = "abcdefghijklmnopqrstuvwxyz"; string upChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string numChars = "1234567890"; string specialChars = "!@;"; string allChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@;"; List unusedList = new List(); unusedList.Add(lowChars); unusedList.Add(upChars); unusedList.Add(numChars); unusedList.Add(specialChars); for (int i = 0; i < length; i++) { if (unusedList.Count > 0) { int index = rnd.Next(unusedList.Count); string nextList = unusedList[index]; char nextChar = nextList[rnd.Next(0,nextList.Length)]; secPass.AppendChar(nextChar); unusedList.RemoveAt(index); } else { char nextChar = allChars[rnd.Next(0,allChars.Length)]; secPass.AppendChar(nextChar); //[System.Text.Encoding]::ASCII. } } Array.Clear(data, 0, data.Length); return secPass; } public string GetPasswordHash(string user, string realm, SecureString password) { return HashPassword(user, realm, password); } public static string HashPassword(string user, string realm, SecureString password) { string result; byte[] hash; using (System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider()) { StringBuilder builder = new StringBuilder(); builder.Append(user); builder.Append(":"); builder.Append(realm); builder.Append(":"); builder.Append(password); hash = md5.ComputeHash(Encoding.ASCII.GetBytes(builder.ToString())); result = BitConverter.ToString(hash); result = result.Replace("-", string.Empty); md5.Clear(); } Array.Clear(hash, 0, hash.Length); return result; } public static DateTime FormatDate(Intel.Management.Wsman.IWsmanItem dateItem) { string dateValue = "2010-03-25T00:00:00Z"; if (dateItem.IsObject) { dateValue = dateItem.Object.Text; } else if (dateItem.IsString) { dateValue = dateItem.ToString(); } dateValue = dateValue.Replace("-", string.Empty).Replace("T", string.Empty).Replace(":", string.Empty); int year, month, day, hour, minute, second; using (System.IO.StringReader reader = new System.IO.StringReader(dateValue)) { char[] buff = new char[4]; //read year reader.Read(buff, 0, buff.Length); year = int.Parse(new string(buff)); buff = new char[2]; //read month reader.Read(buff, 0, buff.Length); month = int.Parse(new string(buff)); //read day reader.Read(buff, 0, buff.Length); day = int.Parse(new string(buff)); //read hour reader.Read(buff, 0, buff.Length); hour = int.Parse(new string(buff)); //read minutes reader.Read(buff, 0, buff.Length); minute = int.Parse(new string(buff)); //read seconds reader.Read(buff, 0, buff.Length); second = int.Parse(new string(buff)); } return new DateTime(year, month, day, hour, minute, second); } #region dispose private bool _disposed = false; /// /// Implement IDisposable method /// /// protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _conn?.Dispose(); } _disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~MeDevice() { Dispose(false); } #endregion }// end ME Device }// End Namespace