355 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;
using System.Security.Principal;
using System.Management.Automation.Provider;
using Intel.Management.Wsman;
namespace Intel.Management.PSModule.Amt
{
class AuditLogService : DriveItem
{
public AuditLogService(IManagedReference refToLog, DriveItem parent)
: base("AccessMonitor", new Content(), parent)
{
_refToLog = refToLog;
}
enum InitiatorType : byte
{
HttpDigest = 0,
KerberosSid = 1,
Local = 2,
}
enum MCLocationType : byte
{
IPv4 = 0,
IPv6 = 1,
None = 2,
}
class LogReader : IContentReader
{
IManagedReference _refToLog;
int _startIndex;
int _totalCount;
bool _reading;
List<byte[]> _records;
XmlDocument _eventDoc;
public LogReader(IManagedReference refToLog)
{
_refToLog = refToLog;
_startIndex = 1;
_totalCount = 0;
_records = new List<byte[]>();
_reading = true;
_eventDoc = new XmlDocument();
_eventDoc.LoadXml(Intel.Management.PSModule.Properties.Resources.AuditEventsXML);
}
public void Dispose()
{
}
public void Close()
{
}
public void Seek(long offset, System.IO.SeekOrigin origin)
{
}
public System.Collections.IList Read(long size)
{
System.Collections.IList list = new System.Collections.ArrayList();
if ( _records.Count < size && _reading)
ReadRecords();
for (int i = 0; i < size && _records.Count > 0; i++)
{
byte[] data = _records[0];
_records.RemoveAt(0);
MemoryStream stream = new System.IO.MemoryStream(data);
BinaryReader reader = new System.IO.BinaryReader(stream);
// read policyNumer (appID + EventID)
uint policyNumber = reader.ReadUInt32();
// get policy Data
byte[] policyData = BitConverter.GetBytes(policyNumber);
Array.Reverse(policyData);
//read event/App IDs
ushort evenId = BitConverter.ToUInt16(policyData, 0);
ushort appId = BitConverter.ToUInt16(policyData, 2);
// read Initiator (user)
string user = string.Empty;
InitiatorType type = (InitiatorType)reader.ReadByte();
switch (type)
{
case InitiatorType.HttpDigest:
int bytesToRead = (int)reader.ReadByte();
// PolicyData is a UInt32 number which consists of two UInt16 values: Event ID, and App ID.
if (bytesToRead > 0 && bytesToRead <= 4)
{
policyData = reader.ReadBytes(bytesToRead);
user = Encoding.UTF8.GetString(policyData);
}
break;
case InitiatorType.KerberosSid:
policyNumber = reader.ReadUInt32();
policyData = BitConverter.GetBytes(policyNumber);
List<byte> sidData = new List<byte>(policyData);
bytesToRead = (int)reader.ReadByte();
// PolicyData is a UInt32 number which consists of two UInt16 values: Event ID, and App ID.
if (bytesToRead > 0 && bytesToRead <= 4)
{
policyData = reader.ReadBytes(bytesToRead);
sidData.InsertRange(0, policyData);
SecurityIdentifier sec = new SecurityIdentifier(sidData.ToArray(), 0);
user = sec.ToString();
/*try
{
NTAccount account = (NTAccount)sec.Translate(typeof(NTAccount));
user = account.Value;
}
catch (Exception)
{
user = sec.Value;
}*/
}
break;
case InitiatorType.Local:
break;
}
//read timestamp
uint seconds = reader.ReadUInt32();
policyData = BitConverter.GetBytes(seconds);
Array.Reverse(policyData);
seconds = BitConverter.ToUInt32(policyData, 0);
DateTime stdTime = new DateTime(1970, 1, 1);
DateTime stamp = stdTime.AddSeconds((double)seconds);
//read Location
string location=string.Empty;
MCLocationType locationType = (MCLocationType)reader.ReadByte();
switch (locationType)
{
case MCLocationType.IPv4:
case MCLocationType.IPv6:
int bytesToRead = (int)reader.ReadByte();
// PolicyData is a UInt32 number which consists of two UInt16 values: Event ID, and App ID.
if (bytesToRead > 0 && bytesToRead <= 4)
{
policyData = reader.ReadBytes(bytesToRead);
location = Encoding.ASCII.GetString(policyData);
}
break;
case MCLocationType.None:
break;
}
// get extended
byte extendedLen = reader.ReadByte();
if (extendedLen >0)
policyData = reader.ReadBytes((int)extendedLen);
else
policyData = new byte[0];
list.Add(GetEvent(appId, evenId, user, stamp, location, policyData));
}
return list;
}
AuditEvent GetEvent(int appId,int eventId,string user,DateTime stamp, string location, byte[] extended)
{
XmlNode node = _eventDoc.DocumentElement.SelectSingleNode(string.Format(
"Group[@AppId=\"{0}\"]", appId.ToString()));
if (node != null)
{
node = node.SelectSingleNode(string.Format(
"Event[@EventId=\"{0}\"]", eventId.ToString()));
}
string message = string.Empty;
if (node == null)
message = "Application Id is " + appId.ToString() + " and " + " EventId is " + eventId.ToString();
else
message = ((XmlElement)node).GetAttribute("Name");
// read extendedData (if any)
return new AuditEvent(appId, eventId,stamp, user, location, message, null);
}
void ReadRecords()
{
IManagedInstance inputObj = _refToLog.CreateMethodInput("ReadRecords");
inputObj.SetProperty("StartIndex", _startIndex.ToString());
IManagedInstance outObj = _refToLog.InvokeMethod(inputObj);
string result = outObj.GetProperty("ReturnValue").ToString();
if (result.Equals("0"))
{
_startIndex += int.Parse(outObj.GetProperty("RecordsReturned").ToString());
_totalCount = int.Parse(outObj.GetProperty("TotalRecordCount").ToString());
_reading = _startIndex < _totalCount;
if (_totalCount>0)
{
foreach (IWsmanItem item in outObj.GetProperty("EventRecords"))
{
byte[] data = Convert.FromBase64String(item.ToString());
_records.Add(data);
}
}
}
else
{
if (result.Equals("1"))
AmtException.ThrowInvokeError(outObj, "Internal error");
else if (result.Equals("2"))
AmtException.ThrowInvokeError(outObj, "Not Ready");
else if (result.Equals("35"))
AmtException.ThrowInvokeError(outObj, "Invalid Index");
else
AmtException.ThrowInvokeError(outObj,string.Empty);
}
}
}
IManagedReference _refToLog;
static readonly string[] _properties = {"TimeOfLastRecord","PercentageFree","CurrentNumberOfRecords","Enabled" };
DateTime _timeOfLastRecord;
int _percentageFree;
ulong _currentNumberOfRecords;
bool _enabled;
bool _propertiesCached;
public override void ClearContent(DriveProvider provider)
{
IManagedInstance inputObj = _refToLog.CreateMethodInput("ClearLog");
IManagedInstance outObj = _refToLog.InvokeMethod(inputObj);
switch (outObj.GetProperty("ReturnValue").ToString())
{
case "0":
break;
case "32770":
AmtException.ThrowInvokeError(outObj, "Not ready");
break;
case "32784":
AmtException.ThrowInvokeError(outObj, "Not permitted");
break;
case "32806":
AmtException.ThrowInvokeError(outObj, "Flash write limit exceeded");
break;
default:
AmtException.ThrowInvokeError(outObj);
break;
}
}
public override object GetReturnObject()
{
return new NameValuePairItem(Name, Value);
}
public override string[] Properties
{
get
{
return _properties;
}
}
public override IContentReader GetContentReader(DriveProvider provider)
{
return new LogReader(_refToLog);
}
public DateTime TimeOfLastRecord
{
get
{
return _timeOfLastRecord;
}
}
public int PercentageFree
{
get
{
return _percentageFree;
}
}
public ulong CurrentNumberOfRecords
{
get
{
return _currentNumberOfRecords;
}
}
public bool Enabled
{
get
{
return _enabled;
}
}
protected override void LoadProperties(DriveProvider provider)
{
if (_propertiesCached == false || provider.Force.IsPresent)
{
IManagedInstance logObj= _refToLog.Get();
IWsmanItem item = logObj.GetProperty("TimeOfLastRecord");
_timeOfLastRecord = AmtDriveInfo.FormatDate(item);
_currentNumberOfRecords = ulong.Parse(logObj.GetProperty("CurrentNumberOfRecords").ToString());
_percentageFree = int.Parse(logObj.GetProperty("PercentageFree").ToString());
string state = logObj.GetProperty("EnabledState").ToString();
_enabled = state.Equals("2") || state.Equals("6");
_propertiesCached = true;
}
}
}
}