1932 lines
51 KiB
C++
Raw Blame History

//----------------------------------------------------------------------------
//
// Copyright (C) 2008 Intel Corporation
//
// File: AuditLogFlow.cpp
//
// Contents: Api code for Intel(R) Active Management Technology
// (Intel<65> 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<unsigned int> 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<AuditRule*> 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<BinaryData> 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<BinaryData> 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<AuditRule*> policy;
GetAuditPolicy(policy);
for(vector<AuditRule*>::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<AuditRule*> &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<unsigned int> & 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<unsigned int>(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<StoragePolicyType>(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<unsigned char>(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<unsigned char> keyBuffer;
vector<unsigned char> 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<unsigned short> 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<int>(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<BinaryData> & 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<BinaryData> &records)
{
try
{
vector<Base64> 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<output.EventRecords().size(); i++)
{
base64Records.push_back(Base64(output.EventRecords().at(i)));
}
// update number of records that was read
recordsRead += output.EventRecords().size();
}while(recordsRead < output.TotalRecordCount());
for(unsigned int i=0; i<base64Records.size(); i++)
{
unsigned char* tmpData = const_cast<unsigned char*>(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<enumerateOutput.HandlesCount() ; i++)
{
getUserInput.Handle(enumerateOutput.Handles().at(i));
if (verbose)
{
cout << "\nGetting Entry With Handle " << enumerateOutput.Handles().at(i) << "..." << endl;
}
// Get The Entry
response = authorizationService.GetUserAclEntryEx(getUserInput, getUserOutput);
// Check Returned Value
if(!CheckReturnStatus(0, response, "GetUserAclEntryEx"))
{
throw AuditLogException("\nError: Failed Getting User Acl Entry.");
}
if (getUserOutput.DigestUsernameExists())
{
if (0 == strcmp(ADDED_AUDITOR_USERNAME, getUserOutput.DigestUsername().c_str()))
{
userHandle = enumerateOutput.Handles().at(i);
if (verbose)
{
cout <<"\nEntry With Handle " << enumerateOutput.Handles().at(i) << " Is The Added Auditor" << endl;
}
break;
}
}
}
if (0 == userHandle)
{
if (verbose)
{
cout << "\nNo Auditor Was Created Using The Sample." << endl;
}
return;
}
// End Check For Auditor Entry
/* --------------------------------------------------
Update Auditor Entry
Changing the auditor realm so it can be deleted
-------------------------------------------------- */
// Get Digest Realm
string digest;
GetDigestRealm(digest);
HASH_MD_5 passHash;
AuditUtils auditUtils;
if (!auditUtils.ComputeMD5(ADDED_AUDITOR_USERNAME, sizeof(ADDED_AUDITOR_USERNAME)-1, digest.c_str(), digest.length(), ADDED_AUDITOR_PASSWORD, sizeof(ADDED_AUDITOR_PASSWORD)-1, passHash))
{
throw AuditLogException("\nError: Failed Computing MD5 Hash.");
}
updateInput.Handle(userHandle);
updateInput.AccessPermission(NETWORK_PERMISSIONS);
updateInput.DigestUsername(ADDED_AUDITOR_USERNAME);
Base64 base64(passHash, sizeof(HASH_MD_5));
updateInput.DigestPassword(base64);
vector<unsigned int> 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<AuditRule*> & 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().size(); i++)
{
delete isCritical;
isCritical = new bool();
*isCritical = (CRITICAL == auditPolicyRule.PolicyType().at(i));
policy.push_back(new AuditRule(static_cast<unsigned short>(auditPolicyRule.AuditApplicationEventID().at(i)/(MAX_INT_VALUE+1)),
static_cast<unsigned short>(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<unsigned char*>(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<unsigned char*>(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<SigningMechanismType>(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;
}
}