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