//
// $Id: LockoutPolicyProbe.cpp,v 1.1 2006/08/21 18:54:04 bakerj Exp $
//
//****************************************************************************************//
// Copyright (c) 2006, 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 "LockoutPolicyProbe.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  LockoutPolicyProbe Class  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
LockoutPolicyProbe* LockoutPolicyProbe::instance = NULL;

LockoutPolicyProbe::LockoutPolicyProbe() {
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//
	//------------------------------------------------------------------------------------//
}

LockoutPolicyProbe::~LockoutPolicyProbe() {
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  Do nothing for now
	//
	//------------------------------------------------------------------------------------//

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Public Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
AbsProbe* LockoutPolicyProbe::Instance() {
	// -----------------------------------------------------------------------
	//
	//  ABSTRACT
	//
	//	Ensure that the LockoutPolicyProbe is a singleton.
	// -----------------------------------------------------------------------

	// Use lazy initialization
	if(instance == NULL) 
		instance = new LockoutPolicyProbe();

	return instance;	
}

ItemVector* LockoutPolicyProbe::CollectItems(Object *object) {
	// -----------------------------------------------------------------------
	//
	//  ABSTRACT
	//
	//  Run the FamilyProbe
	// -----------------------------------------------------------------------
	ItemVector *collectedItems = NULL;

	Item* item = NULL;

	//
	// Get the force_logoff value
	//
	DWORD dwLevel = 0;
	USER_MODALS_INFO_0 *pBufM0 = NULL;
	NET_API_STATUS nStatus;
	LPCWSTR pszServerName = NULL;

	nStatus = NetUserModalsGet(pszServerName,
                              dwLevel,
                              (LPBYTE *)&pBufM0);

	if (nStatus == NERR_Success) {
		if (pBufM0 != NULL) {
			string forceLogoff = this->ConvertDWORD(pBufM0->usrmod0_force_logoff);

			// create a new passwordpolicy item
			item = this->CreateItem();
			item->SetStatus(OvalEnum::EXISTS_STATUS);
			collectedItems = new ItemVector();
			collectedItems->push_back(item);

			item->AppendElement(new ItemEntity("force_logoff",  forceLogoff, OvalEnum::STRING_TYPE, true, OvalEnum::EXISTS_STATUS));

			// Free the allocated memory.
			NetApiBufferFree(pBufM0);
		}

	} else if(nStatus == ERROR_ACCESS_DENIED) {
		// Free the allocated memory.
		if (pBufM0 != NULL)
			NetApiBufferFree(pBufM0);
		throw ProbeException ("Error: The user does not have access to the requested lockout policy information.");
	} else if(nStatus == NERR_InvalidComputer) {
		// Free the allocated memory.
		if (pBufM0 != NULL)
			NetApiBufferFree(pBufM0);
		throw ProbeException ("Error: The computer name is invalid for requesting lockout policy information.");
	}	

	//
	// Get the remaining lockout policy data
	//
	dwLevel = 3;
	USER_MODALS_INFO_3 *pBufM3 = NULL;

	nStatus = NetUserModalsGet(pszServerName,
                              dwLevel,
                              (LPBYTE *)&pBufM3);

	if (nStatus == NERR_Success) {
		if (pBufM3 != NULL) {
			string lockoutDuration = this->ConvertDWORD(pBufM3->usrmod3_lockout_duration);
			string lockoutObservationWindow = this->ConvertDWORD(pBufM3->usrmod3_lockout_observation_window);
			string lockoutThreshold = this->ConvertDWORD(pBufM3->usrmod3_lockout_threshold);


			// create a new passwordpolicy item
			if(item == NULL) 
				item = this->CreateItem();

			item->SetStatus(OvalEnum::EXISTS_STATUS);
			collectedItems = new ItemVector();
			collectedItems->push_back(item);

			item->AppendElement(new ItemEntity("lockout_duration",  lockoutDuration, OvalEnum::STRING_TYPE, false, OvalEnum::EXISTS_STATUS));
			item->AppendElement(new ItemEntity("lockout_observation_window",  lockoutObservationWindow, OvalEnum::STRING_TYPE, false, OvalEnum::EXISTS_STATUS));
			item->AppendElement(new ItemEntity("lockout_threshold",  lockoutThreshold, OvalEnum::STRING_TYPE, false, OvalEnum::EXISTS_STATUS));

			// Free the allocated memory.
			NetApiBufferFree(pBufM3);
		}

	} else if(nStatus == ERROR_ACCESS_DENIED) {
		// Free the allocated memory.
		if (pBufM3 != NULL)
			NetApiBufferFree(pBufM3);
		throw ProbeException ("Error: The user does not have access to the requested lockout policy information.");
	} else if(nStatus == NERR_InvalidComputer) {
		// Free the allocated memory.
		if (pBufM3 != NULL)
			NetApiBufferFree(pBufM3);
		throw ProbeException ("Error: The computer name is invalid for requesting lockout policy information.");
	}

	return collectedItems;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Private Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Item* LockoutPolicyProbe::CreateItem() {
	// -----------------------------------------------------------------------
	//
	//  ABSTRACT
	//
	//  Return a new Item created for storing password policy information
	//
	// -----------------------------------------------------------------------

	Item* item = new Item(0, 
						"http://oval.mitre.org/XMLSchema/oval-system-characteristics-5#windows", 
						"win-sc", 
						"http://oval.mitre.org/XMLSchema/oval-system-characteristics-5#windows windows-system-characteristics-schema.xsd", 
						OvalEnum::ERROR_STATUS, 
						"lockoutpolicy_item");

	return item;
}

string LockoutPolicyProbe::ConvertDWORD(DWORD dw) {
	// -----------------------------------------------------------------------
	//
	//  ABSTRACT
	//
	//  Return a string representation of teh DWORD
	//
	// -----------------------------------------------------------------------

	char dwordBuf[12];
	ZeroMemory(dwordBuf, sizeof(dwordBuf));
	_snprintf(dwordBuf, sizeof(dwordBuf)-1, "%d", dw);
	dwordBuf[sizeof(dwordBuf)-1] = '\0';

	string dwStr = dwordBuf;
	return dwStr;
}
