675 lines
18 KiB
C#

// 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
{
/// <summary>
/// The Setup Status of Me Device
/// </summary>
public enum MeSetupStatus
{
Unknown=-1,
Unconfigured=0,
RemoteStarted=1,
Configured=2,
}
public enum InternetProtocolVersionType : int
{
IPv4 = 4,
Ipv6 = 6,
}
/// <summary>
/// Implements a local Intel Management Engine Device
/// </summary>
[Guid("8B6308C7-CB52-4db2-B0DF-63786CDE58AE")]
[ComVisible(true)]
public class MeDevice : IMeDevice,IDisposable
{
Intel.Management.Wsman.IWsmanConnection _conn = null;
IDictionary<string,IMeVersionInfo> _verInfo;
MeSetupStatus _setupStatus;
string _biosString;
string _configNonce;
string _realm;
string[] _hashes;
bool _ztcEnabled;
bool _ccmSupported;
bool _hostCfgSupported;
/// <summary>
/// Default constructor
/// </summary>
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<string, IMeVersionInfo>();
//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<string> list = new List<string>();
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;
}
/// <summary>
/// Returns local $OSAdmin Wsman Connection
/// </summary>
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<string> unusedList = new List<string>();
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;
/// <summary>
/// Implement IDisposable method
/// </summary>
/// <param name="disposing"></param>
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