|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-85D9878E-4FEF-5E45-9F87-53634CD171E0" xml:lang="en"><title>Integrating |
|
13 a System Server with UPS</title><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <section id="GUID-78B46051-E035-4798-9A4D-B274D4783164"><title>Introduction</title> <p>User Prompt Service (UPS) functionality |
|
15 is provided by the server process <filepath>upsserver.exe</filepath>. The |
|
16 process starts on demand when system servers make calls to the UPS client |
|
17 library. Only applications with a capability of <codeph>ProtServ</codeph> or |
|
18 higher can access <filepath>upsserver.exe</filepath>. </p> <p>A system server |
|
19 should only invoke the UPS for security decisions that a typical phone user |
|
20 will understand (For example, it is inappropriate to ask the user for permission |
|
21 to change a low level network setting.) . </p> <p>Device creators can write |
|
22 a system server that invokes the UPS, if a compatible dialog creator is available |
|
23 and the policies are delivered in an appropriately signed SIS file. They can |
|
24 also write a policy evaluator, but a default policy evaluator is provided |
|
25 by the Symbian platform. </p> <p>If the device creators do not |
|
26 specify any policy file, the UPS uses the platform security check results |
|
27 to decide whether to access requested services. Thus not supplying policy |
|
28 files effectively turns UPS off. </p> </section> |
|
29 <section id="GUID-718CF580-05FE-4F75-A7D8-4487C35675B6"><title>Required background</title><p id="GUID-9C6EBADD-175A-5122-90C4-CED8A9855BAB"><b>Configuring |
|
30 the system server</b> </p> <p>For each system server that accesses the UPS, |
|
31 you need to do the following: </p> <ol id="GUID-D14BDAE1-BD62-530E-B3C4-2FA380BDBDC5"> |
|
32 <li id="GUID-090CE65B-44BF-54CF-8961-69059655C5F5"><p>Create one <codeph>RUpsSession</codeph> per |
|
33 server. </p> <p>Typically, an <codeph>RUpsSubession</codeph> object is created |
|
34 for each connection by a client to the system server and can only have one |
|
35 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> |
|
36 <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 |
|
37 immediately and uses the result of its <codeph>aServerCheckOk</codeph> parameter |
|
38 to set its <codeph>aDecision</codeph> parameter, if a policy file is not defined |
|
39 for a service. Therefore, the default behaviour of an unconfigured UPS is |
|
40 compatible with the existing platform security implementation. </p> </li> |
|
41 <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> |
|
42 </ol><p id="GUID-75BD33B9-28AC-55CD-BF3E-7F62A8D039EB"><b>Considerations</b> </p> <p>Consider |
|
43 the following points before integrating the UPS to a system server </p> <ul> |
|
44 <li id="GUID-11A0A48F-47A3-5A89-9925-8FBAB3F5D8DE"><p>Even though the APIs |
|
45 for the UPS are relatively small, the integration is slightly more complicated |
|
46 than might be expected. This is because existing synchronous security checks |
|
47 must become asynchronous since interaction with the device user is inherently |
|
48 an asynchronous operation. For example, it would be undesirable to block the |
|
49 entire comms server while waiting for the user to respond to a dialog. </p> </li> |
|
50 <li id="GUID-747A3037-13E6-5895-895E-F700368A81B6"><p>Provide an informed |
|
51 security decision the user may need to know about the request they are authorizing. |
|
52 Consequently, it may be necessary to extract the parameters from the client |
|
53 application at the security check stage. </p> </li> |
|
54 <li id="GUID-27A11CBD-BBB5-5D32-8207-D01D207FEC9E"><p>Finally, depending on |
|
55 the service and the security requirements of the manufacturer, an operator |
|
56 user prompts may be in addition to the platform security (e.g. capabilities) |
|
57 checks. Alternatively, user prompts could be used to allow applications without |
|
58 capabilities limited access to a protected service. Because most implementations |
|
59 of the <codeph>CPolicyServer</codeph> fail the client immediately if the platsec |
|
60 check fails these checks may have to be modified. </p> </li> |
|
61 </ul><p> <b>Note</b>: For an example of how to include the above, see the |
|
62 example code later in this document. </p></section> |
|
63 <section id="GUID-3C0A43C1-1CEF-4C0F-83A6-64B3EF73E955"><title>Integration of UPS</title> <p>If the system server uses the <codeph>CPolicyServer</codeph> framework, |
|
64 there are three candidates for the main integration point. </p> <table id="GUID-BBE389D8-77A0-52BA-910D-368BAC25DCC3"> |
|
65 <tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/> |
|
66 <tbody> |
|
67 <row> |
|
68 <entry><p>Function </p> </entry> |
|
69 <entry><p>Description </p> </entry> |
|
70 </row> |
|
71 <row> |
|
72 <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> |
|
73 <entry><p>This allows an arbitrary and even asynchronous check to be made |
|
74 instead of using static security policies. </p> </entry> |
|
75 </row> |
|
76 <row> |
|
77 <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> |
|
78 <entry><p>This virtual method is invoked if the client fails the static security |
|
79 checks. The failure may be overridden or deferred. Asynchronous operations |
|
80 are possible. </p> </entry> |
|
81 </row> |
|
82 <row> |
|
83 <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> |
|
84 <entry><p>The static policy checks could be deferred until the session is |
|
85 created provided that the server connection API is not guarded by user prompts. </p> </entry> |
|
86 </row> |
|
87 </tbody> |
|
88 </tgroup> |
|
89 </table> <p>Use one or a combination of above functions as required to implement |
|
90 UPS APIs </p><p><b>Procedure</b> </p> <p>This demonstrates how user permission |
|
91 prompt support (UPS) may be added to a system server. </p> <ol id="GUID-BC8CDF54-101F-563E-BA74-7DE871A93782"> |
|
92 <li id="GUID-55A1C176-857B-539F-81F1-66FCDEDEF299"><p>An <codeph>RUpsSession</codeph> object |
|
93 has been added to the <codeph>CMsgServer</codeph> class. This is initialized |
|
94 at startup. </p> </li> |
|
95 <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 |
|
96 changed to cause <codeph>CustomFailureActionL</codeph> to be invoked if the |
|
97 static security policy check fails instead of failing the client. </p> </li> |
|
98 <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 |
|
99 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 |
|
100 this information to allow unconfigured systems to be compatible with platsec. |
|
101 It also increases the flexibility of the UPS policy definitions. </p> </li> |
|
102 <li id="GUID-63A4E019-BDFF-5B37-993B-3ED8233EC781"><p>An <codeph>RUpsSubsession</codeph> instance |
|
103 is created for each <codeph>CSession2</codeph> object, i.e. requests from |
|
104 different clients are authorized independently. This could be modified so |
|
105 that there is one UPS sub-session for each client process instead of each |
|
106 connection from a client process. </p> </li> |
|
107 <li id="GUID-82211891-BA54-501F-9E81-D6D78C4476E7"><p>An extra state (<codeph>iAuthorising</codeph>) |
|
108 is added at the start of the CMsgProcessor state machine. </p> </li> |
|
109 <li id="GUID-EC85BB4D-83B9-5AF0-9A19-818B6AD4CE6C"><p>The <codeph>RMessage2</codeph> parameters |
|
110 from the client API are now extracted in the authorization stage to enable |
|
111 the information to be passed to the UPS. </p> </li> |
|
112 <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 |
|
113 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>, |
|
114 if the client cancels the sending of the message or disconnects. </p> </li> |
|
115 <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 |
|
116 checks whether the request was authorized before changing from the authorization |
|
117 to the sending state. </p> </li> |
|
118 </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"> |
|
119 |
|
120 using namespace UserPromptService; |
|
121 |
|
122 TUpsDecision AuthoriseL(RThread &aClientThread, TDesC aDestination) |
|
123 { |
|
124 // Create and connect the session. |
|
125 // In a real server this should be done once at server startup as it is a relatively |
|
126 // expensive operation. |
|
127 RUpsSession session; |
|
128 User::LeaveIfError(session.Connect()); |
|
129 CleanupClosePushL(session); |
|
130 |
|
131 // Initialise the subsession |
|
132 // One of these is required per a concurrent Authorise request. |
|
133 // Note that it only connects to the UPS if it has to. |
|
134 RUpsSubsession subsession; |
|
135 subsession.Initialise(session, aClientThread); |
|
136 CleanupClosePushL(subsession); |
|
137 |
|
138 TServiceId serviceId = {43}; |
|
139 // Out "service id", typically a constant |
|
140 // Variable for the result, typically a member variable because it must exist until |
|
141 // the Authorise request completes. |
|
142 TUpsDecision decision = EUpsDecYes; |
|
143 |
|
144 // Issue the Authorise request |
|
145 TRequestStatus rs; |
|
146 subsession.Authorise(EFalse, // Did out platsec checks pass? |
|
147 serviceId, |
|
148 aDestination, |
|
149 decision, |
|
150 rs); // Would typically be the iStatus of a CActive object |
|
151 |
|
152 // Wait for the request to complete |
|
153 User::WaitForRequest(rs); |
|
154 |
|
155 CleanupStack::PopAndDestroy(&subsession); |
|
156 CleanupStack::PopAndDestroy(&session); |
|
157 return decision; |
|
158 } |
|
159 |
|
160 |
|
161 TInt E32Main() |
|
162 { |
|
163 __UHEAP_MARK; |
|
164 |
|
165 // allocating a cleanup stack also installs it |
|
166 CTrapCleanup* tc = CTrapCleanup::New(); |
|
167 if (tc == 0) |
|
168 return KErrNoMemory; |
|
169 |
|
170 RThread thd; |
|
171 TRAPD(err, AuthoriseL(thd, _L("destination"))); |
|
172 if(err != KErrNone) |
|
173 { |
|
174 User::Panic(_L("example failed: "), err); |
|
175 } |
|
176 delete tc; |
|
177 |
|
178 __UHEAP_MARKEND; |
|
179 return KErrNone; |
|
180 } |
|
181 </codeblock> </section> |
|
182 </conbody></concept> |