policymanagement/policyengine/policyengineserver/src/PolicyManager.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:44:00 +0200
changeset 5 3f7d9dbe57c8
parent 0 b497e44ab2fc
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Implementation of policymanagement components
*
*/


// INCLUDE FILES

#include "PolicyManager.h"
#include "elements.h"
#include "DataTypes.h"
#include "PolicyParser.h"
#include "ElementBase.h"
#include "PolicyProcessor.h"
#include "TrustedSession.h"
#include "ErrorCodes.h"
#include "OperationParser.h"
#include "OperationParserConstants.h"
#include "SettingEnforcementManager.h"
#include "PolicyEngineServer.h"
#include "PolicyEngineXACML.h"
#include "debug.h"


#include "DMUtilClient.h"
#include <PolicyEngineClientServer.h>
#include <ManagementContext.h>


// CONSTANTS
const TInt KMaxServerIdLength = 250;

// -----------------------------------------------------------------------------
// CPolicyManager::CPolicyManager()
// -----------------------------------------------------------------------------
//

CPolicyManager::CPolicyManager( CPolicyProcessor * aPolicyProcessor)
	: CActive( EPriorityLow),  iPolicyProcessor( aPolicyProcessor)
{
	iPolicyStorage = CPolicyStorage::PolicyStorage();
}

// -----------------------------------------------------------------------------
// CPolicyManager::~CPolicyManager()
// -----------------------------------------------------------------------------
//

CPolicyManager::~CPolicyManager()
{
	//CSettingEnforcementManager
	delete iSEManager;

	//descriptors used in operations 
	delete iActiveChildList;
	delete iActiveXACMLContent;
	delete iActiveElementList;
	delete iOperationParser;
	delete iCurrentManagementCommand;
	
	CPolicyEngineServer::RemoveActiveObject( this);
}

// -----------------------------------------------------------------------------
// CPolicyManager::ConstructL()
// -----------------------------------------------------------------------------
//
void CPolicyManager::ConstructL()
{
	CPolicyEngineServer::AddActiveObjectL( this);
	iSEManager = CSettingEnforcementManager::NewL();
}

// -----------------------------------------------------------------------------
// CPolicyStorage::NewL()
// -----------------------------------------------------------------------------
//

CPolicyManager * CPolicyManager::NewL( CPolicyProcessor * aPolicyProcessor)
{
	CPolicyManager * self = new(ELeave) CPolicyManager( aPolicyProcessor);
	
	CleanupStack::PushL( self);
	self->ConstructL();
	CleanupStack::Pop( self);
	
	return self;
	
}

// -----------------------------------------------------------------------------
// CPolicyManager::ExecuteOperationL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::ExecuteOperation( CTrustedSession * aSession, const RMessage2& aMessage)
{
	iMessage = &aMessage;

	//Only one management session is accepted
	if ( CPolicyEngineServer::StatusFlags()->iManagementActive )
	{
		CompleteOperation( KErrInUse);
		return;
	}
	
	CPolicyEngineServer::StatusFlags()->iManagementActive = ETrue;


	//set pointer to trusted session and save reference to RMessage
	iTrustedSession = aSession;
	
	//initialize states
	iOperationStatus = 0;
	iUseBearerCertificate = EFalse;
	iCertificateUpdates = EFalse;

	
	//Add this active object active scheduler	
	if ( !IsAdded())
	{
		CActiveScheduler::Add( this);
	}
	
	//Complete own request
	SetActive();
	TRequestStatus * status = &iStatus;
	User::RequestComplete( status, KErrNone);
}



// -----------------------------------------------------------------------------
// CPolicyManager::RunL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::RunL()
{
	CPolicyEngineServer::SetActiveSubSession( this);	

	//management operations are allowed only when server is free
 	if ( CPolicyEngineServer::StatusFlags()->iProcessorActive )
	{
		SetActive();
		TRequestStatus * status = &iStatus;
		User::RequestComplete( status, KErrNone);
		return;		
	}

	if ( iOperationStatus == 0)
	{
		//Start management session for next operations
		iPolicyStorage->StartCommitSessionL();
	
		iCurrentManagementCommand = HBufC8::NewL( iMessage->GetDesLength(0));
		//Read policy description	
		TPtr8 ptr = iCurrentManagementCommand->Des(); 
		iMessage->ReadL(0, ptr, 0);
		iOperationParser = COperationParser::NewL( ptr);
	
		//parse operations, "iMsg" stores error message
		iOperationParser->ParseOperationsL( iMsg);
	}
	else if ( (iOperationStatus - 1) < iOperationParser->OperationCount())
	{
		//Execute operations, "this" is pointer to callback function 
		iCertificateUpdates = EFalse;
		iOperationParser->ExecuteL( iOperationStatus - 1, this);
		
		if ( iCertificateUpdates)
		{
			CPolicyEngineServer::CertificateMaps()->NewMappingsAvailable();
		}			
	}
	
	if ( iOperationStatus == iOperationParser->OperationCount() + 2)
	{
		//Finish management session and commit changes in repository
		iMsg = ManagementErrors::OperationOk;
		
		if ( iStatus.Int() == KErrNone)
		{
			CommitChangesL();	
			CompleteOperation( iStatus.Int());
			CPolicyStorage::PolicyStorage()->ReleaseElements();
		}
		else
		{
			RunError( iStatus.Int());			
		}
		
	}
	else
	if ( iOperationStatus == iOperationParser->OperationCount() + 1)
	{
		//Make setting enforcements...
		MakeEnforcementL( KErrNone);
	}
	else
	{
		SetActive();
		TRequestStatus * status = &iStatus;
		User::RequestComplete( status, KErrNone);
	}

	iOperationStatus++;
}

// -----------------------------------------------------------------------------
// CPolicyManager::DoCancel()
// -----------------------------------------------------------------------------
//

void CPolicyManager::DoCancel()
{
	RunError( KErrAbort);
}

// -----------------------------------------------------------------------------
// CPolicyManager::DoCancel()
// -----------------------------------------------------------------------------
//

TInt CPolicyManager::RunError( TInt aError)
{
	RDEBUG("CPolicyManager::RunError");
	RDEBUG8_2("Policy engine operation error message: %S", &iMsg);

	//restores possible changes in policy storage
	TRAPD( err, iPolicyStorage->CommitChangesL( EFalse))
	
	if ( err != KErrNone )
	{
		aError = err;	
	}

	//complete operation
	CompleteOperation( aError);	
	
	return KErrNone;
}

// -----------------------------------------------------------------------------
// CPolicyManager::MakeEnforcementL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::MakeEnforcementL( TInt aError)
{
	//initialize enforcement session
	iSEManager->StartEnforcementSessionL( iStatus, iTrustedSession->SessionCertificate());

	//get modified elements 
	iPolicyStorage->GetEditedElementsL( iSEManager);
	
	//start enforcement session enforcement policies
	if ( aError == KErrNone)
	{
		iSEManager->ExecuteEnforcementSessionL();
	}

	
	//set active (waiting for enforcement completing)
	SetActive();	
}

// -----------------------------------------------------------------------------
// CPolicyManager::CompleteOperation()
// -----------------------------------------------------------------------------
//

void CPolicyManager::CompleteOperation( TInt aError )
	{
	RDEBUG_2("CPolicyManager::CompleteOperation( %d )", aError );

	if( aError != KErrNone && aError != KErrParser && KErrOpParser != aError && KErrPolicyManager != aError)
		{
		iMsg = KNullDesC8;
		aError = KErrGeneral;
		}
	else
		{
		aError = KErrNone;
		}

	//finish storage session and enforcement session
	iPolicyStorage->ResetEditableMemory();
	iSEManager->EndEnforcementSession( KErrNone == aError );

	if ( iCertificateUpdates )
		{
		CPolicyEngineServer::CertificateMaps()->NewMappingsAvailable();
		}	

	CPolicyEngineServer::StatusFlags()->iManagementActive = EFalse;
	
	//release resources
	delete iOperationParser;
	iOperationParser = NULL;
	delete iCurrentManagementCommand;
	iCurrentManagementCommand = NULL;

	//write return message to client process
	TParserResponse response( iMsg);
	TPckgC<TParserResponse> retPack(response);
	TRAPD( err, iMessage->WriteL( 1, retPack ) );
	if( err != KErrNone )
		{
		iMessage->Complete( err );
		return;
		}

	iMessage->Complete( aError);
	}

// -----------------------------------------------------------------------------
// CPolicyManager::UpdateStateFlags()
// -----------------------------------------------------------------------------
//
void CPolicyManager::UpdateStateFlagsL()
{
	RDEBUG("CPolicyManager::UpdateStateFlagsL - start");

	RDMUtil dmutil;
	User::LeaveIfError( dmutil.Connect());
	CleanupClosePushL( dmutil);
	TBool securityActive = EFalse;
	User::LeaveIfError( dmutil.UpdatePolicyMngStatusFlags( EPolicyChanged));
	
	//Check is terminal security activated
	CElementBase * iElement = iPolicyStorage->GetElementL( PolicyLanguage::Constants::RolesMappingPolicy);	
	if (iElement)
	{
		TElementReserver reserver(iElement);

		iPolicyStorage->CheckElementL(iElement);

		
		//check child elements, any rule child means that terminal security is acticated
		for (TInt i(0); i < iElement->ElementCount(); i++) {
			CElementBase * element = iElement->Element(i);

			if (element->ElementType() == ERule) {
				RDEBUG("CPolicyManager::UpdateStateFlagsL -> securityActive = ETrue");
				securityActive = ETrue;
				break;
			}
		}
		reserver.Release();
	}
	
	//update policy management flags	
	if ( securityActive)
	{
		User::LeaveIfError( dmutil.UpdatePolicyMngStatusFlags( ETerminalSecurityActive));
	}
	else
	{
		User::LeaveIfError( dmutil.UpdatePolicyMngStatusFlags( ETerminalSecurityDeactive));
	}

	
	CleanupStack::PopAndDestroy( &dmutil);

	RDEBUG("CPolicyManager::UpdateStateFlagsL - end");
}





// -----------------------------------------------------------------------------
// CPolicyManager::CommitChangesL()
// -----------------------------------------------------------------------------
//
void CPolicyManager::CommitChangesL()
{
	//Accept or decline changes to storage...
	iPolicyStorage->SaveEditableMemoryL();

	//This ensures that enforcement settings are committed
	iSEManager->CommitChanges();	
		
	//This ensures that all changes are commited (also enforcement)
	iPolicyStorage->CommitChangesL( ETrue);	
	
	//update state flags
	UpdateStateFlagsL();
	
	RDEBUG8_2("Policy engine operation message: %S", &iMsg);
}


// -----------------------------------------------------------------------------
// CPolicyManager::NewPolicy()
// -----------------------------------------------------------------------------
//

void CPolicyManager::NewElementL( const TInt& aLineOffset, const TDesC8& aTargetElement, const TDesC8& aElementDescription, const TBool& aUseBearerCertificate )
{
	RDEBUG("PolicyEngineServer: CPolicyManager::NewElementL");

	//initialize policy parser...
	CPolicyParser * parser = CPolicyParser::NewL( iPolicyStorage);
	CleanupStack::PushL( parser);
	parser->SetExternalIdChecked( KNoExternalIdConflictsAllowed);
	parser->SetLineOffset( aLineOffset);
	iUseBearerCertificate = aUseBearerCertificate;

	//Parse native model from XACML description
	TInt err(KErrNone);	
	TBuf8<KMaxReturnMessageLength> msg;
	CElementBase * element = parser->ParseXACMLObjects( err, aElementDescription, msg);	
	CleanupStack::PopAndDestroy( parser); //Parser

	if ( err != KErrNone )
	{
		iMsg = msg;
		User::Leave( KErrParser);	
	}
	

	//Add element to policy storage (storage take responsibility to delete object)
	RDEBUG_2("PolicyEngineServer: Element parsed and id created(id %d)", element->GetId());

	element->CreateIdL();
	element->CreateExternalId();
	iPolicyStorage->AddNewElementL( element);
	TElementReserver newElement( element);
		
	//Check is the policy valid and if so, add element to temporary storage
	AssignElementL( aTargetElement, element);
	
	newElement.Release();
}

// -----------------------------------------------------------------------------
// CPolicyManager::ReplaceElementL()
// -----------------------------------------------------------------------------
//
void CPolicyManager::ReplaceElementL( const TInt& aLineOffset, const TDesC8& aTargetElement, const TDesC8& aElementDescription )
{
	RDEBUG("PolicyEngineServer: CPolicyManager::ReplaceElementL");

	//initialize policy parser...
	CPolicyParser * parser = CPolicyParser::NewL( iPolicyStorage);
	CleanupStack::PushL( parser);
	parser->SetExternalIdChecked( KSameExternalIdAllowedForRoot);
	parser->SetLineOffset( aLineOffset);

	//Parse native model from XACML description
	TInt err(KErrNone);	
	TBuf8<KMaxReturnMessageLength> msg;
	CElementBase * element = parser->ParseXACMLObjects( err, aElementDescription, msg);	
	CleanupStack::PopAndDestroy( parser); //Parser

	if ( err != KErrNone )
	{
		iMsg = msg;
		User::Leave( KErrParser);	
	}
	

	//Add element to policy storage (storage take responsibility to delete object)
	RDEBUG_2("PolicyEngineServer: Element parsed and id created(id %d)", element->GetId());

	element->CreateIdL();
	element->CreateExternalId();
	iPolicyStorage->AddNewElementL( element);
	TElementReserver newElement( element);
		
	//Check is the policy valid and if so, add element to temporary storage
	ReAssignElementL( aTargetElement, element);
	
	newElement.Release();
	
}


// -----------------------------------------------------------------------------
// CPolicyManager::AssignPolicyL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::AssignElementL( const TDesC8& aTargetElement, CElementBase * aElement)
{
	RDEBUG("PolicyEngineServer: CPolicyManager::AssignElementL");

	//get parent element and load it
	CElementBase * parentElement = iPolicyStorage->GetEditableElementL( aTargetElement);

	//if parent eleemnt is valid
	if ( !parentElement)
	{
		RDEBUG("PolicyEngineServer: Target element not found");
		iMsg = ManagementErrors::ElementNotFound;
		User::Leave( KErrPolicyManager);
	}
	
	TElementReserver assignReserver( parentElement);
	iPolicyStorage->CheckElementL( parentElement);

	//add parant id to components
	aElement->AddParentIdL( parentElement->GetId());

	//Check is assignment acceptable
	IsAssigmentAcceptableL( parentElement, aElement, ETrue);
	assignReserver.Release();
	

	//Add element to parent element, check is assigment valid
	parentElement->AddIdElementL( aElement);
	parentElement->iElementState = EEditedElement;
}

// -----------------------------------------------------------------------------
// CPolicyManager::AssignPolicyL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::ReAssignElementL( const TDesC8& aTargetElement, CElementBase * aElement)
{
	RDEBUG("PolicyEngineServer: CPolicyManager::ReAssignElementL");

	//get replaced element and load it
	CElementBase * replacedElement = iPolicyStorage->GetEditableElementL( aTargetElement);

	//check that element is valid
	if ( !replacedElement)
	{
		RDEBUG("PolicyEngineServer: Target element not found");
		iMsg = ManagementErrors::ElementNotFound;
		User::Leave( KErrPolicyManager);
	}
	
	//Check element
	TElementReserver assignReserver( replacedElement);
	iPolicyStorage->CheckElementL( replacedElement);

	//copy parents to new element
	aElement->AddParentIdL( replacedElement->iParentId);
		
	//Get parent elements
	CElementBase * parentElement = iPolicyStorage->GetEditableElementL( replacedElement->iParentId);
	
	//check that element is valid
	if ( !parentElement)
	{
		iMsg = ManagementErrors::ElementNotFound;
		User::Leave( KErrPolicyManager);
	}
		
	//Check element
	TElementReserver parentReserver( parentElement);
	iPolicyStorage->CheckElementL( parentElement);

	//Check is reassignment acceptable
	IsAssigmentAcceptableL( parentElement, aElement, EFalse);

	//remove child from parent child list
	parentElement->RemoveChild( replacedElement->GetId());
	
	//Add element to parent element and mark to modified
	parentElement->AddIdElementL( aElement);
	parentElement->iElementState = EEditedElement;
	
	//When edited element list is committed all "EDeletedEditableElement"s will be deleted...
	replacedElement->DeleteMarkRecursiveL();

	
	
	
	parentReserver.Release();
	assignReserver.Release();
}
// -----------------------------------------------------------------------------
// CPolicyManager::RemoveElementL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::RemoveElementL( const TDesC8& aTargetElement)
{
	RDEBUG("CPolicyManager::RemoveElementL");


	iMsg = ManagementErrors::OperationOk;

	//get parent element and load it
	CElementBase * element = iPolicyStorage->GetEditableElementL( aTargetElement);
	
	//error if element not found
	if ( !element )
	{
		RDEBUG("PolicyEngineServer: Target element not found");
		iMsg = ManagementErrors::ElementNotFound;
		User::Leave( KErrPolicyManager);	
	}


	TElementReserver elementReserver( element);
	iPolicyStorage->CheckElementL( element);


	if ( element->iParentId)
	{
		//Remove element reference from parent element

		CElementBase * parentElement = iPolicyStorage->GetEditableElementL( element->iParentId);
		__ASSERT_ALWAYS ( parentElement, User::Panic( Panics::PolicyManagerPanic, KErrGeneral));
			
		//check element, use editable cache
		TElementReserver elementReserver( parentElement);
		iPolicyStorage->CheckElementL( parentElement);
		
		IsRemoveAcceptableL( parentElement, element );

		TInt err = parentElement->RemoveChild( element->GetId());
	
		if ( err != KErrNone )
		{
			User::Leave( KErrPolicyManager);	
		}
		
		parentElement->iElementState = EEditedElement;
		
		elementReserver.Release();
	}
	
	//When edited element list is committed all "EDeletedEditableElement" will be deleted...
	element->DeleteMarkRecursiveL();
	
	elementReserver.Release();
}


// -----------------------------------------------------------------------------
// CPolicyManager::IsAssigmentAcceptable()
// -----------------------------------------------------------------------------
//


void CPolicyManager::IsAssigmentAcceptableL( CElementBase * aParentElement, CElementBase * aElement, TBool aNewElement)
{
	RDEBUG("CPolicyManager::IsAssigmentAcceptableL");

	using namespace PolicyLanguage::Constants;
	using namespace AttributeContainerHelper;
	using namespace PolicyLanguage::NativeLanguage::AttributeValues;
	
	//return if policy check is not needed
	NO_POLICY_CHECK_RETURN;
	RDEBUG_3("CPolicyManager: Parent element (%d) element (%d)", aParentElement->GetId(), aElement->GetId());

	HBufC8* extId = aParentElement->ExternalId();
	TInt match = extId->CompareF( PolicyLanguage::Constants::RolesMappingPolicy );
	if( (match == 0) && aNewElement )
	{
		RDEBUG("CPolicyManager: Parent element is RolesMappingPolicy. Adding trust for server");
		TInt rolesElements = aParentElement->GetChildElementCountL();
				
		RDEBUG_2("CPolicyManager: rolesElements count (%d)", rolesElements);
		if( rolesElements >= 1 )
		{ 
			RDEBUG("CPolicyManager: Trust already exists");
			iMsg = ManagementErrors::AccessDenied;
			User::Leave( KErrPolicyManager);
		}				
		RDEBUG("CPolicyManager: No trust created yet");
	}
	//setup request context
	iPolicyProcessor->ResetRequestContext();
	iPolicyProcessor->SetTargetElement( aElement);
	iPolicyProcessor->SetSessionTrust( iTrustedSession);
	
	//attribute list for request attributes
	RAttributeContainer attributes;
	CleanupClosePushL( attributes);
	
	//action attributes for meta_policy_Set	
	if ( aNewElement)
	{
		attributes.AppendL( EActionAttributes, CAttribute::NewL( PolicyEngineXACML::KActionId, AddPolicy, StringDataType));
	}
	else
	{
		attributes.AppendL( EActionAttributes, CAttribute::NewL( PolicyEngineXACML::KActionId, ReplacePolicy, StringDataType));
	}

	//Trusted subject is either trustedsubject of session or trustedsubject used in element to be added.
	//In a cases where new element contains trustedsubject, it is used. Other cases sessions trustedsubject
	
	//Get new element subjectmatch-elements
	RElementArray subjectMatches;
	CleanupClosePushL( subjectMatches);
	aElement->FindAttributesL( ESubjectMatch, subjectMatches);
	
	//util variables
	TPtrC8 trustedSubject( KNullDesC8);
	TBool oneTrustedSubject = EFalse;
		
	//add trusted subject from target element
	for ( TInt i(0); i < subjectMatches.Count(); i++)
	{
		CMatchObject* subjectMatch = (CMatchObject*) subjectMatches[i];
		
		//check attribute id (Certificate id is also trusted subject!)
		TPtrC8 attributeId = subjectMatch->AttributeDesignator()->GetAttributeid();
		if ( attributeId == PolicyEngineXACML::KTrustedSubject || attributeId == PolicyEngineXACML::KCertificate  )
		{
			//Only one target policy is valid
			if ( oneTrustedSubject && trustedSubject.Compare( subjectMatch->AttributeValue()->Data()->Value()) != 0)
			{
				iMsg = ParserErrors::InvalidElement;
				User::Leave( KErrPolicyManager);				
			}
		
			oneTrustedSubject = ETrue;

			//add trusted subject to attribute list
			trustedSubject.Set( subjectMatch->AttributeValue()->Data()->Value());
			
			//certificates have to be transformed to CASN form
			if ( attributeId == PolicyEngineXACML::KCertificate)
			{
				//create CSubject info
				CCertificateMaps::CSubjectInfo* info = new (ELeave) CCertificateMaps::CSubjectInfo();
				CleanupStack::PushL( info);
				
				//parse CASN info from certificate and add TargetTrustedSubject attribute with CASN value				
				CCertificateMaps::CreateSubjectInfoL( info, trustedSubject);
				attributes.AppendL( ESubjectAttributes, CAttribute::NewL( TargetTrustedSubject, *info->iCASN, StringDataType));
				CleanupStack::PopAndDestroy( info);
			}
			else
			{
				attributes.AppendL( ESubjectAttributes, CAttribute::NewL( TargetTrustedSubject, trustedSubject, StringDataType));
			}
			
		}
	}
	CleanupStack::PopAndDestroy( &subjectMatches);	//subjectMatches
	
	
	
	if ( iUseBearerCertificate )
	{
		if ( !iTrustedSession->CertificatedSession())
		{
			RDEBUG("PolicyEngineServer: Certificated session is required");
			//when bearer certificate is used, session must be certificated
			iMsg = ManagementErrors::SessionMustBeCertificated;
			User::Leave( KErrPolicyManager);				
		}
	
		//add certificate mapping for alias, certificate (TCertInfo) is available inside of trusted session
		CElementBase * rule = iTrustedSession->CreateCertificateMappingL( trustedSubject);
		CleanupStack::PushL( rule);
		
		if ( !rule)
		{
			RDEBUG("PolicyEngineServer: Invalid certificate!");
			iMsg = ManagementErrors::InvalidCertificateMapping;
			User::Leave( KErrPolicyManager);
		}
		else
		{
			rule->CreateIdL();
			rule->CreateExternalId();
			iPolicyStorage->AddNewElementL( rule);
			
			RDEBUG_2("PolicyEngineServer: Auto certifate created (id %d)", rule->GetId());
			
			//add parant id to cert policy
			CElementBase* certMappingPolicy = iPolicyStorage->GetEditableElementL( CertMappingPolicy);
			//if element is not valid
			if (!certMappingPolicy)
			{
				return;
			}
			TElementReserver certReserver( certMappingPolicy);
			iPolicyStorage->CheckElementL( certMappingPolicy);

			rule->AddParentIdL( certMappingPolicy->GetId());

			//Add element to parent element, check is assigment valid
			certMappingPolicy->AddIdElementL( rule);
			certMappingPolicy->iElementState = EEditedElement;
			
						
			certReserver.Release();		
						
			CPolicyEngineServer::CertificateMaps()->NewMappingsAvailable();
			iCertificateUpdates = ETrue;			
		}
		CleanupStack::Pop( rule);	
	}
	

	//add session trusted subject
	if ( iTrustedSession->CertificatedSession())
	{
		attributes.AppendL( ESubjectAttributes, 
				CAttribute::NewL( PolicyEngineXACML::KTrustedSubject, iTrustedSession->CASNForSessionL(), StringDataType));
		attributes.AppendL( ESubjectAttributes, 
				CAttribute::NewL( PolicyEngineXACML::KRoleId, iTrustedSession->CASNForSessionL(), StringDataType));
	}
	else
	{
		attributes.AppendL( ESubjectAttributes, 
				CAttribute::NewL( PolicyEngineXACML::KSubjectId, iTrustedSession->SIDForSession(), StringDataType));
	}

	//certificate mapping must be checked first!! 
	if ( *aParentElement->ExternalId() == CertMappingPolicy)
	{
		TBool validCertificate = EFalse;
		TRAPD( err, validCertificate = iTrustedSession->IsCertificateMappingValidL( aElement))
	
		if ( !validCertificate || err != KErrNone)
		{
			RDEBUG("PolicyEngineServer: Invalid certificate mapping!");
			iMsg = ManagementErrors::InvalidCertificateMapping;
			User::Leave( KErrPolicyManager);
		}
		
		iCertificateUpdates = ETrue;
	}
	
	
	//parent element for new policy
	attributes.AppendL( EResourceAttributes, CAttribute::NewL( PolicyTargetAttr, *aParentElement->ExternalId(), StringDataType));

	//make request
	TMatchResponse response;

	RDEBUG("CPolicyManager - Start request execution");
	iPolicyProcessor->ExecuteRequestL( attributes, response);
	RDEBUG("CPolicyManager - End request execution");
		
	CleanupStack::PopAndDestroy( &attributes);
	RDEBUG("CPolicyManager - CleanupStack::PopAndDestroy( &attributes);");

	if ( response != EPermit)
	{
		RDEBUG("CPolicyManager - Access denied");
		iMsg = ManagementErrors::AccessDenied;
		User::Leave( KErrPolicyManager);
	}
		
	//add current DM session server id to list which defines server ids which DM operations are silent.
	if ( iUseBearerCertificate)
	{
		AddSilentDMOperationServerIdL();
	}
		
}
	
// -----------------------------------------------------------------------------
// CPolicyManager::IdRemoveAcceptableL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::IsRemoveAcceptableL( CElementBase* aParentElement, CElementBase* aElement )
	{
	RDEBUG("CPolicyManager::IsRemoveAcceptableL");

	using namespace PolicyLanguage::Constants;
	using namespace AttributeContainerHelper;
	using namespace PolicyLanguage::NativeLanguage::AttributeValues;

	//return if policy check is not needed
	NO_POLICY_CHECK_RETURN;
	
	//setup request context
	iPolicyProcessor->ResetRequestContext();
	iPolicyProcessor->SetTargetElement( aElement );
	iPolicyProcessor->SetSessionTrust( iTrustedSession );
	
	//attribute list for request attributes
	RAttributeContainer attributes;
	CleanupClosePushL( attributes );
	
	//action attributes for meta_policy_Set	
	attributes.AppendL( EActionAttributes, CAttribute::NewL( PolicyEngineXACML::KActionId, RemovePolicy, StringDataType));

	//subject attributes for trusted sessions
	if( iTrustedSession->CertificatedSession() )
		{
		attributes.AppendL( ESubjectAttributes, 
				CAttribute::NewL( PolicyEngineXACML::KRoleId, iTrustedSession->CASNForSessionL(), StringDataType));
		attributes.AppendL( ESubjectAttributes, 
				CAttribute::NewL( PolicyEngineXACML::KTrustedSubject, iTrustedSession->CASNForSessionL(), StringDataType));
		}
	else
		{
		attributes.AppendL( ESubjectAttributes, 
				CAttribute::NewL( PolicyEngineXACML::KSubjectId, iTrustedSession->SIDForSession(), StringDataType));
		
		}
	
	// ======= original certificate mapping ======================
	//search trustedsubject from target element (element to be deleted)
	HBufC8* targetTrustedSubject = iTrustedSession->GetTargetTrustedSubjectL( aElement, ETrue );	

	//and target element trusted subject to request context....
	if( targetTrustedSubject )
		{
		CleanupStack::PushL( targetTrustedSubject); 
		attributes.AppendL( ESubjectAttributes, CAttribute::NewL( TargetTrustedSubject, *targetTrustedSubject, StringDataType));
		CleanupStack::PopAndDestroy( targetTrustedSubject);
		}
	// ===========================================================
	
	
	// ======= mapped certificates ===============================
	// all certificate mappings, including mapped certificates, are under "cert_mapping_policy"
	CElementBase* certMappings = iPolicyStorage->GetEditableElementL( _L8("cert_mapping_policy") );
	if( certMappings )
		{
		TElementReserver mappedElementReserver( certMappings );
		iPolicyStorage->CheckElementL( certMappings );
	
		RPointerArray<HBufC8> mappedTargetTrustedSubjects;
		iTrustedSession->GetMappedTargetTrustedSubjectL( mappedTargetTrustedSubjects, certMappings, ETrue );
		TInt count = mappedTargetTrustedSubjects.Count();
		if( count )
			{
			for( TInt i = 0; i < count; i++ )
				{
				HBufC8* mappedTargetTrustedSubject = mappedTargetTrustedSubjects[ i ];
				CleanupStack::PushL( mappedTargetTrustedSubject);
				attributes.AppendL( ESubjectAttributes, CAttribute::NewL( PolicyEngineXACML::KCertificateMapped, *mappedTargetTrustedSubject, StringDataType));
				CleanupStack::PopAndDestroy( mappedTargetTrustedSubject ); 
				}
			}
	
		mappedTargetTrustedSubjects.Close();
		mappedElementReserver.Release();
		}
	// ===========================================================
	
	//parent element for new policy
	attributes.AppendL( EResourceAttributes, CAttribute::NewL( PolicyTargetAttr, *aParentElement->ExternalId(), StringDataType));

	//make request
	TMatchResponse response;
	iPolicyProcessor->ExecuteRequestL( attributes, response );
	CleanupStack::PopAndDestroy( &attributes );

	if( response != EPermit )
		{
		iMsg = ManagementErrors::AccessDenied;
		User::Leave( KErrPolicyManager );
		}	
	}
	

// -----------------------------------------------------------------------------
// CPolicyManager::GetElementListL()
// -----------------------------------------------------------------------------
//		
void CPolicyManager::GetElementListL( const RMessage2& aMessage)
{
	
	//element info is two phase operation...
	if ( aMessage.Function() == EGetElementListLength)
	{
		//In first phase descriptor lengths are fetched

		//Read element types
		TElementType type;
		TPckg<TElementType> typePack( type);
		aMessage.ReadL(0, typePack, 0);
		
		//fetch element
		CElementBase * element = iPolicyStorage->GetElementL( PolicyLanguage::Constants::RootElement);
		
		if ( element)
		{
			//reserve element and check it
			TElementReserver elementReserver( element);
			iPolicyStorage->CheckElementL( element);
			
			//get list length
			TInt length = element->GetElementsListLengthL( type);
	
			delete iActiveElementList;
			iActiveElementList = NULL;
			
			iActiveElementList = HBufC8::NewL( length);
			TPtr8 ptr = iActiveElementList->Des();
			element->GetElementsListL( type, ptr);
	
	
			//write values to client side
			TPckgC<TInt> intPack( length); 
			aMessage.WriteL(1, intPack);	
			
			elementReserver.Release();
		}
		else
		{
			User::Leave( KErrNotFound);
		}
	}
	else
	{
		// and in second phase descriptor are written to client side
		if ( iActiveElementList )
		{
			aMessage.WriteL(0, *iActiveElementList);	
		}
		
		//delete child list
		delete iActiveElementList;
		iActiveElementList = 0;
	}
	
}
	
	
	
// -----------------------------------------------------------------------------
// CPolicyManager::GetElementInfoL()
// -----------------------------------------------------------------------------
//


void CPolicyManager::GetElementInfoL( const RMessage2& aMessage)
{


	//element info is two phase operation...
	if ( aMessage.Function() == EGetElementDescriptionAndChildListLength)
	{
		//In first phase descriptor lengths are fetched

		//Read element id
		TPtr8 id = HBufC8::NewLC( aMessage.GetDesLength(0))->Des(); 
		aMessage.ReadL(0, id, 0);
		
		//fetch element
		CElementBase * element = iPolicyStorage->GetElementL( id);
		
		if ( element)
		{
			//reserve element and check it
			TElementReserver elementReserver( element);
			iPolicyStorage->CheckElementL( element);
			
			//Create helper pack, which is delivered to client side			
			TElementInfoHelpPack helper;
			helper.iDescriptionLength = 0;
				
			//get description and child list		
			iActiveDescription = element->DescriptionL();
			if ( iActiveDescription)
			{
				helper.iDescriptionLength = iActiveDescription->Length();
			}
	
			helper.iChildListLength = element->GetChildListLengthL();
	
			//write values to client side
			TPckgC<TElementInfoHelpPack> helperPack( helper); 
			
			delete iActiveChildList;
			iActiveChildList = NULL;
			iActiveChildList = HBufC8::NewL( helper.iChildListLength); 
			TPtr8 ptr = iActiveChildList->Des();
			element->GetChildListL( ptr);
	
			aMessage.WriteL(1, helperPack);	
			
			elementReserver.Release();
		}
		else
		{
			User::Leave( KErrNotFound);
		}
		
		CleanupStack::PopAndDestroy();	//HBufC8
	}
	else
	{
		// and in second phase descriptor are written to client side
		if ( iActiveDescription)
		{
			aMessage.WriteL(0, *iActiveDescription);	
		}

		if ( iActiveChildList)
		{
			aMessage.WriteL(1, *iActiveChildList);	
		}

		
		//description is owned by descriptor element (do not delete)
		iActiveDescription = 0;
		//delete child list
		delete iActiveChildList;
		iActiveChildList = 0;
	}
}

// -----------------------------------------------------------------------------
// CPolicyManager::GetElementXACMLDescriptionL()
// -----------------------------------------------------------------------------
//

void CPolicyManager::GetElementXACMLDescriptionL( const RMessage2& aMessage)
{
	

	//get element XACML description is two phase operation...
	if ( aMessage.Function() == EGetElementXACMLLength)
	{
		//Read element id
		TPtr8 id = HBufC8::NewLC( aMessage.GetDesLength(0))->Des(); 
		aMessage.ReadL(0, id, 0);
	
		//In first phase descriptor length is fetched.
		CElementBase * element = iPolicyStorage->GetElementL( id);

		if ( element)
		{
			//reserve element and check it
			TElementReserver elementReserver( element);
			iPolicyStorage->CheckElementL( element);
	
			//Member pointer is used to save XACML description during two phase operation
			delete iActiveXACMLContent;
			iActiveXACMLContent = NULL;
			iActiveXACMLContent = element->DecodeElementL( EXACML, EFullMode);
		
			TInt length = 0;
			if ( iActiveXACMLContent)
			{
				length = iActiveXACMLContent->Length();
			}
	
			//write values to client side
			TPckg<TInt> descriptionLength( length); 
			aMessage.WriteL(1, descriptionLength);	
			
			elementReserver.Release();
		}
		else
		{
			User::Leave( KErrNotFound);
		}
	
		CleanupStack::PopAndDestroy();	//HBufC8
	}
	else
	{
		// and in second phase descriptor are written to client side
		if ( iActiveXACMLContent )
		{
			aMessage.WriteL(0, *iActiveXACMLContent);	
		}
		
		//delete XACML content
		delete iActiveXACMLContent;
		iActiveXACMLContent = NULL;
		
	}
}

// -----------------------------------------------------------------------------
// CPolicyManager::GetElementXACMLDescriptionL()
// -----------------------------------------------------------------------------
//
void CPolicyManager::IsServerIdValidL( const RMessage2& aMessage)
{
	RDEBUG("PolicyEngineServer: CPolicyManager: Is allowed server id");
	
	//Read server id
	TPtr8 id = HBufC8::NewLC( aMessage.GetDesLength(0))->Des(); 
	aMessage.ReadL(0, id, 0);

	//Create package for data
	TBool response;
	TPckg<TBool> respPck( response);

	//check id
	response = CPolicyStorage::PolicyStorage()->IsServerIdValid( id);

	if ( response )
		{
		RDEBUG("CPolicyManager: Is allowed server id -> TRUE");
		}
	else
		{
		RDEBUG("CPolicyManager: Is allowed server id -> FALSE");
		}
	
	//write response
	aMessage.WriteL(1, respPck);	
	
	CleanupStack::PopAndDestroy();	
}

// -----------------------------------------------------------------------------
// CPolicyManager::GetCertificateRoleL()
// -----------------------------------------------------------------------------
//
void CPolicyManager::GetCertificateRoleL( const RMessage2& aMessage)
	{
	RDEBUG("PolicyEngineServer: CPolicyManager::GetCertificateRoleL");

	//Create package for data
	TCertInfo certInfo;
	TPckg<TCertInfo> certInfoPck( certInfo);
	aMessage.ReadL(0, certInfoPck, 0);

	//TRole
	TRole role;
	TPckg<TRole> rolePck( role);
	
	//get certificate role...
	role = CPolicyEngineServer::CertificateMaps()->CertificateRoleL( certInfo, EFalse );

	//write response
	aMessage.WriteL( 1, rolePck );	
	}


// -----------------------------------------------------------------------------
// CPolicyManager::AddSilentDMOperationServerIdL()
// -----------------------------------------------------------------------------
//
void CPolicyManager::AddSilentDMOperationServerIdL()
{
	//connect to DM util client...
	RDMUtil dmutil;
	User::LeaveIfError( dmutil.Connect());
	CleanupClosePushL( dmutil);
	
	//..and get server id
	TBuf8<KMaxServerIdLength> serverid;
	User::LeaveIfError( dmutil.GetDMSessionServerId( serverid));
	
	User::LeaveIfError( CPolicyStorage::PolicyStorage()->AddNewServerId( serverid));


	CleanupStack::PopAndDestroy( &dmutil); 
}


// -----------------------------------------------------------------------------
// CPolicyManager::IsCurrentServerIdTrustedL()
// -----------------------------------------------------------------------------
//
TBool CPolicyManager::IsCurrentServerIdTrustedL()
{
	TBool trustedServer = EFalse;
	
	//connect to DM util client...
	RDMUtil dmutil;
	User::LeaveIfError( dmutil.Connect());
	CleanupClosePushL( dmutil);
	
	//..and get server id
	TBuf8<KMaxServerIdLength> serverid;
	User::LeaveIfError( dmutil.GetDMSessionServerId( serverid));
	TRAPD( err, trustedServer = CPolicyStorage::PolicyStorage()->IsServerIdValid( serverid) );
	User::LeaveIfError( err );
	CleanupStack::PopAndDestroy( &dmutil); 
	
	return trustedServer;
}