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 + }