|
1 // Copyright (c) 2005-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 // spdb.cpp - IPv6/IPv4 IPsec Security Policy Database (SPD) |
|
15 // Implementation of the IPsec Security Policy Database (SPD) |
|
16 // |
|
17 |
|
18 |
|
19 |
|
20 /** |
|
21 @file spdb.cpp |
|
22 */ |
|
23 #include "epdb.h" |
|
24 #include "spdb.h" |
|
25 #include <networking/pfkeyv2.h> |
|
26 #include "sa_spec.h" |
|
27 #include <networking/ipsecerr.h> |
|
28 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
29 #include <e32std.h> |
|
30 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
31 #ifndef OLD_SELECTOR_ORDERING |
|
32 /** @deprecated |
|
33 * The old syntax allowed total mixing of "filter" and "selector" |
|
34 * keywords. The new syntax requires the filter keywords (outbound, |
|
35 * inbound, merge, final, etc.) to precede any real selectors. |
|
36 * For backward compatibility, allow old deprecated ordering, if |
|
37 * OLD_SELECTOR_ORDERING is defined. |
|
38 */ |
|
39 #define OLD_SELECTOR_ORDERING 1 |
|
40 #endif |
|
41 |
|
42 |
|
43 /** |
|
44 * Static keyword macro. |
|
45 * |
|
46 * Store all keywords as "plain ascii" (narrow, not UNICODE) |
|
47 */ |
|
48 #define KEYWORD(s) {(sizeof(s)-1), (const TText8 *)s} |
|
49 |
|
50 /** |
|
51 * Keyword number macro. |
|
52 * |
|
53 * Generate enum name for the keyword 's'. |
|
54 */ |
|
55 #define KEYENUM(s) E_ ## s |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
63 // CPropList |
|
64 CPropList::CPropList(TInt aGranularity) : |
|
65 CArrayFixFlat<CSecurityProposalSpec *>(aGranularity) |
|
66 {} |
|
67 |
|
68 CPropList* CPropList::NewL(TInt aGranularity) |
|
69 { |
|
70 CPropList* self = new (ELeave) CPropList(aGranularity); |
|
71 self->Construct(aGranularity); |
|
72 return self; |
|
73 } |
|
74 |
|
75 void CPropList::Construct(TInt /* aGranularity */) |
|
76 {} |
|
77 |
|
78 CPropList::CPropList(CPropList* aSAList) : |
|
79 CArrayFixFlat<CSecurityProposalSpec *>(aSAList->Count()) |
|
80 {} |
|
81 |
|
82 CPropList* CPropList::NewL(CPropList* aSAList) |
|
83 { |
|
84 CPropList* self = new (ELeave) CPropList(aSAList); |
|
85 CleanupStack::PushL(self); |
|
86 self->ConstructL(aSAList); |
|
87 CleanupStack::Pop(); |
|
88 return self; |
|
89 } |
|
90 |
|
91 void CPropList::ConstructL(CPropList* aSAList) |
|
92 { |
|
93 TInt count(aSAList->Count()); |
|
94 } |
|
95 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
96 |
|
97 class TKeyword |
|
98 /** |
|
99 * The keyword definition. |
|
100 */ |
|
101 { |
|
102 public: |
|
103 TInt iLength; //< Length of the keyword |
|
104 const TText8 *iWord; //< The keyword |
|
105 }; |
|
106 |
|
107 static TInt Lookup(const TKeyword *const aList, const TInt aLength, const TDesC &aToken) |
|
108 /** |
|
109 * Lookup a keyword from list. |
|
110 * |
|
111 * @param aList The list of keyword |
|
112 * @param aLength The number of keywords in the list |
|
113 * @param aToken The keyword to be looked for |
|
114 * |
|
115 * @return |
|
116 * The index of the matched keyword, or aLength, if none matches. |
|
117 */ |
|
118 { |
|
119 const TInt token_length = aToken.Length(); |
|
120 for (TInt i = 0; i < aLength; i++) |
|
121 { |
|
122 const TKeyword &key = aList[i]; |
|
123 if (key.iLength == token_length) |
|
124 { |
|
125 // Use own matching loop (instead of Compare), because keywords |
|
126 // are stored as 8-bit strings (to make them compact). |
|
127 for (TInt k = token_length;;) |
|
128 { |
|
129 if (--k < 0) |
|
130 return i; // Keyword matched! |
|
131 if (key.iWord[k] != aToken[k]) |
|
132 break; // No Match! |
|
133 } |
|
134 } |
|
135 } |
|
136 return aLength; |
|
137 } |
|
138 |
|
139 |
|
140 typedef enum |
|
141 /** |
|
142 * Tokens of the IPsec policy syntax. |
|
143 */ |
|
144 { |
|
145 token_string, //< Any string of non-white space and non-token characters. |
|
146 token_question, //< Question mark: '?' |
|
147 token_equal, //< Equal sign: '=' |
|
148 token_comma, //< Comma: ',' |
|
149 token_brace_left, //< Left brace: '{' |
|
150 token_brace_right, //< Right brace: '}' |
|
151 token_par_left, //< Left parens: '(' |
|
152 token_par_right, //< Right parens: ')' |
|
153 token_eof //< End of policy string. |
|
154 } token_type; |
|
155 |
|
156 class TParser : public TLex |
|
157 /** |
|
158 * Parser of the policy definition. |
|
159 */ |
|
160 { |
|
161 public: |
|
162 TParser(CSecurityPolicy *aSP, const TDesC &aPolicy, REndPoints &aEp); |
|
163 void ParseL(TUint aStartOffset); |
|
164 private: |
|
165 void ParseEndPointL(); |
|
166 void SetAddressOrEndPointL(RIpAddress &aAddr, TInt aMask, TInt aError); |
|
167 void ParseAddressL(RIpAddress &aAddr, TInt aMask, TInt aError); |
|
168 void ParseAddressAndMaskL(RIpAddress &aAddr, RIpAddress& aMask); |
|
169 void ParseSecurityBundleL(RPolicyActions &aBundle, CTransportSelector *aTS); |
|
170 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
171 void ParseAssociationParametersL(CPolicySpec *aSpec); |
|
172 #else |
|
173 void ParseAssociationParametersL(TSecurityAssocSpec &aSpec); |
|
174 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
175 void ParseSelectorL(CPolicySelector *&aPs); |
|
176 token_type TransportSelectorL(CTransportSelector *& aTS); |
|
177 void ParseAssociationL(); |
|
178 TAlgorithmMap *ParseAlgorithmReferenceL(TInt anInsert); |
|
179 TInt ParseAlgorithmMappingL(TAlgorithmClass aClass); |
|
180 token_type NextToken(); |
|
181 void SkipSpaceAndMark(); |
|
182 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
183 token_type CheckProposalCloseAndMoreProposals(TInt &aPropBraces); |
|
184 CSecurityProposalSpec* CreateProposalL(CPropList& aPropList); |
|
185 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
186 TPtrC iToken; //< The current token. |
|
187 CSecurityPolicy *iSp; //< The result of the parsing operation, The new policy |
|
188 REndPoints &iEp; //< The End Point collection to use for the named endpoints. |
|
189 }; |
|
190 |
|
191 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
192 CSecurityProposalSpec* TParser::CreateProposalL(CPropList& aPropList) |
|
193 { |
|
194 CSecurityProposalSpec* prop = new(ELeave) CSecurityProposalSpec; |
|
195 prop->iType = SADB_SATYPE_UNSPEC; |
|
196 aPropList.AppendL(prop); |
|
197 return prop; |
|
198 } |
|
199 |
|
200 token_type TParser::CheckProposalCloseAndMoreProposals(TInt &aPropBraces) |
|
201 { |
|
202 token_type val; |
|
203 val=NextToken(); |
|
204 if (val == token_brace_right ) |
|
205 { |
|
206 if (--aPropBraces != -1) |
|
207 return NextToken(); |
|
208 } |
|
209 return val; |
|
210 } |
|
211 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
212 void TParser::SkipSpaceAndMark() |
|
213 /** |
|
214 * Skip white space and mark. |
|
215 * |
|
216 * Skip white space and comments. The '#' character |
|
217 * starts a comment that continues to the end of the line. |
|
218 * Syntactically, a comment is white space (and terminates |
|
219 * token string. |
|
220 * |
|
221 * Set the mark on first character that is not white space. |
|
222 */ |
|
223 { |
|
224 TInt comment = 0; |
|
225 while (!Eos()) |
|
226 { |
|
227 const TChar ch = Get(); |
|
228 if (ch == '\n') |
|
229 comment = 0; |
|
230 else if (comment || ch == '#') |
|
231 comment = 1; |
|
232 else if (!ch.IsSpace()) |
|
233 { |
|
234 UnGet(); |
|
235 break; |
|
236 } |
|
237 } |
|
238 Mark(); |
|
239 } |
|
240 |
|
241 token_type TParser::NextToken() |
|
242 /** |
|
243 * Parse over the next token. |
|
244 * |
|
245 * Skip over white space and return the next token. The |
|
246 * parsing point is after the returned token. Set the |
|
247 * iToken to reference the returned token as a string. |
|
248 * |
|
249 * @return The token type |
|
250 */ |
|
251 { |
|
252 token_type val; |
|
253 |
|
254 SkipSpaceAndMark(); |
|
255 if (Eos()) |
|
256 val = token_eof; |
|
257 else |
|
258 { |
|
259 TChar ch = Get(); |
|
260 if (ch == '{') |
|
261 val = token_brace_left; |
|
262 else if (ch == '}') |
|
263 val = token_brace_right; |
|
264 else if (ch == '(') |
|
265 val = token_par_left; |
|
266 else if (ch == ')') |
|
267 val = token_par_right; |
|
268 else if (ch == '=') |
|
269 val = token_equal; |
|
270 else if (ch == ',') |
|
271 val = token_comma; |
|
272 else if (ch == '?') |
|
273 val = token_question; |
|
274 else |
|
275 { |
|
276 val = token_string; |
|
277 while (!Eos()) |
|
278 { |
|
279 ch = Peek(); |
|
280 if (ch == '{' || ch == '}' || |
|
281 ch == '(' || ch == ')' || |
|
282 ch == '=' || ch == '#' || |
|
283 ch == '?' || ch.IsSpace()) |
|
284 break; |
|
285 Inc(); |
|
286 } |
|
287 } |
|
288 } |
|
289 iToken.Set(MarkedToken()); |
|
290 SkipSpaceAndMark(); |
|
291 return val; |
|
292 } |
|
293 |
|
294 TAlgorithmMap *TParser::ParseAlgorithmReferenceL(TInt aInsert) |
|
295 /** |
|
296 * Parse algorithm reference |
|
297 * @code [ library '.' ] algorithm |
|
298 * @endcode |
|
299 * |
|
300 * @param aInsert Create TAlgorithMap, if not found |
|
301 * @return The algorithm map. |
|
302 */ |
|
303 { |
|
304 _LIT(K_null, "null"); |
|
305 |
|
306 if (NextToken() == token_string) |
|
307 { |
|
308 TInt dot = iToken.Locate('.'); |
|
309 const TPtrC lib = dot < 0 ? (TPtrC&)KNullDesC() : iToken.Left(dot); |
|
310 TPtrC alg = dot < 0 ? iToken : iToken.Right(iToken.Length()-dot-1); |
|
311 if (alg.Compare(K_null) == 0) |
|
312 alg.Set(0,0); // 'null' is a special algorithm name! |
|
313 TAlgorithmMap *map = iSp->FindAlg(lib, alg); |
|
314 if (map == NULL && aInsert) |
|
315 map = iSp->NewAlgL(lib, alg); |
|
316 return map; |
|
317 } |
|
318 // Ás this is syntax error, should probably report something.. |
|
319 return NULL; |
|
320 } |
|
321 |
|
322 |
|
323 TInt TParser::ParseAlgorithmMappingL(TAlgorithmClass aClass) |
|
324 /** |
|
325 * Parse algorithm mapping |
|
326 * @code ParseAlgorithmReferenceL '(' id ',' bits [',' dummy]* ')' |
|
327 * @endcode |
|
328 * |
|
329 * The library reference is followed by a list of numbers in |
|
330 * parentheses. The kernel side only needs one or two (for digest) |
|
331 * and rest are ignored (the other numbers may be used by the |
|
332 * key management or configuration tools). |
|
333 * |
|
334 * @param aClass Algorithm type (cipher or digest). |
|
335 * @return KErrNone if no errors. |
|
336 */ |
|
337 { |
|
338 TAlgorithmMap *map = ParseAlgorithmReferenceL(1); |
|
339 if (map && NextToken() == token_par_left) |
|
340 { |
|
341 TInt i, n; |
|
342 map->iClass = aClass; |
|
343 for (i = 0;;++i) |
|
344 { |
|
345 const TInt error = Val(n); |
|
346 if (error != KErrNone) |
|
347 return error; |
|
348 // |
|
349 // Only the first two integers are used by the |
|
350 // kernel IPSEC, pass other numbers silently. |
|
351 // |
|
352 if (i == 0) |
|
353 map->iId = n; |
|
354 else if (i == 1) |
|
355 map->iBits = n; |
|
356 |
|
357 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
358 if (map->iId == SADB_AALG_AES_XCBC_MAC) |
|
359 { |
|
360 map->iClass = EAlgorithmClass_Mac; |
|
361 } |
|
362 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
363 const TInt tok = NextToken(); |
|
364 if (tok == token_par_right) |
|
365 break; |
|
366 else if (tok != token_comma) |
|
367 return KErrGeneral; |
|
368 } |
|
369 // |
|
370 // At least one number (id) must be present |
|
371 // |
|
372 if (i == 0) |
|
373 return KErrGeneral; |
|
374 } |
|
375 return KErrNone; |
|
376 } |
|
377 |
|
378 |
|
379 void TParser::ParseEndPointL() |
|
380 /** |
|
381 * Parse Named End Point |
|
382 * @code name '=' '{' [ '?' ] ip-address '}' |
|
383 * @endcode |
|
384 */ |
|
385 { |
|
386 if (NextToken() != token_string) |
|
387 User::Leave(EIpsec_PolicySpecName); // Endpoint name expeted! |
|
388 // Allocate a slot for the new association specification |
|
389 |
|
390 const TPtrC name(iToken); |
|
391 |
|
392 if (NextToken() != token_equal || |
|
393 NextToken() != token_brace_left) |
|
394 User::Leave(EIpsec_PolicySyntaxError); |
|
395 |
|
396 TInt opt = 0; |
|
397 token_type val = NextToken(); |
|
398 if (val == token_question) |
|
399 { |
|
400 opt = 1; |
|
401 val = NextToken(); |
|
402 } |
|
403 TIpAddress addr; |
|
404 if (val == token_brace_right) |
|
405 addr.SetAddressNone(); |
|
406 else |
|
407 { |
|
408 if (val != token_string || addr.SetAddress(iToken) != KErrNone) |
|
409 User::Leave(EIpsec_PolicyIpAddressExpected); |
|
410 if (NextToken() != token_brace_right) |
|
411 User::Leave(EIpsec_PolicyCloseBraceExpected); |
|
412 } |
|
413 |
|
414 // Add RIpAddress handle to iEndPoints to keep the EP around |
|
415 // as long as this policy is loaded (if EP is attached to some |
|
416 // other objects, like SA, its life extends beyond the policy |
|
417 // life). |
|
418 const TInt index = iSp->iEndPoints.Count(); |
|
419 User::LeaveIfError(iSp->iEndPoints.Append(RIpAddress())); |
|
420 User::LeaveIfError(iSp->iEndPoints[index].Open(iEp, name, addr, opt)); |
|
421 } |
|
422 |
|
423 |
|
424 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
425 void TParser::ParseAssociationParametersL(CPolicySpec *aPolicySpec) |
|
426 #else |
|
427 void TParser::ParseAssociationParametersL(TSecurityAssocSpec &aSpec) |
|
428 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
429 /** |
|
430 * Parse a sequence of association parameters |
|
431 * @code [ 'ah' | 'esp' | 'encrypt_alg' number | 'auth_alg' number | |
|
432 * 'identity' string | 'identity_remote' string | 'identity_local' string | |
|
433 * 'pfs' | |
|
434 * 'protocol_specific' | 'local_port_specific' | 'remote_port_specific' | |
|
435 * 'proxy_specific' | 'local_specific' | 'remote_specific' | |
|
436 * 'src_specific' | 'replay_win_len' number | |
|
437 * 'min_auth_bits' number | 'max_auth_bits' number | |
|
438 * 'min_encrypt_bits' number | 'max_encrypt_bits' number | |
|
439 * 'hard_lifetime_allocations' number | 'hard_lifetime_bytes' number | |
|
440 * 'hard_lifetime_addtime' number | 'hard_lifetime_usetime' number | |
|
441 * 'soft_lifetime_allocations' number | 'soft_lifetime_bytes' number | |
|
442 * 'soft_lifetime_addtime' number | 'soft_lifetime_usetime' number | 'proposal' ]+ '}' |
|
443 * @endcode |
|
444 * |
|
445 * Some parameters are just plain keyword, some have additional numeric |
|
446 * or string arguments. The parameter keywords can be in any order, but |
|
447 * each keyword can only appear once. At least one 'ah' or 'esp' must be |
|
448 * present. |
|
449 * |
|
450 * @param aSpec The specificantion to fill. |
|
451 */ |
|
452 { |
|
453 static const TKeyword list[] = |
|
454 { |
|
455 KEYWORD("ah"), |
|
456 KEYWORD("esp"), |
|
457 KEYWORD("encrypt_alg"), |
|
458 KEYWORD("auth_alg"), |
|
459 KEYWORD("identity"), |
|
460 KEYWORD("identity_remote"), |
|
461 KEYWORD("identity_local"), |
|
462 KEYWORD("pfs"), |
|
463 KEYWORD("protocol_specific"), |
|
464 KEYWORD("local_port_specific"), |
|
465 KEYWORD("remote_port_specific"), |
|
466 KEYWORD("proxy_specific"), // -- kept for backward compatibility |
|
467 KEYWORD("local_specific"), |
|
468 KEYWORD("remote_specific"), |
|
469 KEYWORD("src_specific"), |
|
470 KEYWORD("replay_win_len"), |
|
471 KEYWORD("min_auth_bits"), |
|
472 KEYWORD("max_auth_bits"), |
|
473 KEYWORD("min_encrypt_bits"), |
|
474 KEYWORD("max_encrypt_bits"), |
|
475 KEYWORD("hard_lifetime_allocations"), |
|
476 KEYWORD("hard_lifetime_bytes"), |
|
477 KEYWORD("hard_lifetime_addtime"), |
|
478 KEYWORD("hard_lifetime_usetime"), |
|
479 KEYWORD("soft_lifetime_allocations"), |
|
480 KEYWORD("soft_lifetime_bytes"), |
|
481 KEYWORD("soft_lifetime_addtime"), |
|
482 KEYWORD("soft_lifetime_usetime") |
|
483 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
484 ,KEYWORD("proposal") |
|
485 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
486 }; |
|
487 enum // Order must be exactly the same as above |
|
488 { |
|
489 KEYENUM(ah), |
|
490 KEYENUM(esp), |
|
491 KEYENUM(encrypt_alg), |
|
492 KEYENUM(auth_alg), |
|
493 KEYENUM(identity), |
|
494 KEYENUM(identity_remote), |
|
495 KEYENUM(identity_local), |
|
496 KEYENUM(pfs), |
|
497 KEYENUM(protocol_specific), |
|
498 KEYENUM(local_port_specific), |
|
499 KEYENUM(remote_port_specific), |
|
500 KEYENUM(proxy_specific), |
|
501 KEYENUM(local_specific), |
|
502 KEYENUM(remote_specific), |
|
503 KEYENUM(src_specific), |
|
504 KEYENUM(replay_win_len), |
|
505 KEYENUM(min_auth_bits), |
|
506 KEYENUM(max_auth_bits), |
|
507 KEYENUM(min_encrypt_bits), |
|
508 KEYENUM(max_encrypt_bits), |
|
509 KEYENUM(hard_lifetime_allocations), |
|
510 KEYENUM(hard_lifetime_bytes), |
|
511 KEYENUM(hard_lifetime_addtime), |
|
512 KEYENUM(hard_lifetime_usetime), |
|
513 KEYENUM(soft_lifetime_allocations), |
|
514 KEYENUM(soft_lifetime_bytes), |
|
515 KEYENUM(soft_lifetime_addtime), |
|
516 KEYENUM(soft_lifetime_usetime), |
|
517 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
518 KEYENUM(proposal), |
|
519 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
520 KEYENUM(max_parameters) |
|
521 }; |
|
522 |
|
523 TInt sa_type_defined = 0; |
|
524 TInt error = KErrNone; |
|
525 token_type val; |
|
526 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
527 val = NextToken(); |
|
528 TInt propasalsDefined=0; |
|
529 CSecurityProposalSpec* prop = NULL; |
|
530 while (val == token_string) |
|
531 #else |
|
532 while ((val = NextToken()) == token_string) |
|
533 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
534 { |
|
535 switch (Lookup(list, E_max_parameters, iToken)) |
|
536 { |
|
537 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
538 case E_proposal: |
|
539 propasalsDefined++; |
|
540 prop = CreateProposalL (*aPolicySpec->iPropList); |
|
541 if ((val=NextToken()) != token_brace_left) |
|
542 { |
|
543 User::Leave(EIpsec_PolicySyntaxError); |
|
544 } |
|
545 break; |
|
546 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
547 case E_ah: |
|
548 sa_type_defined++; |
|
549 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
550 aPolicySpec->iSpec.iType = SADB_SATYPE_AH; |
|
551 if (prop) prop->iType = SADB_SATYPE_AH; |
|
552 #else |
|
553 aSpec.iType = SADB_SATYPE_AH; |
|
554 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
555 break; |
|
556 case E_esp: |
|
557 sa_type_defined++; |
|
558 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
559 aPolicySpec->iSpec.iType = SADB_SATYPE_ESP; |
|
560 if (prop) prop->iType = SADB_SATYPE_ESP; |
|
561 #else |
|
562 aSpec.iType = SADB_SATYPE_ESP; |
|
563 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
564 break; |
|
565 case E_encrypt_alg: |
|
566 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
567 if (prop && (error = Val(prop->iEalg, EDecimal)) == KErrNone && |
|
568 iSp->FindAlg(EAlgorithmClass_Cipher, prop->iEalg) == NULL) |
|
569 User::Leave(EIpsec_PolicyUnknownEncrypt); |
|
570 if(prop) |
|
571 aPolicySpec->iSpec.iEalg = prop->iEalg; |
|
572 #else |
|
573 if ((error = Val(aSpec.iEalg, EDecimal)) == KErrNone && |
|
574 iSp->FindAlg(EAlgorithmClass_Cipher, aSpec.iEalg) == NULL) |
|
575 User::Leave(EIpsec_PolicyUnknownEncrypt); |
|
576 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
577 break; |
|
578 case E_auth_alg: |
|
579 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
580 if (prop && (error = Val(prop->iAalg, EDecimal)) == KErrNone && |
|
581 (iSp->FindAlg(EAlgorithmClass_Digest, prop->iAalg) == NULL) |
|
582 && (iSp->FindAlg(EAlgorithmClass_Mac, prop->iAalg) == NULL) ) |
|
583 User::Leave(EIpsec_PolicyUnknownAuth); |
|
584 if(prop) |
|
585 aPolicySpec->iSpec.iAalg = prop->iAalg ; |
|
586 #else |
|
587 if ((error = Val(aSpec.iAalg, EDecimal)) == KErrNone && |
|
588 iSp->FindAlg(EAlgorithmClass_Digest, aSpec.iAalg) == NULL) |
|
589 User::Leave(EIpsec_PolicyUnknownAuth); |
|
590 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
591 break; |
|
592 case E_identity: // temp. backwards compatibility |
|
593 case E_identity_remote: |
|
594 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
595 if (aPolicySpec->iSpec.iIdentityRemote) |
|
596 User::Leave(EIpsec_PolicyIdentityDefined); |
|
597 (void)NextToken(); // Advance iToken to the identity value |
|
598 aPolicySpec->iSpec.iIdentityRemote = CIdentity::NewL(iToken); |
|
599 #else |
|
600 if (aSpec.iIdentityRemote) |
|
601 User::Leave(EIpsec_PolicyIdentityDefined); |
|
602 (void)NextToken(); // Advance iToken to the identity value |
|
603 aSpec.iIdentityRemote = CIdentity::NewL(iToken); |
|
604 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
605 break; |
|
606 case E_identity_local: |
|
607 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
608 if (aPolicySpec->iSpec.iIdentityLocal) |
|
609 User::Leave(EIpsec_PolicyIdentityDefined); |
|
610 (void)NextToken(); // Advance iToken to the identity value |
|
611 aPolicySpec->iSpec.iIdentityLocal = CIdentity::NewL(iToken); |
|
612 #else |
|
613 if (aSpec.iIdentityLocal) |
|
614 User::Leave(EIpsec_PolicyIdentityDefined); |
|
615 (void)NextToken(); // Advance iToken to the identity value |
|
616 aSpec.iIdentityLocal = CIdentity::NewL(iToken); |
|
617 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
618 break; |
|
619 case E_pfs: |
|
620 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
621 aPolicySpec->iSpec.iPfs = 1; |
|
622 #else |
|
623 aSpec.iPfs = 1; |
|
624 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
625 break; |
|
626 case E_protocol_specific: |
|
627 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
628 aPolicySpec->iSpec.iMatchProtocol = 1; |
|
629 #else |
|
630 aSpec.iMatchProtocol = 1; |
|
631 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
632 break; |
|
633 case E_local_port_specific: |
|
634 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
635 aPolicySpec->iSpec.iMatchLocalPort = 1; |
|
636 #else |
|
637 aSpec.iMatchLocalPort = 1; |
|
638 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
639 break; |
|
640 case E_remote_port_specific: |
|
641 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
642 aPolicySpec->iSpec.iMatchRemotePort = 1; |
|
643 #else |
|
644 aSpec.iMatchRemotePort = 1; |
|
645 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
646 break; |
|
647 case E_proxy_specific: |
|
648 // ** should be deprecated -- msa |
|
649 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
650 aPolicySpec->iSpec.iMatchProxy = 1; |
|
651 #else |
|
652 aSpec.iMatchProxy = 1; |
|
653 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
654 break; |
|
655 case E_local_specific: |
|
656 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
657 aPolicySpec->iSpec.iMatchLocal = 1; |
|
658 #else |
|
659 aSpec.iMatchLocal = 1; |
|
660 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
661 break; |
|
662 case E_remote_specific: |
|
663 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
664 aPolicySpec->iSpec.iMatchRemote = 1; |
|
665 #else |
|
666 aSpec.iMatchRemote = 1; |
|
667 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
668 break; |
|
669 case E_src_specific: |
|
670 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
671 aPolicySpec->iSpec.iMatchSrc = 1; |
|
672 #else |
|
673 aSpec.iMatchSrc = 1; |
|
674 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
675 break; |
|
676 case E_replay_win_len: |
|
677 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
678 error = Val(aPolicySpec->iSpec.iReplayWindowLength, EDecimal); |
|
679 #else |
|
680 error = Val(aSpec.iReplayWindowLength, EDecimal); |
|
681 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
682 break; |
|
683 case E_min_auth_bits: |
|
684 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
685 error = Val(aPolicySpec->iSpec.iMinAuthBits, EDecimal); |
|
686 #else |
|
687 error = Val(aSpec.iMinAuthBits, EDecimal); |
|
688 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
689 break; |
|
690 case E_max_auth_bits: |
|
691 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
692 if (prop) |
|
693 { |
|
694 error = Val(prop->iMaxAuthBits, EDecimal); |
|
695 } |
|
696 #else |
|
697 error = Val(aSpec.iMaxAuthBits, EDecimal); |
|
698 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
699 break; |
|
700 case E_min_encrypt_bits: |
|
701 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
702 if (prop) |
|
703 { |
|
704 error = Val(prop->iMinEncryptBits, EDecimal); |
|
705 } |
|
706 #else |
|
707 error = Val(aSpec.iMinEncryptBits, EDecimal); |
|
708 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
709 break; |
|
710 case E_max_encrypt_bits: |
|
711 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
712 if (prop) |
|
713 { |
|
714 error = Val(prop->iMaxEncryptBits, EDecimal); |
|
715 } |
|
716 #else |
|
717 error = Val(aSpec.iMaxEncryptBits, EDecimal); |
|
718 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
719 break; |
|
720 case E_hard_lifetime_allocations: |
|
721 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
722 if (prop) |
|
723 { |
|
724 error = Val(prop->iHard.sadb_lifetime_allocations , EDecimal); |
|
725 } |
|
726 #else |
|
727 error = Val(aSpec.iHard.sadb_lifetime_allocations, EDecimal); |
|
728 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
729 break; |
|
730 case E_hard_lifetime_bytes: |
|
731 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
732 if (prop) |
|
733 { |
|
734 error = Val(prop->iHard.sadb_lifetime_bytes , EDecimal); |
|
735 } |
|
736 #else |
|
737 error = Val(aSpec.iHard.sadb_lifetime_bytes, EDecimal); |
|
738 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
739 break; |
|
740 case E_hard_lifetime_addtime: |
|
741 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
742 if (prop) |
|
743 { |
|
744 error = Val(prop->iHard.sadb_lifetime_addtime , EDecimal); |
|
745 } |
|
746 #else |
|
747 error = Val(aSpec.iHard.sadb_lifetime_addtime, EDecimal); |
|
748 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
749 break; |
|
750 case E_hard_lifetime_usetime: |
|
751 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
752 if (prop) |
|
753 { |
|
754 error = Val(prop->iHard.sadb_lifetime_usetime , EDecimal); |
|
755 } |
|
756 #else |
|
757 error = Val(aSpec.iHard.sadb_lifetime_usetime, EDecimal); |
|
758 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
759 break; |
|
760 case E_soft_lifetime_allocations: |
|
761 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
762 if (prop) |
|
763 { |
|
764 error = Val(prop->iSoft.sadb_lifetime_allocations , EDecimal); |
|
765 } |
|
766 #else |
|
767 error = Val(aSpec.iSoft.sadb_lifetime_allocations, EDecimal); |
|
768 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
769 break; |
|
770 case E_soft_lifetime_bytes: |
|
771 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
772 if (prop) |
|
773 { |
|
774 error = Val(prop->iSoft.sadb_lifetime_bytes , EDecimal); |
|
775 } |
|
776 #else |
|
777 error = Val(aSpec.iSoft.sadb_lifetime_bytes, EDecimal); |
|
778 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
779 break; |
|
780 case E_soft_lifetime_addtime: |
|
781 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
782 if (prop) |
|
783 { |
|
784 error = Val(prop->iSoft.sadb_lifetime_addtime , EDecimal); |
|
785 } |
|
786 #else |
|
787 error = Val(aSpec.iSoft.sadb_lifetime_addtime, EDecimal); |
|
788 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
789 break; |
|
790 case E_soft_lifetime_usetime: |
|
791 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
792 if (prop) |
|
793 { |
|
794 error = Val(prop->iSoft.sadb_lifetime_usetime , EDecimal); |
|
795 } |
|
796 #else |
|
797 error = Val(aSpec.iSoft.sadb_lifetime_usetime, EDecimal); |
|
798 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
799 break; |
|
800 |
|
801 default: |
|
802 User::Leave(EIpsec_PolicyUnknownSpec); |
|
803 } |
|
804 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
805 val = CheckProposalCloseAndMoreProposals(propasalsDefined); |
|
806 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
807 if (error != KErrNone) |
|
808 User::Leave(EIpsec_PolicyNumberExpected); |
|
809 } |
|
810 if (val != token_brace_right) |
|
811 User::Leave(EIpsec_PolicyCloseBraceExpected); |
|
812 else if (sa_type_defined < 1) |
|
813 User::Leave(EIpsec_PolicyNoType); |
|
814 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
815 else if ((aPolicySpec->iSpec.iType == SADB_SATYPE_AH) && !aPolicySpec->iSpec.iAalg) |
|
816 User::Leave(EIpsec_PolicyNoAuthAlgorithm); |
|
817 else if ((aPolicySpec->iSpec.iType == SADB_SATYPE_ESP) && !aPolicySpec->iSpec.iEalg) |
|
818 User::Leave(EIpsec_PolicyNoEncryptAlgorithm); |
|
819 #else |
|
820 else if (sa_type_defined > 1) |
|
821 User::Leave(EIpsec_PolicyTooManyTypes); |
|
822 else if ((aSpec.iType == SADB_SATYPE_AH) && !aSpec.iAalg) |
|
823 User::Leave(EIpsec_PolicyNoAuthAlgorithm); |
|
824 else if ((aSpec.iType == SADB_SATYPE_ESP) && !aSpec.iEalg) |
|
825 User::Leave(EIpsec_PolicyNoEncryptAlgorithm); |
|
826 #endif //SYMBIAN_IPSEC_VOIP_SUPPORT |
|
827 } |
|
828 |
|
829 |
|
830 void TParser::ParseAssociationL() |
|
831 /** |
|
832 * Parse security association |
|
833 * @code name '=' '{' ParseAssociationParametersL |
|
834 * @endcode |
|
835 */ |
|
836 { |
|
837 if (NextToken() != token_string) |
|
838 User::Leave(EIpsec_PolicySpecName); |
|
839 // Allocate a slot for the new association specification |
|
840 CPolicySpec *const ps = new (ELeave) CPolicySpec(); |
|
841 if (iSp->iSpecs.Append(ps) != KErrNone) |
|
842 { |
|
843 ps->Close(); |
|
844 User::Leave(KErrNoMemory); |
|
845 } |
|
846 ps->iName = HBufC::NewMaxL(iToken.Length()); |
|
847 *ps->iName = iToken; |
|
848 |
|
849 if (NextToken() != token_equal || |
|
850 NextToken() != token_brace_left) |
|
851 User::Leave(EIpsec_PolicySyntaxError); |
|
852 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
853 ParseAssociationParametersL(ps); |
|
854 #else |
|
855 ParseAssociationParametersL(ps->iSpec); |
|
856 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
857 } |
|
858 |
|
859 void TParser::ParseSecurityBundleL(RPolicyActions &aActions, CTransportSelector *aTS) |
|
860 /** |
|
861 * Parse security actions |
|
862 * @code [ sa-name '(' [ address ] ')' ]* '}' |
|
863 * @endcode |
|
864 * |
|
865 * Parse a (possibly empty) list of references to security specifications. This will |
|
866 * be the bundle of security actions for a selector. |
|
867 * |
|
868 * @retval aActions The colleted actions |
|
869 * @param aTS The traffic selector. |
|
870 */ |
|
871 { |
|
872 _LIT(K_tunnel, "tunnel"); |
|
873 |
|
874 token_type val; |
|
875 |
|
876 TUint opt = 0; |
|
877 |
|
878 for (;;) |
|
879 { |
|
880 val = NextToken(); |
|
881 // |
|
882 // Experimental addition, allow optional bundle items |
|
883 // by prefixing them with '?'... |
|
884 // |
|
885 if (opt == 0 && val == token_question) |
|
886 { |
|
887 opt = 1; |
|
888 continue; |
|
889 } |
|
890 else if (val != token_string) |
|
891 break; |
|
892 // A temporary(?) special kluge: if the keyword is 'tunnel' |
|
893 // assume this is a plain tunnel specification, without any |
|
894 // relation to the IPSEC. if nobody defined a "tunnel" sa |
|
895 // specification. (should probably disallow 'tunnel' as SA |
|
896 // spec name, to avoid confusion.. ) |
|
897 // |
|
898 CPolicySpec *spec = iSp->FindSpec(iToken); |
|
899 if (spec == NULL && iToken.Compare(K_tunnel) != 0) |
|
900 User::Leave(EIpsec_PolicySpecNotFound); |
|
901 |
|
902 if (NextToken() != token_par_left) |
|
903 User::Leave(EIpsec_PolicyLeftParen); |
|
904 |
|
905 CPolicyAction *action = new (ELeave) CPolicyAction; |
|
906 if (aActions.Append(action) != KErrNone) |
|
907 { |
|
908 action->Close(); |
|
909 User::Leave(KErrNoMemory); |
|
910 } |
|
911 if ((action->iSpec = spec) != NULL) |
|
912 spec->Open(); |
|
913 // Record the current selector into each action (this is to make it |
|
914 // easier to generate the TS list into Acquire message). |
|
915 if ((action->iTS = aTS) != NULL) |
|
916 aTS->Open(); |
|
917 action->iOptional = opt; |
|
918 |
|
919 if ((val = NextToken()) == token_string) |
|
920 { |
|
921 SetAddressOrEndPointL(action->iTunnel, 0, EIpsec_PolicyInvalidIpAddress); |
|
922 action->iIsTunnel = 1; // Flag a tunnel. |
|
923 val = NextToken(); |
|
924 } |
|
925 if (val != token_par_right) |
|
926 User::Leave(EIpsec_PolicyRightParen); |
|
927 opt = 0; // Optional only affects single item at time. |
|
928 } |
|
929 if (val != token_brace_right) |
|
930 User::Leave(EIpsec_PolicyCloseBraceExpected); |
|
931 } |
|
932 |
|
933 |
|
934 void TParser::SetAddressOrEndPointL(RIpAddress &aAddr, TInt aMask, TInt aError) |
|
935 /** |
|
936 * Initiliaze address from current token. |
|
937 * |
|
938 * The token can contain direct address literal or a name of an end point. |
|
939 * If a name is used, it must exist. |
|
940 * |
|
941 * @retval aAddr The address to initialize. |
|
942 * @param aMask Non-zero, if address is used as mask. |
|
943 * @param aError The error to use if end point does not exist (leave) |
|
944 */ |
|
945 { |
|
946 TIpAddress addr; |
|
947 if (addr.SetAddress(iToken, aMask) == KErrNone) |
|
948 { |
|
949 // plain address |
|
950 User::LeaveIfError(aAddr.Open(iEp, addr)); |
|
951 } |
|
952 else if (aAddr.Open(iEp, iToken) != KErrNone) |
|
953 { |
|
954 // Named endpoint not found |
|
955 User::Leave(aError); |
|
956 } |
|
957 } |
|
958 |
|
959 void TParser::ParseAddressL(RIpAddress &aAddr, TInt aMask, TInt aError) |
|
960 /** |
|
961 * Parse next token as address. |
|
962 * @code address |
|
963 * @endcode |
|
964 * |
|
965 * @retval aAddr The address to initialize |
|
966 * @param aMask Non-zero, if address is used as mask. |
|
967 * @param aError The error to use, if error |
|
968 */ |
|
969 { |
|
970 if (NextToken() != token_string) |
|
971 { |
|
972 User::Leave(aError); |
|
973 } |
|
974 else |
|
975 { |
|
976 SetAddressOrEndPointL(aAddr, aMask, aError); |
|
977 } |
|
978 } |
|
979 |
|
980 |
|
981 void TParser::ParseAddressAndMaskL(RIpAddress &aAddr, RIpAddress& aMask) |
|
982 /** |
|
983 * Parse two tokens as addres and address mask |
|
984 * @code ParseAddressL ParseAddressL |
|
985 * @endcode |
|
986 * |
|
987 * @param aAddr The address to initialize |
|
988 * @param aMask The mask to initialize |
|
989 */ |
|
990 { |
|
991 ParseAddressL(aAddr, 0, EIpsec_PolicyIpAddressExpected); |
|
992 ParseAddressL(aMask, 1, EIpsec_PolicyIpMaskExpected); |
|
993 } |
|
994 |
|
995 token_type TParser::TransportSelectorL(CTransportSelector *&aTs) |
|
996 /** |
|
997 * Parse one transport selector. |
|
998 * @code [ |
|
999 * 'remote' ParseAddressAndMaskL | 'local' ParseAddressAndMaskL | |
|
1000 * 'user_id' | 'protocol' number | |
|
1001 * 'local_port' number | 'remote_port' number | |
|
1002 * 'icmp_type' number | 'type' number | 'icmp_code' number ]* |
|
1003 * @endcode |
|
1004 */ |
|
1005 { |
|
1006 static const TKeyword list[] = |
|
1007 { |
|
1008 KEYWORD("remote"), |
|
1009 KEYWORD("local"), |
|
1010 KEYWORD("user_id"), |
|
1011 KEYWORD("protocol"), |
|
1012 KEYWORD("local_port"), |
|
1013 KEYWORD("remote_port"), |
|
1014 KEYWORD("icmp_type"), |
|
1015 KEYWORD("icmp_code"), |
|
1016 KEYWORD("type"), |
|
1017 }; |
|
1018 |
|
1019 enum // Order must be exactly the same as above |
|
1020 { |
|
1021 KEYENUM(remote), |
|
1022 KEYENUM(local), |
|
1023 KEYENUM(user_id), |
|
1024 KEYENUM(protocol), |
|
1025 KEYENUM(local_port), |
|
1026 KEYENUM(remote_port), |
|
1027 KEYENUM(icmp_type), |
|
1028 KEYENUM(icmp_code), |
|
1029 KEYENUM(type), // synonym for "icmp_type" (use for MH and similar) |
|
1030 |
|
1031 KEYENUM(max_parameters) |
|
1032 }; |
|
1033 |
|
1034 token_type val; |
|
1035 // |
|
1036 // By default, a new selector will match everything (mask is all zero) |
|
1037 // |
|
1038 RPolicySelectorInfo data; |
|
1039 RPolicySelectorInfo mask; |
|
1040 data.FillZ(); |
|
1041 mask.FillZ(); |
|
1042 |
|
1043 #if OLD_SELECTOR_ORDERING |
|
1044 // If selector already exists, continue filling it. |
|
1045 if (aTs != NULL) |
|
1046 { |
|
1047 data = aTs->iData; |
|
1048 mask = aTs->iMask; |
|
1049 aTs->Close(); |
|
1050 aTs = NULL; |
|
1051 } |
|
1052 #endif |
|
1053 |
|
1054 do |
|
1055 { |
|
1056 TUint8 tmp8; |
|
1057 |
|
1058 switch (Lookup(list, E_max_parameters, iToken)) |
|
1059 { |
|
1060 case E_remote: |
|
1061 ParseAddressAndMaskL(data.iRemote, mask.iRemote); |
|
1062 break; |
|
1063 case E_local: |
|
1064 ParseAddressAndMaskL(data.iLocal, mask.iLocal); |
|
1065 break; |
|
1066 case E_user_id: |
|
1067 break; // Needs to be examined, TIdentity? -- msa |
|
1068 case E_protocol: |
|
1069 mask.iProtocol = 0xFF; |
|
1070 User::LeaveIfError(Val(data.iProtocol, EDecimal)); |
|
1071 break; |
|
1072 case E_local_port: |
|
1073 if (mask.iPortLocal) |
|
1074 User::Leave(EIpsec_PolicySyntaxError); // Already defined (or type/code) |
|
1075 mask.iPortLocal = 0xFFFF; |
|
1076 User::LeaveIfError(Val(data.iPortLocal, EDecimal)); |
|
1077 mask.iFlags |= KTransportSelector_PORTS; |
|
1078 data.iFlags |= KTransportSelector_PORTS; |
|
1079 break; |
|
1080 case E_remote_port: |
|
1081 if (mask.iPortRemote) |
|
1082 User::Leave(EIpsec_PolicySyntaxError); // Already defined |
|
1083 mask.iPortRemote = ~0; |
|
1084 User::LeaveIfError(Val(data.iPortRemote, EDecimal)); |
|
1085 mask.iFlags |= KTransportSelector_PORTS; |
|
1086 data.iFlags |= KTransportSelector_PORTS; |
|
1087 break; |
|
1088 case E_icmp_type: |
|
1089 case E_type: |
|
1090 if ((mask.iPortLocal | mask.iPortRemote) & 0xFF00) |
|
1091 User::Leave(EIpsec_PolicySyntaxError); // Already defined (or port used) |
|
1092 mask.iPortLocal |= 0xFF00; |
|
1093 User::LeaveIfError(Val(tmp8, EDecimal)); |
|
1094 data.iPortLocal |= tmp8 << 8; |
|
1095 // For Type/Code remote port selector is always same as local port value |
|
1096 mask.iPortRemote = mask.iPortLocal; |
|
1097 data.iPortRemote = data.iPortLocal; |
|
1098 mask.iFlags |= KTransportSelector_PORTS; |
|
1099 data.iFlags &= ~KTransportSelector_PORTS; |
|
1100 break; |
|
1101 case E_icmp_code: |
|
1102 if ((mask.iPortLocal | mask.iPortRemote) & 0x00FF) |
|
1103 User::Leave(EIpsec_PolicySyntaxError); // Already defined (or port used) |
|
1104 mask.iPortLocal |= 0x00FF; |
|
1105 User::LeaveIfError(Val(tmp8, EDecimal)); |
|
1106 data.iPortLocal |= tmp8; |
|
1107 // For Type/Code remote port selector is always same as local port value |
|
1108 mask.iPortRemote = mask.iPortLocal; |
|
1109 data.iPortRemote = data.iPortLocal; |
|
1110 mask.iFlags |= KTransportSelector_PORTS; |
|
1111 data.iFlags &= ~KTransportSelector_PORTS; |
|
1112 break; |
|
1113 default: |
|
1114 #if OLD_SELECTOR_ORDERING |
|
1115 val = token_string; |
|
1116 goto wrapup; |
|
1117 #else |
|
1118 User::Leave(EIpsec_PolicyUnknownSelector); |
|
1119 #endif |
|
1120 } |
|
1121 } |
|
1122 while |
|
1123 ((val = NextToken()) == token_string); |
|
1124 #if OLD_SELECTOR_ORDERING |
|
1125 wrapup: |
|
1126 #endif |
|
1127 aTs = new (ELeave) CTransportSelector(data, mask, NULL); |
|
1128 return val; |
|
1129 } |
|
1130 |
|
1131 void TParser::ParseSelectorL(CPolicySelector *&aPs) |
|
1132 /** |
|
1133 * Parse a policy selector |
|
1134 * @code [ 'final' | 'merge' | 'outbound' | 'inbound' | 'if' interface ]* |
|
1135 * TransportSelectorL '=' ( '{' ParseSecurityBundleL | 'drop' ) |
|
1136 * @endcode |
|
1137 */ |
|
1138 { |
|
1139 static const TKeyword list[] = |
|
1140 { |
|
1141 KEYWORD("final"), |
|
1142 KEYWORD("merge"), |
|
1143 KEYWORD("outbound"), |
|
1144 KEYWORD("inbound"), |
|
1145 KEYWORD("if"), |
|
1146 }; |
|
1147 |
|
1148 enum // Order must be exactly the same as above |
|
1149 { |
|
1150 KEYENUM(final), |
|
1151 KEYENUM(merge), |
|
1152 KEYENUM(outbound), |
|
1153 KEYENUM(inbound), |
|
1154 KEYENUM(if), |
|
1155 |
|
1156 KEYENUM(max_parameters) |
|
1157 }; |
|
1158 |
|
1159 _LIT(K_drop, "drop"); |
|
1160 |
|
1161 token_type val; |
|
1162 // |
|
1163 aPs = new (ELeave) CPolicySelector(); |
|
1164 |
|
1165 // |
|
1166 // ...by default the "merge" must be off to match. |
|
1167 // |
|
1168 aPs->iFilterMask = KPolicyFilter_MERGE; |
|
1169 |
|
1170 do |
|
1171 { |
|
1172 #if OLD_SELECTOR_ORDERING |
|
1173 check_again: |
|
1174 #endif |
|
1175 switch (Lookup(list, E_max_parameters, iToken)) |
|
1176 { |
|
1177 case E_final: |
|
1178 if (aPs->iFilterData & KPolicyFilter_FINAL) |
|
1179 User::Leave(EIpsec_PolicySyntaxError); // Duplicate "final" keyword. |
|
1180 // No need to set "mask", this is a flag only. |
|
1181 aPs->iFilterData |= KPolicyFilter_FINAL; |
|
1182 break; |
|
1183 case E_merge: |
|
1184 if ((aPs->iFilterMask & KPolicyFilter_MERGE) == 0) |
|
1185 User::Leave(EIpsec_PolicySyntaxError); // Duplicate "merge" keyword. |
|
1186 aPs->iFilterMask &= ~KPolicyFilter_MERGE; // allow this selector to be merged. |
|
1187 break; |
|
1188 case E_outbound: |
|
1189 if (aPs->iFilterData & KPolicyFilter_SYMMETRIC) |
|
1190 User::Leave(EIpsec_PolicyInboundOutbound); |
|
1191 aPs->iFilterData |= KPolicyFilter_OUTBOUND; |
|
1192 aPs->iFilterMask |= KPolicyFilter_OUTBOUND; |
|
1193 break; |
|
1194 case E_inbound: |
|
1195 if (aPs->iFilterData & KPolicyFilter_SYMMETRIC) |
|
1196 User::Leave(EIpsec_PolicyInboundOutbound); |
|
1197 aPs->iFilterData |= KPolicyFilter_INBOUND; |
|
1198 aPs->iFilterMask |= KPolicyFilter_INBOUND; |
|
1199 break; |
|
1200 case E_if: |
|
1201 if (aPs->iInterface || NextToken() != token_string) |
|
1202 User::Leave(EIpsec_PolicySyntaxError); // <-- need own error code? |
|
1203 aPs->iInterface = iSp->LookupInterfaceL(iToken); |
|
1204 break; |
|
1205 default: |
|
1206 val = TransportSelectorL(aPs->iTS); |
|
1207 #if OLD_SELECTOR_ORDERING |
|
1208 if (Lookup(list, E_max_parameters, iToken) < E_max_parameters) |
|
1209 goto check_again; |
|
1210 #endif |
|
1211 goto wrapup; |
|
1212 } |
|
1213 } |
|
1214 while |
|
1215 ((val = NextToken()) == token_string); |
|
1216 wrapup: |
|
1217 |
|
1218 if (val != token_equal) |
|
1219 User::Leave(EIpsec_PolicySyntaxError); |
|
1220 if (NextToken() == token_brace_left) |
|
1221 ParseSecurityBundleL(aPs->iActions, aPs->iTS); |
|
1222 else if (iToken.Compare(K_drop) == 0) |
|
1223 aPs->iFilterData |= KPolicyFilter_DROP; |
|
1224 else |
|
1225 User::Leave(EIpsec_PolicySyntaxError); |
|
1226 } |
|
1227 |
|
1228 #ifdef __VC32__ |
|
1229 #pragma warning(disable : 4097) // typedef-name used as synonym for class-name |
|
1230 #endif |
|
1231 |
|
1232 TParser::TParser(CSecurityPolicy *aSp, const TDesC &aPolicy, REndPoints &aEp) : |
|
1233 TLex(aPolicy), iSp(aSp), iEp(aEp) |
|
1234 { |
|
1235 } |
|
1236 |
|
1237 void TParser::ParseL(TUint aStartOffset) |
|
1238 /** |
|
1239 * Parse complete security policy |
|
1240 * @code ( |
|
1241 * 'sa' ParseAssociationL | |
|
1242 * 'encrypt' ParseAlgorithmMappingL | |
|
1243 * 'auth' ParseAlgorithmMappingL | |
|
1244 * 'ep' ParseEndPointL )* |
|
1245 * @endcode |
|
1246 * |
|
1247 * @param aStartOffset Starting offset of the actual policy |
|
1248 * @leave error on syntax or other error. |
|
1249 */ |
|
1250 { |
|
1251 static const TKeyword list[] = |
|
1252 { |
|
1253 KEYWORD("sa"), |
|
1254 KEYWORD("encrypt"), |
|
1255 KEYWORD("auth"), |
|
1256 KEYWORD("ep"), |
|
1257 }; |
|
1258 enum |
|
1259 { |
|
1260 KEYENUM(sa), |
|
1261 KEYENUM(encrypt), |
|
1262 KEYENUM(auth), |
|
1263 KEYENUM(ep), |
|
1264 |
|
1265 KEYENUM(max_list) |
|
1266 }; |
|
1267 |
|
1268 CPolicySelector **last = &iSp->iSelectors; |
|
1269 |
|
1270 Inc(aStartOffset); |
|
1271 while (NextToken() == token_string) |
|
1272 { |
|
1273 switch (Lookup(list, E_max_list, iToken)) |
|
1274 { |
|
1275 case E_sa: |
|
1276 ParseAssociationL(); |
|
1277 break; |
|
1278 case E_encrypt: |
|
1279 ParseAlgorithmMappingL(EAlgorithmClass_Cipher); |
|
1280 break; |
|
1281 case E_auth: |
|
1282 ParseAlgorithmMappingL(EAlgorithmClass_Digest); |
|
1283 break; |
|
1284 case E_ep: |
|
1285 ParseEndPointL(); |
|
1286 break; |
|
1287 default: |
|
1288 ParseSelectorL(*last); |
|
1289 if (*last) |
|
1290 last = &(*last)->iNext; |
|
1291 break; |
|
1292 } |
|
1293 } |
|
1294 if (!Eos()) |
|
1295 // Parsing didn't detect error, but not all parsed! |
|
1296 User::Leave(EIpsec_PolicySyntaxError); |
|
1297 } |
|
1298 |
|
1299 |
|
1300 CSecurityPolicy::CSecurityPolicy() |
|
1301 /** |
|
1302 * Constructor. |
|
1303 */ |
|
1304 { |
|
1305 IPSEC_OBJECT_INC; |
|
1306 } |
|
1307 |
|
1308 |
|
1309 TInt CSecurityPolicy::SetPolicy(CSecurityPolicy * &aPolicy, const TDesC &aNewPolicy, TUint &aOffset, REndPoints &aEp) |
|
1310 /** |
|
1311 * Construct a new binary policy and replace a the current with it. |
|
1312 * |
|
1313 * @retval aPolicy Holder of the current binary policy |
|
1314 * @param aNewPolicy The new policy definition (text string) |
|
1315 * @retval aOffset The initial start, and final point in parsing |
|
1316 * @param aEp The End point collection to store the named endpoints |
|
1317 * |
|
1318 * @return KErrNone on success, and some < 0 error code otherwise. |
|
1319 */ |
|
1320 { |
|
1321 delete aPolicy; |
|
1322 aPolicy = new CSecurityPolicy(); |
|
1323 if (aPolicy == NULL) |
|
1324 return KErrNoMemory; |
|
1325 |
|
1326 TParser parser(aPolicy, aNewPolicy, aEp); |
|
1327 aPolicy->iAlgorithms = new CAlgorithmList; |
|
1328 if (aPolicy->iAlgorithms == NULL) |
|
1329 return KErrNoMemory; |
|
1330 TRAPD(result, parser.ParseL(aOffset); ); |
|
1331 aOffset = parser.MarkedOffset(); |
|
1332 return result; |
|
1333 } |
|
1334 |
|
1335 CSecurityPolicy::~CSecurityPolicy() |
|
1336 /** |
|
1337 * Descructor. |
|
1338 */ |
|
1339 { |
|
1340 // release association descriptions/templates |
|
1341 for (TInt i = iSpecs.Count(); --i >= 0; ) |
|
1342 { |
|
1343 CPolicySpec *const s = iSpecs[i]; |
|
1344 if (s) |
|
1345 s->Close(); |
|
1346 } |
|
1347 iSpecs.Close(); |
|
1348 |
|
1349 // release End Points assocated with this policy |
|
1350 for (TInt j = iEndPoints.Count(); --j >= 0; ) |
|
1351 { |
|
1352 iEndPoints[j].Close(); |
|
1353 } |
|
1354 iEndPoints.Close(); |
|
1355 |
|
1356 // release the policy selectors |
|
1357 CPolicySelector *ps; |
|
1358 while ((ps = iSelectors) != NULL) |
|
1359 { |
|
1360 iSelectors = ps->iNext; |
|
1361 delete ps; |
|
1362 } |
|
1363 |
|
1364 // release the named interface entries |
|
1365 while (iInterfaces) |
|
1366 { |
|
1367 CSelectorInterface *tmp = iInterfaces; |
|
1368 iInterfaces = tmp->iNext; |
|
1369 delete tmp; |
|
1370 } |
|
1371 |
|
1372 // ..and algorithms table |
|
1373 delete iAlgorithms; |
|
1374 IPSEC_OBJECT_DEC; |
|
1375 } |
|
1376 |
|
1377 CPolicySelector::CPolicySelector() |
|
1378 /** |
|
1379 * Constructor |
|
1380 */ |
|
1381 { |
|
1382 IPSEC_OBJECT_INC; |
|
1383 } |
|
1384 |
|
1385 CPolicySelector::~CPolicySelector() |
|
1386 /** |
|
1387 * Descructor. |
|
1388 */ |
|
1389 { |
|
1390 |
|
1391 // Release policy actions |
|
1392 for (TInt i = iActions.Count(); --i >= 0; ) |
|
1393 { |
|
1394 CPolicyAction *const action = iActions[i]; |
|
1395 if (action) |
|
1396 action->Close(); |
|
1397 } |
|
1398 iActions.Close(); |
|
1399 |
|
1400 // Release transport selector(s) |
|
1401 if (iTS) |
|
1402 iTS->Close(); |
|
1403 |
|
1404 IPSEC_OBJECT_DEC; |
|
1405 } |
|
1406 |
|
1407 // |
|
1408 CSelectorInterface::CSelectorInterface() |
|
1409 /** |
|
1410 * Constructor |
|
1411 */ |
|
1412 { |
|
1413 IPSEC_OBJECT_INC; |
|
1414 } |
|
1415 |
|
1416 CSelectorInterface::~CSelectorInterface() |
|
1417 /** |
|
1418 * Descructor. |
|
1419 */ |
|
1420 { |
|
1421 delete iName; |
|
1422 IPSEC_OBJECT_DEC; |
|
1423 } |
|
1424 |
|
1425 const CSelectorInterface *CSecurityPolicy::LookupInterfaceL(const TDesC &aName) |
|
1426 /** |
|
1427 * Locate interface by name from policy. |
|
1428 * |
|
1429 * Return an existing interface object, if found and otherwise, |
|
1430 * create and initialize new object. |
|
1431 * |
|
1432 * @param aName The interface name |
|
1433 * @return The interface |
|
1434 * @leave KErrNoMemory, if allocation fails. |
|
1435 */ |
|
1436 { |
|
1437 CSelectorInterface *si; |
|
1438 // |
|
1439 // See if interface already exists |
|
1440 // |
|
1441 for (si = iInterfaces; si != NULL; si = si->iNext) |
|
1442 if (aName.Compare(*si->iName) == 0) |
|
1443 return si; // Already exists, reuse |
|
1444 // |
|
1445 // First time occurrence of this interface name, create a new entry |
|
1446 // |
|
1447 si = new (ELeave) CSelectorInterface(); |
|
1448 si->iNext = iInterfaces; |
|
1449 iInterfaces = si; |
|
1450 si->iName = HBufC::NewMaxL(aName.Length()); |
|
1451 *si->iName = aName; |
|
1452 return si; |
|
1453 } |
|
1454 |
|
1455 CPolicySpec *CSecurityPolicy::FindSpec(const TDesC &aName) const |
|
1456 /** |
|
1457 * Locate security association specification by name. |
|
1458 * |
|
1459 * @param aName |
|
1460 * @return The specification or NULL, if not found |
|
1461 * |
|
1462 */ |
|
1463 { |
|
1464 for (TInt i = iSpecs.Count(); i > 0; ) |
|
1465 { |
|
1466 CPolicySpec *const s = iSpecs[--i]; |
|
1467 if (aName.Compare(*s->iName) == 0) |
|
1468 return s; |
|
1469 } |
|
1470 return NULL; |
|
1471 } |
|
1472 |
|
1473 // |
|
1474 |
|
1475 CPolicyAction::~CPolicyAction() |
|
1476 /** |
|
1477 * Desctructor. |
|
1478 */ |
|
1479 { |
|
1480 if (iSpec) |
|
1481 iSpec->Close(); |
|
1482 if (iTS) |
|
1483 iTS->Close(); |
|
1484 } |
|
1485 |
|
1486 // |
|
1487 |
|
1488 CPolicySpec::CPolicySpec() |
|
1489 { |
|
1490 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
1491 iPropList = CPropList::NewL(1); |
|
1492 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
1493 } |
|
1494 |
|
1495 |
|
1496 CPolicySpec::~CPolicySpec() |
|
1497 /** |
|
1498 * Destructor. |
|
1499 */ |
|
1500 { |
|
1501 delete iName; |
|
1502 // |
|
1503 // Identity blocks are reference counted, there |
|
1504 // may still be SA's referring to them |
|
1505 // |
|
1506 if (iSpec.iIdentityLocal) |
|
1507 iSpec.iIdentityLocal->Close(); |
|
1508 if (iSpec.iIdentityRemote) |
|
1509 iSpec.iIdentityRemote->Close(); |
|
1510 } |