//
// $Id: ActiveDirectoryData.cpp,v 1.1 2004/06/01 17:05:19 bakerj Exp $
//
//************************** Property of the MITRE Corporation ***************************//
//
// Copyright (c) 2003 - The MITRE Corporation
//
// This file is part of the Query-based Network Assessment project.
//
// The Query-based Network Assessment is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License.
//
// The Query-based Network Assessment is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with the
// Query-based Network Assessment; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//****************************************************************************************//

#include "ActiveDirectoryData.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Class ActiveDirectoryData  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

ActiveDirectoryData::ActiveDirectoryData(DOMNode* testNodeIn)
{
	string testNodeName;

	// Validate the test node.

	if (testNodeIn->getNodeType() != DOMNode::ELEMENT_NODE )
	{
		throw ProbeDataException("Error: (ActiveDirectoryData) Invalid test node specified.");
	}
	else
	{
		testNodeName = DOMCommon::ToString(testNodeIn->getNodeName());
		if (testNodeName.compare("activedirectory_test") != 0)
		{
			throw ProbeDataException("Error: (ActiveDirectoryData) Invalid test node specified.");
		}
	}

	// Initialize the data members.

	testId = "";
	naming_context = new TypedData(LITTERAL_TYPE, "");
	relative_dn = new TypedData(LITTERAL_TYPE, "");
	attribute = new TypedData(LITTERAL_TYPE, "");
	exists = false;
	object_class = "";
	adstype = "";
	value = "";
	msg = "";

	// Call the ParseNode() function to populate the new ActiveDirectoryData object that was
	// just initialized.

	ParseNode(testNodeIn);
}

ActiveDirectoryData::ActiveDirectoryData(nvpVector* dnVectorIn)
{
	testId = "";
	naming_context = new TypedData(LITTERAL_TYPE, "");
	relative_dn = new TypedData(LITTERAL_TYPE, "");
	attribute = new TypedData(LITTERAL_TYPE, "");
	exists = false;
	object_class = "";
	adstype = "";
	value = "";
	msg = "";
}

ActiveDirectoryData::~ActiveDirectoryData()
{
	// Do nothing for now
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Public Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

void ActiveDirectoryData::Write(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* dataDocumentIn)
{
	//------------------------------------------------------------------------------------//
	//
	//  ABSTRACT
	//
	//	Write a windows active directory data element to the data document.
	//
	//------------------------------------------------------------------------------------//

	// Create a new test node.

	DOMElement* activedirectory_test = CreateNewTestNode(dataDocumentIn, "activedirectory_test");

	//	Add the naming_context element.

	AddChildNode(dataDocumentIn, activedirectory_test, "naming_context", naming_context->data);

	//	Add the relative_dn element.

	if(naming_context->data.compare("") != 0)
		AddChildNode(dataDocumentIn, activedirectory_test, "relative_dn", relative_dn->data);

	// Add the attribute element

	if(relative_dn->data.compare("") != 0)
		AddChildNode(dataDocumentIn, activedirectory_test, "attribute", attribute->data);

	if(exists)
	{
		AddChildNode(dataDocumentIn, activedirectory_test, "object_class", object_class);
		AddChildNode(dataDocumentIn, activedirectory_test, "adstype", adstype);
		AddChildNode(dataDocumentIn, activedirectory_test, "value", value, DetermineDataType(value));
	}

	//	Add the message element - as a string.

	AddChildNode(dataDocumentIn, activedirectory_test, "message", msg);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Private Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

void ActiveDirectoryData::ParseNode(DOMNode* testNodeIn)
{
	//------------------------------------------------------------------------------------//
	//
	//  ABSTRACT
	//
	//	Parse the provided DOMNode, gathering all data to populate the current
	//  ActiveDirectoryData oject.
	//	
	//------------------------------------------------------------------------------------//

	string childNodeName = "";
	string childOp = "";
	string tmpChildNodeName = "";
	string tmp = "";

	DOMNode* child = NULL;
	DOMNodeList* childList = NULL;
	DOMNode *tmpChild = NULL;
	DOMNodeList *tmpChildList = NULL;

	// Retreive the test id from the DOMNode.

	testId = DOMCommon::GetAttributeByName(testNodeIn, "id");
	if (testId.compare("") == 0)
	{
		throw ProbeDataException("Error: (ActiveDirectoryData) Unable to find the 'id' attribute for a windows active directory test.");
	}

	// Get a list of the child nodes and their values.

	childList = testNodeIn->getChildNodes();

	// Retreive the data needed by the active directory probe.  For each needed element, both
	// the type and value must be stored.  The type can be of LITTERAL_TYPE or
	// PATTERN_MATCH_TYPE depending on the supplied operator.

	unsigned int index = 0;

	while (index < childList->getLength())
	{
		child = childList->item(index);

		//	only concerned with ELEMENT_NODEs

		if (child->getNodeType() == DOMNode::ELEMENT_NODE)
		{
			childNodeName = DOMCommon::ToString(child->getNodeName());
			childOp = DOMCommon::GetAttributeByName(child, "operator");
			
			//--------------------------------------------------//
			//----              NAMING CONTEXT              ----//
			//--------------------------------------------------//

			if (strncmp(childNodeName.c_str(), "naming_context", 14) == 0)
			{
				naming_context->data = DOMCommon::GetDataNodeValue(child);

				if(childOp.compare("pattern match") == 0) naming_context->type = PATTERN_MATCH_TYPE;
				else naming_context->type = LITTERAL_TYPE;
			}

			//--------------------------------------------------//
			//----       RELATIVE DISTINGUISHED NAME        ----//
			//--------------------------------------------------//

			else if (strncmp(childNodeName.c_str(), "relative_dn", 11)==0)
			{
				relative_dn->data = DOMCommon::GetDataNodeValue(child);

				if(childOp.compare("pattern match") == 0) relative_dn->type = PATTERN_MATCH_TYPE;
				else relative_dn->type = LITTERAL_TYPE;
			}

			//--------------------------------------------------//
			//----                ATTRIBUTE                 ----//
			//--------------------------------------------------//

			else if (strncmp(childNodeName.c_str(), "attribute", 9)==0)
			{
				attribute->data = DOMCommon::GetDataNodeValue(child);

				if(childOp.compare("pattern match") == 0) attribute->type = PATTERN_MATCH_TYPE;
				else attribute->type = LITTERAL_TYPE;
			}
		}

		index++;
	}
}
	