networksecurity/ipsec/ipsec6/src/spdb.cpp
changeset 0 af10295192d8
child 20 7e41d162e158
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     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 	}