1110 lines
28 KiB
C++

//----------------------------------------------------------------------------
//
// Copyright (C) 2006 Intel Corporation
//
// File: SetupFileReaderWriter.cpp
//
// Contents: Demonstrates how to read and write a configuration setup file.
//
// Notes: This file contains a number of functions that demonstrate how
// to read and write a configuration setup file.
//
//----------------------------------------------------------------------------
#include <windows.h>
#include "SetupFileReaderWriter.h"
#include "ConfigFile.h"
static const char* G_S_DEFAULT_MEBX_PWD = "admin";
static const unsigned short G_S_DEFAULT_MEBX_PWD_LENGTH = 5;
////////////////////////////
// DataRecordEntry functions
////////////////////////////
DataRecordEntry::DataRecordEntry()
{
_moduleId = 0;
_variableId = 0;
_variableLength = 0;
_variableValue = NULL;
}
DataRecordEntry::DataRecordEntry(const unsigned short moduleId,
const unsigned short variableId,
const unsigned short variableLength,
const unsigned char* variableValue)
{
_variableValue = NULL;
SetModuleId(moduleId);
SetVariableId(variableId);
SetVariableValue(variableLength, variableValue);
}
DataRecordEntry::DataRecordEntry(const DataRecordEntry& entry)
{
_variableValue = NULL;
SetModuleId(entry._moduleId);
SetVariableId(entry._variableId);
SetVariableValue(entry._variableLength, entry._variableValue);
}
DataRecordEntry& DataRecordEntry::operator=(const DataRecordEntry& entry)
{
if (this == &entry)
return *this;
_variableValue = NULL;
SetModuleId(entry._moduleId);
SetVariableId(entry._variableId);
SetVariableValue(entry._variableLength, entry._variableValue);
return *this;
}
DataRecordEntry::~DataRecordEntry()
{
if(_variableValue)
{
delete _variableValue;
_variableValue = NULL;
}
}
unsigned short DataRecordEntry::GetModuleId() const
{
return _moduleId;
}
unsigned short DataRecordEntry::GetVariableId() const
{
return _variableId;
}
unsigned short DataRecordEntry::GetVariableLength() const
{
return _variableLength;
}
unsigned short DataRecordEntry::GetVariableValue(const unsigned short bufferLen,
unsigned char* buffer) const
{
if(_variableValue == NULL ||
buffer == NULL)
{
return 0;
}
if (memcpy_s(buffer, min(_variableLength, bufferLen), _variableValue, min(_variableLength, bufferLen)))
{
printf("Error: Can't Copy Memory");
return 0;
}
return min(_variableLength, bufferLen);
}
void DataRecordEntry::SetModuleId(const unsigned short moduleId)
{
_moduleId = moduleId;
}
void DataRecordEntry::SetVariableId(const unsigned short variableId)
{
_variableId = variableId;
}
void DataRecordEntry::SetVariableValue(const unsigned short bufferLen,
const unsigned char* buffer)
{
if(_variableValue)
{
delete _variableValue;
_variableValue = NULL;
}
_variableLength = bufferLen;
_variableValue = new unsigned char[bufferLen];
if(buffer)
{
if (memcpy_s(_variableValue, _variableLength, buffer, bufferLen))
{
printf("Error: Can't Copy Memory");
}
}
}
///////////////////////
// DataRecord functions
///////////////////////
DataRecord::DataRecord(const bool isValid, const bool isScrambled)
:_recordEntries(),
_isValid(isValid),
_isScrambled(isScrambled)
{
_recordEntries = new vector<DataRecordEntry>();
}
DataRecord::DataRecord(const DataRecord& record)
{
_recordEntries = NULL;
CopyRecord(record);
}
DataRecord& DataRecord::operator=(const DataRecord& record)
{
if (this == &record)
return *this;
_recordEntries = NULL;
CopyRecord(record);
return *this;
}
DataRecord::~DataRecord()
{
if(_recordEntries)
{
delete _recordEntries;
_recordEntries = NULL;
}
}
void DataRecord::AddRecordEntry(const unsigned short moduleId,
const unsigned short variableId,
const unsigned short variableLength,
const unsigned char* variableValue)
{
DataRecordEntry entry(moduleId, variableId,
variableLength, variableValue);
_recordEntries->push_back(entry);
}
bool DataRecord::GetIsValid() const
{
return _isValid;
}
bool DataRecord::GetIsScrambled() const
{
return _isScrambled;
}
vector<DataRecordEntry> DataRecord::GetRecordEntries() const
{
return *_recordEntries;
}
void DataRecord::SetValid(const bool isValid)
{
_isValid = isValid;
}
void DataRecord::SetScrambled(const bool isScrambled)
{
_isScrambled = isScrambled;
}
void DataRecord::CopyRecord(const DataRecord& record)
{
if(_recordEntries)
{
delete _recordEntries;
_recordEntries = NULL;
}
SetValid(record._isValid);
SetScrambled(record._isScrambled);
if(record._recordEntries)
{
_recordEntries = new vector<DataRecordEntry>(*(record._recordEntries));
}
else
{
_recordEntries = new vector<DataRecordEntry>();
}
}
bool DataRecord::FindEntry(const unsigned short moduleId,
const unsigned short variableId,
unsigned short* variableLength,
const unsigned short bufferLength,
unsigned char* buffer) const
{
vector<DataRecordEntry>::iterator it;
for(it = _recordEntries->begin(); it != _recordEntries->end(); it++)
{
if(it->GetModuleId() == moduleId &&
it->GetVariableId() == variableId)
{
if(variableLength)
{
*variableLength = it->GetVariableLength();
}
if(buffer)
{
it->GetVariableValue(bufferLength, buffer);
}
return true;
}
}
return false;
}
///////////////////
// Global Functions
///////////////////
// Validate a UUID
bool ValidateUuid(const unsigned char* uuid1, const unsigned char* uuid2)
{
if(memcmp(uuid1, uuid2, GUID_SIZE) != 0)
{
return false;
}
return true;
}
// set a DATA_RECORD_ENTRY_T from a DataRecord
void SetEntry(DATA_RECORD_ENTRY_T* entry, const DataRecordEntry& recordEntry)
{
entry->ModuleIdentifier = recordEntry.GetModuleId();
entry->VariableIdentifier = recordEntry.GetVariableId();
entry->VariableLength = recordEntry.GetVariableLength();
recordEntry.GetVariableValue(recordEntry.GetVariableLength(), &entry->VariableValue);
}
// Parse the SetupFile header
int ParseFileHeader(const unsigned int bufferLength,
const unsigned char* buffer,
SetupFileInfo* fileInfo,
unsigned int* moduleListSize,
set<unsigned short>* moduleList)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
SETUP_HEADER_T* fileHeader;
fileHeader = (SETUP_HEADER_T*)buffer;
unsigned char setupFileGuid[GUID_SIZE] = SETUP_GUID;
unsigned char setupFileGuid2[GUID_SIZE] = SETUP_GUID_2;
unsigned char setupFileGuid3[GUID_SIZE] = SETUP_GUID_3;
unsigned char setupFileGuid4[GUID_SIZE] = SETUP_GUID_4;
const unsigned char* strSetupFileGuid = NULL;
switch (fileHeader->MajorVersion)
{
case SETUP_FILE_VERSION_1:
strSetupFileGuid = setupFileGuid;
break;
case SETUP_FILE_VERSION_2:
strSetupFileGuid = setupFileGuid2;
break;
case SETUP_FILE_VERSION_3:
strSetupFileGuid = setupFileGuid3;
break;
case SETUP_FILE_VERSION_4:
strSetupFileGuid = setupFileGuid4;
break;
default:
return CONFIG_VERSION_UNSUPPORTED;
}
if(!ValidateUuid(
strSetupFileGuid,
(unsigned char*)&(fileHeader->FileTypeUuid)))
{
return CONFIG_INVALID_UUID;
}
if(fileHeader->MajorVersion > MAX_MAJOR_VERSION)
{
return CONFIG_VERSION_UNSUPPORTED;
}
if(fileHeader->RecordNumber != 0)
{
return CONFIG_INVALID_RECORD_NUMBER;
}
unsigned int length = CHUNK_SIZE * (fileHeader->RecordChunkCount +
(fileHeader->DataRecordCount * fileHeader->RecordChunkCount));
if(length > bufferLength)
{
return CONFIG_INVALID_BUFFER_LENGTH;
}
if(fileHeader->RecordHeaderByteCount < sizeof(SETUP_HEADER_T) ||
fileHeader->RecordHeaderByteCount >
CHUNK_SIZE * fileHeader->RecordChunkCount)
{
return CONFIG_INVALID_RECORD_HEADER_BYTE_COUNT;
}
const unsigned short* TMP = (const unsigned short*)&(fileHeader->ModuleList);
unsigned int counter = 0;
unsigned int bytesInHeader = sizeof(SETUP_HEADER_T) - 1;
while(TMP[counter] != 0)
{
counter ++;
bytesInHeader += 2;
if(bytesInHeader > fileHeader->RecordHeaderByteCount)
{
return CONFIG_INVALID_MODULE_LIST;
}
}
// fill values
if(fileInfo)
{
fileInfo->headerChunkCount = fileHeader->RecordChunkCount;
fileInfo->recordCount = fileHeader->DataRecordCount;
fileInfo->recordsConsumed = fileHeader->DataRecordsConsumed;
fileInfo->dataRecordChunkCount = fileHeader->DataRecordChunkCount;
fileInfo->majorVersion = fileHeader->MajorVersion;
fileInfo->minorVersion = fileHeader->MinorVersion;
fileInfo->consumeRecords = (fileHeader->FileFlags.DontConsumeRecords == 0);
}
if(moduleList)
{
for(unsigned int i = 0; i < counter; i++)
{
moduleList->insert(TMP[i]);
}
}
if(moduleListSize)
{
*moduleListSize = counter;
}
return CONFIG_SUCCESS;
}
int WriteFileHeader(unsigned char* buffer,
const SetupFileInfo fileInfo,
const set<unsigned short>& moduleList)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
unsigned short numLegalModules;
set<unsigned short>::const_iterator it = moduleList.find(0);
if(it == moduleList.end())
{
numLegalModules = (unsigned short)moduleList.size();
}
else
{
numLegalModules = (unsigned short)moduleList.size() - 1;
}
unsigned short byteCount = sizeof(SETUP_HEADER_T) + numLegalModules*2;
if(byteCount > fileInfo.headerChunkCount*CHUNK_SIZE)
{
return CONFIG_INVALID_HEADER_CHUNK_COUNT;
}
memset(buffer, 0, fileInfo.headerChunkCount*CHUNK_SIZE);
SETUP_HEADER_T* header = (SETUP_HEADER_T*)buffer;
unsigned char setupFileGuid[GUID_SIZE] = SETUP_GUID;
unsigned char setupFileGuid2[GUID_SIZE] = SETUP_GUID_2;
unsigned char setupFileGuid3[GUID_SIZE] = SETUP_GUID_3;
unsigned char setupFileGuid4[GUID_SIZE] = SETUP_GUID_4;
switch (fileInfo.majorVersion)
{
case SETUP_FILE_VERSION_1:
if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid, ARRAYSIZE(setupFileGuid)))
{
return CONFIG_INVALID_BUFFER;
}
break;
case SETUP_FILE_VERSION_2:
if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid2, ARRAYSIZE(setupFileGuid2)))
{
return CONFIG_INVALID_BUFFER;
}
break;
case SETUP_FILE_VERSION_3:
if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid3, ARRAYSIZE(setupFileGuid3)))
{
return CONFIG_INVALID_BUFFER;
}
break;
case SETUP_FILE_VERSION_4:
if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid4, ARRAYSIZE(setupFileGuid4)))
{
return CONFIG_INVALID_BUFFER;
}
break;
default:
return CONFIG_VERSION_UNSUPPORTED;
}
bool singleRecord =
((fileInfo.majorVersion >= SETUP_FILE_VERSION_2) &&
fileInfo.consumeRecords == false);
header->RecordChunkCount = fileInfo.headerChunkCount;
header->RecordHeaderByteCount = byteCount;
header->MajorVersion = fileInfo.majorVersion;
header->MinorVersion = fileInfo.minorVersion;
header->RecordNumber = 0;
header->DataRecordCount = singleRecord ? 1 : fileInfo.recordCount;
header->DataRecordsConsumed = singleRecord ? 0 : fileInfo.recordsConsumed;
header->DataRecordChunkCount = fileInfo.dataRecordChunkCount;
header->FileFlags.DontConsumeRecords = singleRecord ? 1 : 0;
unsigned short* tmp = &header->ModuleList;
it = moduleList.begin();
while(it != moduleList.end())
{
if((*it) != 0)
{
*tmp = *it;
tmp++;
}
it++;
}
*tmp = 0;
return CONFIG_SUCCESS;
}
// retrieve a Data Record
int GetDataRecord(const unsigned short numChunks,
const unsigned char* buffer,
const unsigned char majorVersion,
const unsigned char minorVersion,
set<unsigned short>* legalModules,
DataRecord* record)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
DATA_RECORD_HEADER_T* recordHeader;
DATA_RECORD_ENTRY_T* recordEntry;
recordHeader = (DATA_RECORD_HEADER_T*)buffer;
if(recordHeader->RecordChunkCount != numChunks)
{
return CONFIG_INVALID_RECORD_CHUNK_COUNT;
}
unsigned int base = recordHeader->RecordHeaderByteCount;
if(base > (unsigned int)(numChunks * CHUNK_SIZE))
{
return CONFIG_INVALID_RECORD_HEADER_BYTE_COUNT;
}
bool valid = recordHeader->RecordFlags.Valid;
static bool scrambled = recordHeader->RecordFlags.Scrambled;
if(!valid)
{
return CONFIG_INVALID_RECORD;
}
if(recordHeader->RecordTypeIdentifier != RECORD_IDENTIFIER_DATA_RECORD)
{
return CONFIG_RECORD_TYPE_INVALID;
}
if (scrambled != recordHeader->RecordFlags.Scrambled)
{
return CONFIG_INVALID_SCRAMBLED_STATE;
}
DataRecord dr(valid, scrambled);
unsigned int entryDwordLength;
bool first = true;
// in SETUP_FILE_VERSION_2 default "admin" must be followed by
// a new MEBx password
bool findNewMebxPwd = false;
// in SETUP_FILE_VERSION_2
// ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION
// may not appear after any CM settings
bool cmVarFound = false;
// in SETUP_FILE_VERSION_2
// CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD must be preceded
// by setting CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG to
//
if (scrambled)
{
DescrambleRecordData((unsigned char *)buffer + base, recordHeader->RecordChunkCount * CHUNK_SIZE - base);
}
while(valid) // if valid is false - do not search for entries
{
recordEntry = (DATA_RECORD_ENTRY_T*)(buffer + base);
if(first)
{
// make sure first entry is current MEBx password
if(recordEntry->ModuleIdentifier != MODULE_IDENTIFIER_ME_KERNEL ||
recordEntry->VariableIdentifier != ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD)
{
return CONFIG_MISSING_CURRENT_MEBX_PWD_ENTRY;
}
first = false;
if(recordEntry->VariableLength == G_S_DEFAULT_MEBX_PWD_LENGTH
&& memcmp(&(recordEntry->VariableValue), G_S_DEFAULT_MEBX_PWD, min(G_S_DEFAULT_MEBX_PWD_LENGTH, sizeof(recordEntry->VariableValue))) == 0)
{// default password found
findNewMebxPwd = true;
}
}
if(recordEntry->ModuleIdentifier == 0 &&
recordEntry->VariableIdentifier == 0 &&
recordEntry->VariableLength == 0 &&
recordEntry->Reserved == 0)
{
// NULL Entry Terminator
break;
}
if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_ME_KERNEL &&
recordEntry->VariableIdentifier == ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD)
{// new MEBx pwd found
findNewMebxPwd = false;
}
if(recordEntry->ModuleIdentifier ==
MODULE_IDENTIFIER_ME_KERNEL
&& recordEntry->VariableIdentifier ==
ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION
&& majorVersion >= SETUP_FILE_VERSION_2)
{
if(cmVarFound)
{
return CONFIG_INVALID_MANAGEABILITY_FEATURE_SELECTION;
}
}
if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_AMT_CM)
{
cmVarFound = true;
}
//if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_AMT_CM
// && recordEntry->VariableIdentifier ==
// CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG
// && recordEntry->VariableValue == CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG_DELETE)
// {
// userDefinedCertsDeleted = true;
//}
//if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_AMT_CM
// && recordEntry->VariableIdentifier ==
// CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD
// && majorVersion >= SETUP_FILE_VERSION_2)
// {
// if(!userDefinedCertsDeleted)
// {
// return CONFIG_INVALID_CERT_SETTINGS;
// }
//}
if(legalModules)
{// validate moduleId
if(recordEntry->ModuleIdentifier != 0)
{
set<unsigned short>::iterator it = legalModules->find(recordEntry->ModuleIdentifier);
if(it == legalModules->end())
{
return CONFIG_INVALID_MODULE_ID;
}
}
// else - filler value
}
dr.AddRecordEntry(recordEntry->ModuleIdentifier,
recordEntry->VariableIdentifier,
recordEntry->VariableLength,
&(recordEntry->VariableValue));
entryDwordLength = 2 + (recordEntry->VariableLength + 3)/4;
base += 4*entryDwordLength;
if(base > (unsigned int)CHUNK_SIZE * numChunks)
{
return CONFIG_INVALID_ENTRY_LIST;
}
}
if(majorVersion >= SETUP_FILE_VERSION_2 && findNewMebxPwd)
{
return CONFIG_MISSING_NEW_MEBX_PWD_ENTRY;
}
if(record)
{
record->CopyRecord(dr);
}
return CONFIG_SUCCESS;
}
int WriteDataRecord(const unsigned short numChunks,
unsigned char* buffer,
const unsigned char majorVersion,
const unsigned char minorVersion,
const unsigned int recordNumber,
const DataRecord& record,
set<unsigned short>* modulesUsed)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
unsigned int requiredDwords = (sizeof(DATA_RECORD_HEADER_T) + 3)/4;
bool currentMEBxPwdFound = false;
bool isDefaultMEBxPwd = false;
bool newMEBxPwdFound = false;
bool manFeatureFound = false;
bool pkiDnsSuffixFound = false;
bool configServerFqdnFound = false;
bool provisioningServerAddressFound = false;
bool meProvisioningHaltActivateFound = false;
int currPwdIndex = -1;
int newPwdIndex = -1;
int manSelectionIndex = -1;
int meProvisioningHaltActivateIndex = -1;
vector<DataRecordEntry> entries = record.GetRecordEntries();
unsigned int numEntries = (unsigned int)entries.size();
for(unsigned int i = 0; i < numEntries; i++)
{
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_ME_KERNEL &&
entries[i].GetVariableId() == ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD)
{
currPwdIndex = i;
currentMEBxPwdFound = true;
if(entries[i].GetVariableLength() == G_S_DEFAULT_MEBX_PWD_LENGTH)
{
unsigned char tmp[G_S_DEFAULT_MEBX_PWD_LENGTH + 1];
entries[i].GetVariableValue(G_S_DEFAULT_MEBX_PWD_LENGTH + 1, &(tmp[0]));
if(memcmp(tmp, G_S_DEFAULT_MEBX_PWD, G_S_DEFAULT_MEBX_PWD_LENGTH) == 0)
{
isDefaultMEBxPwd = true;
}
}
}
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_ME_KERNEL &&
entries[i].GetVariableId() == ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD)
{
newPwdIndex = i;
newMEBxPwdFound = true;
}
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_ME_KERNEL &&
entries[i].GetVariableId() == ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION)
{
manSelectionIndex = i;
manFeatureFound = true;
}
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM &&
entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_PKI_DNS_SUFFIX)
{
pkiDnsSuffixFound = true;
}
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM &&
entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_CONFIG_SERVER_FQDN)
{
configServerFqdnFound = true;
}
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM &&
entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_PSADDR)
{
provisioningServerAddressFound = true;
}
if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM &&
entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_ME_PROVISION_HALT_ACTIVE)
{
meProvisioningHaltActivateIndex = i;
meProvisioningHaltActivateFound = true;
}
requiredDwords += (2 + (entries[i].GetVariableLength() + 3)/4);
}
requiredDwords += 2; // for NULL terminating entry
if(!currentMEBxPwdFound)
{
return CONFIG_MISSING_CURRENT_MEBX_PWD_ENTRY;
}
if(majorVersion >= SETUP_FILE_VERSION_2 && isDefaultMEBxPwd && !newMEBxPwdFound)
{
return CONFIG_MISSING_NEW_MEBX_PWD_ENTRY;
}
if(4*requiredDwords > (unsigned int)numChunks*CHUNK_SIZE)
{
return CONFIG_INVALID_RECORD_CHUNK_COUNT;
}
memset(buffer, 0, numChunks*CHUNK_SIZE);
DATA_RECORD_HEADER_T* header;
DATA_RECORD_ENTRY_T* entry;
bool scrambled = record.GetIsScrambled();
header = (DATA_RECORD_HEADER_T*)buffer;
header->RecordTypeIdentifier = RECORD_IDENTIFIER_DATA_RECORD;
header->RecordFlags.Valid = (record.GetIsValid()) ? 1 : 0;
header->RecordFlags.Scrambled = scrambled ? 1 : 0;
header->RecordChunkCount = numChunks;
unsigned short headerDwords = ((sizeof(DATA_RECORD_HEADER_T) + 3)/4) * 4;
header->RecordHeaderByteCount = headerDwords;
header->RecordNumber = recordNumber;
unsigned int base = header->RecordHeaderByteCount;
unsigned int entryDwordLength;
// first insert CurrentMEBx Pwd
entry = (DATA_RECORD_ENTRY_T*)(buffer + base);
SetEntry(entry, entries[currPwdIndex]);
if(modulesUsed)
{
modulesUsed->insert(entries[currPwdIndex].GetModuleId());
}
entryDwordLength = 2 + (entry->VariableLength + 3)/4;
base += 4*entryDwordLength;
// next insert newMebx, if found
if(newMEBxPwdFound)
{
entry = (DATA_RECORD_ENTRY_T*)(buffer + base);
SetEntry(entry, entries[newPwdIndex]);
entryDwordLength = 2 + (entry->VariableLength + 3)/4;
base += 4*entryDwordLength;
}
// next insert manageability selection, if found
if(manFeatureFound)
{
entry = (DATA_RECORD_ENTRY_T*)(buffer + base);
SetEntry(entry, entries[manSelectionIndex]);
entryDwordLength = 2 + (entry->VariableLength + 3)/4;
base += 4*entryDwordLength;
}
bool waitForHaltActiveAfterConfigServerSettings = false;
// The "ME provisioning Halt/Activate" command must appear in the file only after "PKIDNSSuffix",
// "ConfigServerFQDN" and "Provisioning Server Address"
if ((pkiDnsSuffixFound || configServerFqdnFound || provisioningServerAddressFound) && meProvisioningHaltActivateFound)
{
waitForHaltActiveAfterConfigServerSettings = true;
}
for(unsigned int i = 0; i < numEntries; i++)
{
if(i == currPwdIndex || i == newPwdIndex || i == manSelectionIndex)
{
continue;
}
if (i == meProvisioningHaltActivateIndex)
{
if (waitForHaltActiveAfterConfigServerSettings)
{
continue;
}
}
entry = (DATA_RECORD_ENTRY_T*)(buffer + base);
SetEntry(entry, entries[i]);
if(modulesUsed)
{
modulesUsed->insert(entries[i].GetModuleId());
}
entryDwordLength = 2 + (entry->VariableLength + 3)/4;
base += 4*entryDwordLength;
}
// The "ME provisioning Halt/Activate" command must appear in the file only after "PKIDNSSuffix",
// "ConfigServerFQDN" and "Provisioning Server Address"
if (waitForHaltActiveAfterConfigServerSettings)
{
entry = (DATA_RECORD_ENTRY_T*)(buffer + base);
SetEntry(entry, entries[meProvisioningHaltActivateIndex]);
if(modulesUsed)
{
modulesUsed->insert(entries[meProvisioningHaltActivateIndex].GetModuleId());
}
entryDwordLength = 2 + (entry->VariableLength + 3)/4;
base += 4*entryDwordLength;
}
entry = (DATA_RECORD_ENTRY_T*)(buffer + base);
entry->ModuleIdentifier = 0;
entry->VariableIdentifier = 0;
entry->VariableLength = 0;
entry->Reserved = 0;
if (scrambled)
{
ScrambleRecordData(buffer + headerDwords, header->RecordChunkCount * CHUNK_SIZE - headerDwords);
}
return CONFIG_SUCCESS;
}
int BufferToRecords(const unsigned int bufferLength,
const unsigned char* buffer,
SetupFileInfo* fileData,
vector<DataRecord>* records)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
SetupFileInfo tmp;
SetupFileInfo* fileInfo = (fileData ? fileData : &tmp);
unsigned int moduleListSize;
try
{
auto moduleList = std::unique_ptr<set<unsigned short>>(new set<unsigned short>());
int retVal = ParseFileHeader(bufferLength, buffer, fileInfo,
&moduleListSize, moduleList.get());
if (retVal != CONFIG_SUCCESS)
{
return retVal;
}
DataRecord record;
// verfiy the number of records consumed
for (unsigned int i = 0; i < fileInfo->recordsConsumed; i++)
{
retVal = GetDataRecord(fileInfo->dataRecordChunkCount,
(buffer + CHUNK_SIZE * (fileInfo->headerChunkCount + i*fileInfo->dataRecordChunkCount)),
fileInfo->majorVersion, fileInfo->minorVersion,
moduleList.get(), &record);
if (retVal != CONFIG_INVALID_RECORD)
{
return CONFIG_INVALID_FILE;
}
}
for (unsigned int i = fileInfo->recordsConsumed;
i < fileInfo->recordCount; i++)
{
retVal = GetDataRecord(fileInfo->dataRecordChunkCount,
(buffer + CHUNK_SIZE * (fileInfo->headerChunkCount + i*fileInfo->dataRecordChunkCount)),
fileInfo->majorVersion, fileInfo->minorVersion,
moduleList.get(), &record);
if (retVal == CONFIG_SUCCESS)
{
if (records)
{
records->push_back(record);
}
}
else
{
return retVal;
}
}
return CONFIG_SUCCESS;
}
catch (std::bad_alloc&)
{
printf("ERROR: can't allocate memory");
return MEMORY_ALLOC_ERROR;
}
}
int GetRecordByIndex(const unsigned int bufferLength,
const unsigned char* buffer,
const unsigned int index,
DataRecord* record)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
SetupFileInfo fileInfo;
unsigned int moduleListSize;
try
{
auto moduleList = std::unique_ptr<set<unsigned short>>(new set<unsigned short>());
int retVal = ParseFileHeader(bufferLength, buffer, &fileInfo,
&moduleListSize, moduleList.get());
if (retVal != CONFIG_SUCCESS)
{
return retVal;
}
if (index == 0 || index > fileInfo.recordCount)
{
return CONFIG_INVALID_INDEX;
}
retVal = GetDataRecord(fileInfo.dataRecordChunkCount,
(buffer + CHUNK_SIZE * (fileInfo.headerChunkCount + (index - 1)*fileInfo.dataRecordChunkCount)),
fileInfo.majorVersion, fileInfo.minorVersion,
moduleList.get(), record);
return retVal;
}
catch (std::bad_alloc&)
{
printf("ERROR: can't allocate memory");
return MEMORY_ALLOC_ERROR;
}
}
int GetNextValidRecord(const unsigned int bufferLength,
const unsigned char* buffer,
DataRecord* record)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
SetupFileInfo fileInfo;
unsigned int moduleListSize;
try
{
auto moduleList = std::unique_ptr<set<unsigned short>>(new set<unsigned short>());
int retVal = ParseFileHeader(bufferLength, buffer, &fileInfo,
&moduleListSize, moduleList.get());
if (retVal != CONFIG_SUCCESS)
{
return retVal;
}
if (fileInfo.recordsConsumed >= fileInfo.recordCount)
{
return CONFIG_NO_VALID_RECORDS;
}
unsigned int index = fileInfo.recordCount - fileInfo.recordsConsumed;
retVal = GetDataRecord(fileInfo.dataRecordChunkCount,
(buffer + CHUNK_SIZE * (fileInfo.headerChunkCount + (index - 1)*fileInfo.dataRecordChunkCount)),
fileInfo.majorVersion, fileInfo.minorVersion,
moduleList.get(), record);
if (retVal == CONFIG_INVALID_RECORD)
{
retVal = CONFIG_INVALID_FILE;
}
return retVal;
}
catch (std::bad_alloc&)
{
printf("ERROR: can't allocate memory");
return MEMORY_ALLOC_ERROR;
}
}
int RecordsToBuffer(const vector<DataRecord>& records,
const SetupFileInfo& setupInfo,
const unsigned int bufferLength,
unsigned char* buffer)
{
if(buffer == NULL)
{
return CONFIG_INVALID_BUFFER;
}
unsigned int numRecords = (unsigned int)records.size();
if((numRecords != setupInfo.recordCount) || (0 != setupInfo.recordsConsumed))
{
return CONFIG_INVALID_INPUT;
}
unsigned int requiredLength = (setupInfo.headerChunkCount + numRecords*setupInfo.dataRecordChunkCount)*CHUNK_SIZE;
if(bufferLength < requiredLength)
{
return CONFIG_INVALID_BUFFER_LENGTH;
}
set<unsigned short> modulesUsed;
int retVal = CONFIG_SUCCESS;
unsigned int index = 1;
unsigned int offset = CHUNK_SIZE * setupInfo.headerChunkCount;
try
{
auto tempBuffer = std::unique_ptr<unsigned char[]>(new unsigned char[requiredLength]);
memset(tempBuffer.get(), 0, requiredLength);
while (index <= numRecords)
{
retVal = WriteDataRecord(setupInfo.dataRecordChunkCount,
tempBuffer.get() + offset, setupInfo.majorVersion,
setupInfo.minorVersion, index, records[index - 1],
&modulesUsed);
if (retVal != CONFIG_SUCCESS)
{
break;
}
offset += (CHUNK_SIZE * setupInfo.dataRecordChunkCount);
index++;
}
if (retVal == CONFIG_SUCCESS)
{
retVal = WriteFileHeader(tempBuffer.get(), setupInfo, modulesUsed);
}
if (retVal == CONFIG_SUCCESS)
{
if (memcpy_s(buffer, bufferLength, tempBuffer.get(), requiredLength))
{
return CONFIG_INVALID_BUFFER_LENGTH;
}
}
return retVal;
}
catch (std::bad_alloc&)
{
printf("ERROR: can't allocate memory");
return MEMORY_ALLOC_ERROR;
}
}
int GetChunkCount(const DataRecord& record)
{
unsigned int requiredDwords = (sizeof(DATA_RECORD_HEADER_T) + 3)/4;
vector<DataRecordEntry> entries = record.GetRecordEntries();
unsigned int numEntries = (unsigned int)entries.size();
for(int i = 0; i < (int)numEntries; i++)
{
requiredDwords += (2 + (entries[i].GetVariableLength() + 3)/4);
}
requiredDwords += 2; // for NULL terminating entry
return (4*requiredDwords + (CHUNK_SIZE - 1))/CHUNK_SIZE;
}