os/security/authorisation/userpromptservice/examples/integration/tmsgserver/tmsgserver.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
* Example code
sl@0
    16
*
sl@0
    17
*/
sl@0
    18
sl@0
    19
sl@0
    20
#include "tmsgcommon.h"
sl@0
    21
#include "tmsgserver.h"
sl@0
    22
#include <e32cmn.h>
sl@0
    23
#include <e32debug.h>
sl@0
    24
sl@0
    25
inline CShutdown::CShutdown() :CTimer(-1) {CActiveScheduler::Add(this);}
sl@0
    26
inline void CShutdown::ConstructL() {CTimer::ConstructL();}
sl@0
    27
inline void CShutdown::Start() {After(KMyShutdownDelay);}
sl@0
    28
sl@0
    29
void CShutdown::RunL()
sl@0
    30
	{
sl@0
    31
	CActiveScheduler::Stop();
sl@0
    32
	}
sl@0
    33
sl@0
    34
sl@0
    35
// CMsgServer ****************************************************************
sl@0
    36
inline UserPromptService::RUpsSession& CMsgServer::Ups() {return iUps;}
sl@0
    37
sl@0
    38
const TInt CMsgServer::iRanges[KPolicyRanges] =
sl@0
    39
	{
sl@0
    40
	ESendMsg,			// network services requried
sl@0
    41
	ECancelSendMsg,		// no capability needed to request
sl@0
    42
	ESeperatorEndAll
sl@0
    43
	};
sl@0
    44
sl@0
    45
const TUint8 CMsgServer::iElementsIndex[KPolicyRanges] = 
sl@0
    46
	{
sl@0
    47
	0,								// capability check for networkservices
sl@0
    48
	EAlwaysPass,					// no check needed to cancel a request
sl@0
    49
	CPolicyServer::ENotSupported	
sl@0
    50
	};
sl@0
    51
sl@0
    52
static const TInt KMsgServerCustomFailureAction = -1;
sl@0
    53
sl@0
    54
const CPolicyServer::TPolicyElement CMsgServer::iPolicyElements[KPolicyElements] =
sl@0
    55
	{
sl@0
    56
	{_INIT_SECURITY_POLICY_C1(ECapabilityNetworkServices), KMsgServerCustomFailureAction}
sl@0
    57
	};
sl@0
    58
sl@0
    59
const CPolicyServer::TPolicy CMsgServer::iPolicy =
sl@0
    60
	{
sl@0
    61
	CPolicyServer::EAlwaysPass, // so that any client can connect	
sl@0
    62
	KPolicyRanges,									 
sl@0
    63
	iRanges,
sl@0
    64
	iElementsIndex,
sl@0
    65
	iPolicyElements,
sl@0
    66
	};
sl@0
    67
sl@0
    68
sl@0
    69
CMsgServer::CMsgServer()
sl@0
    70
	: CPolicyServer(EPriorityStandard, iPolicy, ESharableSessions)
sl@0
    71
	{
sl@0
    72
	}
sl@0
    73
sl@0
    74
CMsgServer::~CMsgServer()
sl@0
    75
	{
sl@0
    76
	iUps.Close();
sl@0
    77
	}
sl@0
    78
sl@0
    79
CMsgServer* CMsgServer::NewLC()
sl@0
    80
	{
sl@0
    81
	CMsgServer* self = new(ELeave) CMsgServer();
sl@0
    82
	CleanupStack::PushL(self);
sl@0
    83
	self->ConstructL();
sl@0
    84
	return self;
sl@0
    85
	}
sl@0
    86
sl@0
    87
void CMsgServer::ConstructL() 
sl@0
    88
	{
sl@0
    89
	// Create the RUpsSession
sl@0
    90
	// A sub-session is created for each client
sl@0
    91
	User::LeaveIfError(iUps.Connect());
sl@0
    92
sl@0
    93
	StartL(KMsgServerName);
sl@0
    94
	iShutdown.ConstructL();
sl@0
    95
	iShutdown.Start();	
sl@0
    96
	}
sl@0
    97
sl@0
    98
CPolicyServer::TCustomResult CMsgServer::CustomFailureActionL(const RMessage2& aMessage, TInt /*aAction*/, const TSecurityInfo& /*aMissing*/)
sl@0
    99
/** This function is only invoked for requests that allow UPS authorisation. The 
sl@0
   100
 * message may be rejected later if the user denies the request.
sl@0
   101
 */
sl@0
   102
	{
sl@0
   103
	CSession2* s = aMessage.Session();
sl@0
   104
	__ASSERT_ALWAYS(s != NULL, User::Invariant());
sl@0
   105
	CMsgServerSession* session = static_cast<CMsgServerSession*>(s);
sl@0
   106
	session->SetPlatsecResult(EFalse);	
sl@0
   107
	return CPolicyServer::EPass;	// The request may be rejected later by the UPS
sl@0
   108
	}
sl@0
   109
sl@0
   110
CSession2* CMsgServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
sl@0
   111
	{
sl@0
   112
	TVersion v(KMsgServerVersionMajor, KMsgServerVersionMinor, KMsgServerVersionBuild);
sl@0
   113
	if (!User::QueryVersionSupported(v,aVersion))
sl@0
   114
		{
sl@0
   115
		User::Leave(KErrNotSupported);		
sl@0
   116
		}
sl@0
   117
	return new(ELeave) CMsgServerSession();
sl@0
   118
	}
sl@0
   119
sl@0
   120
void CMsgServer::AddSession()
sl@0
   121
	{
sl@0
   122
	++iSessionCount;
sl@0
   123
	iShutdown.Cancel();
sl@0
   124
	}
sl@0
   125
sl@0
   126
void CMsgServer::DropSession()
sl@0
   127
	{
sl@0
   128
	if (--iSessionCount==0)	iShutdown.Start();
sl@0
   129
	}
sl@0
   130
sl@0
   131
void PanicClient(const RMessagePtr2& aMessage,TMsgServerPanic aPanic)
sl@0
   132
	{
sl@0
   133
	aMessage.Panic(KMsgServerName,aPanic);
sl@0
   134
	}
sl@0
   135
sl@0
   136
// CMsgServerSession *********************************************************
sl@0
   137
inline CMsgServer& CMsgServerSession::Server()
sl@0
   138
{return *static_cast<CMsgServer*>(const_cast<CServer2*>(CSession2::Server()));}
sl@0
   139
sl@0
   140
CMsgServerSession::CMsgServerSession()
sl@0
   141
	: iPlatsecResult(ETrue)
sl@0
   142
	{
sl@0
   143
	}
sl@0
   144
sl@0
   145
CMsgServerSession::~CMsgServerSession()
sl@0
   146
	{
sl@0
   147
	delete iProcessor;	
sl@0
   148
	iAuth.Close();
sl@0
   149
	Server().DropSession();
sl@0
   150
	}
sl@0
   151
sl@0
   152
void CMsgServerSession::CreateL()
sl@0
   153
	{
sl@0
   154
	Server().AddSession();
sl@0
   155
	iProcessor = CMsgProcessor::NewL(iAuth);
sl@0
   156
	}
sl@0
   157
sl@0
   158
void CMsgServerSession::ServiceL(const RMessage2& aMessage)
sl@0
   159
	{
sl@0
   160
	if (! iAuthInitialised)
sl@0
   161
		{
sl@0
   162
		RThread client;
sl@0
   163
		aMessage.ClientL(client);
sl@0
   164
		CleanupClosePushL(client);
sl@0
   165
		User::LeaveIfError(iAuth.Initialise(Server().Ups(), client));
sl@0
   166
		CleanupStack::PopAndDestroy(&client);
sl@0
   167
		iAuthInitialised = ETrue;
sl@0
   168
		}	
sl@0
   169
	
sl@0
   170
	iProcessor->ProcessL(aMessage, iPlatsecResult);
sl@0
   171
	// Reset to 'passed' for next message because SetPlatsecResult is only ever called
sl@0
   172
	// when a check fails.
sl@0
   173
	iPlatsecResult = ETrue;	
sl@0
   174
	}
sl@0
   175
sl@0
   176
void CMsgServerSession::SetPlatsecResult(TBool aResult)
sl@0
   177
	{
sl@0
   178
	iPlatsecResult = aResult;
sl@0
   179
	}
sl@0
   180
sl@0
   181
// CMsgProcessor *********************************************************((((
sl@0
   182
CMsgProcessor* CMsgProcessor::NewL(UserPromptService::RUpsSubsession& aAuth)
sl@0
   183
	{
sl@0
   184
	CMsgProcessor* self = new(ELeave) CMsgProcessor(aAuth);
sl@0
   185
	CleanupStack::PushL(self);
sl@0
   186
	self->ConstructL();
sl@0
   187
	CleanupStack::Pop(self);
sl@0
   188
	return self;
sl@0
   189
	}
sl@0
   190
sl@0
   191
CMsgProcessor::CMsgProcessor(UserPromptService::RUpsSubsession& aAuth)
sl@0
   192
	: CActive(EPriorityStandard), iState(EIdle), iAuth(aAuth)
sl@0
   193
	{
sl@0
   194
	CActiveScheduler::Add(this);
sl@0
   195
	}
sl@0
   196
sl@0
   197
void CMsgProcessor::ConstructL()
sl@0
   198
	{
sl@0
   199
	User::LeaveIfError(iTimer.CreateLocal());
sl@0
   200
	}
sl@0
   201
sl@0
   202
CMsgProcessor::~CMsgProcessor()
sl@0
   203
	{	
sl@0
   204
	Deque();
sl@0
   205
	Reset();
sl@0
   206
	iTimer.Close();
sl@0
   207
	}
sl@0
   208
sl@0
   209
TInt CMsgProcessor::RunError(TInt aError)
sl@0
   210
	{
sl@0
   211
	if (iState != EIdle) iMessage.Complete(aError);
sl@0
   212
sl@0
   213
	Reset();
sl@0
   214
	return KErrNone;
sl@0
   215
	}
sl@0
   216
sl@0
   217
void CMsgProcessor::Reset() 
sl@0
   218
/**
sl@0
   219
 * Resets the processor for the next message.
sl@0
   220
 */
sl@0
   221
	{
sl@0
   222
	iMsgTo.Close();
sl@0
   223
	iMsgBody.Close();
sl@0
   224
	iState = EIdle;
sl@0
   225
	}
sl@0
   226
sl@0
   227
void CMsgProcessor::RunL()
sl@0
   228
	{
sl@0
   229
	User::LeaveIfError(iStatus.Int());
sl@0
   230
	switch (iState)
sl@0
   231
		{
sl@0
   232
		case EAuthorising:			
sl@0
   233
			// Check whether the request was authorised before proceeding
sl@0
   234
			if (iDecision == EUpsDecSessionNo || iDecision == EUpsDecNo)
sl@0
   235
				{ // The user or UPS denied the client's request so fail with security error.				  
sl@0
   236
				iMessage.Complete(KErrPermissionDenied);
sl@0
   237
				Reset();
sl@0
   238
				}
sl@0
   239
			else
sl@0
   240
				{ // Request authorised so carry on as normal
sl@0
   241
				SendL();	
sl@0
   242
				}
sl@0
   243
			break;
sl@0
   244
		case ESending:						
sl@0
   245
			// Message send so complete request and return
sl@0
   246
			iMessage.Complete(KErrNone);
sl@0
   247
			Reset();
sl@0
   248
			break;
sl@0
   249
		default: // invalid state - should never happen
sl@0
   250
			__ASSERT_ALWAYS(EFalse, User::Invariant()); 
sl@0
   251
			break;
sl@0
   252
		}
sl@0
   253
	}
sl@0
   254
sl@0
   255
void CMsgProcessor::DoCancel()
sl@0
   256
	{
sl@0
   257
	switch (iState)
sl@0
   258
		{
sl@0
   259
		case EIdle:
sl@0
   260
			break; // nothing to do
sl@0
   261
		case EAuthorising:
sl@0
   262
			iAuth.CancelPrompt();			
sl@0
   263
			break;
sl@0
   264
		case ESending:
sl@0
   265
			iTimer.Cancel();
sl@0
   266
			break;
sl@0
   267
		default: // invalid state - should never happen
sl@0
   268
			__ASSERT_ALWAYS(EFalse, User::Invariant());
sl@0
   269
		}
sl@0
   270
	if (iState != EIdle) iMessage.Complete(KErrCancel);
sl@0
   271
	Reset();
sl@0
   272
	}
sl@0
   273
sl@0
   274
void CMsgProcessor::GetParamsL(const RMessage2& aMessage)
sl@0
   275
/**
sl@0
   276
 * Reads the parameters for sending a message. This data is also needed for the authorisation prompt
sl@0
   277
 */
sl@0
   278
	{
sl@0
   279
	TInt l = aMessage.GetDesLength(0);
sl@0
   280
	if (l <= 0) User::Leave(KErrArgument);
sl@0
   281
	iMsgTo.CreateL(l);
sl@0
   282
	aMessage.ReadL(0, iMsgTo);
sl@0
   283
	l = aMessage.GetDesLength(1);
sl@0
   284
	if (l <= 0) User::Leave(KErrArgument);
sl@0
   285
	iMsgBody.CreateL(l);
sl@0
   286
	aMessage.ReadL(1, iMsgBody);
sl@0
   287
	}
sl@0
   288
sl@0
   289
void CMsgProcessor::AuthoriseL(const RMessage2& aMessage, TBool aPlatsecResult)
sl@0
   290
/**
sl@0
   291
 * Implementation of the new authorisation state
sl@0
   292
 * @param	aMessage		The message handle containing the SendMsg parameters
sl@0
   293
 * @param	aPlatsecResult	Whether the client has the correct capabilities etc
sl@0
   294
 */
sl@0
   295
	{
sl@0
   296
	iState = EAuthorising;
sl@0
   297
	iPlatsecResult = aPlatsecResult;
sl@0
   298
	iMessage = aMessage;
sl@0
   299
	GetParamsL(iMessage);	// message parameters are used to identify the request 
sl@0
   300
	iAuth.Authorise(iPlatsecResult, TUid::Uid(KServiceId), iMsgTo, iDecision, iStatus);
sl@0
   301
	SetActive();
sl@0
   302
	}
sl@0
   303
sl@0
   304
void CMsgProcessor::SendL() 
sl@0
   305
/**
sl@0
   306
 * Simulatate the sending of a message by displaying the body
sl@0
   307
 * to the screen and waiting for three seconds.
sl@0
   308
 * 
sl@0
   309
 * No changes necessary to support user prompts.
sl@0
   310
 */
sl@0
   311
	{
sl@0
   312
	iState = ESending;
sl@0
   313
	HBufC* tmp = HBufC::NewMaxLC(iMsgTo.Length() + iMsgBody.Length() + 3);
sl@0
   314
	tmp->Des().Format(_L("%S: %S"), &iMsgTo, &iMsgBody);
sl@0
   315
	User::LeaveIfError(User::InfoPrint(*tmp));
sl@0
   316
	CleanupStack::PopAndDestroy(tmp);
sl@0
   317
	iTimer.After(iStatus, 3 * 1000 * 1000);
sl@0
   318
	SetActive();
sl@0
   319
	}
sl@0
   320
sl@0
   321
void CMsgProcessor::ProcessL(const RMessage2& aMessage, TBool aPlatsecResult)
sl@0
   322
	{
sl@0
   323
	switch (aMessage.Function())
sl@0
   324
		{
sl@0
   325
		case ESendMsg:
sl@0
   326
			if (iState == EIdle)
sl@0
   327
				{ // The first state is now authorisation				
sl@0
   328
				AuthoriseL(aMessage, aPlatsecResult);
sl@0
   329
				}
sl@0
   330
			else
sl@0
   331
				{ // Concurrent requests not supported
sl@0
   332
				aMessage.Complete(KErrInUse); 
sl@0
   333
				}
sl@0
   334
			break;
sl@0
   335
		case ECancelSendMsg:
sl@0
   336
			Cancel();
sl@0
   337
			aMessage.Complete(KErrNone);
sl@0
   338
			break;
sl@0
   339
		default:
sl@0
   340
			User::Leave(KErrNotSupported);
sl@0
   341
		}
sl@0
   342
	}
sl@0
   343
sl@0
   344
static void RunServerL()
sl@0
   345
	{
sl@0
   346
	// normal server startup code
sl@0
   347
	User::LeaveIfError(RThread::RenameMe(KMsgServerName));
sl@0
   348
	CActiveScheduler* s=new(ELeave) CActiveScheduler;
sl@0
   349
	CleanupStack::PushL(s);
sl@0
   350
	CActiveScheduler::Install(s);	
sl@0
   351
	CMsgServer::NewLC();
sl@0
   352
	RProcess::Rendezvous(KErrNone);
sl@0
   353
	CActiveScheduler::Start();
sl@0
   354
	CleanupStack::PopAndDestroy(2, s); 
sl@0
   355
	}
sl@0
   356
sl@0
   357
TInt E32Main()
sl@0
   358
	{
sl@0
   359
	__UHEAP_MARK;
sl@0
   360
	CTrapCleanup* cleanup=CTrapCleanup::New();
sl@0
   361
	TInt r=KErrNoMemory;
sl@0
   362
	if (cleanup)
sl@0
   363
		{
sl@0
   364
		TRAP(r,RunServerL());
sl@0
   365
		delete cleanup;
sl@0
   366
		}
sl@0
   367
	__UHEAP_MARKEND;
sl@0
   368
	return r;
sl@0
   369
	}
sl@0
   370