675 lines
18 KiB
C#
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
|