Symbian3/SDK/Source/GUID-85D9878E-4FEF-5E45-9F87-53634CD171E0.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 7 51a74ef9ed63
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-85D9878E-4FEF-5E45-9F87-53634CD171E0" xml:lang="en"><title>Integrating
a System Server with UPS</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<section id="GUID-78B46051-E035-4798-9A4D-B274D4783164"><title>Introduction</title> <p>User Prompt Service (UPS) functionality
is provided by the server process <filepath>upsserver.exe</filepath>. The
process starts on demand when system servers make calls to the UPS client
library. Only applications with a capability of <codeph>ProtServ</codeph> or
higher can access <filepath>upsserver.exe</filepath>. </p> <p>A system server
should only invoke the UPS for security decisions that a typical phone user
will understand (For example, it is inappropriate to ask the user for permission
to change a low level network setting.) . </p> <p>Device creators can write
a system server that invokes the UPS, if a compatible dialog creator is available
and the policies are delivered in an appropriately signed SIS file. They can
also write a policy evaluator, but a default policy evaluator is provided
by the Symbian platform. </p> <p>If the device creators do not
specify any policy file, the UPS uses the platform security check results
to decide whether to access requested services. Thus not supplying policy
files effectively turns UPS off. </p> </section>
<section id="GUID-718CF580-05FE-4F75-A7D8-4487C35675B6"><title>Required background</title><p id="GUID-9C6EBADD-175A-5122-90C4-CED8A9855BAB"><b>Configuring
the system server</b> </p> <p>For each system server that accesses the UPS,
you need to do the following: </p> <ol id="GUID-D14BDAE1-BD62-530E-B3C4-2FA380BDBDC5">
<li id="GUID-090CE65B-44BF-54CF-8961-69059655C5F5"><p>Create one <codeph>RUpsSession</codeph> per
server. </p> <p>Typically, an <codeph>RUpsSubession</codeph> object is created
for each connection by a client to the system server and can only have one
outstanding call to <xref href="GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74.dita#GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74/GUID-82C3C51A-F785-3DBA-910A-47CAF47B39F6"><apiname>RUpsSubsession::Authorise()</apiname></xref>. </p> </li>
<li id="GUID-61E4A569-F5C3-593C-9954-2803E822F0BF"><p> <xref href="GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74.dita#GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74/GUID-82C3C51A-F785-3DBA-910A-47CAF47B39F6"><apiname>RUpsSubsession::Authorise()</apiname></xref> completes
immediately and uses the result of its <codeph>aServerCheckOk</codeph> parameter
to set its <codeph>aDecision</codeph> parameter, if a policy file is not defined
for a service. Therefore, the default behaviour of an unconfigured UPS is
compatible with the existing platform security implementation. </p> </li>
<li id="GUID-035F2AEE-95B8-5085-9079-A4B8A6EC9B6A"><p>Close each <xref href="GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74.dita"><apiname>RUpsSubsession</apiname></xref>. </p> </li>
</ol><p id="GUID-75BD33B9-28AC-55CD-BF3E-7F62A8D039EB"><b>Considerations</b> </p> <p>Consider
the following points before integrating the UPS to a system server </p> <ul>
<li id="GUID-11A0A48F-47A3-5A89-9925-8FBAB3F5D8DE"><p>Even though the APIs
for the UPS are relatively small, the integration is slightly more complicated
than might be expected. This is because existing synchronous security checks
must become asynchronous since interaction with the device user is inherently
an asynchronous operation. For example, it would be undesirable to block the
entire comms server while waiting for the user to respond to a dialog. </p> </li>
<li id="GUID-747A3037-13E6-5895-895E-F700368A81B6"><p>Provide an informed
security decision the user may need to know about the request they are authorizing.
Consequently, it may be necessary to extract the parameters from the client
application at the security check stage. </p> </li>
<li id="GUID-27A11CBD-BBB5-5D32-8207-D01D207FEC9E"><p>Finally, depending on
the service and the security requirements of the manufacturer, an operator
user prompts may be in addition to the platform security (e.g. capabilities)
checks. Alternatively, user prompts could be used to allow applications without
capabilities limited access to a protected service. Because most implementations
of the <codeph>CPolicyServer</codeph> fail the client immediately if the platsec
check fails these checks may have to be modified. </p> </li>
</ul><p> <b>Note</b>: For an example of how to include the above, see the
example code later in this document. </p></section>
<section id="GUID-3C0A43C1-1CEF-4C0F-83A6-64B3EF73E955"><title>Integration of UPS</title> <p>If the system server uses the <codeph>CPolicyServer</codeph> framework,
there are three candidates for the main integration point. </p> <table id="GUID-BBE389D8-77A0-52BA-910D-368BAC25DCC3">
<tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
<tbody>
<row>
<entry><p>Function </p> </entry>
<entry><p>Description </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-5BDFF5B1-DC1F-393A-879B-9D8DE080B4E2.dita#GUID-5BDFF5B1-DC1F-393A-879B-9D8DE080B4E2/GUID-49DDDDAC-B256-3B43-B059-EE369EAEA2BB"><apiname>CPolicyServer::CustomSecurityCheckL()</apiname></xref>  </p> </entry>
<entry><p>This allows an arbitrary and even asynchronous check to be made
instead of using static security policies. </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-5BDFF5B1-DC1F-393A-879B-9D8DE080B4E2.dita#GUID-5BDFF5B1-DC1F-393A-879B-9D8DE080B4E2/GUID-93C9B0EE-8B94-3A95-BBA7-5B1C8BED6E28"><apiname> CPolicyServer::CustomFailureActionL()</apiname></xref>  </p> </entry>
<entry><p>This virtual method is invoked if the client fails the static security
checks. The failure may be overridden or deferred. Asynchronous operations
are possible. </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-D5A30C75-E22C-34E8-913B-7D2CA6AD5C51.dita#GUID-D5A30C75-E22C-34E8-913B-7D2CA6AD5C51/GUID-B37413F7-D8FD-35AD-A037-99023D7CE986"><apiname> CSession2::ServiceL()</apiname></xref>  </p> </entry>
<entry><p>The static policy checks could be deferred until the session is
created provided that the server connection API is not guarded by user prompts. </p> </entry>
</row>
</tbody>
</tgroup>
</table> <p>Use one or a combination of above functions as required to implement
UPS APIs </p><p><b>Procedure</b> </p> <p>This demonstrates how user permission
prompt support (UPS) may be added to a system server. </p> <ol id="GUID-BC8CDF54-101F-563E-BA74-7DE871A93782">
<li id="GUID-55A1C176-857B-539F-81F1-66FCDEDEF299"><p>An <codeph>RUpsSession</codeph> object
has been added to the <codeph>CMsgServer</codeph> class. This is initialized
at startup. </p> </li>
<li id="GUID-8DD68273-846D-568A-A7BE-330523722503"><p> <xref href="GUID-AB9191BA-9E9B-3ED8-9968-4E43C1803C0D.dita#GUID-AB9191BA-9E9B-3ED8-9968-4E43C1803C0D/GUID-6A3E9888-EA11-3352-A634-946C66A3946C"><apiname>CMsgServer::iPolicyElements</apiname></xref> was
changed to cause <codeph>CustomFailureActionL</codeph> to be invoked if the
static security policy check fails instead of failing the client. </p> </li>
<li id="GUID-C2AF0E9B-C46A-59E4-ADB7-21D2018582DD"><p> <xref href="GUID-AB9191BA-9E9B-3ED8-9968-4E43C1803C0D.dita#GUID-AB9191BA-9E9B-3ED8-9968-4E43C1803C0D/GUID-3498AEBD-A092-3D0B-98EB-50A1B9DC65B5"><apiname>CMsgServer::CustomFailureActionL()</apiname></xref> notifies
the session object that the platsec check failed. This is important because <xref href="GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74.dita#GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74/GUID-82C3C51A-F785-3DBA-910A-47CAF47B39F6"><apiname>RUpsSubsession::Authorise()</apiname></xref> requires
this information to allow unconfigured systems to be compatible with platsec.
It also increases the flexibility of the UPS policy definitions. </p> </li>
<li id="GUID-63A4E019-BDFF-5B37-993B-3ED8233EC781"><p>An <codeph>RUpsSubsession</codeph> instance
is created for each <codeph>CSession2</codeph> object, i.e. requests from
different clients are authorized independently. This could be modified so
that there is one UPS sub-session for each client process instead of each
connection from a client process. </p> </li>
<li id="GUID-82211891-BA54-501F-9E81-D6D78C4476E7"><p>An extra state (<codeph>iAuthorising</codeph>)
is added at the start of the CMsgProcessor state machine. </p> </li>
<li id="GUID-EC85BB4D-83B9-5AF0-9A19-818B6AD4CE6C"><p>The <codeph>RMessage2</codeph> parameters
from the client API are now extracted in the authorization stage to enable
the information to be passed to the UPS. </p> </li>
<li id="GUID-91D30A49-B703-5E01-BAC9-F9205DB9BAA2"><p> <xref href="GUID-C4092739-2792-3411-90CC-174398AE4A4C.dita#GUID-C4092739-2792-3411-90CC-174398AE4A4C/GUID-9DE31D77-70B7-3072-A602-75D995749DB3"><apiname>CMsgProcessor::DoCancel</apiname></xref> is
updated to cancel the call to <xref href="GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74.dita#GUID-1C63BE5E-6F66-38CB-931E-B2C51309CB74/GUID-06BF925F-53C1-33D4-97F3-46ECB10CC27F"><apiname>RUpsSubsession::Authorise</apiname></xref>,
if the client cancels the sending of the message or disconnects. </p> </li>
<li id="GUID-684BEA9C-B6F7-5369-A243-9D0689BBD421"><p> <xref href="GUID-C4092739-2792-3411-90CC-174398AE4A4C.dita#GUID-C4092739-2792-3411-90CC-174398AE4A4C/GUID-013B385A-2A30-36D6-990A-873CF329F9E7"><apiname>CMsgProcessor::RunL</apiname></xref> now
checks whether the request was authorized before changing from the authorization
to the sending state. </p> </li>
</ol> <p>The following code snippet explains how the UPS APIs can be called. </p> <codeblock id="GUID-1B2C7094-BFA3-5C49-ABDB-4721BC71D8CE" xml:space="preserve">

using namespace UserPromptService;

TUpsDecision AuthoriseL(RThread &amp;aClientThread, TDesC aDestination)
    {
 // Create and connect the session.
 // In a real server this should be done once at server startup as it is a relatively
 // expensive operation.
 RUpsSession session;
 User::LeaveIfError(session.Connect());
 CleanupClosePushL(session);

 // Initialise the subsession
 // One of these is required per a concurrent Authorise request.
 // Note that it only connects to the UPS if it has to.
    RUpsSubsession subsession;
 subsession.Initialise(session, aClientThread);
 CleanupClosePushL(subsession);

 TServiceId serviceId = {43};
 // Out "service id", typically a constant
 // Variable for the result, typically a member variable because it must exist until
 // the Authorise request completes.
 TUpsDecision decision = EUpsDecYes;

 // Issue the Authorise request
 TRequestStatus rs;
 subsession.Authorise(EFalse, // Did out platsec checks pass?
                         serviceId, 
                         aDestination, 
                         decision, 
                         rs); // Would typically be the iStatus of a CActive object

    // Wait for the request to complete
 User::WaitForRequest(rs);

 CleanupStack::PopAndDestroy(&amp;subsession);
 CleanupStack::PopAndDestroy(&amp;session);
 return decision;
 }


TInt E32Main()
 {
 __UHEAP_MARK;

 // allocating a cleanup stack also installs it
 CTrapCleanup* tc = CTrapCleanup::New();
 if (tc == 0)
  return KErrNoMemory;

 RThread thd;
 TRAPD(err, AuthoriseL(thd, _L("destination")));
 if(err != KErrNone)
  {
  User::Panic(_L("example failed: "), err);
  }
 delete tc;

 __UHEAP_MARKEND;
 return KErrNone;
 }
</codeblock> </section>
</conbody></concept>