os/kernelhwsrv/kernel/eka/euser/cbase/ub_polsvr.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\euser\cbase\ub_polsvr.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "ub_std.h"
sl@0
    19
sl@0
    20
_LIT(KPolicyServer, "CPolicyServer");
sl@0
    21
sl@0
    22
#include <e32debug.h>
sl@0
    23
#define __PSD(x) __PLATSEC_DIAGNOSTIC_STRING(x)
sl@0
    24
sl@0
    25
EXPORT_C CPolicyServer::CPolicyServer(TInt aPriority, const TPolicy& aPolicy, TServerType aType)
sl@0
    26
	: CServer2(aPriority, aType), iPolicy(aPolicy)
sl@0
    27
	{
sl@0
    28
#ifdef _DEBUG
sl@0
    29
	TUint i;
sl@0
    30
	TInt prev = iPolicy.iRanges[0];
sl@0
    31
	//iPolicy.iRangeCount must be greater than 0. (ie you must have at least
sl@0
    32
	//one policy
sl@0
    33
	__ASSERT_DEBUG(iPolicy.iRangeCount > 0, Panic(EPolSvrIRangeCountInvalid));
sl@0
    34
	//iRanges must start from request number 0.
sl@0
    35
	__ASSERT_DEBUG(prev == 0, Panic(EPolSvr1stRangeNotZero));
sl@0
    36
	__ASSERT_DEBUG((iPolicy.iElementsIndex[0] < ESpecialCaseHardLimit
sl@0
    37
		|| iPolicy.iElementsIndex[0] > ESpecialCaseLimit), 
sl@0
    38
		Panic(EPolSvrElementsIndexValueInvalid) );
sl@0
    39
	for(i=1; i<iPolicy.iRangeCount; i++)
sl@0
    40
		{
sl@0
    41
		TInt next = iPolicy.iRanges[i];
sl@0
    42
		//iRanges must be in increasing order.
sl@0
    43
		__ASSERT_DEBUG(next > prev, Panic(EPolSvrRangesNotIncreasing));
sl@0
    44
		//iElementsIndex must not contain invalid values.
sl@0
    45
		__ASSERT_DEBUG((iPolicy.iElementsIndex[i] < ESpecialCaseHardLimit
sl@0
    46
			|| iPolicy.iElementsIndex[i] > ESpecialCaseLimit), 
sl@0
    47
			Panic(EPolSvrElementsIndexValueInvalid) );
sl@0
    48
		prev = next;
sl@0
    49
		}
sl@0
    50
	//iOnConnect must not be an invalid value.
sl@0
    51
	__ASSERT_DEBUG((iPolicy.iOnConnect < ESpecialCaseHardLimit
sl@0
    52
		|| iPolicy.iOnConnect > ESpecialCaseLimit), 
sl@0
    53
		Panic(EPolSvrIOnConnectValueInvalid) );
sl@0
    54
#endif
sl@0
    55
	}
sl@0
    56
sl@0
    57
EXPORT_C void CPolicyServer::RunL()
sl@0
    58
	{
sl@0
    59
	const RMessage2& msg = Message();
sl@0
    60
	msg.ClearAuthorised();
sl@0
    61
	TInt fn = msg.Function();
sl@0
    62
sl@0
    63
	__ASSERT_COMPILE(-1 == RMessage2::EConnect);
sl@0
    64
	if(fn >= RMessage2::EConnect) 
sl@0
    65
		//So this implies any "normal" message or Connect
sl@0
    66
		//Now we have two steps to follow each having two mutually exculsive
sl@0
    67
		//parts.
sl@0
    68
		//Step 1: Find policy.
sl@0
    69
		//Step 2: Apply policy.
sl@0
    70
		{
sl@0
    71
		const TPolicyElement* element = 0;
sl@0
    72
		TUint specialCase = 0;
sl@0
    73
		//1a: If its a normal message.  Find the associate policy or special
sl@0
    74
		//case action.
sl@0
    75
		if(fn >= 0)
sl@0
    76
			{
sl@0
    77
			element = FindPolicyElement(fn, specialCase);
sl@0
    78
			}
sl@0
    79
		//1b: If its a connect message, there's a shortcut to the policy.
sl@0
    80
		else 
sl@0
    81
			{
sl@0
    82
			TUint8 i = iPolicy.iOnConnect;
sl@0
    83
			if(i >= ESpecialCaseHardLimit)
sl@0
    84
				specialCase = i;
sl@0
    85
			else
sl@0
    86
				element = &(iPolicy.iElements[i]);
sl@0
    87
			}
sl@0
    88
		//2a: We found a policy that we can automatically apply... Apply it!
sl@0
    89
		if(element)
sl@0
    90
			{
sl@0
    91
			TSecurityInfo missing;
sl@0
    92
			//If policy check succeeds, allow it through
sl@0
    93
			if(element->iPolicy.CheckPolicy(msg, missing, __PSD("Checked by CPolicyServer::RunL")))
sl@0
    94
				{
sl@0
    95
				ProcessL(msg);
sl@0
    96
				}
sl@0
    97
			//Else see what failure action is required (return error code,
sl@0
    98
			//panic client, ask user, etc...)
sl@0
    99
			else
sl@0
   100
				{
sl@0
   101
				CheckFailedL(msg, element->iAction, missing);
sl@0
   102
				}
sl@0
   103
			}
sl@0
   104
		//2b: The policy is a special case
sl@0
   105
		else 
sl@0
   106
			{
sl@0
   107
			switch(specialCase)
sl@0
   108
				{
sl@0
   109
				//If you change this you'll have to add to the switch statement
sl@0
   110
				__ASSERT_COMPILE(ESpecialCaseLimit == 252u);
sl@0
   111
				case ECustomCheck:
sl@0
   112
					{
sl@0
   113
					TInt action = EFailClient; 
sl@0
   114
					//The default action after failing a CustomSecurityCheck is
sl@0
   115
					//to complete the message with KErrPermissionDenied.  If
sl@0
   116
					//you want a different action, then change the action
sl@0
   117
					//parameter prior to returning from your derived
sl@0
   118
					//implementation of CustomSecurityCheckL
sl@0
   119
					TSecurityInfo missing;
sl@0
   120
					__ASSERT_COMPILE(SCapabilitySet::ENCapW == 2);
sl@0
   121
					memset(&missing, 0, sizeof(SSecurityInfo));
sl@0
   122
					TCustomResult result = CustomSecurityCheckL(msg, action, missing);
sl@0
   123
					if(result == EPass)
sl@0
   124
						{
sl@0
   125
						ProcessL(msg);
sl@0
   126
						}
sl@0
   127
					else if(result == EFail)
sl@0
   128
						{
sl@0
   129
						CheckFailedL(msg, action, missing); 
sl@0
   130
						}
sl@0
   131
					else if(result == EAsync)
sl@0
   132
						{
sl@0
   133
						//Do Nothing.  Derived CustomSecurityCheck is
sl@0
   134
						//responsible for calling ProcessL/CheckFailedL
sl@0
   135
						}
sl@0
   136
					else
sl@0
   137
						Panic(EPolSvrInvalidCustomResult);
sl@0
   138
					}
sl@0
   139
					break;	
sl@0
   140
				case ENotSupported:
sl@0
   141
					msg.Complete(KErrNotSupported);	
sl@0
   142
					break;
sl@0
   143
				case EAlwaysPass:
sl@0
   144
					ProcessL(msg);
sl@0
   145
					break;
sl@0
   146
				default:
sl@0
   147
					Panic(EPolSvrPolicyInvalid);
sl@0
   148
					break;
sl@0
   149
				}
sl@0
   150
			}
sl@0
   151
		}
sl@0
   152
	//else it must be either Disconnect or bad message.  Both are handled by
sl@0
   153
	//ProcessL
sl@0
   154
	else 
sl@0
   155
		{
sl@0
   156
		ProcessL(msg);
sl@0
   157
		}
sl@0
   158
sl@0
   159
	// Queue reception of next message if it hasn't already been done
sl@0
   160
	if(!IsActive())
sl@0
   161
		ReStart();
sl@0
   162
	}
sl@0
   163
sl@0
   164
EXPORT_C TInt CPolicyServer::RunError(TInt aError)
sl@0
   165
	{
sl@0
   166
	ProcessError(Message(), aError);
sl@0
   167
	if (!IsActive())
sl@0
   168
		ReStart();
sl@0
   169
	return KErrNone;
sl@0
   170
	}
sl@0
   171
sl@0
   172
EXPORT_C void CPolicyServer::ProcessL(const RMessage2& aMsg)
sl@0
   173
	{
sl@0
   174
	aMsg.SetAuthorised();
sl@0
   175
	TInt fn = aMsg.Function();
sl@0
   176
sl@0
   177
	if(fn >= 0)
sl@0
   178
		{
sl@0
   179
		CSession2* session=aMsg.Session();
sl@0
   180
		if(session)
sl@0
   181
			{
sl@0
   182
			session->ServiceL(aMsg);
sl@0
   183
			}
sl@0
   184
		else
sl@0
   185
			{
sl@0
   186
			NotConnected(aMsg);
sl@0
   187
			}
sl@0
   188
		}
sl@0
   189
	else if(fn==RMessage2::EConnect)
sl@0
   190
		{
sl@0
   191
		Connect(aMsg);
sl@0
   192
		}
sl@0
   193
	else if(fn==RMessage2::EDisConnect)
sl@0
   194
		{
sl@0
   195
		Disconnect(aMsg);
sl@0
   196
		}
sl@0
   197
	else
sl@0
   198
		{
sl@0
   199
		BadMessage(aMsg);
sl@0
   200
		}
sl@0
   201
	}
sl@0
   202
sl@0
   203
EXPORT_C void CPolicyServer::ProcessError(const RMessage2& aMsg, TInt aError)
sl@0
   204
	{
sl@0
   205
	__ASSERT_COMPILE(-1 == RMessage2::EConnect);
sl@0
   206
	__ASSERT_ALWAYS(aMsg.Function() >= RMessage2::EConnect, User::Panic(KPolicyServer, 2));
sl@0
   207
	if(aMsg.Authorised() && aMsg.Function() >= 0)
sl@0
   208
		{
sl@0
   209
		aMsg.Session()->ServiceError(aMsg, aError);
sl@0
   210
		}
sl@0
   211
	else //Either ServiceL hadn't been called yet (not (yet) authorised) or
sl@0
   212
		//it's a Connect message
sl@0
   213
		{
sl@0
   214
		aMsg.Complete(aError);
sl@0
   215
		}
sl@0
   216
	}
sl@0
   217
sl@0
   218
EXPORT_C CPolicyServer::TCustomResult CPolicyServer::CustomSecurityCheckL(const RMessage2& /*aMsg*/, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
sl@0
   219
	{
sl@0
   220
	Panic(EPolSvrCallingBaseImplementation);
sl@0
   221
	return EFail;
sl@0
   222
	}
sl@0
   223
sl@0
   224
EXPORT_C void CPolicyServer::CheckFailedL(const RMessage2& aMsg, TInt aAction, const TSecurityInfo& aMissing)
sl@0
   225
	{
sl@0
   226
	if(aAction < 0)
sl@0
   227
		{
sl@0
   228
		TCustomResult result = CustomFailureActionL(aMsg, aAction, aMissing);
sl@0
   229
		if(result == EPass)
sl@0
   230
			ProcessL(aMsg);
sl@0
   231
		else if(result == EFail)
sl@0
   232
			aMsg.Complete(KErrPermissionDenied);
sl@0
   233
		else if(result == EAsync)
sl@0
   234
			{}
sl@0
   235
			//Do Nothing.  Derived CustomFailureActionL is responsible for
sl@0
   236
			//calling ProcessL/completing message with KErrPermissionDenied
sl@0
   237
		else
sl@0
   238
			Panic(EPolSvrInvalidCustomResult);
sl@0
   239
		}
sl@0
   240
	else if(aAction == EFailClient)
sl@0
   241
		{
sl@0
   242
		aMsg.Complete(KErrPermissionDenied);
sl@0
   243
		}
sl@0
   244
	else //if (aAction == EPanic) and all other +ve values
sl@0
   245
		{
sl@0
   246
		_LIT(KE32UserCBase, "E32USER-CBase");
sl@0
   247
		aMsg.Panic(KE32UserCBase, EPolSvrActionPanicClient);
sl@0
   248
		}
sl@0
   249
	}
sl@0
   250
sl@0
   251
EXPORT_C CPolicyServer::TCustomResult CPolicyServer::CustomFailureActionL(const RMessage2& /*aMsg*/, TInt /*aAction*/, const TSecurityInfo& /*aMissing*/)
sl@0
   252
	{
sl@0
   253
	Panic(EPolSvrCallingBaseImplementation);
sl@0
   254
	return EFail;
sl@0
   255
	}
sl@0
   256
sl@0
   257
const CPolicyServer::TPolicyElement* CPolicyServer::FindPolicyElement(TInt aFn, TUint& aSpecialCase) const
sl@0
   258
	{
sl@0
   259
	//Connect (aFn == -1) is handled through iPolicy.iOnConnect.  So aFn should
sl@0
   260
	//always be greater than -1.
sl@0
   261
	__ASSERT_DEBUG(aFn >= 0, User::Panic(KPolicyServer, 1));
sl@0
   262
sl@0
   263
	TUint l = 0;
sl@0
   264
	TUint u = iPolicy.iRangeCount;
sl@0
   265
	TUint m = 0;
sl@0
   266
	while(u > l)
sl@0
   267
		{
sl@0
   268
		m = (l+u) >> 1;
sl@0
   269
		if(iPolicy.iRanges[m] > aFn)
sl@0
   270
			u = m;
sl@0
   271
		else
sl@0
   272
			l = m + 1;
sl@0
   273
		}
sl@0
   274
	--l;
sl@0
   275
	//the mth element of iElementsIndex tells us the index in iElements
sl@0
   276
	//we want
sl@0
   277
	TUint8 i = iPolicy.iElementsIndex[l];
sl@0
   278
	//if the mth element of iElementsIndex is >= 250 -> Special Case
sl@0
   279
	if(i >= ESpecialCaseHardLimit)
sl@0
   280
		{
sl@0
   281
		aSpecialCase = i;
sl@0
   282
		return 0;
sl@0
   283
		}
sl@0
   284
	return &(iPolicy.iElements[i]);
sl@0
   285
	}
sl@0
   286
sl@0
   287
sl@0
   288
sl@0
   289
sl@0
   290
/**
sl@0
   291
Extension function
sl@0
   292
sl@0
   293
sl@0
   294
*/
sl@0
   295
EXPORT_C TInt CPolicyServer::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
sl@0
   296
	{
sl@0
   297
	return CServer2::Extension_(aExtensionId, a0, a1);
sl@0
   298
	}