//
// $Id: RegistryEffectiveRightsData.cpp,v 1.10 2005/08/05 20:19:38 bakerj Exp $
//
//****************************************************************************************//
// Copyright (c) 2005, The MITRE Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice, this list
//       of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice, this 
//       list of conditions and the following disclaimer in the documentation and/or other
//       materials provided with the distribution.
//     * Neither the name of The MITRE Corporation nor the names of its contributors may be
//       used to endorse or promote products derived from this software without specific 
//       prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//****************************************************************************************//

#include "RegistryEffectiveRightsData.h"

// Initialize the item Vector
sVector RegistryEffectiveRightsData::items;

//****************************************************************************************//
//						RegistryEffectiveRightsData Class								  //	
//****************************************************************************************//
RegistryEffectiveRightsData::RegistryEffectiveRightsData(DOMElement *test)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Initialize a new RegistryData based on the node provided
	// -----------------------------------------------------------------------

	//	Validate the test node
	string testName = XmlCommon::GetElementName((DOMElement*)test);
	if(testName.compare("regkeyeffectiverights_test") != 0)
		throw ProbeDataException("Error: RegistryData() Invalid test node specified.");

	//	Init the data members 
	hive = new ObjectElement();
	key = new ObjectElement();
	trustee_name = new DataElement();
	trustee_domain = new DataElement();
	trustee_sid = new DataElement();
	acl_type = new DataElement();
	standard_delete = new DataElement();
	standard_read_control = new DataElement();
	standard_write_dac = new DataElement();
	standard_write_owner = new DataElement();
	standard_synchronize = new DataElement();
	access_system_security = new DataElement();
	generic_read = new DataElement();
	generic_write = new DataElement();
	generic_execute = new DataElement();
	generic_all = new DataElement();
	key_query_value = new DataElement();
	key_set_value = new DataElement();
	key_create_sub_key = new DataElement();
	key_enumerate_sub_keys = new DataElement();
	key_notify = new DataElement();
	key_create_link = new DataElement();
	key_wow64_64key = new DataElement();
	key_wow64_32key = new DataElement();
	key_wow64_res = new DataElement();

	//	Call the parse node function
	ParseNode(test);

	// set the xmlns and schema location
	this->SetXmlnsAlias("windows");
	this->SetXmlns("http://oval.mitre.org/XMLSchema/system_characteristics#windows");
	this->SetSchemaLocation("http://oval.mitre.org/XMLSchema/system_characteristics#windows windows-system-characteristics-schema.xsd");
}

RegistryEffectiveRightsData::RegistryEffectiveRightsData()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Initialize a new RegistryData as an empty object.
	// -----------------------------------------------------------------------

	//	Init the data members 
	hive = new ObjectElement();
	key = new ObjectElement();
	trustee_name = new DataElement();
	trustee_domain = new DataElement();
	trustee_sid = new DataElement();
	acl_type = new DataElement();
	standard_delete = new DataElement();
	standard_read_control = new DataElement();
	standard_write_dac = new DataElement();
	standard_write_owner = new DataElement();
	standard_synchronize = new DataElement();
	access_system_security = new DataElement();
	generic_read = new DataElement();
	generic_write = new DataElement();
	generic_execute = new DataElement();
	generic_all = new DataElement();
	key_query_value = new DataElement();
	key_set_value = new DataElement();
	key_create_sub_key = new DataElement();
	key_enumerate_sub_keys = new DataElement();
	key_notify = new DataElement();
	key_create_link = new DataElement();
	key_wow64_64key = new DataElement();
	key_wow64_32key = new DataElement();
	key_wow64_res = new DataElement();

	// set the xmlns and schema location
	this->SetXmlnsAlias("windows");
	this->SetXmlns("http://oval.mitre.org/XMLSchema/system_characteristics#windows");
	this->SetSchemaLocation("http://oval.mitre.org/XMLSchema/system_characteristics#windows windows-system-characteristics-schema.xsd");
}

RegistryEffectiveRightsData::~RegistryEffectiveRightsData()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Delete data members
	// -----------------------------------------------------------------------

	delete hive;
	delete key;
	delete trustee_name;
	delete trustee_domain;
	delete trustee_sid;
	delete acl_type;
	delete standard_delete;
	delete standard_read_control;
	delete standard_write_dac;
	delete standard_write_owner;
	delete standard_synchronize;
	delete access_system_security;
	delete generic_read;
	delete generic_write;
	delete generic_execute;
	delete generic_all;
	delete key_query_value;
	delete key_set_value;
	delete key_create_sub_key;
	delete key_enumerate_sub_keys;
	delete key_notify;
	delete key_create_link;
	delete key_wow64_64key;
	delete key_wow64_32key;
	delete key_wow64_res;
}

// ***************************************************************************************	//
//								Public members												//
// ***************************************************************************************	//
void RegistryEffectiveRightsData::Write()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Write a windows registry key data element to the data document.
	// -----------------------------------------------------------------------

	// Create a string representation of the item
	string item = hive->object + ":" + key->object;

	// Ensure that the item has not already been written
	if(WroteItem(&items, item))
		return;

	//	Create a new item node
	DOMElement *registryItem = CreateNewItemNode(dataDocument, "regkeyeffectiverights_item");

	// Add the object element
	DOMElement *objectElm = XmlCommon::AddChildElement(dataDocument, registryItem, "object");

	// Add the status attribute to the object if not default value
	string strStatus = this->SwitchStatusType(this->objectStatus);
	if (strStatus.compare("exists") != 0)
		XmlCommon::AddAttribute(objectElm, "status", strStatus);

	//	Add the hive element - as a string
	AddObjectChildElement(dataDocument, objectElm, "hive", this->hive);

	//	Add the key element - as a string
	AddObjectChildElement(dataDocument, objectElm, "key", this->key);

	// Add the data section if the object status is exists
	if(objectStatus == exists && !this->isPatternMatchObject) {
		DOMElement *dataElm = XmlCommon::AddChildElement(dataDocument, registryItem, "data");

		// Add data subelements
		AddDataChildElement(dataDocument, dataElm, "trustee_name", this->trustee_name);
		AddDataChildElement(dataDocument, dataElm, "trustee_domain", this->trustee_domain);
		AddDataChildElement(dataDocument, dataElm, "trustee_sid", this->trustee_sid);
		AddDataChildElement(dataDocument, dataElm, "acl_type", this->acl_type);
		AddDataChildElement(dataDocument, dataElm, "standard_delete", this->standard_delete);
		AddDataChildElement(dataDocument, dataElm, "standard_read_control", this->standard_read_control);
		AddDataChildElement(dataDocument, dataElm, "standard_write_dac", this->standard_write_dac);
		AddDataChildElement(dataDocument, dataElm, "standard_write_owner", this->standard_write_owner);
		AddDataChildElement(dataDocument, dataElm, "standard_synchronize", this->standard_synchronize);
		AddDataChildElement(dataDocument, dataElm, "access_system_security", this->access_system_security);
		AddDataChildElement(dataDocument, dataElm, "generic_read", this->generic_read);
		AddDataChildElement(dataDocument, dataElm, "generic_write", this->generic_write);
		AddDataChildElement(dataDocument, dataElm, "generic_execute", this->generic_execute);
		AddDataChildElement(dataDocument, dataElm, "generic_all", this->generic_all);
		AddDataChildElement(dataDocument, dataElm, "key_query_value", this->key_query_value);
		AddDataChildElement(dataDocument, dataElm, "key_set_value", this->key_set_value);
		AddDataChildElement(dataDocument, dataElm, "key_create_sub_key", this->key_create_sub_key);
		AddDataChildElement(dataDocument, dataElm, "key_enumerate_sub_keys", this->key_enumerate_sub_keys);
		AddDataChildElement(dataDocument, dataElm, "key_notify", this->key_notify);
		AddDataChildElement(dataDocument, dataElm, "key_create_link", this->key_create_link);
		AddDataChildElement(dataDocument, dataElm, "key_wow64_64key", this->key_wow64_64key);
		AddDataChildElement(dataDocument, dataElm, "key_wow64_32key", this->key_wow64_32key);
		AddDataChildElement(dataDocument, dataElm, "key_wow64_res", this->key_wow64_res);
	}

	// Add the new item to the data document
	InsertItem(dataDocument, registryItem, "regkeyeffectiverights_items");
}

// ***************************************************************************************	//
//								Private members												//
// ***************************************************************************************	//
void RegistryEffectiveRightsData::ParseNode(DOMElement *test)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Parse the node gathering all data to popular this RegistryData
	//	
	// -----------------------------------------------------------------------

	// Retreive the test id from the DOMNode.
	testId = XmlCommon::GetAttributeByName(test, "id");
	if (testId.compare("") == 0) {
		throw ProbeDataException("Error: Unable to find the 'id' attribute for specified the test.");
	}

	///////////////////////////////////////////////////////////////////////////
	//	Parse the node
	///////////////////////////////////////////////////////////////////////////
	// Get the object element
	DOMNode *object = XmlCommon::FindNodeNS(test, "object");
	if (object == NULL) {
		throw new ProbeDataException("Error: Unable to locate object section for test: " + testId + "\n");

	}

	// Loop over childern of the object node
	//	get a list of the child nodes and their values
	string childName	= "";
	string childValue	= "";
	string childOp		= "";
	

	DOMNodeList *objectChildren = object->getChildNodes();
	unsigned int index = 0;
	while(index < objectChildren->getLength())
	{
		DOMNode *tmpNode = objectChildren->item(index);

		//	only concerned with ELEMENT_NODEs
		if (tmpNode->getNodeType() == DOMNode::ELEMENT_NODE)
		{
			DOMElement *objectChild = (DOMElement*)tmpNode;
			//	get the name of the child
			childName = XmlCommon::GetElementName(objectChild);
			childValue = XmlCommon::GetDataNodeValue(objectChild);
			childOp = XmlCommon::GetAttributeByName(objectChild, "operator");
			
			// Convert the type
			objectTypes curType;
			if(childOp.compare("pattern match") == 0){
				curType = pattern_match;
				this->isPatternMatchObject = true;
			} else {
				curType = literal;
			}
			
			//	Get the hive value	
			if(childName.compare("hive")==0) {

				hive->object = childValue;
				hive->type = curType;
				
			//	Get the key value
			}else if(childName.compare("key")==0) {

				key->object = childValue;
				key->type = curType;
			
			}
		}

		index ++;
	}
}
	