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 _records; XmlDocument _eventDoc; public LogReader(IManagedReference refToLog) { _refToLog = refToLog; _startIndex = 1; _totalCount = 0; _records = new List(); _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 sidData = new List(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; } } } }