|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Wrapper around RMessage2 that provides message validation and error handling |
|
15 // to improve robustness of system servers under IPC attack |
|
16 // |
|
17 // |
|
18 |
|
19 #if !defined(CLIENTMESSAGE_H) |
|
20 #define CLIENTMESSAGE_H |
|
21 |
|
22 #include <e32std.h> |
|
23 #include <e32base.h> |
|
24 #include <e32debug.h> |
|
25 #include <babitflags.h> |
|
26 |
|
27 namespace BSUL |
|
28 { |
|
29 |
|
30 //Version number of the client server framework code |
|
31 const TInt KClientMessageVersion = 0x1; |
|
32 |
|
33 //Forward Declarations |
|
34 class CMessageParameterBase; |
|
35 |
|
36 //Const Declarations |
|
37 |
|
38 /** |
|
39 Returned to caller to indicate that the requested message number is not |
|
40 supported by the current server |
|
41 @publishedPartner |
|
42 @released |
|
43 */ |
|
44 const TInt KErrInvalidFunction = -1004; |
|
45 |
|
46 /** |
|
47 Returned to caller if a message is passed in containing a non-descriptor |
|
48 parameter which doesn't meet the constraints specified in the schema |
|
49 @publishedPartner |
|
50 @released |
|
51 */ |
|
52 const TInt KErrBadParameter = -1005; |
|
53 |
|
54 /** |
|
55 Returned to caller in UREL mode when the server attempts to call a |
|
56 CMessageParameterBase function which is not defined for the given |
|
57 parameter type. E.g. calling GetIntL() on a Descriptor parameter. |
|
58 @publishedPartner |
|
59 @released |
|
60 */ |
|
61 const TInt KErrWrongParameterType = -1006; |
|
62 |
|
63 /** |
|
64 Returned to caller in UREL mode when a message is found to be |
|
65 incorrectly defined in the message schema. |
|
66 @publishedPartner |
|
67 @released |
|
68 */ |
|
69 const TInt KErrBadMessageSchema = -1007; |
|
70 |
|
71 |
|
72 /** |
|
73 Returned to caller to indicate that the requested parameter has not yet |
|
74 been validated |
|
75 @publishedPartner |
|
76 @released |
|
77 */ |
|
78 const TInt KErrNotValidated = -1008; //Server internal error |
|
79 |
|
80 /** |
|
81 Returned to caller to indicate that the ClientMessage framework has |
|
82 not yet been initialised |
|
83 @publishedPartner |
|
84 @released |
|
85 */ |
|
86 const TInt KErrNotInitialised = -1009; //Server internal error |
|
87 |
|
88 |
|
89 //Enum Declarations |
|
90 |
|
91 /** |
|
92 This is the list of Panic codes used by the ClientMessage framework |
|
93 @publishedPartner |
|
94 @released |
|
95 */ |
|
96 enum |
|
97 { |
|
98 /**This panic is raised in UDEB mode when the server attempts to call a |
|
99 CMessageParameterBase function which is not defined for the given |
|
100 parameter type. E.g. calling GetIntL() on a Descriptor parameter. |
|
101 */ |
|
102 ECMPanicWrongParameterType = 0, |
|
103 |
|
104 /**This panic is raised when the server attempts to read from a |
|
105 descriptor in the clients process and supplies a target descriptor |
|
106 that is smaller than the client descriptor. |
|
107 */ |
|
108 ECMPanicBadDescriptor, |
|
109 |
|
110 /**This panic is raised when a TParameterDetails structure for a |
|
111 given parameter is incorrectly defined in the message schema |
|
112 */ |
|
113 ECMPanicBadMessageSchema |
|
114 }; |
|
115 |
|
116 /** |
|
117 This Enum lists the currently supported Parameter types. |
|
118 These enum values are used as indices to the Parameter Factory Function |
|
119 which instantiates the appropriate CMessageParammeterBase derived |
|
120 object to represent a given message parameter. |
|
121 @publishedPartner |
|
122 @released |
|
123 */ |
|
124 enum TParamType |
|
125 { |
|
126 EParamNull = 0, |
|
127 EParamInt, |
|
128 EParamDes8Read, |
|
129 EParamDes8, |
|
130 EParamPckg, |
|
131 EParamDes16Read, |
|
132 EParamDes16, |
|
133 EParamPtr |
|
134 }; |
|
135 |
|
136 /** |
|
137 This enum lists the currently supported flags that can be passed to the server |
|
138 in TClientMessageServerData::iFlags. Note that internally this value is stored |
|
139 in a TBitFlags32 type but this type cannot be statically initialised in a dll |
|
140 so the value is passed to the framework in a TInt. The bottom 16 bit flags are |
|
141 reserved for the framework's internal use. |
|
142 |
|
143 @publishedPartner |
|
144 @released |
|
145 */ |
|
146 enum TServerFlags |
|
147 { |
|
148 /** Default empty flag */ |
|
149 ESrvFlagNone = 0, |
|
150 /** Setting this flag indicates that for bad message errors, request |
|
151 should be completed with error code rather than panicking the client */ |
|
152 ESrvFlagDoNotPanicClientOnBadMessageErrors = 0x40000000, |
|
153 /** Indicates that bad messages should be logged in UDEB */ |
|
154 ESrvFlagLogBadMessages = 0x80000000 |
|
155 }; |
|
156 |
|
157 //Typedef Declarations |
|
158 |
|
159 /** |
|
160 This typedef is used to simplify the declaration of custom |
|
161 parameter validation functions |
|
162 @publishedPartner |
|
163 @released |
|
164 */ |
|
165 typedef void (*TCustomValidationFn)(CMessageParameterBase* aParameter); |
|
166 |
|
167 |
|
168 |
|
169 //Struct Declarations |
|
170 |
|
171 /** |
|
172 This structure defines the format for storing information for an |
|
173 individual message parameter. |
|
174 |
|
175 iType - This defines the parameter type and is used by the CMessageParameterBase |
|
176 class to instantiate the appropriate derived class via the |
|
177 KParameterFactoryFunctions factory lookup table. |
|
178 |
|
179 iMin, iMax - These are two constraints that are used in the ValidateL |
|
180 method of a class derived from CMessageParameter to validate the message |
|
181 as required by that parameter. |
|
182 The constraints that are used depend on the type as follows: |
|
183 EParamInt: |
|
184 -iMin = Minimum int value accepted |
|
185 -iMax = Maximum int value accepted. This must be > iMin |
|
186 |
|
187 NOTE: Currently unsigned integers are not explicitly supported, |
|
188 however 16 bit unsigned integers are implicitly supported |
|
189 by the EParamInt type. Note that the constraint above |
|
190 (iMax > iMin) means that the maximum supported value for an |
|
191 unsigned int is 0x7FFFFFFF. |
|
192 |
|
193 EParamDes8Read: |
|
194 EParamDes16Read: |
|
195 -iMin = Minimum length of descriptor in clients address space. |
|
196 If no minimum restriction exists this should be set to 0 in |
|
197 the schema. This must be >= 0 |
|
198 -iMax = Maximum length of descriptor in clients address space. |
|
199 The descriptor supplied by the client must not have a |
|
200 length that exceeds this value. This must be >= iMin |
|
201 EParamDes8: |
|
202 EParamDes16: |
|
203 -iMin = Minimum MaxLength of descriptor in clients address space. |
|
204 The descriptor supplied by the client must have a MaxLength |
|
205 that is at least as big as this value. This must be >= 0 |
|
206 -iMax = Maximum length of descriptor in clients address space. |
|
207 The descriptor supplied by the client must not have a |
|
208 length that exceeds this value. This must be >= 0. |
|
209 |
|
210 NOTE: As the EParamDes* types use MaxLength() as a restriction |
|
211 They cannot be used if the client intends to pass a TDesC |
|
212 derived descriptor. If the client intends read only use |
|
213 then the explicit EParamDes*Read types should be used instead. |
|
214 |
|
215 EParamPckg: |
|
216 -iMin = Minimum length of descriptor in clients address space. |
|
217 If no minimum restriction exists this should be set to 0 in |
|
218 the schema. This must be >= 0 |
|
219 -iMax = Maximum length of descriptor in clients address space. |
|
220 The descriptor supplied by the client must not have a |
|
221 length that exceeds this value. This must be >= iMin |
|
222 |
|
223 EParamPtr: |
|
224 -iMin = Unused |
|
225 -iMax = Unused |
|
226 @publishedPartner |
|
227 @released |
|
228 */ |
|
229 struct TParameterDetails |
|
230 { |
|
231 const TInt iType; |
|
232 const TInt iMin; |
|
233 const TInt iMax; |
|
234 }; |
|
235 |
|
236 /** |
|
237 This struct is used to represent a single message from the client. |
|
238 It defines the function number corresponding to the message, the security |
|
239 policy for the message, the number of paramaters that are passed to the |
|
240 function and the type and constraint information for each of the parameters |
|
241 as described above. The server must define an array of these objects to be |
|
242 used by CClientMessage to validate all incoming messages. |
|
243 |
|
244 NOTE: It is assumed that the message parameters are contiguous. I.E. if there is one |
|
245 parameter it is assumed to be located at index 0, if there are 2 parameters they |
|
246 are located at index 0,1 etc. |
|
247 |
|
248 @publishedPartner |
|
249 @released |
|
250 */ |
|
251 struct TClientMessageSchema |
|
252 { |
|
253 |
|
254 //Version number of the framework |
|
255 const TInt iVersion; |
|
256 |
|
257 //The message number described by this schema |
|
258 const TInt iFunction; |
|
259 |
|
260 //The security policy for this message. The CClientMessage framework |
|
261 //uses this security policy to police incoming messages. |
|
262 const TStaticSecurityPolicy& iPolicy; |
|
263 |
|
264 //The number of parameters expected by this message |
|
265 const TInt iParamCount; |
|
266 |
|
267 //The array of TParameterDetails structs describing the |
|
268 //parameter types and constraints for this message |
|
269 const TParameterDetails* iParams; |
|
270 |
|
271 //Reserved values for future proofing |
|
272 const TInt iReserved1; |
|
273 const TInt iReserved2; |
|
274 }; |
|
275 |
|
276 /** |
|
277 This struct is used to initialise the ClientMessage Framework. |
|
278 This struct provides the framework with the message schema and |
|
279 the custom validation functions for the server as well as the server |
|
280 name and flags. |
|
281 The struct should be populated by the server using the SERVER_DATA |
|
282 macro defined below. |
|
283 @publishedPartner |
|
284 @released |
|
285 */ |
|
286 struct TClientMessageServerData |
|
287 { |
|
288 //Version number of this structure |
|
289 const TInt iVersion; |
|
290 |
|
291 //The number of messages accepted by this server |
|
292 const TInt iMessageCount; |
|
293 |
|
294 //The array of TClientMessageSchema structs defining the schema for |
|
295 //each message accpeted by this server |
|
296 const TClientMessageSchema* iMessageSchema; |
|
297 |
|
298 //The number of custom validation fucntions suplpied by this server |
|
299 const TInt iValidationFnCount; |
|
300 |
|
301 //The array of custom validation functions supplied by this server. |
|
302 //These validation functions are called from ValidateL to provide |
|
303 //customised validation of any parameter type. |
|
304 const TCustomValidationFn* iCustomValidationFns; |
|
305 |
|
306 //The name of the server using the framework. This string is used both |
|
307 //in logging bad messages and in panicing the client or the server. |
|
308 //In line with Panic category strings, this value should be 16 characters or less. |
|
309 const TUint8* iServerName; |
|
310 |
|
311 //Flags used to pass settings info into the framework. The supported values are |
|
312 //defined in the TServerFlags enum above. |
|
313 const TInt iFlags; |
|
314 |
|
315 //Reserved values for future proofing |
|
316 const TInt iReserved1; |
|
317 const TInt iReserved2; |
|
318 }; |
|
319 |
|
320 //Macro Definitions |
|
321 |
|
322 /** |
|
323 This macro is used to simplify declaration of TClientMessageSchema entries. |
|
324 The function number, security policy and pointer to array of TParameterDetails |
|
325 structures is converted into the expected format for the declaration of a |
|
326 TClientMessageSchema structure. |
|
327 @publishedPartner |
|
328 @released |
|
329 */ |
|
330 #define MESSAGE_SCHEMA(Function,Policy,Params) {KClientMessageVersion,Function,Policy,sizeof(Params)/sizeof(TParameterDetails),Params,0,0} |
|
331 |
|
332 |
|
333 /** |
|
334 This TParameterDetails structure is used to represent a message with no |
|
335 parameters. This is required as the schema expects a const TParameterDetails*. |
|
336 @publishedPartner |
|
337 @released |
|
338 */ |
|
339 const TParameterDetails KNoParams[1] = {{EParamNull,0,0}}; |
|
340 |
|
341 /** |
|
342 This macro is used to simplify declaration of TClientMessageSchema entries |
|
343 for functions with no parameters. Because the number of parameters is set |
|
344 to 0, a CMessageParameterBase derived object is not instantiated for this |
|
345 parameter type. |
|
346 @publishedPartner |
|
347 @released |
|
348 */ |
|
349 #define MESSAGE_SCHEMA_NO_PARAMS(Function,Policy) {KClientMessageVersion,Function,Policy,0,KNoParams,0,0} |
|
350 |
|
351 |
|
352 /** |
|
353 This macro is used to simplify declaration of the TClientMessageServerData structure. |
|
354 The pointer to the array of TClientMessageSchemas, pointer to array of |
|
355 TCustomValidationFns, server name and server flags are converted into the |
|
356 expected format for the declaration of a TClientMessageServerData structure. |
|
357 @publishedPartner |
|
358 @released |
|
359 */ |
|
360 #define SERVER_DATA(ClientMessages,ValidationFns,ServerName,Flags){KClientMessageVersion,sizeof(ClientMessages)/sizeof(TClientMessageSchema),ClientMessages,sizeof(ValidationFns)/sizeof(TCustomValidationFn),ValidationFns,(TUint8*)ServerName,Flags,0,0} |
|
361 |
|
362 |
|
363 //Class Declarations |
|
364 |
|
365 /** |
|
366 This is the abstract base class for all message parameter classes. |
|
367 The class defines one pure virtual function, ValidateL, which all derived classes |
|
368 must implement. This class also defines default implementation for the access |
|
369 methods which should be properly defined in all derived classes. |
|
370 This class is not intended for external derivation. |
|
371 @publishedPartner |
|
372 @released |
|
373 */ |
|
374 NONSHARABLE_CLASS(CMessageParameterBase) : public CBase |
|
375 { |
|
376 public: |
|
377 static CMessageParameterBase* CreateL(const TParameterDetails& aParam, TInt aParamIndex, |
|
378 const RMessage2& aMessage); |
|
379 virtual void ValidateL() = 0; |
|
380 virtual ~CMessageParameterBase(){}; |
|
381 |
|
382 virtual TInt GetIntL(); |
|
383 virtual const TAny* GetPtrL(); |
|
384 virtual const TDesC8& GetDes8L(); |
|
385 virtual const TDesC& GetDes16L(); |
|
386 virtual TInt GetDesLengthL(); |
|
387 virtual TInt GetDesMaxLengthL(); |
|
388 virtual void ReadL(TDes8& aDes, TInt aOffset); |
|
389 virtual void ReadL(TDes& aDes, TInt aOffset); |
|
390 virtual void WriteL(const TDesC8& aDes, TInt aOffset); |
|
391 virtual void WriteL(const TDesC& aDes, TInt aOffset); |
|
392 |
|
393 virtual TInt Min(); |
|
394 virtual TInt Max(); |
|
395 |
|
396 protected: |
|
397 CMessageParameterBase(const TParameterDetails& aParam, TInt aParamIndex, |
|
398 const RMessage2& aMessage, TCustomValidationFn aValidationFn); |
|
399 |
|
400 private: |
|
401 static TCustomValidationFn GetValidationFunctionL(const TParameterDetails& aParam); |
|
402 |
|
403 protected: |
|
404 //The index of this parameter within the corresponding RMessage2 object |
|
405 TInt iIndex; |
|
406 |
|
407 //A reference to the RMessage2 object that contains this parameter |
|
408 const RMessage2& iMessage; |
|
409 |
|
410 //A reference to the structure that defines the expected type |
|
411 //and constraints for this parameter |
|
412 const TParameterDetails& iParamDetails; |
|
413 |
|
414 //A custom validation function to allow user defined validation |
|
415 //this function is called from ValidateL |
|
416 TCustomValidationFn iValidationFn; |
|
417 |
|
418 }; |
|
419 |
|
420 /** |
|
421 This class is used by a server to sanitise incoming messages. |
|
422 The class provides a wrapper around an RMessage2 object and provides a method |
|
423 for validation of the message against the constraints defined in the message schema. |
|
424 This class also provides methods for safely accessing the message arguments, |
|
425 and for error handling and logging of bad messages. |
|
426 This class is not intended for derivation. |
|
427 @publishedPartner |
|
428 @released |
|
429 */ |
|
430 NONSHARABLE_CLASS(CClientMessage) : public CBase |
|
431 { |
|
432 public: |
|
433 IMPORT_C static void InitialiseFrameworkL(const TClientMessageServerData& aServerData); |
|
434 IMPORT_C static CClientMessage* NewL(const RMessage2& aMessage); |
|
435 IMPORT_C virtual ~CClientMessage(); |
|
436 |
|
437 IMPORT_C TInt Function(); |
|
438 IMPORT_C const RMessage2& Message(); |
|
439 IMPORT_C virtual void ValidateL(); |
|
440 IMPORT_C virtual void ValidateL(TInt aParam); |
|
441 IMPORT_C virtual void CompleteRequestL(TInt aError); |
|
442 IMPORT_C virtual void PanicClient(const TDesC& aServer, TInt aPanic); |
|
443 |
|
444 IMPORT_C virtual TInt GetIntL(TInt aParam); |
|
445 IMPORT_C virtual const TAny* GetPtrL(TInt aParam); |
|
446 IMPORT_C virtual const TDesC8& GetDes8L(TInt aParam); |
|
447 IMPORT_C virtual const TDesC& GetDes16L(TInt aParam); |
|
448 IMPORT_C virtual TInt GetDesLengthL(TInt aParam); |
|
449 IMPORT_C virtual TInt GetDesMaxLengthL(TInt aParam); |
|
450 IMPORT_C virtual void ReadL(TInt aParam, TDes8& aDes, TInt aOffset = 0); |
|
451 IMPORT_C virtual void ReadL(TInt aParam, TDes16& aDes, TInt aOffset = 0); |
|
452 IMPORT_C virtual void WriteL(TInt aParam, const TDesC8& aDes, TInt aOffset = 0); |
|
453 IMPORT_C virtual void WriteL(TInt aParam, const TDesC16& aDes, TInt aOffset = 0); |
|
454 |
|
455 private: |
|
456 virtual void LogBadMessageL(TInt aError); |
|
457 virtual void CheckSecurityPolicyL(const TSecurityPolicy& aPolicy); |
|
458 CClientMessage(const RMessage2& aMessage,const TClientMessageServerData& aServerData); |
|
459 void ConstructL(); |
|
460 const TClientMessageSchema* FindMessageSchema(); |
|
461 void CheckValidatedL(TInt aParam); |
|
462 TBool LogBadMessages(); |
|
463 |
|
464 private: |
|
465 //Array of pointers to CMessageParameterBase Derived parameter objects used |
|
466 // to validate and access the individual message arguments |
|
467 RPointerArray <CMessageParameterBase> iParameters; |
|
468 |
|
469 //Reference to the underlying RMessage2 wrapped by this object |
|
470 const RMessage2& iMessage; |
|
471 |
|
472 //Reference to TClientMessageServerData structure stored in TLS for |
|
473 //this thread. This structure is passed in to the framework by the server |
|
474 //on initialisation. |
|
475 const TClientMessageServerData& iServerData; |
|
476 |
|
477 //Bit flags for use internally within CClientMessage. |
|
478 TBitFlags32 iFlags; |
|
479 }; |
|
480 /** |
|
481 This class is used for Base64 based encoding and decoding . |
|
482 This class provides a method for encoding and decoding |
|
483 @publishedPartner |
|
484 @released |
|
485 */ |
|
486 class Base64Codec |
|
487 { |
|
488 // base64 and UU coding defines. |
|
489 /** |
|
490 This is the list of Bitmask used for encoding and decoding |
|
491 @publishedPartner |
|
492 @released |
|
493 */ |
|
494 enum EMaskValues |
|
495 { |
|
496 ESixBitMask = 0x3F, |
|
497 EEightBitMask = 0xFF |
|
498 }; |
|
499 |
|
500 /** |
|
501 This is the list of shift values used for encoding and decoding |
|
502 @publishedPartner |
|
503 @released |
|
504 */ |
|
505 enum EMaskShiftValues |
|
506 { |
|
507 ESix = 6, |
|
508 EFour = 4, |
|
509 ETwo = 2, |
|
510 EZero = 0 |
|
511 }; |
|
512 |
|
513 /** |
|
514 This enum is used as padding charcter |
|
515 @publishedPartner |
|
516 @released |
|
517 */ |
|
518 enum |
|
519 { |
|
520 EPadChar = 64 |
|
521 }; |
|
522 public: |
|
523 IMPORT_C static TInt Encode(const TDesC8& aSrcString, TDes8& aDestString); |
|
524 IMPORT_C static TInt Decode(const TDesC8& aSrcString, TDes8& aDestString); |
|
525 }; |
|
526 }//namespace |
|
527 |
|
528 #endif |