os/kernelhwsrv/kernel/eka/euser/cbase/ub_polsvr.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/cbase/ub_polsvr.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,298 @@
     1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\euser\cbase\ub_polsvr.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "ub_std.h"
    1.22 +
    1.23 +_LIT(KPolicyServer, "CPolicyServer");
    1.24 +
    1.25 +#include <e32debug.h>
    1.26 +#define __PSD(x) __PLATSEC_DIAGNOSTIC_STRING(x)
    1.27 +
    1.28 +EXPORT_C CPolicyServer::CPolicyServer(TInt aPriority, const TPolicy& aPolicy, TServerType aType)
    1.29 +	: CServer2(aPriority, aType), iPolicy(aPolicy)
    1.30 +	{
    1.31 +#ifdef _DEBUG
    1.32 +	TUint i;
    1.33 +	TInt prev = iPolicy.iRanges[0];
    1.34 +	//iPolicy.iRangeCount must be greater than 0. (ie you must have at least
    1.35 +	//one policy
    1.36 +	__ASSERT_DEBUG(iPolicy.iRangeCount > 0, Panic(EPolSvrIRangeCountInvalid));
    1.37 +	//iRanges must start from request number 0.
    1.38 +	__ASSERT_DEBUG(prev == 0, Panic(EPolSvr1stRangeNotZero));
    1.39 +	__ASSERT_DEBUG((iPolicy.iElementsIndex[0] < ESpecialCaseHardLimit
    1.40 +		|| iPolicy.iElementsIndex[0] > ESpecialCaseLimit), 
    1.41 +		Panic(EPolSvrElementsIndexValueInvalid) );
    1.42 +	for(i=1; i<iPolicy.iRangeCount; i++)
    1.43 +		{
    1.44 +		TInt next = iPolicy.iRanges[i];
    1.45 +		//iRanges must be in increasing order.
    1.46 +		__ASSERT_DEBUG(next > prev, Panic(EPolSvrRangesNotIncreasing));
    1.47 +		//iElementsIndex must not contain invalid values.
    1.48 +		__ASSERT_DEBUG((iPolicy.iElementsIndex[i] < ESpecialCaseHardLimit
    1.49 +			|| iPolicy.iElementsIndex[i] > ESpecialCaseLimit), 
    1.50 +			Panic(EPolSvrElementsIndexValueInvalid) );
    1.51 +		prev = next;
    1.52 +		}
    1.53 +	//iOnConnect must not be an invalid value.
    1.54 +	__ASSERT_DEBUG((iPolicy.iOnConnect < ESpecialCaseHardLimit
    1.55 +		|| iPolicy.iOnConnect > ESpecialCaseLimit), 
    1.56 +		Panic(EPolSvrIOnConnectValueInvalid) );
    1.57 +#endif
    1.58 +	}
    1.59 +
    1.60 +EXPORT_C void CPolicyServer::RunL()
    1.61 +	{
    1.62 +	const RMessage2& msg = Message();
    1.63 +	msg.ClearAuthorised();
    1.64 +	TInt fn = msg.Function();
    1.65 +
    1.66 +	__ASSERT_COMPILE(-1 == RMessage2::EConnect);
    1.67 +	if(fn >= RMessage2::EConnect) 
    1.68 +		//So this implies any "normal" message or Connect
    1.69 +		//Now we have two steps to follow each having two mutually exculsive
    1.70 +		//parts.
    1.71 +		//Step 1: Find policy.
    1.72 +		//Step 2: Apply policy.
    1.73 +		{
    1.74 +		const TPolicyElement* element = 0;
    1.75 +		TUint specialCase = 0;
    1.76 +		//1a: If its a normal message.  Find the associate policy or special
    1.77 +		//case action.
    1.78 +		if(fn >= 0)
    1.79 +			{
    1.80 +			element = FindPolicyElement(fn, specialCase);
    1.81 +			}
    1.82 +		//1b: If its a connect message, there's a shortcut to the policy.
    1.83 +		else 
    1.84 +			{
    1.85 +			TUint8 i = iPolicy.iOnConnect;
    1.86 +			if(i >= ESpecialCaseHardLimit)
    1.87 +				specialCase = i;
    1.88 +			else
    1.89 +				element = &(iPolicy.iElements[i]);
    1.90 +			}
    1.91 +		//2a: We found a policy that we can automatically apply... Apply it!
    1.92 +		if(element)
    1.93 +			{
    1.94 +			TSecurityInfo missing;
    1.95 +			//If policy check succeeds, allow it through
    1.96 +			if(element->iPolicy.CheckPolicy(msg, missing, __PSD("Checked by CPolicyServer::RunL")))
    1.97 +				{
    1.98 +				ProcessL(msg);
    1.99 +				}
   1.100 +			//Else see what failure action is required (return error code,
   1.101 +			//panic client, ask user, etc...)
   1.102 +			else
   1.103 +				{
   1.104 +				CheckFailedL(msg, element->iAction, missing);
   1.105 +				}
   1.106 +			}
   1.107 +		//2b: The policy is a special case
   1.108 +		else 
   1.109 +			{
   1.110 +			switch(specialCase)
   1.111 +				{
   1.112 +				//If you change this you'll have to add to the switch statement
   1.113 +				__ASSERT_COMPILE(ESpecialCaseLimit == 252u);
   1.114 +				case ECustomCheck:
   1.115 +					{
   1.116 +					TInt action = EFailClient; 
   1.117 +					//The default action after failing a CustomSecurityCheck is
   1.118 +					//to complete the message with KErrPermissionDenied.  If
   1.119 +					//you want a different action, then change the action
   1.120 +					//parameter prior to returning from your derived
   1.121 +					//implementation of CustomSecurityCheckL
   1.122 +					TSecurityInfo missing;
   1.123 +					__ASSERT_COMPILE(SCapabilitySet::ENCapW == 2);
   1.124 +					memset(&missing, 0, sizeof(SSecurityInfo));
   1.125 +					TCustomResult result = CustomSecurityCheckL(msg, action, missing);
   1.126 +					if(result == EPass)
   1.127 +						{
   1.128 +						ProcessL(msg);
   1.129 +						}
   1.130 +					else if(result == EFail)
   1.131 +						{
   1.132 +						CheckFailedL(msg, action, missing); 
   1.133 +						}
   1.134 +					else if(result == EAsync)
   1.135 +						{
   1.136 +						//Do Nothing.  Derived CustomSecurityCheck is
   1.137 +						//responsible for calling ProcessL/CheckFailedL
   1.138 +						}
   1.139 +					else
   1.140 +						Panic(EPolSvrInvalidCustomResult);
   1.141 +					}
   1.142 +					break;	
   1.143 +				case ENotSupported:
   1.144 +					msg.Complete(KErrNotSupported);	
   1.145 +					break;
   1.146 +				case EAlwaysPass:
   1.147 +					ProcessL(msg);
   1.148 +					break;
   1.149 +				default:
   1.150 +					Panic(EPolSvrPolicyInvalid);
   1.151 +					break;
   1.152 +				}
   1.153 +			}
   1.154 +		}
   1.155 +	//else it must be either Disconnect or bad message.  Both are handled by
   1.156 +	//ProcessL
   1.157 +	else 
   1.158 +		{
   1.159 +		ProcessL(msg);
   1.160 +		}
   1.161 +
   1.162 +	// Queue reception of next message if it hasn't already been done
   1.163 +	if(!IsActive())
   1.164 +		ReStart();
   1.165 +	}
   1.166 +
   1.167 +EXPORT_C TInt CPolicyServer::RunError(TInt aError)
   1.168 +	{
   1.169 +	ProcessError(Message(), aError);
   1.170 +	if (!IsActive())
   1.171 +		ReStart();
   1.172 +	return KErrNone;
   1.173 +	}
   1.174 +
   1.175 +EXPORT_C void CPolicyServer::ProcessL(const RMessage2& aMsg)
   1.176 +	{
   1.177 +	aMsg.SetAuthorised();
   1.178 +	TInt fn = aMsg.Function();
   1.179 +
   1.180 +	if(fn >= 0)
   1.181 +		{
   1.182 +		CSession2* session=aMsg.Session();
   1.183 +		if(session)
   1.184 +			{
   1.185 +			session->ServiceL(aMsg);
   1.186 +			}
   1.187 +		else
   1.188 +			{
   1.189 +			NotConnected(aMsg);
   1.190 +			}
   1.191 +		}
   1.192 +	else if(fn==RMessage2::EConnect)
   1.193 +		{
   1.194 +		Connect(aMsg);
   1.195 +		}
   1.196 +	else if(fn==RMessage2::EDisConnect)
   1.197 +		{
   1.198 +		Disconnect(aMsg);
   1.199 +		}
   1.200 +	else
   1.201 +		{
   1.202 +		BadMessage(aMsg);
   1.203 +		}
   1.204 +	}
   1.205 +
   1.206 +EXPORT_C void CPolicyServer::ProcessError(const RMessage2& aMsg, TInt aError)
   1.207 +	{
   1.208 +	__ASSERT_COMPILE(-1 == RMessage2::EConnect);
   1.209 +	__ASSERT_ALWAYS(aMsg.Function() >= RMessage2::EConnect, User::Panic(KPolicyServer, 2));
   1.210 +	if(aMsg.Authorised() && aMsg.Function() >= 0)
   1.211 +		{
   1.212 +		aMsg.Session()->ServiceError(aMsg, aError);
   1.213 +		}
   1.214 +	else //Either ServiceL hadn't been called yet (not (yet) authorised) or
   1.215 +		//it's a Connect message
   1.216 +		{
   1.217 +		aMsg.Complete(aError);
   1.218 +		}
   1.219 +	}
   1.220 +
   1.221 +EXPORT_C CPolicyServer::TCustomResult CPolicyServer::CustomSecurityCheckL(const RMessage2& /*aMsg*/, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
   1.222 +	{
   1.223 +	Panic(EPolSvrCallingBaseImplementation);
   1.224 +	return EFail;
   1.225 +	}
   1.226 +
   1.227 +EXPORT_C void CPolicyServer::CheckFailedL(const RMessage2& aMsg, TInt aAction, const TSecurityInfo& aMissing)
   1.228 +	{
   1.229 +	if(aAction < 0)
   1.230 +		{
   1.231 +		TCustomResult result = CustomFailureActionL(aMsg, aAction, aMissing);
   1.232 +		if(result == EPass)
   1.233 +			ProcessL(aMsg);
   1.234 +		else if(result == EFail)
   1.235 +			aMsg.Complete(KErrPermissionDenied);
   1.236 +		else if(result == EAsync)
   1.237 +			{}
   1.238 +			//Do Nothing.  Derived CustomFailureActionL is responsible for
   1.239 +			//calling ProcessL/completing message with KErrPermissionDenied
   1.240 +		else
   1.241 +			Panic(EPolSvrInvalidCustomResult);
   1.242 +		}
   1.243 +	else if(aAction == EFailClient)
   1.244 +		{
   1.245 +		aMsg.Complete(KErrPermissionDenied);
   1.246 +		}
   1.247 +	else //if (aAction == EPanic) and all other +ve values
   1.248 +		{
   1.249 +		_LIT(KE32UserCBase, "E32USER-CBase");
   1.250 +		aMsg.Panic(KE32UserCBase, EPolSvrActionPanicClient);
   1.251 +		}
   1.252 +	}
   1.253 +
   1.254 +EXPORT_C CPolicyServer::TCustomResult CPolicyServer::CustomFailureActionL(const RMessage2& /*aMsg*/, TInt /*aAction*/, const TSecurityInfo& /*aMissing*/)
   1.255 +	{
   1.256 +	Panic(EPolSvrCallingBaseImplementation);
   1.257 +	return EFail;
   1.258 +	}
   1.259 +
   1.260 +const CPolicyServer::TPolicyElement* CPolicyServer::FindPolicyElement(TInt aFn, TUint& aSpecialCase) const
   1.261 +	{
   1.262 +	//Connect (aFn == -1) is handled through iPolicy.iOnConnect.  So aFn should
   1.263 +	//always be greater than -1.
   1.264 +	__ASSERT_DEBUG(aFn >= 0, User::Panic(KPolicyServer, 1));
   1.265 +
   1.266 +	TUint l = 0;
   1.267 +	TUint u = iPolicy.iRangeCount;
   1.268 +	TUint m = 0;
   1.269 +	while(u > l)
   1.270 +		{
   1.271 +		m = (l+u) >> 1;
   1.272 +		if(iPolicy.iRanges[m] > aFn)
   1.273 +			u = m;
   1.274 +		else
   1.275 +			l = m + 1;
   1.276 +		}
   1.277 +	--l;
   1.278 +	//the mth element of iElementsIndex tells us the index in iElements
   1.279 +	//we want
   1.280 +	TUint8 i = iPolicy.iElementsIndex[l];
   1.281 +	//if the mth element of iElementsIndex is >= 250 -> Special Case
   1.282 +	if(i >= ESpecialCaseHardLimit)
   1.283 +		{
   1.284 +		aSpecialCase = i;
   1.285 +		return 0;
   1.286 +		}
   1.287 +	return &(iPolicy.iElements[i]);
   1.288 +	}
   1.289 +
   1.290 +
   1.291 +
   1.292 +
   1.293 +/**
   1.294 +Extension function
   1.295 +
   1.296 +
   1.297 +*/
   1.298 +EXPORT_C TInt CPolicyServer::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
   1.299 +	{
   1.300 +	return CServer2::Extension_(aExtensionId, a0, a1);
   1.301 +	}