//---------------------------------------------------------------------------- // // Copyright (C) 2008 Intel Corporation // // File: AuditLogFlow.cpp // // Contents: Api code for Intel(R) Active Management Technology // (Intel� AMT) AccessMonitor Sample. // // Notes: This file contains the AccessMonitor flow implementation. // //---------------------------------------------------------------------------- #include "AuditLogFlow.h" #include "AccessMonitorUtils.h" #include "CimOpenWsmanClient.h" #include "CIM_SoftwareIdentity.h" // PUBLIC AUDIT_LOG FUNCTIONS /***************************************************************************** * Constructor of the AuditLogFlow class. ****************************************************************************/ AuditLogFlow::AuditLogFlow(ICimWsmanClient* tempWsmanClient, bool tempVerbose) : wsmanClient(tempWsmanClient), auditLog(wsmanClient), auditPolicyRule(wsmanClient), authorizationService(wsmanClient), coreVersion(""), verbose(tempVerbose) { isAuditLogInitialize = false; isAuditPolicyInitialize = false; isAuthorizationServiceInitialize = false; } /***************************************************************************** * Destructor of the AuditLogFlow class. ****************************************************************************/ AuditLogFlow::~AuditLogFlow() { } /***************************************************************************** * Traversing to the AMT_AuthorizationService instance. ****************************************************************************/ AMT_AuthorizationService AuditLogFlow::GetAuthorizationServiceInstance() { if(!isAuthorizationServiceInitialize) { AMT_AuthorizationService authorizationService(wsmanClient); authorizationService.Name("Intel(r) AMT Authorization Service"); authorizationService.Get(); isAuthorizationServiceInitialize = true; return authorizationService; } else { authorizationService.Get(authorizationService.Reference()); return authorizationService; } } /***************************************************************************** * Traversing to the AMT_AuditLog instance. ****************************************************************************/ AMT_AuditLog AuditLogFlow::GetAuditLogInstance() { if(!isAuditLogInitialize) { AMT_AuditLog auditLog(wsmanClient); auditLog.Name("Intel(r) AMT:Audit Log"); auditLog.Get(); isAuditLogInitialize = true; return auditLog; } else { auditLog.Get(auditLog.Reference()); return auditLog; } } /***************************************************************************** * Traversing to the AMT_AuditPolicyRule instance. ****************************************************************************/ AMT_AuditPolicyRule AuditLogFlow::GetAuditPolicyInstance() { if(!isAuditPolicyInitialize) { AMT_AuditPolicyRule auditPolicyRule(wsmanClient); auditPolicyRule.PolicyRuleName("Audit Policy Rule"); auditPolicyRule.Get(); isAuditPolicyInitialize = true; return auditPolicyRule; } else { auditPolicyRule.Get(auditPolicyRule.Reference()); return auditPolicyRule; } } /***************************************************************************** * Api function that runs an Api test: * Enables auditing, manipulates audit policy, manipulates audit log, * and cleans after these things. ****************************************************************************/ void AuditLogFlow::ApiTest() { cout << "\nStarting Full API Test..." << endl; EnableAuditing(); ManipulateAuditPolicy(); ManipulateAuditLog(); ClearAuditLog(); Unprovisioning(); cout << "\nAPI Test ended successfully." << endl; } /***************************************************************************** * Api function that adds an auditor: * Adds a user (ACL entry) with permissions to the Auditing Realm - 20 ****************************************************************************/ void AuditLogFlow::AddAuditor() { AuthMethod authMethod = wsmanClient->Connection().authmethod; if (authMethod == KERBEROS) { cout << "\n'Add Auditor' Flow is Not Supported When Using Kerberos." << endl; return; } if (verbose) { FunctionCall("AddAuditor"); putchar('\n'); } cout << "\nAdding an Auditor:" << endl << "==================" << endl << "Auditor Username = " << ADDED_AUDITOR_USERNAME << endl << "Auditor Password = " << ADDED_AUDITOR_PASSWORD << endl; vector realms; realms.push_back(AUDIT_REALM); AddUserAclEntryEx(ADDED_AUDITOR_USERNAME, ADDED_AUDITOR_PASSWORD, realms, NETWORK_PERMISSIONS); cout << "\nAn Auditor Was Added Successfully." << endl; } /***************************************************************************** * Api function that Enables Auditing Feature in the iAMT. * The Function Enable the Auditing Feature using EnbaleAuditing command * (if needed) and Set Signing Key command (if needed). ****************************************************************************/ void AuditLogFlow::EnableAuditing() { if (verbose) { FunctionCall("EnableAuditing"); putchar('\n'); } AuditLogStatus auditLogStatus; GetAuditLogStatus(auditLogStatus); if (AUDIT_DISABLED & auditLogStatus.State) { if (AUDIT_NO_KEY & auditLogStatus.State) { SetSigningKeyingMaterial(); } else { if (DisplayWarning("\nWARNING:\n" "========\n" "Signing key material already defined, do you want to overwrite it [Y/N]? ")) { SetSigningKeyingMaterial(); } } EnableAuditing(true); GetAuditLogStatus(auditLogStatus); if (AUDIT_DISABLED & auditLogStatus.State) { throw AuditLogException("\nError: Auditing is disabled while it should be enabled!"); } cout << "\n\nAuditing Enabled Successfully." << endl; return; } if (!DisplayWarning("\nWARNING:\n" "========\n" "Auditing already enabled, do you want to change the current Audit-Log signing certificate and key [y/n]? ")) { return; } SetSigningKeyingMaterial(); GetAuditLogStatus(auditLogStatus); if (AUDIT_DISABLED & auditLogStatus.State) { throw AuditLogException("\nError: Auditing is disabled while it should be enabled!"); } cout << "\nAuditing Enabled Successfully." << endl; } /***************************************************************************** * Api function that performs Clear Audit Log Operation. ****************************************************************************/ void AuditLogFlow::ClearAuditLog() { unsigned int lockHandle; try { if (verbose) { FunctionCall("ClearAuditLog"); putchar('\n'); } // Retrieve the AMT_AuditLog instance auditLog = GetAuditLogInstance(); cout << "\nLock Audit-Log..." << endl; LockAuditLog(AUDIT_LOG_LOCK, lockHandle); cout << "\nClear Audit-Log..." << endl; unsigned int response = auditLog.ClearLog(); // Check Returned Value if (!CheckReturnStatus(0, response, "ClearAuditLog")) { throw AuditLogException("\nError: Failed to clear log"); } cout << "\nUnLock Audit-Log..." << endl; LockAuditLog(AUDIT_LOG_UNLOCK, lockHandle); cout << "\nAudit Log was cleared successfully." << endl; } catch(...) { cout << "\nError: Clear Audit Log Failed." << endl << "UnLock Audit-Log..." << endl; LockAuditLog(AUDIT_LOG_UNLOCK, lockHandle); throw; } } /***************************************************************************** * Api function that performs Audit Policy Operations. ****************************************************************************/ void AuditLogFlow::ManipulateAuditPolicy() { vector policy; bool ruleInitiallyEnabled; try { AuditUtils auditUtils; if (verbose) { FunctionCall("ManipulateAuditPolicy"); putchar('\n'); } cout << "\nGetting Audit Policy..." << endl; GetAuditPolicy(policy); // Check number of Policies. if (policy.size() == 0) { cout << "\nThere are no rules defined in the Audit Policy." << endl; } else { // Display Policies auditUtils.DisplayAuditPolicy(policy); } // Check Audit Rule status bool* critical = new bool(POLICY_FLAG_ISCRITICAL); GetAuditRuleStatus(ruleInitiallyEnabled, critical); // If the Audit rule exists, critical flag will be changed // Add Audit Policy cout << "\nEnabling Audit Rule..." << endl; EnableAuditRule(AuditRule(APP_ID, EVENT_ID, critical)); delete critical; critical = NULL; auditUtils.ClearAndReleaseAuditPolicy(policy); // Display the New Policies cout << "\nGetting Audit Policy..." << endl; GetAuditPolicy(policy); // Check number of Policies. if (policy.size() == 0) { cout << "\nThere are no rules defined in the Audit Policy." << endl; } else { // Display Policies auditUtils.DisplayAuditPolicy(policy); } CleanAfterManipulateAuditPolicy(policy, ruleInitiallyEnabled); cout << "\nManipulate audit policy ended successfully." << endl; } catch(...) { cout << "\nError: ManipulateAuditPolicy failed." << endl; CleanAfterManipulateAuditPolicy(policy, ruleInitiallyEnabled); throw; } } /***************************************************************************** * Api function that performs audit-log unprovision action. ****************************************************************************/ void AuditLogFlow::Unprovisioning() { unsigned int lockHandle; if (verbose) { FunctionCall("Unprovisioning"); putchar('\n'); } cout << endl << "Lock Audit-Log for Unprovisioning with " << DEFAULT_LOCK_TIMEOUT << " seconds timeout..." << endl; // Lock Audit Log with setting UnProvision flag to true. LockAuditLog(UNPROVISIONING_LOCK, lockHandle); cout << endl << "Platform is locked for unprovision:" << endl << "An administrator can perform an unprovision operation within the next " << DEFAULT_LOCK_TIMEOUT << " seconds timeout..." << endl; cout << endl << "Unprovision Lock ended successfully." << endl; } /***************************************************************************** * Api function that performs Audit Log Operations (read, write, export audit-log). ****************************************************************************/ void AuditLogFlow::ManipulateAuditLog() { AuditSignature auditSignature; AuditLogStatus auditLogStatus; vector records; bool valid = false; unsigned int lockHandle; string fwCoreVersion; AuditUtils auditUtils; try { if (verbose) { FunctionCall("ManipulateAuditLog"); putchar('\n'); } // Locking auditlog cout << "\nLocking Auditlog..." << endl; LockAuditLog(AUDIT_LOG_LOCK ,lockHandle); cout << "\nGetting Audit-Log Status..." << endl; GetAuditLogStatus(auditLogStatus); // Display Audit Log Status auditUtils.DisplayAuditLogStatus(auditLogStatus); // Check if the audit-log is not empty. if (auditLogStatus.CurrentNumberOfRecords != 0) { // Reading auditlog records cout << "\nReading Auditlog Records..." << endl; // Read Records ReadAuditLog(records); // Display Number Of Records cout << "\nNumber Of Records: " << records.size() << endl; } else { cout << "\nThe Audit Log Is Empty..." << endl; } // Add Audit Policy GetCoreVersion(fwCoreVersion); if (Version(fwCoreVersion) > Version(FIRST_VERSION_SUPPORTING_AUDIT_STORAGE_POLICY) || Version(fwCoreVersion) == Version(FIRST_VERSION_SUPPORTING_AUDIT_STORAGE_POLICY)) { if (verbose) { cout << "\nPlatform supports Audit Storage Policy, performing related commands..." << endl; } StoragePolicyType storagePolicyType; unsigned int daysToKeep = 0; // Get Audit Log Storage Policy cout << "\nGetting Audit Log Storage Policy..." << endl; GetAuditLogStoragePolicy(storagePolicyType, daysToKeep); // Display Audit Log Storage Policy auditUtils.DisplayAuditLogStoragePolicy(storagePolicyType, daysToKeep, "Audit Log Storage Policy"); // Set Audit Log Storage Policy cout << "\nSetting Audit Log Storage Policy..." << endl; SetAuditLogStoragePolicy(RESTRICTED_ROLL_OVER, DAYS_TO_KEEP); StoragePolicyType tmpStoragePolicyType; unsigned int tmpDaysToKeep = 0; // Get Audit Log Storage Policy cout << "\nGetting Audit Log Storage Policy..." << endl; GetAuditLogStoragePolicy(tmpStoragePolicyType, tmpDaysToKeep); // Display Audit Log Storage Policy auditUtils.DisplayAuditLogStoragePolicy(tmpStoragePolicyType, tmpDaysToKeep, "Audit Log Storage Policy"); // Restore Audit Log Storage Policy cout << "\nRestoring Audit Log Storage Policy..." << endl; SetAuditLogStoragePolicy(storagePolicyType, daysToKeep); } // Get Audit Log Signature cout << "\nExport Audit Log Signature..." << endl; ExportAuditLogSignature(auditSignature); // Parse and Display Trial Records if (!auditUtils.ParseExportAuditLogSignature(auditSignature, verbose)) { throw AuditLogException("\nError: Can't Display The Audit Signature.\n"); } // Check for 2 Certificates for sample purpose. if (auditSignature.LengthOfCertificates.size() != 2) { char buffer[BUFF_SIZE]; _itoa_s(auditSignature.LengthOfCertificates.size(),buffer, BUFF_SIZE, BASE); throw AuditLogException(strcat_s("\nError: Invalid Number of Certificates: Expected 2 (Audit and Sub CA) and got only ", 100, buffer) == 0 ? buffer : "ERROR"); } // Check if the Audit Log Signature is valid if (!auditUtils.VerifyAuditLogSignature(auditSignature, records, valid, verbose)) { throw AuditLogException("\nError: Can't Validate Signature.\n"); } if (!valid) { throw AuditLogException("\nError: Audit Log Signature is invalid.\n"); } } catch(...) { records.clear(); // UnLocking auditlog cout << "\nUnLocking Auditlog..." << endl; LockAuditLog(AUDIT_LOG_UNLOCK ,lockHandle); } records.clear(); // UnLocking auditlog cout << "\nUnLocking Auditlog..." << endl; LockAuditLog(AUDIT_LOG_UNLOCK ,lockHandle); cout << "\nManipulate audit log ended successfully." << endl; } /***************************************************************************** * Api function that Displays the Audit Log to the screen. ****************************************************************************/ void AuditLogFlow::ViewAuditLog() { vector records; ViewAuditLog(records); records.clear(); cout << "\nView audit log ended successfully." << endl; } /***************************************************************************** * Api function that Performs a cleanup for added stuff of the sample to restore * the machine to its factory defaults. ****************************************************************************/ void AuditLogFlow::CleanUp() { if (verbose) { FunctionCall("CleanUp"); putchar('\n'); } cout << "\nCleaning Up Sample..." << endl; AuthMethod authMethod = wsmanClient->Connection().authmethod; if (authMethod == DIGEST) { RemoveAddedAuditor(); } // Disable Auditing EnableAuditing(false); cout << "\nClean-up ended successfully." << endl; } // PRIVATE AUDIT_LOG FUNCTIONS /***************************************************************************** * Function that returns the Audit rule Status. * Arguments: * ruleInitiallyEnabled - [out] Audit rule Status. ****************************************************************************/ void AuditLogFlow::GetAuditRuleStatus(OUT bool & ruleInitiallyEnabled, bool *critical) { try { if (verbose) { FunctionCall("GetAuditRuleStatus"); putchar('\n'); } ruleInitiallyEnabled = false; vector policy; GetAuditPolicy(policy); for(vector::const_iterator itr = policy.begin(); itr != policy.end(); itr++) { if ((*itr) != NULL) { if((*itr)->GetApplicationID() == APP_ID && (*itr)->GetEventID() == EVENT_ID) { ruleInitiallyEnabled = true; if((NULL != critical) && !(*(*itr)->IsCritical())) { *critical = *((*itr)->IsCritical()); } break; } } } } catch(...) { cout << "\nError: Getting the audit rule status failed." << endl; throw; } } /***************************************************************************** * Function that performs cleaning-up after ManipulateAuditPolicy. * * Arguments: * policy - vector of AuditRule to clean and release ****************************************************************************/ void AuditLogFlow::CleanAfterManipulateAuditPolicy(vector &policy, bool ruleInitiallyEnabled) { AuditUtils auditUtils; try { // Clean Up Code // Disable Audit Event. cout << "\nReturning the Audit Rule to it's initial enabled state..." << endl; if(!ruleInitiallyEnabled) { DisableAuditRule(AuditRule()); } auditUtils.ClearAndReleaseAuditPolicy(policy); // Display the New Policies cout << "\nGetting Audit Policy..." << endl; GetAuditPolicy(policy); // Check number of Policies. if (policy.size() == 0) { cout << "\nThere are no rules defined in the Audit Policy." << endl; } else { // Display Policies auditUtils.DisplayAuditPolicy(policy); } auditUtils.ClearAndReleaseAuditPolicy(policy); } catch(...) { cout << "\nError: can't clean after ManipulateAuditPolicy." << endl; auditUtils.ClearAndReleaseAuditPolicy(policy); throw; } } /***************************************************************************** * Get the digest realm string * Arguments: * digest_realm - on successful return will hold * a pointer to the digest_realm string ****************************************************************************/ void AuditLogFlow::GetDigestRealm(OUT string & digest_realm) { try { if (verbose) { FunctionCall("GetDigestRealm"); putchar('\n'); } AMT_GeneralSettings generalSettings(wsmanClient); generalSettings.InstanceID("Intel(r) AMT: General Settings"); generalSettings.Get(); digest_realm = generalSettings.DigestRealm(); if (verbose) { cout << "\nDigestRealm string is : " << digest_realm.c_str() << endl; } } catch(...) { cout << "\nError: Get Digest Realm Failed." << endl; throw; } } /***************************************************************************** * Add a User ACL entry * Arguments: * username - The user name * password - The user password * realms - The user realms list. * accessPermission - The user access permission ****************************************************************************/ void AuditLogFlow::AddUserAclEntryEx(const string & username, const string & password, vector & realms, unsigned short accessPermission) { try { if (verbose) { FunctionCall("AddUserAclEntryEx"); putchar('\n'); } // Retrieve the AMT_AuthorizationService instance authorizationService = GetAuthorizationServiceInstance(); AMT_AuthorizationService::AddUserAclEntryEx_INPUT input; AMT_AuthorizationService::AddUserAclEntryEx_OUTPUT output; // Get Digest Realm string digest; GetDigestRealm(digest); // Computing Password MD5 Hash according to the NI (user:digest:password) HASH_MD_5 passHash; AuditUtils auditUtils; if (!auditUtils.ComputeMD5(username.c_str(), username.length(), digest.c_str(), digest.length(), password.c_str(), password.length(), passHash)) { throw AuditLogException("\nError: Failed Computing MD5 Hash."); } input.AccessPermission(accessPermission); input.DigestUsername(username); Base64 base64(passHash, sizeof(HASH_MD_5)); input.DigestPassword(base64); input.Realms(realms); if (verbose) { cout << "\nAdding ACL Entry:" << endl << "=================" << endl << "Username = " << username.c_str() << endl << "New Password = " << password.c_str() << endl << "MD5 Hash = "; for (unsigned int i = 0; i < sizeof(HASH_MD_5); ++i) { cout << hex << (unsigned short)passHash[i] << " "; } cout << dec; cout << endl << "Realms = "; for (unsigned int i = 0; i < realms.size(); ++i) { cout << realms.at(i) << " "; if (i!=(realms.size()-1)) { cout << ", "; } } cout << endl; } unsigned int response = authorizationService.AddUserAclEntryEx(input, output); // Check Return Value if (!CheckReturnStatus(0, response, "AddUserAclEntryEx")) { throw AuditLogException("\nError: Failed Adding User Acl Entry."); } } catch(...) { cout << "\nError: Failed Adding User Acl Entry." << endl; throw; } } /***************************************************************************** * Function that returns the Audit Log Status. * Arguments: * auditLogStatus - [out] Audit Log Status. ****************************************************************************/ void AuditLogFlow::GetAuditLogStatus(OUT AuditLogStatus & auditLogStatus) { try { if (verbose) { FunctionCall("GetAuditLogStatus"); putchar('\n'); } AMT_AuditLog auditLog; string fwCoreVersion = ""; GetCoreVersion(fwCoreVersion); if(Version(fwCoreVersion) < Version(FIRST_VERSION_SUPPORTING_DASH_1_0)) { //No early binding's Get() curently returns XML, do it using late binding throw AuditLogException("\nThe sample doesn't support early versions yet."); } else { auditLog = GetAuditLogInstance(); } if (auditLog.TimeOfLastRecordExists()) { auditLogStatus.TimeOfLastRecord = GetIntegerOutOfCimDateTimeString(auditLog.TimeOfLastRecord().DateTimeString()); } else { cout << "\nWarning: Time Of Last Record Not Specified in output, using default value." << endl; } auditLogStatus.PrecentegeFree = auditLog.PercentageFree(); auditLogStatus.CurrentNumberOfRecords = static_cast(auditLog.CurrentNumberOfRecords()); auditLogStatus.State = auditLog.AuditState(); auditLogStatus.MaxAllowedAuditors = auditLog.MaxAllowedAuditors(); } catch(...) { cout << "\nError: Get Audit Log Status Failed." << endl; throw; } } /***************************************************************************** * Function that returns the AMT's core version. * Arguments: * fwCoreVersion - [out] core version. ****************************************************************************/ void AuditLogFlow::GetCoreVersion(OUT string & fwCoreVersion) { if (coreVersion.empty()) { try { if (verbose) { FunctionCall("GetCoreVersion"); putchar('\n'); } CIM_SoftwareIdentity softwareIdentity(wsmanClient); CIM_SoftwareIdentity::CimKeys keys; keys.InstanceID("AMT FW Core Version"); softwareIdentity.Get(keys); fwCoreVersion = softwareIdentity.VersionString().c_str(); coreVersion = fwCoreVersion; } catch (...) { cout << "\nError: Get Core Version Failed." << endl; throw; } } else { fwCoreVersion = coreVersion; } } /***************************************************************************** * Function that returns the Audit Log Storage Policy. * Arguments: * auditLogStoragePolicy - [out] Audit Log Storage Policy in use. * daysToKeep - [out] Minimal days to keep any record. * This parameter will be returned only when policy is RESTRICTED_ROLL_OVER. * Otherwise, this parameter will be set to 0. ****************************************************************************/ void AuditLogFlow::GetAuditLogStoragePolicy(OUT StoragePolicyType & auditStoragePolicy, OUT unsigned int & daysToKeep) { try { if (verbose) { FunctionCall("GetAuditLogStoragePolicy"); putchar('\n'); } AMT_AuditLog auditLog; string fwCoreVersion = ""; GetCoreVersion(fwCoreVersion); if (Version(fwCoreVersion) < Version(FIRST_VERSION_SUPPORTING_DASH_1_0)) { //No early binding's Get() curently returns XML, do it using late binding throw AuditLogException("\nThe sample doesn't support early versions yet."); } else { auditLog = GetAuditLogInstance(); } if (auditLog.StoragePolicyExists()) { auditStoragePolicy = static_cast(auditLog.StoragePolicy()); } if (auditLog.MinDaysToKeepExists()) { daysToKeep = auditLog.MinDaysToKeep(); } } catch (...) { cout << "\nError: Get Audit Log Storage Policy Failed." << endl; throw; } } /***************************************************************************** * Function that sets the Audit Log Storage Policy. * Arguments: * auditLogStoragePolicy - [out] Audit Log Storage Policy type to set. * daysToKeep - [out] The minimum number of days to keep any Auditlog record (from 1 to 100). * This parameter affects the behavior of Audit Log only when policy is set * to RESTRICTED_ROLL_OVER. Otherwise, this parameter is ignored. ****************************************************************************/ void AuditLogFlow::SetAuditLogStoragePolicy(const StoragePolicyType & auditStoragePolicy, const unsigned int & daysToKeep) { AuditUtils auditUtils; try { if (verbose) { FunctionCall("SetAuditLogStoragePolicy"); putchar('\n'); } if (verbose) { auditUtils.DisplayAuditLogStoragePolicy(auditStoragePolicy, daysToKeep, "Set Audit Log Storage Policy"); } AMT_AuditLog auditLog; string fwCoreVersion = ""; GetCoreVersion(fwCoreVersion); if (Version(fwCoreVersion) < Version(FIRST_VERSION_SUPPORTING_DASH_1_0)) { //No early binding's Get() curently returns XML, do it using late binding throw AuditLogException("\nThe sample doesn't support early versions yet."); } else { auditLog = GetAuditLogInstance(); } auditLog.StoragePolicy(static_cast(auditStoragePolicy)); if (RESTRICTED_ROLL_OVER == auditStoragePolicy) { auditLog.MinDaysToKeep(daysToKeep); } //Note: // In case this part of code is being called for platforms < FIRST_VERSION_SUPPORTING_DASH_1_0 (5.1) // a manipulation on XML is needed; perform these 3 steps instead the Put call below in the code: // 1. string inputXML = auditLog.Serialize(); // 2. do manipulation on XML - remove the Datetime element and namespace // 3. auditLog.Put(inputXML, wsmanClient); // Since this part of the code is being called only for FIRST_VERSION_SUPPORTING_DASH_1_0 (5.1) and above // no XML manipulation is needed. auditLog.Put(); } catch (...) { cout << "\nError: Set Audit Log Storage Policy Failed." << endl; throw; } } /***************************************************************************** * Function that performs SetSigningKeyingMaterial command. ****************************************************************************/ void AuditLogFlow::SetSigningKeyingMaterial() { // Set Audit Keying Materials vector keyBuffer; vector certBuffer; try { if (verbose) { FunctionCall("SetSigningKeyingMaterial"); putchar('\n'); } // Retrieve the AMT_AuditLog instance auditLog = GetAuditLogInstance(); AMT_AuditLog::SetSigningKeyMaterial_INPUT input; string fwCoreVersion = ""; GetCoreVersion(fwCoreVersion); if (Version(fwCoreVersion) < Version(FIRST_VERSION_SUPPORTING_SHA2)) { input.SigningMechanismType(RSA_SHA1); } else { input.SigningMechanismType(SHA_FOR_SHA2_SUPPORTING_VERSION); } // Load Certifiate and Private Key. AuditUtils auditUtils; if (!auditUtils.LoadAuditSigningKey(keyBuffer, verbose)) { throw AuditLogException("\nError: Can't Load Certificates and Key."); } //Base64 base64_1(keyBuffer.data(), keyBuffer.size()); unsigned char* keyBufferPtr = keyBuffer.data(); Base64 base64_1(keyBufferPtr, keyBuffer.size()); input.SigningKey(base64_1); //Load Certificates vector certLen; if (!auditUtils.LoadCertificatesToBuffer(certBuffer, certLen, verbose)) { throw AuditLogException("\nError: Failed Loading Certificates."); } input.LengthOfCertificates(certLen); if (certLen.size()<2) { throw AuditLogException("\nError: Failed Loading Certificates."); } //Base64 base64_2(certBuffer.data(), certBuffer.size()); unsigned char* certBufferPtr = certBuffer.data(); Base64 base64_2(certBufferPtr, certBuffer.size()); input.Certificates(base64_2); cout << "\nSetting Signing Keying Material..." << endl; unsigned int response = auditLog.SetSigningKeyMaterial(input); // Check Return Value if (!CheckReturnStatus(0, response, "SetSigningKeyingMaterial")) { throw AuditLogException("\nError: Failed Setting Audit-Log Signing Key and Certificates."); } cout << "\nSet Signing Keying Material Ended Successfully." << endl; } catch(...) { throw; } } /***************************************************************************** * Function that locks the Audit Log. * Arguments: * lock - flag that tells the function if to lock or unlock * handle - Input and Output Paramater that represent the Lock Handle. ****************************************************************************/ void AuditLogFlow::LockAuditLog(AuditLockType lock, unsigned int &handle) { try { if (verbose) { FunctionCall("LockAuditLog"); putchar('\n'); cout << "\nAudit Lock Type = " << lock << endl; } // Retrieve the AMT_AuditLog instance auditLog = GetAuditLogInstance(); AMT_AuditLog::SetAuditLock_INPUT input; AMT_AuditLog::SetAuditLock_OUTPUT output; // Check if unlocking. if (lock == AUDIT_LOG_UNLOCK) { input.Handle(handle); } // Set Timeout input.LockTimeoutInSeconds(static_cast(DEFAULT_LOCK_TIMEOUT)); // Set Locking input.Flag(lock); // Invoking Set Audit Lock unsigned int response = auditLog.SetAuditLock(input, output); // Check Return Value if (!CheckReturnStatus(0, response, "LockAuditLog")) { throw AuditLogException("\nError: failed to lock Audit-log."); } // check if locking if (lock == AUDIT_LOG_LOCK || lock == UNPROVISIONING_LOCK) { handle = output.Handle(); if (verbose) { cout << "Lock Handle = " << handle << endl; } } } catch(...) { cout << "\nError: Lock Audit Log Failed." << endl; throw; } } /***************************************************************************** * Function that Displays the Audit Log to the screen. * Arguments: * records - [out] Audit Log's Records ****************************************************************************/ void AuditLogFlow::ViewAuditLog(OUT vector & records) { unsigned int lockHandle; try { // Locking auditlog cout << "\nLocking Auditlog..." << endl; LockAuditLog(AUDIT_LOG_LOCK ,lockHandle); // Reading auditlog records cout << "\nReading Auditlog Records..." << endl; ReadAuditLog(records); // Display Records AuditUtils auditUtils; auditUtils.DisplayAuditLogRecords(records); } catch(...) { // UnLocking auditlog cout <<"\nUnLocking Auditlog..." << endl; LockAuditLog(AUDIT_LOG_UNLOCK ,lockHandle); throw; } // Clean Up Code try { // UnLocking auditlog cout <<"\nUnLocking Auditlog..." << endl; LockAuditLog(AUDIT_LOG_UNLOCK ,lockHandle); } catch(...) { cout <<"\nError: UnLocking auditlog failed." << endl; throw; } } /***************************************************************************** * Function that reads the Audit Log records and return them as output parameter * Arguments: * records - [out] Output parameter that will contain the audit log records. ****************************************************************************/ void AuditLogFlow::ReadAuditLog(OUT vector &records) { try { vector base64Records; if (verbose) { FunctionCall("ReadAuditLog"); putchar('\n'); } // Retrieve the AMT_AuditLog instance auditLog = GetAuditLogInstance(); AMT_AuditLog::ReadRecords_INPUT input; AMT_AuditLog::ReadRecords_OUTPUT output; // Read Records unsigned int recordsRead = 0; do { input.StartIndex(recordsRead + 1); // Call SOAP Method. unsigned int response = auditLog.ReadRecords(input, output); // Check Return Value. if (!CheckReturnStatus(0, response, "ReadAuditLogRecords")) { throw AuditLogException("\nError: Failed Getting Audit-Log records."); } // Insert Records to new vector for(unsigned int i=0; i(base64Records.at(i).Data()); unsigned int tmpLength = base64Records.at(i).Length(); records.push_back(BinaryData(tmpData, tmpLength)); } } catch (...) { cout << "\nError: Read Audit Log Failed." << endl; throw; } } /***************************************************************************** * This Function Removes the Auditor that was created using AddAuditor function. ****************************************************************************/ void AuditLogFlow::RemoveAddedAuditor() { try { if (verbose) { FunctionCall("RemoveAddedAuditor"); putchar('\n'); } // Retrieve the AMT_AuthorizationService instance authorizationService = GetAuthorizationServiceInstance(); string ip; unsigned int userHandle = 0; AMT_AuthorizationService::EnumerateUserAclEntries_INPUT enumerateInput; AMT_AuthorizationService::EnumerateUserAclEntries_OUTPUT enumerateOutput; AMT_AuthorizationService::GetUserAclEntryEx_INPUT getUserInput; AMT_AuthorizationService::GetUserAclEntryEx_OUTPUT getUserOutput; AMT_AuthorizationService::UpdateUserAclEntryEx_INPUT updateInput; AMT_AuthorizationService::RemoveUserAclEntry_INPUT removeInput; // Enumerate Entries enumerateInput.StartIndex(1); if (verbose) { cout << "\nEnumerating Entries..." << endl; } unsigned int response = authorizationService.EnumerateUserAclEntries(enumerateInput, enumerateOutput); // Check Returned Value if(!CheckReturnStatus(0, response, "EnumerateUserAclEntries")) { throw AuditLogException("\nError: Failed Enumerating User Acl Entries."); } // End Enumerate Entries // Check For Auditor Entry // go through every handle, get its user name and check if its the added auditor name for (unsigned int i=0 ; i realms; realms.push_back(UAC_REALM); updateInput.Realms(realms); string originalUsername = wsmanClient->Connection().username; string originalPass = wsmanClient->Connection().password; // Move to the auditor credentials UpdateWsmanClientCredentials(ADDED_AUDITOR_USERNAME, ADDED_AUDITOR_PASSWORD); if (verbose) { cout << "\nUpdating Auditor Realms..." << endl; } response = authorizationService.UpdateUserAclEntryEx(updateInput); // Check Returned Value if(!CheckReturnStatus(0, response, "UpdateUserAclEntryEx")) { throw AuditLogException("\nError: Failed Updating User Acl Entry."); } // End Update Auditor Entry // Remove Auditor Entry // Move back to the original credentials UpdateWsmanClientCredentials(originalUsername, originalPass); removeInput.Handle(userHandle); if (verbose) { cout << "\nRemoving The Auditor..." << endl; } response = authorizationService.RemoveUserAclEntry(removeInput); // Check Returned Value if(!CheckReturnStatus(0, response, "RemoveUserAclEntry")) { throw AuditLogException("\nError: Failed Removing User Acl Entry.\n"); } // End Remove Auditor Entry cout << "\nThe Added Auditor Removed Successfully." << endl; } catch (...) { cout <<"\nError: Remove Added Auditor Failed." << endl; throw; } } /***************************************************************************** * Function that Disables Audit Event in the Audit Policy * Arguments: * auditRule - The rule to disable in the Audit Policy ****************************************************************************/ void AuditLogFlow::DisableAuditRule(const AuditRule & auditRule) { try { if (verbose) { FunctionCall("DisableAuditEvent"); putchar('\n'); } // Retrieve the AMT_AuditPolicyRule instance auditPolicyRule = GetAuditPolicyInstance(); AMT_AuditPolicyRule::SetAuditPolicy_INPUT input; input.AuditedAppID(auditRule.GetApplicationID()); input.EventID(auditRule.GetEventID()); input.PolicyType(NON_CRITICAL); input.Enable(false); if (verbose) { cout << endl << "Disable Event:" << endl << "==============" << endl << "App ID = " << (unsigned short)auditRule.GetApplicationID() << endl << "Event ID = " << (unsigned short)auditRule.GetEventID() << endl; } unsigned int response = auditPolicyRule.SetAuditPolicy(input); // Check Return Value. if (!CheckReturnStatus(0, response, "SetAuditPolicy")) { throw AuditLogException("\nError: Failed to Set Audit Policy.\n"); } cout << "\nAudit Rule Disabled Successfully." << endl; } catch (...) { cout << "\nError: Disable Audit Rule Failed." << endl; throw; } } /***************************************************************************** * Function that returns the Audit Policy. * Arguments: * policy - [out] Audit Policy. ****************************************************************************/ void AuditLogFlow::GetAuditPolicy(OUT vector & policy) { bool* isCritical = NULL; try { if (verbose) { FunctionCall("GetAuditPolicy"); putchar('\n'); } // Retrieve the AMT_AuditPolicyRule instance auditPolicyRule = GetAuditPolicyInstance(); policy.clear(); // Check Number of policies for (unsigned int i=0 ; i(auditPolicyRule.AuditApplicationEventID().at(i)/(MAX_INT_VALUE+1)), static_cast(auditPolicyRule.AuditApplicationEventID().at(i)%(MAX_INT_VALUE+1)), isCritical)); } if (isCritical) { delete isCritical; isCritical = NULL; } } catch (...) { if (isCritical) { delete isCritical; isCritical = NULL; } cout << "\nError: Get Audit Policy Failed." << endl; throw; } } /***************************************************************************** * Function that Enables Audit Event in AMT Audit Policy. * Arguments: * auditRule - The rule to enable in the Audit Policy ****************************************************************************/ void AuditLogFlow::EnableAuditRule(const AuditRule & auditRule) { try { if (verbose) { FunctionCall("EnableAuditRule"); putchar('\n'); } // Retrieve the AMT_AuditPolicyRule instance auditPolicyRule = GetAuditPolicyInstance(); AMT_AuditPolicyRule::SetAuditPolicy_INPUT input; if (verbose) { char isCriticalChar = '\0'; if (auditRule.IsCritical() != NULL) { isCriticalChar = (*(auditRule.IsCritical()) == POLICY_FLAG_ISCRITICAL) ? 'Y' : 'N'; } cout << endl << "Enable Event:" << endl << "=============" << endl << "App ID = " << (unsigned short)auditRule.GetApplicationID() << endl << "Event ID = " << (unsigned short)auditRule.GetEventID() << endl << "Critical = " << isCriticalChar << endl; } // Setting New Policy for "ACL Entry Modified" Event. input.Enable(true); input.AuditedAppID(auditRule.GetApplicationID()); input.EventID(auditRule.GetEventID()); if (auditRule.IsCritical()) { input.PolicyType(*auditRule.IsCritical()); } unsigned int response = auditPolicyRule.SetAuditPolicy(input); // Check Return Value. if (!CheckReturnStatus(0, response, "SetAuditPolicy")) { throw AuditLogException("\nError: Failed to Set Audit Policy."); } cout << "\nAudit Rule Enabled Successfully." << endl; } catch (...) { cout << "\nError: Enable Audit Rule Failed." << endl; throw; } } /***************************************************************************** * Function that Enables/Disables Auditing Feature in the AMT. * Arguments: * enable - Enable or Disable auditing ****************************************************************************/ void AuditLogFlow::EnableAuditing(bool enable) { try { if (verbose == true) { FunctionCall("EnableAuditing"); putchar('\n'); } // Retrieve the AMT_AuditLog instance auditLog = GetAuditLogInstance(); AMT_AuditLog::RequestStateChange_INPUT input; AMT_AuditLog::RequestStateChange_OUTPUT output; if(enable) { input.RequestedState(ENABLE_AUDITING); } else { input.RequestedState(DISBLE_AUDITING); } cout << endl << (enable ? "Enabling" : "Disabling") << " Auditing..." << endl; // Enable Auditing unsigned int response = auditLog.RequestStateChange(input, output); // Check Return Value. if (!CheckReturnStatus(0, response, "RequestStateChange")) { string excStr = "\nError: Can't "; excStr.append(enable ? "Enable" : "Disable"); excStr.append(" Auditing."); throw AuditLogException((char*)excStr.c_str()); } } catch (...) { cout << "\nError: " << (enable ? "Enable" : "Disable") << " Auditing Failed." << endl; throw; } } /***************************************************************************** * Function that Gets the exported Audit Signature * Arguments: * auditSignature - [out] Output parameter that contains the Audit Signature. ****************************************************************************/ void AuditLogFlow::ExportAuditLogSignature(OUT AuditSignature & auditSignature) { Base64 *base64 = NULL; unsigned int response; unsigned char* tmpData; unsigned int tmpLength; try { if (verbose) { FunctionCall("ExportAuditLogSignature"); putchar('\n'); } // Retrieve the AMT_AuditLog instance auditLog = GetAuditLogInstance(); AMT_AuditLog::ExportAuditLogSignature_INPUT input; AMT_AuditLog::ExportAuditLogSignature_OUTPUT output; string fwCoreVersion = ""; GetCoreVersion(fwCoreVersion); if (Version(fwCoreVersion) < Version(FIRST_VERSION_SUPPORTING_SHA2)) { input.SigningMechanism(RSA_SHA1); } else { input.SigningMechanism(SHA_FOR_SHA2_SUPPORTING_VERSION); } if (Version(fwCoreVersion) < Version(FIRST_VERSION_SUPPORTING_DASH_1_0)) { //No early binding's Get() curently returns XML, do it using late binding throw AuditLogException("\nThe sample doesn't support early versions yet."); } else { response = auditLog.ExportAuditLogSignature(input, output); } // Check Return Value. if (!CheckReturnStatus(0, response, "ExportAuditLogSignature")) { throw AuditLogException("\nError: Failed to export Audit-Log."); } // Set the output struct parameter if (output.SignatureExists()) { base64 = new Base64(output.Signature()); if (base64) { tmpData = const_cast(base64->Data()); tmpLength = base64->Length(); auditSignature.Signature = BinaryData(tmpData, tmpLength); delete base64; base64 = NULL; } } else { cout << "\nWarning: Signature Not Specified in output, using default value." << endl; } auditSignature.LengthOfCertificates = output.LengthOfCertificates(); if (output.CertificatesExists()) { if (base64) { delete base64; base64 = NULL; } base64 = new Base64(output.Certificates()); if (base64) { tmpData = const_cast(base64->Data()); tmpLength = base64->Length(); auditSignature.Certificates = BinaryData(tmpData, tmpLength); delete base64; base64 = NULL; } } else { cout << "\nWarning: Certificates Not Specified in output, using default value." << endl; } if (output.StartLogTimeExists()) { auditSignature.StartLogTime = GetIntegerOutOfCimDateTimeString(output.StartLogTime().DateTimeString()); } else { cout << "\nWarning: Start Log Time Not Specified in output, using default value." << endl; } if (output.EndLogTimeExists()) { auditSignature.EndLogTime = GetIntegerOutOfCimDateTimeString(output.EndLogTime().DateTimeString()); } else { cout << "\nWarning: End Log Time Not Specified in output, using default value." << endl; } if (output.GenerationTimeExists()) { auditSignature.GenerationTime = GetIntegerOutOfCimDateTimeString(output.GenerationTime().DateTimeString()); } else { cout << "\nWarning: Generation Time Not Specified in output, using default value." << endl; } auditSignature.TotalRecordCount = output.TotalRecordCount(); auditSignature.FQDN = output.FQDN(); if (output.SignatureMechanismExists()) { auditSignature.SignatureMechanism = static_cast(output.SignatureMechanism()); } else { cout << "\nWarning: Signature Mechanism Not Specified in output, using default value." << endl; } unsigned int a; if (output.UUID().length() > 0) { string strUuid = output.UUID(); for (unsigned int i =0 ; i < strUuid.length()-1 ; i++) { a=0; if (strUuid.at(i) >= 'A' && strUuid.at(i) <= 'F') { a = 10 + (strUuid.at(i) - 'A'); } else if (strUuid.at(i) >= 'a' && strUuid.at(i) <= 'f') { a = 10 + (strUuid.at(i) - 'a'); } else if (strUuid.at(i) >= '0' && strUuid.at(i) <= '9') { a = (strUuid.at(i) - '0'); } else { cout << "Error: Cannot Parse UUID - Bad Format!" << endl; } a*=16; i++; if (strUuid.at(i) >= 'A' && strUuid.at(i) <= 'F') { a += 10 + (strUuid.at(i) - 'A'); } else if (strUuid.at(i) >= 'a' && strUuid.at(i) <= 'f') { a += 10 + (strUuid.at(i) - 'a'); } else if (strUuid.at(i) >= '0' && strUuid.at(i) <= '9') { a += (strUuid.at(i) - '0'); } else { cout << "Error: Cannot Parse UUID - Bad Format!" << endl; } auditSignature.UUID.push_back(a); } } else { cout << "\nWarning: UUID Not Specified in output, using default value." << endl; } } catch (...) { cout << "\nError: Export Audit Log Signature Failed." << endl; throw; } } // Helper Function /***************************************************************************** * The Function updates he WSMAN Client credentials * Arguments: * newUsername - The New Username * newPassword - The New Password ****************************************************************************/ void AuditLogFlow::UpdateWsmanClientCredentials(string newUsername, string newPassword) { try { wsmanClient->SetUserName(newUsername.c_str()); wsmanClient->SetPassword(newPassword.c_str()); } catch (...) { cout << "\nError: Creation of WS-Management Client Failed." << endl; wsmanClient = NULL; throw; } } /***************************************************************************** * The Function creates and returns a number representation of the date given. * Arguments: * date - date in the Moccana format. * Returns: * int - the numeric representation of the date. ****************************************************************************/ int AuditLogFlow::GetIntegerOutOfCimDateTimeString(string date) { // convert from string in CimDateTime format, i.e. "20040101000235.000000+000" // to string in Moccana format, i.e. "2004-01-01T00:02:35Z" string result = ""; result.append(date.substr(0,4)); result.append("-"); result.append(date.substr(4,2)); result.append("-"); result.append(date.substr(6,2)); result.append("T"); result.append(date.substr(8,2)); result.append(":"); result.append(date.substr(10,2)); result.append(":"); result.append(date.substr(12,2)); result.append("Z"); date = result; //end of conversion const unsigned int SECONDS = 60; const unsigned int MIMUTES = 60; const unsigned int HOURS = 24; const unsigned int DAYS_A_MONTH = 30; const unsigned int DAYS_A_YEAR = 365; string dates[6]; unsigned int datesNumbers[6]; char chars[] = {'-','-','T',':',':','Z'}; short monthDiff[] = {0,1,-1,0,0,1,1,2,3,3,4,4}; int pos = 0; int offset = 0; unsigned int intDate = 0; try { for (int i=0 ; i < 6 ; i++) { pos = date.find(chars[i], offset); dates[i] = date.substr(offset, (pos-offset)); offset = pos+1; } for (int i=0 ; i < 6 ; i++) { StringToUInteger(dates[i], datesNumbers[i]); } intDate += (datesNumbers[0]-1970) * (DAYS_A_YEAR*HOURS*MIMUTES*SECONDS); for (unsigned int i = 0 ; i <=(datesNumbers[0]-1970) ; i++) { if (!((1970+i)%400)) { //leap intDate += (HOURS*MIMUTES*SECONDS); } else if (((1970+i)%100)) { if (!((1970+i)%4)) { //leap intDate += (HOURS*MIMUTES*SECONDS); } } } intDate += ( (((datesNumbers[1]-1)*DAYS_A_MONTH)+monthDiff[datesNumbers[1]-1]) *HOURS*MIMUTES*SECONDS); intDate += (datesNumbers[2]-1) * (HOURS*MIMUTES*SECONDS); intDate += datesNumbers[3] * (MIMUTES*SECONDS); intDate += datesNumbers[4] * (SECONDS); intDate += datesNumbers[5]; return intDate; } catch(...) { cout << "\nError: Can't Parse The Date String!" << endl; throw; } } /***************************************************************************** * The Function checks and converts a string into unsigned int. * Arguments: * str - the given string. * t - the numeric string representation. ****************************************************************************/ void AuditLogFlow::StringToUInteger(const string& str, unsigned int& t) { try { unsigned int res = 0, tmp; char c; for (unsigned int i=0; i < str.size(); i++) { c = str.at(i); if (c < '0' || c > '9') // illegal char { throw AuditLogException("Illegal character in date string."); } tmp = res; for(unsigned int j = 1; j < 10; j++) { res += tmp; if(res < tmp) // overflow { throw AuditLogException("Overflow occured in date string."); } } res += c - '0'; if (res < tmp) // overflow { throw AuditLogException("Overflow occured in date string."); } } t = res; } catch(...) { cout << "\nError: Can't Parse The Date String!" << endl; throw; } }