|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: IKEv1/IPSEC SA negotiation |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <x509cert.h> |
|
19 #include <x500dn.h> |
|
20 #include <random.h> |
|
21 #include <vpnlogmessages.rsg> |
|
22 |
|
23 #include "ikev1negotiation.h" |
|
24 #include "ikedebug.h" |
|
25 #include "ikev1isakmpstream.h" |
|
26 #include "ikev1timeout.h" |
|
27 #include "ikev1payload.h" |
|
28 #include "ikev1plugin.h" |
|
29 #include "ikev1crack.h" |
|
30 #include "ikev1trans.h" |
|
31 #include "ipsecsadata.h" |
|
32 #include "ipsecsalifetime.h" |
|
33 #include "pfkeymsg.h" |
|
34 #include "kmdapi.h" |
|
35 #include "ikev1pkiservice.h" |
|
36 #include "ikev1crypto.h" |
|
37 #include "ikev1natdiscovery.h" |
|
38 #include "ikev1private.h" |
|
39 #include "vpnapidefs.h" |
|
40 #include "ikepkiutils.h" |
|
41 #include "vpnclientuids.h" |
|
42 #include "ikecalist.h" |
|
43 #include "ikecaelem.h" |
|
44 #include "ikecert.h" |
|
45 #include "ikev1pluginsession.h" |
|
46 #include "ikesocketdefs.h" |
|
47 #include "kmdeventloggerif.h" |
|
48 #include "pfkeyextdatautil.h" |
|
49 #include "ipsecsalist.h" |
|
50 |
|
51 const TInt KSubjectName = 1; |
|
52 |
|
53 ///////////////////////////////////////////////////////////////////////////////// |
|
54 // CIkev1Negotiation related stuff |
|
55 ///////////////////////////////////////////////////////////////////////////////// |
|
56 |
|
57 |
|
58 // |
|
59 //Proto negotiation to send a informational payload and be destroyed |
|
60 // |
|
61 CIkev1Negotiation* CIkev1Negotiation::NewL( CIkev1PluginSession* aPluginSession, |
|
62 CPFKeySocketIf& aPFKeySocketIf, |
|
63 MIkeDebug& aDebug, |
|
64 const TInetAddr& aRemote, |
|
65 const TCookie& aInitiator, |
|
66 const TCookie& aResponder ) |
|
67 { |
|
68 CIkev1Negotiation* self = new ( ELeave ) CIkev1Negotiation( aPluginSession, |
|
69 aPFKeySocketIf, |
|
70 aDebug ); |
|
71 CleanupStack::PushL( self ); |
|
72 self->iRemoteAddr = aRemote; |
|
73 self->iCookie_I = aInitiator; |
|
74 self->iCookie_R = aResponder; |
|
75 self->iExchange = ISAKMP_EXCHANGE_INFO; |
|
76 self->iDOI = IPSEC_DOI; |
|
77 self->iTimer = CIkev1Timeout::NewL( *self ); |
|
78 CleanupStack::Pop( self ); |
|
79 return self; |
|
80 } |
|
81 |
|
82 CIkev1Negotiation* CIkev1Negotiation::NewL( CIkev1PluginSession* aPluginSession, |
|
83 CPFKeySocketIf& aPFKeySocketIf, |
|
84 MIkeDebug& aDebug, |
|
85 const TInetAddr& aRemote, |
|
86 const TCookie& aInitiator, |
|
87 TBool aAutoLogin ) |
|
88 { |
|
89 CIkev1Negotiation* self = new ( ELeave ) CIkev1Negotiation( aPluginSession, |
|
90 aPFKeySocketIf, |
|
91 aDebug, |
|
92 aRemote, |
|
93 aInitiator ); |
|
94 CleanupStack::PushL( self ); |
|
95 self->ConstructL( aAutoLogin ); |
|
96 CleanupStack::Pop( self ); |
|
97 return self; |
|
98 } |
|
99 |
|
100 CIkev1Negotiation* CIkev1Negotiation::NewL( CIkev1PluginSession* aPluginSession, |
|
101 CPFKeySocketIf& aPFKeySocketIf, |
|
102 MIkeDebug& aDebug, |
|
103 TIkev1SAData* aIkev1SAdata, |
|
104 TUint aRole, |
|
105 const TPfkeyMessage *aReq ) |
|
106 { |
|
107 CIkev1Negotiation* self = new ( ELeave ) CIkev1Negotiation( aPluginSession, |
|
108 aPFKeySocketIf, |
|
109 aDebug ); |
|
110 CleanupStack::PushL( self ); |
|
111 self->ConstructL( aIkev1SAdata, aRole, aReq ); |
|
112 CleanupStack::Pop( self ); |
|
113 return self; |
|
114 } |
|
115 |
|
116 |
|
117 CIkev1Negotiation* CIkev1Negotiation::NewL( CIkev1PluginSession* aPluginSession, |
|
118 CPFKeySocketIf& aPFKeySocketIf, |
|
119 MIkeDebug& aDebug, |
|
120 const TInetAddr& aRemote, |
|
121 TBool aAutoLogin ) |
|
122 { |
|
123 CIkev1Negotiation* self = new ( ELeave ) CIkev1Negotiation( aPluginSession, |
|
124 aPFKeySocketIf, |
|
125 aDebug, |
|
126 aRemote ); |
|
127 CleanupStack::PushL( self ); |
|
128 self->iCookie_I = self->CreateCookieL(); |
|
129 self->ConstructL( aAutoLogin ); |
|
130 CleanupStack::Pop( self ); |
|
131 return self; |
|
132 } |
|
133 |
|
134 CIkev1Negotiation* CIkev1Negotiation::NewL( CIkev1PluginSession* aPluginSession, |
|
135 CPFKeySocketIf& aPFKeySocketIf, |
|
136 MIkeDebug& aDebug, |
|
137 const TInetAddr& aRemote, |
|
138 const TPfkeyMessage& aReq ) |
|
139 { |
|
140 CIkev1Negotiation* self = new ( ELeave ) CIkev1Negotiation( aPluginSession, |
|
141 aPFKeySocketIf, |
|
142 aDebug, |
|
143 aRemote ); |
|
144 CleanupStack::PushL( self ); |
|
145 self->iCookie_I = self->CreateCookieL(); |
|
146 self->ConstructL( aReq ); |
|
147 CleanupStack::Pop( self ); |
|
148 return self; |
|
149 } |
|
150 |
|
151 // |
|
152 // Destructor |
|
153 // |
|
154 CIkev1Negotiation::~CIkev1Negotiation() |
|
155 { |
|
156 DEBUG_LOG1( _L("CIkev1Negotiation::~CIkev1Negotiation this=0x%x"), this ); |
|
157 |
|
158 |
|
159 if ( iRole == INITIATOR && |
|
160 iAcquirePending ) |
|
161 { |
|
162 // Response with error to pending Acquire. |
|
163 AcquireSAErrorResponse( KKmdIkeNegotFailed ); |
|
164 } |
|
165 |
|
166 delete iIpsecSaSpiRetriever; |
|
167 delete iSavedIkeMsgBfr; |
|
168 |
|
169 if( iPluginSession ) |
|
170 { |
|
171 iPluginSession->RemoveNegotiation( this ); |
|
172 } |
|
173 |
|
174 iCookie_I.FillZ(ISAKMP_COOKIE_SIZE); |
|
175 |
|
176 if(iTimer) |
|
177 { |
|
178 iTimer->Cancel(); |
|
179 delete iTimer; |
|
180 } |
|
181 |
|
182 delete iOwnCert; |
|
183 delete iPeerX509Cert; |
|
184 delete iPeerTrustedCA; // Peer trusted CA name |
|
185 delete iICA1; |
|
186 delete iICA2; |
|
187 |
|
188 delete iPkiService; // Trusted CA certificate list |
|
189 |
|
190 delete iSAPayload; |
|
191 delete iPeerIdentPayload; |
|
192 delete iOwnIdentPayload; |
|
193 |
|
194 //Keys |
|
195 delete iOwnKeys; //structure containing the public and private keys |
|
196 delete iOwnPublicKey; //Public Key |
|
197 |
|
198 //Phase_I Proposal |
|
199 TAttrib *attr; |
|
200 while ((attr = iProposal_I.iAttrList) != NULL) |
|
201 { |
|
202 iProposal_I.iAttrList = attr->iNext; |
|
203 delete attr; |
|
204 } |
|
205 |
|
206 delete iChosenProposal_I.iAttrList; //Only one transformation chosen |
|
207 |
|
208 //Phase_II proposals (include transformations) |
|
209 delete iProposal_IIList; |
|
210 |
|
211 //Phase_II chosen Proposal |
|
212 delete iChosenProp_IIList; |
|
213 delete iInboundSPIList; |
|
214 delete iCRACKneg; |
|
215 delete iTransactionNeg; // Transaction exchange |
|
216 delete iInternalAddr; |
|
217 delete iNatDiscovery; |
|
218 delete iSARekeyInfo; |
|
219 delete iLastMsg; |
|
220 } |
|
221 |
|
222 |
|
223 // |
|
224 // CIkev1Negotiation |
|
225 // Constructor for remote initiated negotiation |
|
226 // |
|
227 CIkev1Negotiation::CIkev1Negotiation( CIkev1PluginSession* aPluginSession, |
|
228 CPFKeySocketIf& aPFKeySocketIf, |
|
229 MIkeDebug& aDebug, |
|
230 const TInetAddr& aRemote, |
|
231 const TCookie& aInitiator ) |
|
232 : iCookie_I( aInitiator ), |
|
233 iRemoteAddr( aRemote ), |
|
234 iPluginSession( aPluginSession ), |
|
235 iPFKeySocketIf( aPFKeySocketIf ), |
|
236 iDebug( aDebug ) |
|
237 { |
|
238 |
|
239 DEBUG_LOG1( _L("CIkev1Negotiation::CIkev1Negotiation, RESPONDER this=0x%x"), this ); |
|
240 iCookie_R.FillZ(ISAKMP_COOKIE_SIZE); |
|
241 iSAId = iPluginSession->GetSAId(); |
|
242 iPluginSession->LinkNegotiation(this); |
|
243 iRole = RESPONDER; |
|
244 iStage = 1; //next phase for the responder is 2 |
|
245 } |
|
246 |
|
247 // |
|
248 // Constructor for local initiated negotiation |
|
249 // |
|
250 |
|
251 CIkev1Negotiation::CIkev1Negotiation( CIkev1PluginSession* aPluginSession, |
|
252 CPFKeySocketIf& aPFKeySocketIf, |
|
253 MIkeDebug& aDebug, |
|
254 const TInetAddr& aRemote ) |
|
255 : iRemoteAddr( aRemote ), |
|
256 iPluginSession( aPluginSession ), |
|
257 iPFKeySocketIf( aPFKeySocketIf ), |
|
258 iDebug( aDebug ) |
|
259 { |
|
260 DEBUG_LOG1( _L("CIkev1Negotiation::CIkev1Negotiation, INITIATOR this=0x%x"), this ); |
|
261 iCookie_I.FillZ(ISAKMP_COOKIE_SIZE); |
|
262 iCookie_R.FillZ(ISAKMP_COOKIE_SIZE); |
|
263 iSAId = iPluginSession->GetSAId(); |
|
264 iPluginSession->LinkNegotiation(this); |
|
265 iRole = INITIATOR; |
|
266 iStage = 0; |
|
267 } |
|
268 |
|
269 // |
|
270 // Constructor for Phase II initiated negotiations |
|
271 // |
|
272 |
|
273 CIkev1Negotiation::CIkev1Negotiation( CIkev1PluginSession* aPluginSession, |
|
274 CPFKeySocketIf& aPFKeySocketIf, |
|
275 MIkeDebug& aDebug ) |
|
276 : iPluginSession( aPluginSession ), |
|
277 iPFKeySocketIf( aPFKeySocketIf ), |
|
278 iDebug( aDebug ) |
|
279 { |
|
280 DEBUG_LOG1( _L("CIkev1Negotiation::CIkev1Negotiation, this=0x%x"), this ); |
|
281 iCookie_I.FillZ(ISAKMP_COOKIE_SIZE); |
|
282 iCookie_R.FillZ(ISAKMP_COOKIE_SIZE); |
|
283 iSAId = iPluginSession->GetSAId(); |
|
284 iPluginSession->LinkNegotiation(this); |
|
285 } |
|
286 |
|
287 //Used when creating a negotiation as a RESPONDER! |
|
288 //Used also when Initiator (= Phase 1 negotiation stated by the policy activation) |
|
289 //Leaves if error detected |
|
290 void CIkev1Negotiation::ConstructL(TBool aAutoLogin) |
|
291 { |
|
292 iIpsecSaSpiRetriever = CIpsecSaSpiRetriever::NewL( *this, |
|
293 iPFKeySocketIf ); |
|
294 |
|
295 iAutoLogin = aAutoLogin; |
|
296 CommonConstructL(); |
|
297 } |
|
298 |
|
299 |
|
300 //Used when an Acquire is received |
|
301 //Leaves if error detected |
|
302 void CIkev1Negotiation::ConstructL(const TPfkeyMessage &aReq) |
|
303 { |
|
304 iIpsecSaSpiRetriever = CIpsecSaSpiRetriever::NewL( *this, |
|
305 iPFKeySocketIf ); |
|
306 |
|
307 CommonConstructL(); |
|
308 GetAcquireDataL(aReq); |
|
309 } |
|
310 |
|
311 //Used when initiating a new Phase II negotiation from a negotiated ISAKMP SA. |
|
312 void CIkev1Negotiation::ConstructL( TIkev1SAData* aSA, |
|
313 TUint aRole, |
|
314 const TPfkeyMessage *aReq ) |
|
315 { |
|
316 |
|
317 iIpsecSaSpiRetriever = CIpsecSaSpiRetriever::NewL( *this, |
|
318 iPFKeySocketIf ); |
|
319 |
|
320 iPhase = PHASE_II; |
|
321 |
|
322 //Almost like common construct |
|
323 iTimer = CIkev1Timeout::NewL(*this); |
|
324 |
|
325 //Phase II proposal lists |
|
326 iProposal_IIList = new (ELeave) CProposal_IIList(1); |
|
327 |
|
328 iRemoteAddr.SetPort(IKE_PORT); |
|
329 |
|
330 iSeq = aSA->iSeq; |
|
331 iLocalAddr = aSA->iLocalAddr; |
|
332 iRemoteAddr = aSA->iRemoteAddr; // Remote Address from peer |
|
333 iLastRemoteAddr = aSA->iDestinAddr; // Remote Address last transmitted |
|
334 |
|
335 iLastIKEMsgInfo = aSA->iLastIKEMsgInfo; |
|
336 iLastMsg = HBufC8::NewL(4096); |
|
337 if ( aSA->iLastMsg != NULL ) |
|
338 { |
|
339 *iLastMsg = *aSA->iLastMsg; |
|
340 } |
|
341 |
|
342 iRole = aRole; // If we are initiator or responder |
|
343 |
|
344 //Header Data |
|
345 iCookie_I = aSA->iCookie_I; // Initiator Cookie (Used with responder to create KEYID) |
|
346 iCookie_R = aSA->iCookie_R; // Responder Cookie |
|
347 iPrevExchange = aSA->iPrevExchange; |
|
348 iExchange = IKE_QUICK_MODE; |
|
349 |
|
350 iMessageId = RandomMessageId(); |
|
351 |
|
352 iFlags = aSA->iFlags; // Flags in the msg header |
|
353 |
|
354 // iNotifyMessageId = aSA->iHdr.iNotifyMessageId; // Message Id. for Informational Exchanges |
|
355 |
|
356 //SA Data |
|
357 iDOI = IPSEC_DOI; |
|
358 |
|
359 iChosenProposal_I.iProtocol = PROTO_ISAKMP; |
|
360 iChosenProposal_I.iProposalNum = 0; |
|
361 // iChosenProposal_I.iSPI.Copy(aSA->iChosenProposal_I.iSPI); |
|
362 iChosenProposal_I.iNumTransforms = 1; |
|
363 iChosenProposal_I.iAttrList = new (ELeave) TAttrib; //allocated now and deleted when destroying the obj |
|
364 // *iChosenProposal_I.iAttrList = *aSA->iChosenProposal_I.iAttrList; |
|
365 iChosenProposal_I.iAttrList->iEncrAlg = aSA->iEncrAlg; |
|
366 iChosenProposal_I.iAttrList->iHashAlg = aSA->iHashAlg; |
|
367 iChosenProposal_I.iAttrList->iGroupDesc = aSA->iGroupDesc; |
|
368 iChosenProposal_I.iAttrList->iGroupType = aSA->iGroupType; |
|
369 iChosenProposal_I.iAttrList->iKeyLength = aSA->iKeyLength; |
|
370 if ( aSA->iLifeTimeSecs ) |
|
371 iChosenProposal_I.iAttrList->iLifeDurationSecs.Copy((TUint8 *)&aSA->iLifeTimeSecs, sizeof(TUint32)); |
|
372 if ( aSA->iLifeTimeKB ) |
|
373 iChosenProposal_I.iAttrList->iLifeDurationKBytes.Copy((TUint8 *)&aSA->iLifeTimeKB, sizeof(TUint32)); |
|
374 |
|
375 |
|
376 iHostData = aSA->iIkeData; |
|
377 if ( iHostData->iCAList && iHostData->iCAList->Count() ) |
|
378 { |
|
379 iPkiService = CIkeV1PkiService::NewL(iHostData, iDebug); |
|
380 } |
|
381 |
|
382 if (aRole == INITIATOR) |
|
383 { |
|
384 GetAcquireDataL(*aReq); //Data needed from the acquire |
|
385 } |
|
386 else //RESPONDER |
|
387 { |
|
388 iAcquireSeq = 1; //msg Seq. number |
|
389 } |
|
390 |
|
391 // |
|
392 //NAT Traversal data |
|
393 // |
|
394 iFamiliarPeer = aSA->iFamiliarPeer; |
|
395 iNAT_T_Required = aSA->iNAT_T_Required; |
|
396 |
|
397 // |
|
398 //Copy an Internal address object (if exists) to the new negotiation |
|
399 // |
|
400 if ( aSA->iVirtualIp ) |
|
401 { |
|
402 iInternalAddr = CInternalAddress::NewL(*(aSA->iVirtualIp)); |
|
403 } |
|
404 |
|
405 iNAT_D_Flags = aSA->iNAT_D_Flags; |
|
406 if ( iNAT_D_Flags ) { |
|
407 // |
|
408 // Use IETF specified NAT traversal |
|
409 // |
|
410 iNatDiscovery = CIkev1NatDiscovery::NewL(aSA->iNAT_D_Flags); |
|
411 } |
|
412 |
|
413 //Keys (DH Generated public value when own) |
|
414 iSKEYID.Copy(aSA->iSKEYID); |
|
415 iSKEYID_d.Copy(aSA->iSKEYID_d); |
|
416 iSKEYID_a.Copy(aSA->iSKEYID_a); |
|
417 iSKEYID_e.Copy(aSA->iSKEYID_e); |
|
418 |
|
419 //IV used by des_cbc and des3_cbc is 8 but digest returns 16 bytes for MDx and 20 for SHS (first 8 used) |
|
420 iIV = aSA->iIV; //normal IV |
|
421 iIVSize = iIV.Length(); |
|
422 |
|
423 iLastIV = aSA->iLastIV; //Saves the last IV of PHASE_I to compute iNotifIV everytime |
|
424 |
|
425 //Nonces |
|
426 // iNONCE_I = aSA->iNONCE_I; |
|
427 // iNONCE_R = aSA->iNONCE_R; |
|
428 // |
|
429 // If the ISAKMP SA (=aSA) has been originally negotiated due the policy activation (iAutoLogin = ETrue) |
|
430 // The iLocalAddr maybe then undefined in aSA. |
|
431 // If local end is acting as an initiator, method GetAcquireDataL updates iLocalAddr in CIkev1Negotiation object. |
|
432 // In that case take iLocalAddr value from there and store it to CIsakmpSa (aSA) object. |
|
433 // If local end is acting as a responder, resolve iLocalAddr value. |
|
434 // |
|
435 if ( aSA->iAutoLogin ) |
|
436 { |
|
437 if ( aRole == INITIATOR) |
|
438 iLocalAddr = aSA->iLocalAddr; |
|
439 else User::LeaveIfError( iPluginSession->GetLocalAddress( iLocalAddr ) ); |
|
440 } |
|
441 iDPDSupported = aSA->iDPDSupported; |
|
442 |
|
443 iSAId = aSA->iSAId; // Reference to existin ISAKMP SA |
|
444 iStage = 1; //if initiator the stage will be set in a subsequent call to InitPhase_IIL() |
|
445 } |
|
446 |
|
447 //Leaves if error detected |
|
448 void CIkev1Negotiation::CommonConstructL() |
|
449 { |
|
450 iPhase = PHASE_I; |
|
451 iTimer = CIkev1Timeout::NewL(*this); |
|
452 |
|
453 //Phase II proposal lists |
|
454 iProposal_IIList = new (ELeave) CProposal_IIList(1); |
|
455 |
|
456 iRemoteAddr.SetPort(IKE_PORT); |
|
457 |
|
458 iHostData = &iPluginSession->IkeData(); |
|
459 if (!iHostData) |
|
460 { |
|
461 DEBUG_LOG(_L("The host has no data. Negotiation aborted")); |
|
462 User::Leave(KKmdIkeNoPolicyErr); |
|
463 } |
|
464 |
|
465 if ( iHostData->iCAList && iHostData->iCAList->Count() ) |
|
466 { |
|
467 iPkiService = CIkeV1PkiService::NewL(iHostData, iDebug); |
|
468 TInt stat ( EFalse ); |
|
469 stat=ReadCAsL(iHostData->iCAList); // Build trusted CA list |
|
470 if ( !stat ) |
|
471 { |
|
472 SetErrorStatus( KVpnErrInvalidCaCertFile ); |
|
473 User::Leave(KVpnErrInvalidCaCertFile); |
|
474 } |
|
475 } |
|
476 iSendCert = iHostData->iAlwaysSendCert; //If true will always be sent, otherwise only with a CR |
|
477 |
|
478 //Proposals |
|
479 if (!BuildProposals1L()) |
|
480 { |
|
481 SetFinished(); |
|
482 User::Leave(KKmdIkePolicyFileErr); //if any error returns |
|
483 } |
|
484 |
|
485 iEncoding = X509_CERT_SIG; //Only type in use |
|
486 |
|
487 iChosenProposal_I.iAttrList = new (ELeave) TAttrib; //allocated now and deleted when destroying the obj |
|
488 User::LeaveIfError( iPluginSession->GetLocalAddress( iLocalAddr ) ); |
|
489 |
|
490 //PFKEY data (is overwritten if initiator because we use the data given in the acquire |
|
491 |
|
492 iAcquireSeq = 1;//msg Seq. number of acquire needed for the UPDATE |
|
493 iSeq = 1; //Sequence number for pfkey messages |
|
494 |
|
495 iLastRemoteAddr = iRemoteAddr; // Used as destination address when sending data |
|
496 #ifdef _DEBUG |
|
497 TBuf<40> txt_addr; |
|
498 iRemoteAddr.OutputWithScope(txt_addr); |
|
499 #endif |
|
500 |
|
501 iLastMsg = HBufC8::NewL(4096); |
|
502 |
|
503 DEBUG_LOG1( _L("New negotiation with Host %S"), |
|
504 &txt_addr ); |
|
505 |
|
506 if ( !iHostData->iUseNatProbing && iHostData->iEspUdpPort == 0 ) |
|
507 { |
|
508 // |
|
509 // Use IETF specified NAT traversal |
|
510 // |
|
511 iNatDiscovery = CIkev1NatDiscovery::NewL(0); |
|
512 } |
|
513 |
|
514 if ( iRole == RESPONDER ) |
|
515 { |
|
516 // |
|
517 // Get base value internal address (=VPN virtual IP) |
|
518 // |
|
519 iInternalAddr = iPluginSession->InternalAddressL(); |
|
520 } |
|
521 } |
|
522 |
|
523 |
|
524 TBool CIkev1Negotiation::ReadCAsL(CArrayFixFlat<TCertInfo*> *aCAList) |
|
525 { |
|
526 |
|
527 TBool Status = iPkiService->ImportCACertsL(aCAList); |
|
528 |
|
529 #ifdef _DEBUG |
|
530 if ( !Status ) |
|
531 { |
|
532 DEBUG_LOG( _L("Trusted CA list creation failed!") ); |
|
533 } |
|
534 #endif // _DEBUG |
|
535 |
|
536 return Status; |
|
537 |
|
538 } |
|
539 |
|
540 TBool CIkev1Negotiation::ReadOwnCertL() |
|
541 { |
|
542 // |
|
543 // Read own certificate from PKI store using own trusted CA as |
|
544 // specified issuer |
|
545 // |
|
546 TBool Status = EFalse; |
|
547 _LIT(KVpnApplUid, "101F7993"); |
|
548 if ( iPkiService && iHostData->iCAList ) |
|
549 { |
|
550 TCertInfo* CertInfo; |
|
551 HBufC8* CAName = HBufC8::NewLC(256); |
|
552 TInt i = 0; |
|
553 if ( iHostData->iCAList->At(0)->iData!=KVpnApplUid ) |
|
554 { |
|
555 while ( i < iHostData->iCAList->Count() ) |
|
556 { |
|
557 |
|
558 CertInfo = iHostData->iCAList->At(i); |
|
559 CAName->Des().Copy(CertInfo->iData); // Assure that CA name is in ASCII format |
|
560 if ( iPkiService->ReadUserCertWithNameL(CAName->Des(), iHostData, EFalse) == KErrNone ) |
|
561 { |
|
562 Status = ETrue; |
|
563 delete iOwnCert; // delete old if exists |
|
564 iOwnCert = iPkiService->GetCertificate(); |
|
565 delete iPeerTrustedCA; // for sure |
|
566 iPeerTrustedCA = iPkiService->GetTrustedCA(); |
|
567 CleanupStack::PopAndDestroy(CAName); //CAName |
|
568 CAName=NULL; |
|
569 break; |
|
570 } |
|
571 i ++; |
|
572 } |
|
573 if (!Status) |
|
574 { |
|
575 CleanupStack::PopAndDestroy(CAName); |
|
576 CAName=NULL; |
|
577 } |
|
578 } |
|
579 else |
|
580 { |
|
581 CIkeCaList* trustedCaList = iPkiService->CaList(); |
|
582 CleanupStack::PopAndDestroy(CAName); |
|
583 CAName=NULL; |
|
584 while ( i < trustedCaList->Count() ) |
|
585 { |
|
586 |
|
587 CIkeCaElem* CaElem = (*trustedCaList)[i]; |
|
588 CAName = IkeCert::GetCertificateFieldDERL(CaElem->Certificate(), KSubjectName); |
|
589 if (CAName == NULL) |
|
590 { |
|
591 User::Leave(KErrArgument); |
|
592 } |
|
593 CleanupStack::PushL(CAName); |
|
594 if ( iPkiService->ReadUserCertWithNameL(*CAName, iHostData, ETrue) == KErrNone) |
|
595 { |
|
596 Status = ETrue; |
|
597 delete iOwnCert; // delete old if exists |
|
598 iOwnCert = iPkiService->GetCertificate(); |
|
599 delete iPeerTrustedCA; |
|
600 iPeerTrustedCA = iPkiService->GetTrustedCA(); |
|
601 CleanupStack::PopAndDestroy(CAName); |
|
602 CAName=NULL; |
|
603 |
|
604 |
|
605 break; |
|
606 } |
|
607 i ++; |
|
608 |
|
609 CleanupStack::PopAndDestroy(CAName); |
|
610 CAName=NULL; |
|
611 } |
|
612 } |
|
613 if ( !Status ) |
|
614 { |
|
615 DEBUG_LOG( _L("Error loading Own Certificate!") ); |
|
616 } |
|
617 } |
|
618 return Status; |
|
619 } |
|
620 |
|
621 |
|
622 |
|
623 void CIkev1Negotiation::GetAcquireDataL(const TPfkeyMessage &aReq) |
|
624 { |
|
625 // ACQUIRE Contains: <Base, Addr(Src & Dest) (Addr(Proxy)), (Ident(S & D)), (Sensitivity), Proposal> |
|
626 |
|
627 iLocalAddr = *aReq.iSrcAddr.iAddr; //Copies our own address because it's the only way to know it |
|
628 |
|
629 //Phase II proposals |
|
630 //Only one combination received so only one transform |
|
631 CProposal_II *prop_II = new (ELeave) CProposal_II(); |
|
632 CleanupStack::PushL(prop_II); |
|
633 prop_II->ConstructL(); |
|
634 iProposal_IIList->AppendL(prop_II); |
|
635 CleanupStack::Pop(); //prop_II safe in case of leave |
|
636 |
|
637 prop_II->iProposalNum = FIRST_IPSEC_PROPOSAL; |
|
638 prop_II->iNumTransforms = 1; |
|
639 prop_II->iReplayWindowLength = aReq.iProposal.iExt->sadb_prop_replay; |
|
640 TAttrib_II *attr_II = new (ELeave) TAttrib_II(); |
|
641 CleanupStack::PushL(attr_II); |
|
642 prop_II->iAttrList->AppendL(attr_II); //added into the proposal so it's safe if function leaves |
|
643 CleanupStack::Pop(); //attr_II safe in case of leave |
|
644 |
|
645 attr_II->iTransformNum = FIRST_IPSEC_TRANSFORM; |
|
646 |
|
647 if (aReq.iBase.iMsg->sadb_msg_satype==SADB_SATYPE_AH) |
|
648 { |
|
649 prop_II->iProtocol = PROTO_IPSEC_AH; |
|
650 if (aReq.iProposal.iComb->sadb_comb_auth == SADB_AALG_MD5HMAC) |
|
651 { |
|
652 attr_II->iTransformID = AH_MD5; |
|
653 attr_II->iAuthAlg = DOI_HMAC_MD5; |
|
654 } |
|
655 else if (aReq.iProposal.iComb->sadb_comb_auth == SADB_AALG_SHA1HMAC) |
|
656 { |
|
657 attr_II->iTransformID=AH_SHA; |
|
658 attr_II->iAuthAlg = DOI_HMAC_SHA; |
|
659 } |
|
660 else |
|
661 { |
|
662 DEBUG_LOG(_L("Unsupported Authentication Algorithm in Acquire")); |
|
663 SetFinished(); |
|
664 return; |
|
665 } |
|
666 // No auth with variable encryption |
|
667 } |
|
668 else if (aReq.iBase.iMsg->sadb_msg_satype == SADB_SATYPE_ESP) |
|
669 { |
|
670 prop_II->iProtocol=PROTO_IPSEC_ESP; |
|
671 /* Request ESP from peer host */ |
|
672 |
|
673 attr_II->iTransformID = aReq.iProposal.iComb->sadb_comb_encrypt; |
|
674 switch ( attr_II->iTransformID ) |
|
675 { |
|
676 case ESP_DES_CBC: |
|
677 case ESP_3DES_CBC: |
|
678 case ESP_NULL: |
|
679 break; |
|
680 |
|
681 case ESP_AES_CBC: |
|
682 attr_II->iKeyLength = aReq.iProposal.iComb->sadb_comb_encrypt_maxbits; |
|
683 break; |
|
684 |
|
685 default: |
|
686 DEBUG_LOG(_L("IPsec Encryption algorithm is not implemented. Wrong algorithms file")); |
|
687 SetFinished(); |
|
688 return; |
|
689 |
|
690 } |
|
691 if (aReq.iProposal.iComb->sadb_comb_auth != SADB_AALG_NONE) |
|
692 { |
|
693 if (aReq.iProposal.iComb->sadb_comb_auth == SADB_AALG_MD5HMAC) |
|
694 attr_II->iAuthAlg = DOI_HMAC_MD5; |
|
695 else if (aReq.iProposal.iComb->sadb_comb_auth == SADB_AALG_SHA1HMAC) |
|
696 attr_II->iAuthAlg = DOI_HMAC_SHA; |
|
697 else |
|
698 { |
|
699 DEBUG_LOG(_L("Unsupported Authentication Algorithm in Acquire")); |
|
700 SetFinished(); |
|
701 return; |
|
702 } |
|
703 } |
|
704 } |
|
705 |
|
706 //Check if PFS in use... |
|
707 if (aReq.iProposal.iComb->sadb_comb_flags & SADB_SAFLAGS_PFS) |
|
708 { |
|
709 iPFS=ETrue; |
|
710 switch (iHostData->iGroupDesc_II) |
|
711 { |
|
712 case IKE_PARSER_MODP_768: |
|
713 attr_II->iGroupDesc = MODP_768; |
|
714 break; |
|
715 case IKE_PARSER_MODP_1024: |
|
716 attr_II->iGroupDesc = MODP_1024; |
|
717 break; |
|
718 case IKE_PARSER_MODP_1536: |
|
719 attr_II->iGroupDesc = MODP_1536; |
|
720 break; |
|
721 case IKE_PARSER_MODP_2048: |
|
722 attr_II->iGroupDesc = MODP_2048; |
|
723 break; |
|
724 default: |
|
725 DEBUG_LOG(_L("ISAKMP Proposals error (Bad Group description)")); |
|
726 SetFinished(); |
|
727 return; |
|
728 } |
|
729 } |
|
730 else |
|
731 { |
|
732 iPFS=EFalse; |
|
733 attr_II->iGroupDesc = 0; //No group assigned because no PFS |
|
734 } |
|
735 |
|
736 if (aReq.iProposal.iComb->sadb_comb_flags & SADB_SAFLAGS_TUNNEL) |
|
737 { |
|
738 attr_II->iEncMode = DOI_TUNNEL; |
|
739 } |
|
740 else |
|
741 { |
|
742 attr_II->iEncMode = DOI_TRANSPORT; |
|
743 } |
|
744 |
|
745 iIDLocalPort = (TUint16)aReq.iSrcAddr.iAddr->Port(); |
|
746 iIDRemotePort = (TUint16)aReq.iDstAddr.iAddr->Port(); |
|
747 iIDProtocol = aReq.iDstAddr.iExt->sadb_address_proto; //May be needed for phase II ID |
|
748 |
|
749 //Source Identity |
|
750 if (aReq.iSrcIdent.iExt) |
|
751 { |
|
752 if (aReq.iSrcIdent.iExt->sadb_ident_type == SADB_IDENTTYPE_PREFIX) |
|
753 { |
|
754 if ( !ProcessIdentityData(aReq.iSrcIdent.iData, &iLocalIDType_II, |
|
755 &iLocalAddr1_ID_II, &iLocalAddr2_ID_II) ) |
|
756 { |
|
757 SetFinished(); |
|
758 return; |
|
759 } |
|
760 } |
|
761 else //Invalid identity type |
|
762 { |
|
763 DEBUG_LOG1(_L("Invalid Local identity type (%d)"), aReq.iSrcIdent.iExt->sadb_ident_type); |
|
764 SetFinished(); |
|
765 return; |
|
766 } |
|
767 } |
|
768 else |
|
769 { |
|
770 //We need to assign a default address if other info is to be sent in the same payload |
|
771 if (attr_II->iEncMode == DOI_TUNNEL || iIDLocalPort != 0 || iIDRemotePort != 0 || |
|
772 iIDProtocol != 0 || aReq.iDstIdent.iExt) |
|
773 { |
|
774 DEBUG_LOG(_L("Local Identity not defined and needed. Using Own address as local identity.")); |
|
775 iLocalAddr1_ID_II = iLocalAddr; |
|
776 if ((iLocalAddr.Family() == KAfInet) || iLocalAddr.IsV4Mapped() ) |
|
777 iLocalIDType_II = ID_IPV4_ADDR; |
|
778 else |
|
779 iLocalIDType_II = ID_IPV6_ADDR; |
|
780 iDefaultLocalID = ETrue; //Must be sent but won't be used when updating the SAD |
|
781 } |
|
782 } |
|
783 |
|
784 //Destination Identity |
|
785 if (aReq.iDstIdent.iExt) |
|
786 { |
|
787 if (aReq.iDstIdent.iExt->sadb_ident_type == SADB_IDENTTYPE_PREFIX) |
|
788 { |
|
789 if ( !ProcessIdentityData(aReq.iDstIdent.iData, &iRemoteIDType_II, |
|
790 &iRemoteAddr1_ID_II, &iRemoteAddr2_ID_II) ) |
|
791 { |
|
792 SetFinished(); |
|
793 return; |
|
794 } |
|
795 } |
|
796 else //Invalid identity type |
|
797 { |
|
798 |
|
799 DEBUG_LOG1( _L("Invalid Destination identity type (%d)"), aReq.iDstIdent.iExt->sadb_ident_type ); |
|
800 SetFinished(); |
|
801 return; |
|
802 } |
|
803 } |
|
804 else |
|
805 { |
|
806 // |
|
807 // RemoteID_II is required only if LocalID_II already exists |
|
808 // If transports mode |
|
809 // Build RemoteID_II for Quick mode negotiation from specified remote IP address |
|
810 // else Use subnet 0/0 as remote id |
|
811 // |
|
812 if ( iLocalIDType_II != 0 ) |
|
813 { |
|
814 if ( attr_II->iEncMode == DOI_TUNNEL ) { |
|
815 if ( iLocalIDType_II == ID_IPV4_ADDR || iLocalIDType_II == ID_IPV4_ADDR_SUBNET ) { |
|
816 iRemoteAddr1_ID_II.Init(KAfInet); |
|
817 iRemoteAddr2_ID_II.Init(KAfInet); |
|
818 iRemoteIDType_II = ID_IPV4_ADDR_SUBNET; |
|
819 } |
|
820 else { |
|
821 iRemoteAddr1_ID_II.Init(KAfInet6); |
|
822 iRemoteAddr2_ID_II.Init(KAfInet6); |
|
823 iRemoteIDType_II = ID_IPV6_ADDR_SUBNET; |
|
824 } |
|
825 } |
|
826 else { |
|
827 iRemoteAddr1_ID_II = *aReq.iDstAddr.iAddr; |
|
828 if ( iRemoteAddr1_ID_II.Family() == KAfInet6 ) |
|
829 iRemoteIDType_II = ID_IPV6_ADDR; |
|
830 else iRemoteIDType_II = ID_IPV4_ADDR; |
|
831 } |
|
832 iDefaultRemoteID = ETrue; //Must be sent but won't be used when updating the SAD |
|
833 } |
|
834 } |
|
835 |
|
836 //Only Hard Lifetimes taken into account |
|
837 TInt64 lifetime64 = aReq.iProposal.iComb->sadb_comb_soft_addtime; |
|
838 iHardLifetime = aReq.iProposal.iComb->sadb_comb_hard_addtime; |
|
839 |
|
840 if ( lifetime64 == 0 ) |
|
841 { |
|
842 lifetime64 = iHardLifetime; |
|
843 } |
|
844 |
|
845 TUint high = 0; |
|
846 TUint low = 0; |
|
847 if (lifetime64!=0) |
|
848 { |
|
849 high = ByteOrder::Swap32(I64HIGH(lifetime64)); |
|
850 if (high > 0) |
|
851 attr_II->iLifeDurationSecs.Copy((TUint8 *)&high, sizeof(high)); |
|
852 low = ByteOrder::Swap32(I64LOW(lifetime64)); |
|
853 attr_II->iLifeDurationSecs.Append((TUint8 *)&low, sizeof(low)); |
|
854 } |
|
855 |
|
856 //Bytes lifetime |
|
857 lifetime64 = aReq.iProposal.iComb->sadb_comb_soft_bytes; |
|
858 lifetime64 = (lifetime64/1024); //Bytes to KB |
|
859 if (lifetime64 != 0) |
|
860 { |
|
861 high = ByteOrder::Swap32(I64HIGH(lifetime64)); |
|
862 if (high > 0) |
|
863 attr_II->iLifeDurationKBytes.Copy((TUint8 *)&high, sizeof(high)); |
|
864 low = ByteOrder::Swap32(I64LOW(lifetime64)); |
|
865 attr_II->iLifeDurationKBytes.Append((TUint8 *)&low, sizeof(low)); |
|
866 } |
|
867 |
|
868 //Save some pf_key data to use later in PFKEY_UPDATE msg |
|
869 iAcquireSeq = aReq.iBase.iMsg->sadb_msg_seq; //msg Seq. number |
|
870 iPfkeyAcquirePID = aReq.iBase.iMsg->sadb_msg_pid; //msg PID. |
|
871 iAcquirePending = ETrue; |
|
872 DEBUG_LOG2( _L("Acq seq= %d , PID= %d"), iAcquireSeq, iPfkeyAcquirePID ); |
|
873 |
|
874 } |
|
875 |
|
876 // |
|
877 // CIkev1Negotiation::ExecuteL() |
|
878 // An ISAKMP message has been received belonging to this negotiation. |
|
879 // Process the message and advance the negotiation session to appropriate |
|
880 // next state/stage. |
|
881 // |
|
882 TBool CIkev1Negotiation::ExecuteL( const ThdrISAKMP& aHdr, |
|
883 const TInetAddr& aRemote, |
|
884 TInt aLocalPort ) |
|
885 { |
|
886 aLocalPort = aLocalPort; |
|
887 |
|
888 TBool ret=EFalse; |
|
889 const ThdrISAKMP *hdr; |
|
890 TUint8 *msg = NULL; //to place the new msg |
|
891 TBuf8<IKEV1_MAX_IV_SIZE> tmp_IV(iIV); //Temporal IV. Used to update the real one if the msg OK |
|
892 |
|
893 TLastIKEMsg msg_info(aHdr); //For retransmitted IKE msg detection |
|
894 if ( IsRetransmit(msg_info) ) { |
|
895 DEBUG_LOG(_L("Retransmitted IKE message received.")); |
|
896 TBool FloatedPort = EFalse; |
|
897 if ( iNAT_D_Flags & (REMOTE_END_NAT + LOCAL_END_NAT) ) |
|
898 FloatedPort = ETrue; |
|
899 TPtr8 lastMsg(iLastMsg->Des()); |
|
900 iPluginSession->SendIkeMsgL(lastMsg, iLastRemoteAddr, FloatedPort); |
|
901 return EFalse; |
|
902 } |
|
903 |
|
904 if ( iPhase == PHASE_II && |
|
905 aHdr.GetExchange() != IKE_QUICK_MODE ) |
|
906 { |
|
907 DEBUG_LOG(_L("Bad packet (retransmission?)")); |
|
908 #ifdef _DEBUG |
|
909 const TPtrC8 ikeMsgPtr( (TUint8 *)&aHdr, (TUint16)aHdr.GetLength() ); |
|
910 TInetAddr dstAddr; |
|
911 iPluginSession->GetLocalAddress( dstAddr ); |
|
912 dstAddr.SetPort( aLocalPort ); |
|
913 TRACE_MSG_IKEV1( ikeMsgPtr, iRemoteAddr, dstAddr ); |
|
914 #endif // _DEBUG |
|
915 |
|
916 SetFinished(); |
|
917 return EFalse; //Bad packet, is a retransmission |
|
918 } |
|
919 |
|
920 iLastRemoteAddr = aRemote; //Save last remote address (used in NAT cases) |
|
921 |
|
922 iLengthLeft = aHdr.GetLength(); //Used to check the size in the payload are OK |
|
923 |
|
924 DEBUG_LOG2( _L("---------- Phase %d - Stage %d ----------"), iPhase, iStage ); |
|
925 |
|
926 if ((iStage==1) && (iPhase==PHASE_I)) //Only saved for the first message |
|
927 iExchange = aHdr.GetExchange(); |
|
928 |
|
929 DEBUG_LOG1( _L("Exchange %d"), aHdr.GetExchange() ); |
|
930 |
|
931 if (aHdr.GetFlags() & ISAKMP_HDR_EFLAG) //if encrypted |
|
932 { |
|
933 //before anything, prints the packet |
|
934 DEBUG_LOG(_L("Received message (encr).")); |
|
935 DEBUG_LOG(_L("Decrypting...")); |
|
936 msg = new (ELeave)(TUint8[aHdr.GetLength()]); //to place the new msg |
|
937 CleanupStack::PushL(msg); |
|
938 |
|
939 Mem::Copy(msg,(TUint8 *)&aHdr,sizeof(aHdr)); //The header is not encrypted |
|
940 |
|
941 if ((iPhase==PHASE_II) && (iStage == 1)) |
|
942 { |
|
943 iMessageId = aHdr.GetMessageId(); //Saves the ID to compute IV |
|
944 DEBUG_LOG(_L("Quick IV:")); |
|
945 ComputeIVL(iIV, iMessageId); |
|
946 } |
|
947 |
|
948 DecryptL((TUint8 *)aHdr.Next(),&msg[sizeof(aHdr)], aHdr.GetLength()-sizeof(aHdr),iIV, iSKEYID_e, iChosenProposal_I.iAttrList->iEncrAlg); |
|
949 if ((iStage == 6 && iExchange == ISAKMP_EXCHANGE_ID) || |
|
950 (iStage == 3 && iExchange == ISAKMP_EXCHANGE_AGGR)) |
|
951 { |
|
952 iLastIV.Copy(iIV); //Saves last IV in Phase 1 |
|
953 DEBUG_LOG(_L("Last IV Saved!")); |
|
954 } |
|
955 hdr=(ThdrISAKMP *)msg; //decrypted msg |
|
956 |
|
957 } |
|
958 else if (iFlags & ISAKMP_HDR_EFLAG) // IKE message SHOULD be encrypted |
|
959 { |
|
960 hdr=&aHdr; //no encryption |
|
961 DEBUG_LOG(_L("Received message.")); |
|
962 #ifdef _DEBUG |
|
963 const TPtrC8 ikeMsgPtr( (TUint8 *)hdr, (TUint16)hdr->GetLength() ); |
|
964 TInetAddr dstAddr; |
|
965 iPluginSession->GetLocalAddress( dstAddr ); |
|
966 dstAddr.SetPort( aLocalPort ); |
|
967 TRACE_MSG_IKEV1( ikeMsgPtr, iRemoteAddr, dstAddr ); |
|
968 #endif // _DEBUG |
|
969 DEBUG_LOG(_L("The message is NOT encrypted (ignored)")); |
|
970 return EFalse; |
|
971 } |
|
972 else |
|
973 hdr=&aHdr; //no encryption |
|
974 |
|
975 DEBUG_LOG(_L("Received message.")); |
|
976 #ifdef _DEBUG |
|
977 const TPtrC8 ikeMsgPtr( (TUint8 *)hdr, (TUint16)hdr->GetLength() ); |
|
978 TInetAddr dstAddr; |
|
979 iPluginSession->GetLocalAddress( dstAddr ); |
|
980 dstAddr.SetPort( aLocalPort ); |
|
981 TRACE_MSG_IKEV1( ikeMsgPtr, iRemoteAddr, dstAddr ); |
|
982 #endif // _DEBUG |
|
983 |
|
984 if (iPhase==PHASE_I) |
|
985 ret = Phase_IExchangeL(*hdr);//MAIN MODE && AGGRESSIVE MODE |
|
986 else |
|
987 { |
|
988 ret = Phase_IIExchangeL(*hdr);//QUICK MODE |
|
989 } |
|
990 if (!ret) //Incorrect packet. Restore the IV |
|
991 { |
|
992 DEBUG_LOG(_L("Restoring previous IV")); |
|
993 iIV.Copy(tmp_IV); |
|
994 } |
|
995 else //correct packet |
|
996 { |
|
997 SaveRetransmitInfo(msg_info); // store new last received IKE message info |
|
998 } |
|
999 |
|
1000 if ( msg ) //If used erase it (when encryption) |
|
1001 CleanupStack::PopAndDestroy(); |
|
1002 |
|
1003 return ret; |
|
1004 } |
|
1005 |
|
1006 TBool CIkev1Negotiation::ExecutePhase2L( const ThdrISAKMP &aHdr, |
|
1007 const TInetAddr &aRemote, |
|
1008 TInt aLocalPort ) |
|
1009 { |
|
1010 return ExecuteL( aHdr, aRemote, aLocalPort ); |
|
1011 } |
|
1012 |
|
1013 // |
|
1014 // CIkev1Negotiation::ExecuteTransactionL |
|
1015 // An ISAKMP Transaction exchange message received. |
|
1016 // Call CTransNegotiation::ExecuteL method and process returned status |
|
1017 // |
|
1018 TBool CIkev1Negotiation::ExecuteTransactionL( const ThdrISAKMP& aHdr, |
|
1019 const TInetAddr& aRemote, |
|
1020 TInt aLocalPort ) |
|
1021 { |
|
1022 TInt status; |
|
1023 TBool ret = ETrue; |
|
1024 if ( iTransactionNeg ) { |
|
1025 status = iTransactionNeg->ExecuteL( aHdr, aRemote, aLocalPort ); |
|
1026 if ( status == TRANSACTION_SUCCESS ) { |
|
1027 // |
|
1028 // XAUTH / CONFIG-MODE completed succesfully |
|
1029 // |
|
1030 IsakmpPhase1CompletedL(); |
|
1031 } |
|
1032 else { |
|
1033 if ( status == TRANSACTION_FAILED ) { |
|
1034 // |
|
1035 // XAUTH / CONFIG-MODE completed succesfully |
|
1036 // |
|
1037 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
1038 R_VPN_MSG_VPN_GW_AUTH_FAIL, |
|
1039 KKmdIkeAuthFailedErr, |
|
1040 iPluginSession->VpnIapId(), |
|
1041 &iRemoteAddr ); |
|
1042 SendDeleteL(PROTO_ISAKMP); |
|
1043 SetFinished(); |
|
1044 } |
|
1045 } |
|
1046 } |
|
1047 else ret = EFalse; |
|
1048 |
|
1049 return ret; |
|
1050 } |
|
1051 |
|
1052 |
|
1053 // |
|
1054 // CIkev1Negotiation::AuthDialogCompletedL |
|
1055 // Authentication dialog is completed. Check CAuthDialogInfo object ID |
|
1056 // and call eithet CIKECRACKNegotiation::ProcessUserResponseL or |
|
1057 // CTransNegotiation::ProcessUserResponseL to handle dialog data |
|
1058 // |
|
1059 void CIkev1Negotiation::AuthDialogCompletedL(CAuthDialogInfo *aUserInfo) |
|
1060 { |
|
1061 if ( !aUserInfo || (!aUserInfo->iUsername && !aUserInfo->iSecret) ) |
|
1062 { |
|
1063 DEBUG_LOG(_L("Legacy authentication cancelled by user!")); |
|
1064 SendDeleteL(PROTO_ISAKMP); |
|
1065 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
1066 R_VPN_MSG_VPN_GW_AUTH_FAIL, |
|
1067 KErrCancel, |
|
1068 iPluginSession->VpnIapId(), |
|
1069 &iRemoteAddr ); |
|
1070 SetErrorStatus(KErrCancel); |
|
1071 return; |
|
1072 } |
|
1073 |
|
1074 TInt status; |
|
1075 |
|
1076 if ( aUserInfo->GetObjId() == XAUTH_DIALOG_ID ) |
|
1077 { |
|
1078 if ( iTransactionNeg ) |
|
1079 status = iTransactionNeg->ProcessUserResponseL(aUserInfo); |
|
1080 else status = TRANSACTION_FAILED; |
|
1081 |
|
1082 if ( status == TRANSACTION_FAILED ) |
|
1083 { |
|
1084 /*-------------------------------------------------------- |
|
1085 * |
|
1086 * XAUTH negotiation failed. Negotiation shall be deleted |
|
1087 * |
|
1088 *--------------------------------------------------------*/ |
|
1089 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
1090 R_VPN_MSG_VPN_GW_AUTH_FAIL, |
|
1091 status, |
|
1092 iPluginSession->VpnIapId(), |
|
1093 &iRemoteAddr ); |
|
1094 SetErrorStatus(KKmdIkeAuthFailedErr); |
|
1095 AcquireSAErrorResponse(KKmdIkeAuthFailedErr); |
|
1096 } |
|
1097 } |
|
1098 else |
|
1099 { |
|
1100 if ( iCRACKneg ) |
|
1101 status = iCRACKneg->ProcessUserResponseL(aUserInfo); |
|
1102 else status = CRACK_FAILED; |
|
1103 |
|
1104 if ( status == CRACK_FAILED ) |
|
1105 { |
|
1106 /*-------------------------------------------------------- |
|
1107 * |
|
1108 * Crack negotiation failed. Negotiation shall be deleted |
|
1109 * |
|
1110 *--------------------------------------------------------*/ |
|
1111 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
1112 R_VPN_MSG_VPN_GW_AUTH_FAIL, |
|
1113 status, |
|
1114 iPluginSession->VpnIapId(), |
|
1115 &iRemoteAddr ); |
|
1116 SetErrorStatus(KKmdIkeAuthFailedErr); |
|
1117 AcquireSAErrorResponse(KKmdIkeAuthFailedErr); |
|
1118 } |
|
1119 } |
|
1120 } |
|
1121 |
|
1122 |
|
1123 // |
|
1124 // CIkev1Negotiation::StartCRACKAuthL |
|
1125 // Start CRACK authentication phase of IKE phase I negotiation |
|
1126 // - Create CIKECRACKNegotiation object and call it`s ConstructL |
|
1127 // - Set iStage variable to 7 to indicate that CRACK authentication |
|
1128 // is going |
|
1129 // |
|
1130 TBool CIkev1Negotiation::StartCRACKAuthL() |
|
1131 { |
|
1132 TInt status; |
|
1133 |
|
1134 iStage = 7; |
|
1135 |
|
1136 if ( !iCRACKneg ) { |
|
1137 iCRACKneg = new(ELeave) CIKECRACKNegotiation( iDebug ); |
|
1138 TBuf<2> DummyDomain; |
|
1139 // |
|
1140 // If the IKE Id-type value is configured to value "Opaque |
|
1141 // String" and iFQDN length is larger than zero in the current |
|
1142 // policy ==> iFQDN value contains "Group name" value |
|
1143 // which shall be conveyed to the peer in CRACK "Domain name" |
|
1144 // attribute |
|
1145 // |
|
1146 iFlags |= ISAKMP_HDR_EFLAG; //From now on encryption is used |
|
1147 |
|
1148 if ( (iHostData->iIdType == ID_KEY_ID) && (iHostData->iFQDN.Length() > 0 ) ) |
|
1149 status = iCRACKneg->ConstructL(iHostData->iCRACKLAMType, this, iHostData->iFQDN); |
|
1150 else status = iCRACKneg->ConstructL(iHostData->iCRACKLAMType, this, DummyDomain); |
|
1151 if ( status == CRACK_FAILED ) { |
|
1152 return EFalse; |
|
1153 } |
|
1154 } |
|
1155 |
|
1156 return ETrue; |
|
1157 } |
|
1158 |
|
1159 // |
|
1160 // CIkev1Negotiation::IsakmpPhase1CompletedL |
|
1161 // This method is called when an ISAKMP phase 1 negotiation is succesfully |
|
1162 // completed. The following actions are taken: |
|
1163 // -- If either Extended authentication or/and Config mode required |
|
1164 // If iTransactionNeg data member exists it means that XAUTH/CONFIG mode |
|
1165 // has been succesfully completed. |
|
1166 // If iTransactionNeg data member is NULL, XAUTH/CONFIG mode shall be initiated |
|
1167 // -- If No XAUTH/CONFIG mode (or if XAUTH/CONFIG mode already completed). |
|
1168 // If iAutoLogin is TRUE save ISAKMP SA and deconstruct negotiation. |
|
1169 // If iAutoLogin is False, save ISAKMP SA and; |
|
1170 // if negotiation role is initiator continue with Quick mode exchange. |
|
1171 // if negotiation role is responder deconstruct negotiation. |
|
1172 // |
|
1173 TBool CIkev1Negotiation::IsakmpPhase1CompletedL() |
|
1174 { |
|
1175 TBool Status; |
|
1176 |
|
1177 if ( iTransactionNeg ) { |
|
1178 // |
|
1179 // Try to get Internal address information and delete iTransactionNeg |
|
1180 // |
|
1181 delete iInternalAddr; |
|
1182 iInternalAddr = iTransactionNeg->GetInternalAddr(); |
|
1183 delete iTransactionNeg; |
|
1184 iTransactionNeg = NULL; |
|
1185 } |
|
1186 else { |
|
1187 if ( (iRole == INITIATOR) && (iHostData->iUseXauth || iHostData->iUseCfgMode) ) |
|
1188 { |
|
1189 TBool useModeCfg; |
|
1190 if ( iSARekeyInfo ) |
|
1191 useModeCfg = EFalse; // Use existing virtual Ip, if any |
|
1192 else |
|
1193 useModeCfg = iHostData->iUseCfgMode; |
|
1194 |
|
1195 iTransactionNeg = CTransNegotiation::NewL( iHostData->iUseXauth, |
|
1196 useModeCfg, |
|
1197 iPluginSession, |
|
1198 this, |
|
1199 iDebug ); |
|
1200 |
|
1201 // If only MODE_CFG is needed a request is sent |
|
1202 if(useModeCfg && !iHostData->iUseXauth) |
|
1203 iTransactionNeg->BuildConfigRequestL(); |
|
1204 |
|
1205 iStage = 8; |
|
1206 return ETrue; |
|
1207 } |
|
1208 } |
|
1209 |
|
1210 SaveISAKMPSAL(); |
|
1211 |
|
1212 if ( iAutoLogin ) { |
|
1213 // |
|
1214 // ISAKMP Phase 1 completed. Quick mode is NOT started because there is no acquire pending |
|
1215 // but phase 1 negotiation is started by the policy activation. |
|
1216 // |
|
1217 CInternalAddress* internalAddr = NULL; |
|
1218 if ( iInternalAddr != NULL ) |
|
1219 { |
|
1220 internalAddr = CInternalAddress::NewL(*iInternalAddr); |
|
1221 } |
|
1222 iPluginSession->IkeSaCompleted(KErrNone, internalAddr); |
|
1223 SetFinished(); // Causes negotiation object destruction |
|
1224 iAutoLogin = EFalse; |
|
1225 Status = EFalse; |
|
1226 } |
|
1227 else { |
|
1228 if ( iRole == INITIATOR ) { |
|
1229 TBool internalAddressChanged = EFalse; |
|
1230 if ( iInternalAddr ) { |
|
1231 // |
|
1232 // Report internal IP address changed event |
|
1233 // |
|
1234 internalAddressChanged = iPluginSession->InternalAddressChangedL(*iInternalAddr); |
|
1235 } |
|
1236 if ( (!iSARekeyInfo || |
|
1237 iPhaseIIAfterIkeSaRekey) && |
|
1238 !internalAddressChanged ) |
|
1239 { |
|
1240 iPhaseIIAfterIkeSaRekey = EFalse; |
|
1241 iPrevExchange = iExchange; //Needed to know how to begin Phase II (Sending or receiving) |
|
1242 iExchange = IKE_QUICK_MODE; |
|
1243 iPhase = PHASE_II; |
|
1244 iStage = 1; |
|
1245 Status = ETrue; |
|
1246 iMessageId = RandomMessageId(); |
|
1247 InitPhase2L(); //Immediately inits PHASE_II. No reply expected. |
|
1248 } |
|
1249 else { |
|
1250 // |
|
1251 // Rekeyed IKE SA or internal address changed. No IKE quick mode started |
|
1252 // Pending acquire will be failed, if internal address has changed. |
|
1253 // |
|
1254 SetFinished(); |
|
1255 Status = EFalse; |
|
1256 } |
|
1257 } |
|
1258 else { |
|
1259 SetFinished(); // Causes negotiation object destruction |
|
1260 Status = EFalse; |
|
1261 } |
|
1262 } |
|
1263 |
|
1264 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogInfo, |
|
1265 R_VPN_MSG_VPN_GW_AUTH_OK, |
|
1266 KErrNone, |
|
1267 iPluginSession->VpnIapId(), |
|
1268 &iRemoteAddr ); |
|
1269 |
|
1270 TInt NatStatus = iNAT_D_Flags; // Record "IETF" NAT status |
|
1271 if ( NatStatus == 0 ) |
|
1272 { |
|
1273 if ( iNAT_T_Required ) |
|
1274 NatStatus = 4; // Local end is NAT:ted (discovered via "Nokia" NAT-T) |
|
1275 else if ( !iHostData->iUseNatProbing ) |
|
1276 NatStatus = iHostData->iEspUdpPort; // "Forced" ESP UDP encapsulation ? |
|
1277 } |
|
1278 |
|
1279 TInetAddr localAddr; |
|
1280 iPluginSession->GetLocalAddress( localAddr ); |
|
1281 LOG_KMD_EVENT2( MKmdEventLoggerIf::KLogInfo, |
|
1282 R_VPN_MSG_ADDR_INFO_FOR_VPN_AP, |
|
1283 NatStatus, iPluginSession->VpnIapId(), |
|
1284 (iInternalAddr ? &iInternalAddr->iClientIntAddr : NULL), |
|
1285 &localAddr ); |
|
1286 |
|
1287 return Status; |
|
1288 } |
|
1289 |
|
1290 |
|
1291 //Sends the initial IKE packets to start the negotiation. PHASE I |
|
1292 void CIkev1Negotiation::InitNegotiationL() //Equiv. to stage 1 |
|
1293 { |
|
1294 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
1295 |
|
1296 TInt vendor_id_type; |
|
1297 |
|
1298 //Main mode stage 1 |
|
1299 |
|
1300 switch (iHostData->iMode) |
|
1301 { |
|
1302 case IKE_PARSER_MAIN: |
|
1303 iExchange = ISAKMP_EXCHANGE_ID; // Identity Protection (Main mode in IKE) |
|
1304 DEBUG_LOG(_L("IKE: Initiating negotiation (Main Mode)")); |
|
1305 break; |
|
1306 case IKE_PARSER_AGGRESSIVE: |
|
1307 iExchange = ISAKMP_EXCHANGE_AGGR; // Agressive |
|
1308 DEBUG_LOG(_L("IKE: Initiating negotiation (Aggressive Mode)")); |
|
1309 break; |
|
1310 default: |
|
1311 DEBUG_LOG1(_L("Bad Mode used (%d)"), iHostData->iMode); |
|
1312 return; |
|
1313 } |
|
1314 iStage = 1; |
|
1315 DEBUG_LOG2(_L("---------- Phase %d - Stage %d ----------"),iPhase, iStage); |
|
1316 |
|
1317 iCookie_R.FillZ(ISAKMP_COOKIE_SIZE); //Set responder Cookie to 0 |
|
1318 |
|
1319 iDOI = IPSEC_DOI; |
|
1320 iEncoding = X509_CERT_SIG; //Only cert Allowed |
|
1321 msg->IsakmpInit(this); |
|
1322 msg->IsakmpSa(); |
|
1323 |
|
1324 const TUint8 *ptr = msg->iBuf.Ptr() + sizeof(ThdrISAKMP); |
|
1325 const TSAISAKMP *sa = (TSAISAKMP*)ptr; |
|
1326 //Generic payload NOT included |
|
1327 iSAPayloadSize = sa->GetLength() - sizeof(TPayloadISAKMP); |
|
1328 delete iSAPayload; |
|
1329 iSAPayload = NULL; |
|
1330 iSAPayload = new (ELeave) TUint8[iSAPayloadSize]; |
|
1331 ptr += sizeof(TPayloadISAKMP); |
|
1332 Mem::Copy(iSAPayload, ptr,iSAPayloadSize); |
|
1333 |
|
1334 TBool cert_required = EFalse; //If any proposal requires a cert to send a CR if needed |
|
1335 TBool preshared_key = EFalse; //Preshared key authentication |
|
1336 TBool crack_used = EFalse; |
|
1337 |
|
1338 TAttrib *transf = iProposal_I.iAttrList; |
|
1339 for (TInt i=0; (i < iProposal_I.iNumTransforms) && (!cert_required); i++) |
|
1340 { |
|
1341 switch (transf->iAuthMethod) |
|
1342 { |
|
1343 case RSA_SIG: //Proposals involving certificates |
|
1344 case DSS_SIG: |
|
1345 cert_required = ETrue; |
|
1346 break; |
|
1347 case IKE_A_CRACK: |
|
1348 cert_required = ETrue; |
|
1349 crack_used = ETrue; |
|
1350 break; |
|
1351 default: // No cert involved |
|
1352 preshared_key = ETrue; |
|
1353 transf = transf->iNext; |
|
1354 } |
|
1355 } |
|
1356 |
|
1357 if (crack_used && |
|
1358 !iHostData->iCRACKLAMUserName && |
|
1359 !iHostData->iCRACKLAMPassword) |
|
1360 { |
|
1361 TBuf<256> UserName; |
|
1362 TBuf<64> Password; |
|
1363 CIkev1Dialog* Dialog = CIkev1Dialog::NewL(iPluginSession, iPluginSession->DialogAnchor(), iDebug); |
|
1364 if (KErrNone != Dialog->GetSyncUNPWCacheDialog(UserName, Password)) |
|
1365 { |
|
1366 DEBUG_LOG(_L("Failed to get credentials for crack auth!")); |
|
1367 SetFinished(); |
|
1368 delete Dialog; |
|
1369 return; |
|
1370 } |
|
1371 iHostData->iCRACKLAMUserName = TStringData::NewL(UserName); |
|
1372 iHostData->iCRACKLAMPassword = TStringData::NewL(Password); |
|
1373 delete Dialog; |
|
1374 } |
|
1375 |
|
1376 if (iExchange == ISAKMP_EXCHANGE_AGGR) //Aggressive contains more payloads |
|
1377 { |
|
1378 if ( preshared_key && !cert_required ) { |
|
1379 // |
|
1380 // Only pre-shared key authentication proposal(s) exists |
|
1381 // Check if is necessary to ask user name/password (= IKE ID/preshared key) |
|
1382 // from user |
|
1383 // |
|
1384 if ( CheckCredentials(iHostData) != KErrNone ) { |
|
1385 DEBUG_LOG(_L("Failed to get credentials for Aggressive pre-shared auth!")); |
|
1386 SetFinished(); |
|
1387 return; |
|
1388 } |
|
1389 } |
|
1390 ComputeNonceL(); //Nonce to be sent |
|
1391 if ( cert_required && !iOwnCert ) |
|
1392 ReadOwnCertL(); // For possible DER ASN1 distuingish name Ident |
|
1393 msg->IsakmpKeyL(); |
|
1394 msg->IsakmpNonce(); |
|
1395 msg->IsakmpOwnIdentL(); |
|
1396 |
|
1397 //For aggressive mode we send a CR if a cert is going to be needed |
|
1398 if ((!iPeerX509Cert) && (cert_required)) |
|
1399 { |
|
1400 msg->IsakmpCertificateReqL(); |
|
1401 } |
|
1402 if ( iHostData->iUseNatProbing ) |
|
1403 vendor_id_type = EXPANDED_VENDOR_ID; |
|
1404 else vendor_id_type = HASH_VENDOR_ID; |
|
1405 msg->IsakmpVendorId(vendor_id_type, |
|
1406 (TUint8*)iCookie_I.Ptr(), |
|
1407 (TUint8*)iCookie_R.Ptr(), iLocalAddr); |
|
1408 |
|
1409 } |
|
1410 |
|
1411 if ( iHostData->iDPDHeartBeat != 0 ) |
|
1412 BuildDPDVendorId(*msg); |
|
1413 |
|
1414 if ( iNatDiscovery ) { |
|
1415 iNatDiscovery->BuildNatVendorId(*msg); |
|
1416 iNatDiscovery->BuildRfcNatVendorId(*msg); |
|
1417 } |
|
1418 |
|
1419 if ( iHostData->iUseXauth || iHostData->iUseCfgMode ) { |
|
1420 CTransNegotiation::BuildXauthVendorId(*msg); |
|
1421 } |
|
1422 |
|
1423 SendL(*msg); |
|
1424 iStage = 2; |
|
1425 } |
|
1426 |
|
1427 //Builds the proposal list from the structure in the engine |
|
1428 TBool CIkev1Negotiation::BuildProposals1L() |
|
1429 { |
|
1430 TProposalData *p_list = iHostData->iPropList; |
|
1431 |
|
1432 if (!p_list) |
|
1433 { |
|
1434 DEBUG_LOG(_L("ERROR: No proposals in the configuration file. Negotiation Cancelled")); |
|
1435 return EFalse; |
|
1436 } |
|
1437 iProposal_I.iSPI.FillZ(4); //filled with 0 (not send anyway) |
|
1438 iProposal_I.iProposalNum = FIRST_ISAKMP_PROPOSAL; |
|
1439 iProposal_I.iProtocol = PROTO_ISAKMP; |
|
1440 iProposal_I.iNumTransforms = 0; |
|
1441 |
|
1442 TUint8 trans_num = FIRST_ISAKMP_TRANSFORM; |
|
1443 |
|
1444 TAttrib *prev=NULL,*attrlist=NULL; |
|
1445 |
|
1446 while ( p_list ) |
|
1447 { |
|
1448 iProposal_I.iNumTransforms ++; |
|
1449 attrlist = new (ELeave) TAttrib; |
|
1450 if (!iProposal_I.iAttrList) //First transform |
|
1451 iProposal_I.iAttrList=attrlist; //attrlist safe |
|
1452 if (prev) |
|
1453 prev->iNext = attrlist; |
|
1454 prev = attrlist; |
|
1455 |
|
1456 attrlist->iTransformID = KEY_IKE; //only one allowed by Protocol ISAKMP (KEY_IKE) |
|
1457 attrlist->iTransformNum = trans_num; |
|
1458 trans_num++; |
|
1459 switch (p_list->iEncrAlg) |
|
1460 { |
|
1461 case IKE_PARSER_DES_CBC: |
|
1462 attrlist->iEncrAlg=DES_CBC; //DES_CBC |
|
1463 break; |
|
1464 case IKE_PARSER_DES3_CBC: |
|
1465 attrlist->iEncrAlg=DES3_CBC; //DES3_CBC |
|
1466 break; |
|
1467 case IKE_PARSER_AES_CBC: |
|
1468 attrlist->iEncrAlg = AES_CBC; //AES_CBC |
|
1469 attrlist->iKeyLength = (TUint16)p_list->iEncrKeyLth; |
|
1470 if (!attrlist->iKeyLength) |
|
1471 attrlist->iKeyLength = 128; //default AES key size |
|
1472 break; |
|
1473 default: |
|
1474 DEBUG_LOG(_L("ISAKMP Proposals error (Bad Encryption algorithm)")); |
|
1475 return EFalse; |
|
1476 } |
|
1477 switch (p_list->iHashAlg) |
|
1478 { |
|
1479 case IKE_PARSER_MD5: |
|
1480 attrlist->iHashAlg=HASH_MD5; //HASH_MD5 |
|
1481 break; |
|
1482 case IKE_PARSER_SHA1: |
|
1483 attrlist->iHashAlg=HASH_SHA1; //HASH_SHA1 |
|
1484 break; |
|
1485 default: |
|
1486 DEBUG_LOG(_L("ISAKMP Proposals error (Bad Hash algorithm)")); |
|
1487 return EFalse; |
|
1488 } |
|
1489 switch (p_list->iAuthMeth) |
|
1490 { |
|
1491 case IKE_PARSER_RSA_SIG: |
|
1492 attrlist->iAuthMethod=RSA_SIG; |
|
1493 break; |
|
1494 case IKE_PARSER_DSS_SIG: |
|
1495 attrlist->iAuthMethod=DSS_SIG; |
|
1496 break; |
|
1497 case IKE_PARSER_PRE_SHARED: |
|
1498 attrlist->iAuthMethod=PRE_SHARED; |
|
1499 break; |
|
1500 case IKE_PARSER_CRACK: |
|
1501 attrlist->iAuthMethod=IKE_A_CRACK; //CRACK authentication |
|
1502 break; |
|
1503 |
|
1504 default: |
|
1505 DEBUG_LOG(_L("ISAKMP Proposals error (Bad Authentication Method)")); |
|
1506 return EFalse; |
|
1507 } |
|
1508 |
|
1509 switch (p_list->iGroupDesc) |
|
1510 { |
|
1511 case IKE_PARSER_MODP_768: |
|
1512 attrlist->iGroupDesc = MODP_768; |
|
1513 break; |
|
1514 case IKE_PARSER_MODP_1024: |
|
1515 attrlist->iGroupDesc = MODP_1024; |
|
1516 break; |
|
1517 case IKE_PARSER_MODP_1536: |
|
1518 attrlist->iGroupDesc = MODP_1536; |
|
1519 break; |
|
1520 case IKE_PARSER_MODP_2048: |
|
1521 attrlist->iGroupDesc = MODP_2048; |
|
1522 break; |
|
1523 default: |
|
1524 DEBUG_LOG(_L("ISAKMP Proposals error (Bad Group description)")); |
|
1525 return EFalse; |
|
1526 } |
|
1527 |
|
1528 switch (p_list->iGroupType) |
|
1529 { |
|
1530 case IKE_PARSER_MODP: |
|
1531 attrlist->iGroupType = MODP; |
|
1532 break; |
|
1533 case IKE_PARSER_DEFAULT: |
|
1534 break; |
|
1535 default: |
|
1536 DEBUG_LOG(_L("ISAKMP Proposals error (Bad Group Type)")); |
|
1537 return EFalse; |
|
1538 } |
|
1539 |
|
1540 switch (p_list->iPRF) |
|
1541 { |
|
1542 case IKE_PARSER_DES3_CBC_MAC: |
|
1543 attrlist->iPRF=OAKLEY_PRF_3DES_CBC_MAC; |
|
1544 break; |
|
1545 case IKE_PARSER_NONE: |
|
1546 break; |
|
1547 default: |
|
1548 DEBUG_LOG(_L("ISAKMP Proposals error (Bad PRF specified)")); |
|
1549 return EFalse; |
|
1550 } |
|
1551 |
|
1552 TUint32 lifetime = ByteOrder::Swap32(p_list->iLifetimeSec); |
|
1553 if (lifetime) |
|
1554 attrlist->iLifeDurationSecs.Copy((TUint8 *)&lifetime, sizeof(lifetime)); |
|
1555 |
|
1556 lifetime = ByteOrder::Swap32(p_list->iLifetimeKb); |
|
1557 if (lifetime) |
|
1558 attrlist->iLifeDurationKBytes.Copy((TUint8 *)&lifetime, sizeof(lifetime)); |
|
1559 |
|
1560 // |
|
1561 // Store parameters for extended authentication |
|
1562 // |
|
1563 attrlist->iXauthUsed = iHostData->iUseXauth; |
|
1564 attrlist->iRole = iRole; |
|
1565 |
|
1566 p_list = p_list->iNext; |
|
1567 |
|
1568 } |
|
1569 attrlist->iNext=NULL; //Last transform |
|
1570 |
|
1571 |
|
1572 return ETrue; |
|
1573 } |
|
1574 |
|
1575 //Builds Phase_II proposals from the config. file to when acting as RESPONDER to see if |
|
1576 //proposals received are acceptable. |
|
1577 TInt CIkev1Negotiation::BuildProposals2L() |
|
1578 { |
|
1579 CIpsecSaSpecList* SaList = NULL; |
|
1580 TInetAddr empty_addr; //empty address |
|
1581 TInt err = KErrNone; |
|
1582 |
|
1583 TRAP(err, |
|
1584 if ( iLocalIDType_II == 0 ) //Local ID not received (so remote neither) so it's the same as gateway |
|
1585 { |
|
1586 TInetAddr localSelector(iLocalAddr); |
|
1587 localSelector.SetPort(iIDLocalPort); |
|
1588 TInetAddr remoteSelector(iRemoteAddr); |
|
1589 remoteSelector.SetPort(iIDRemotePort); |
|
1590 |
|
1591 SaList = iPluginSession->GetIpseSaSpecListLC(localSelector, empty_addr, |
|
1592 remoteSelector, empty_addr, |
|
1593 iIDProtocol ); |
|
1594 } |
|
1595 else // either none or both (RFC 2409 5.5 so we must have both) |
|
1596 { |
|
1597 TInetAddr localSelector(iLocalAddr1_ID_II); |
|
1598 localSelector.SetPort(iIDLocalPort); |
|
1599 TInetAddr remoteSelector(iRemoteAddr1_ID_II); |
|
1600 remoteSelector.SetPort(iIDRemotePort); |
|
1601 |
|
1602 |
|
1603 SaList = iPluginSession->GetIpseSaSpecListLC(localSelector, |
|
1604 iLocalAddr2_ID_II, |
|
1605 remoteSelector, |
|
1606 iRemoteAddr2_ID_II, |
|
1607 iIDProtocol ); |
|
1608 } |
|
1609 |
|
1610 CleanupStack::Pop(SaList); |
|
1611 ); |
|
1612 |
|
1613 if (err != KErrNone) |
|
1614 return err; |
|
1615 |
|
1616 CleanupStack::PushL(SaList); |
|
1617 |
|
1618 //Phase II proposals |
|
1619 |
|
1620 CProposal_II *prop = NULL; |
|
1621 TAttrib_II *attr_II = NULL; |
|
1622 const TIpsecSaSpec *spec = NULL; |
|
1623 TInt count = SaList->Count(); |
|
1624 TInt i = 0; |
|
1625 |
|
1626 while ( i < count ) |
|
1627 { |
|
1628 prop = new (ELeave) CProposal_II(); |
|
1629 CleanupStack::PushL(prop); |
|
1630 prop->ConstructL(1); |
|
1631 iProposal_IIList->AppendL(prop); |
|
1632 CleanupStack::Pop(); //prop safe |
|
1633 // |
|
1634 // Only 1 proposal which may be AND'd (many prop with same num) if many bundles |
|
1635 // Only 1 transform because no OR'ing implemented in IPSEC |
|
1636 // |
|
1637 prop->iProposalNum = FIRST_IPSEC_PROPOSAL; |
|
1638 prop->iNumTransforms = 1; |
|
1639 |
|
1640 attr_II = new (ELeave) TAttrib_II(); |
|
1641 CleanupStack::PushL(attr_II); |
|
1642 prop->iAttrList->AppendL(attr_II); |
|
1643 CleanupStack::Pop(); //attr_II safe |
|
1644 |
|
1645 attr_II->iTransformNum = FIRST_IPSEC_TRANSFORM; |
|
1646 |
|
1647 spec = &(SaList->At(i)); |
|
1648 |
|
1649 if (spec->iType == SADB_SATYPE_AH) |
|
1650 { |
|
1651 prop->iProtocol=PROTO_IPSEC_AH; |
|
1652 if (spec->iAalg == SADB_AALG_MD5HMAC) |
|
1653 { |
|
1654 attr_II->iTransformID = AH_MD5; |
|
1655 attr_II->iAuthAlg = DOI_HMAC_MD5; |
|
1656 } |
|
1657 else if (spec->iAalg == SADB_AALG_SHA1HMAC) |
|
1658 { |
|
1659 attr_II->iTransformID=AH_SHA; |
|
1660 attr_II->iAuthAlg = DOI_HMAC_SHA; |
|
1661 } |
|
1662 else |
|
1663 { |
|
1664 DEBUG_LOG(_L("Unsupported Authentication Algorithm in IPsec Policy")); |
|
1665 err = KKmdIkeNoProposalErr; |
|
1666 break; |
|
1667 } |
|
1668 // No auth with variable encryption |
|
1669 } |
|
1670 else if (spec->iType == SADB_SATYPE_ESP) |
|
1671 { |
|
1672 prop->iProtocol = PROTO_IPSEC_ESP; |
|
1673 // Request ESP from peer host |
|
1674 |
|
1675 attr_II->iTransformID = spec->iEalg; |
|
1676 switch ( attr_II->iTransformID ) |
|
1677 { |
|
1678 case ESP_DES_CBC: |
|
1679 case ESP_3DES_CBC: |
|
1680 case ESP_NULL: |
|
1681 break; |
|
1682 |
|
1683 case ESP_AES_CBC: |
|
1684 attr_II->iKeyLength = spec->iEalgLen; //If 0 it won't be sent |
|
1685 break; |
|
1686 |
|
1687 default: |
|
1688 DEBUG_LOG(_L("IPsec Encryption algorithm is not implemented. Wrong algorithms file")); |
|
1689 err = KKmdIkeNoProposalErr; |
|
1690 break; |
|
1691 } |
|
1692 |
|
1693 if (err != KErrNone) |
|
1694 { |
|
1695 break; |
|
1696 } |
|
1697 |
|
1698 if (spec->iAalg != SADB_AALG_NONE) |
|
1699 { |
|
1700 if (spec->iAalg == SADB_AALG_MD5HMAC) |
|
1701 attr_II->iAuthAlg = DOI_HMAC_MD5; |
|
1702 else if (spec->iAalg == SADB_AALG_SHA1HMAC) |
|
1703 attr_II->iAuthAlg = DOI_HMAC_SHA; |
|
1704 else |
|
1705 { |
|
1706 DEBUG_LOG(_L("Unsupported Authentication Algorithm in IPsec Policy")); |
|
1707 err = KKmdIkeNoProposalErr; |
|
1708 break; |
|
1709 } |
|
1710 } |
|
1711 } |
|
1712 |
|
1713 //Check if PFS in use... |
|
1714 iPFS = spec->iPfs; |
|
1715 |
|
1716 if (spec->iTransportMode) |
|
1717 attr_II->iEncMode = DOI_TRANSPORT; |
|
1718 else attr_II->iEncMode = DOI_TUNNEL; |
|
1719 |
|
1720 ////////////////////////////////////////////////////////// |
|
1721 // |
|
1722 // Check if remote identity defined in Security Policy |
|
1723 // If it is not set iDefaultLocalID = ETrue. |
|
1724 // This prevents destination identity information to IPSEC |
|
1725 // in PFKEY Update- and Add primitives |
|
1726 // (see UpdateSADatabaseL() method) |
|
1727 // |
|
1728 ////////////////////////////////////////////////////////// |
|
1729 if ( spec->iRemoteIdentity.Length() == 0 ) |
|
1730 iDefaultLocalID = ETrue; |
|
1731 if ( !ExamineRemoteIdentity(spec->iRemoteIdentity) ) |
|
1732 { |
|
1733 DEBUG_LOG(_L("Remote Identity mismatch with IPsec Policy")); |
|
1734 err = KKmdIkeNoProposalErr; |
|
1735 break; |
|
1736 } |
|
1737 |
|
1738 //Only Hard Lifetimes taken into account |
|
1739 TInt64 lifetime64 = spec->iHard.iAddTime; |
|
1740 TUint high = 0; |
|
1741 TUint low = 0; |
|
1742 if (lifetime64!=0) |
|
1743 { |
|
1744 high = ByteOrder::Swap32(I64HIGH(lifetime64)); |
|
1745 if (high > 0) |
|
1746 attr_II->iLifeDurationSecs.Copy((TUint8 *)&high, sizeof(high)); |
|
1747 low = ByteOrder::Swap32(I64LOW(lifetime64)); |
|
1748 attr_II->iLifeDurationSecs.Append((TUint8 *)&low, sizeof(low)); |
|
1749 } |
|
1750 |
|
1751 //Bytes lifetime |
|
1752 lifetime64 = spec->iHard.iBytes; |
|
1753 lifetime64 = (lifetime64/1024); //Bytes to KB |
|
1754 if (lifetime64 != 0) |
|
1755 { |
|
1756 high = ByteOrder::Swap32(I64HIGH(lifetime64)); |
|
1757 if (high > 0) |
|
1758 attr_II->iLifeDurationKBytes.Copy((TUint8 *)&high, sizeof(high)); |
|
1759 low = ByteOrder::Swap32(I64LOW(lifetime64)); |
|
1760 attr_II->iLifeDurationKBytes.Append((TUint8 *)&low, sizeof(low)); |
|
1761 } |
|
1762 if (iPFS) |
|
1763 { |
|
1764 switch (iHostData->iGroupDesc_II) |
|
1765 { |
|
1766 case IKE_PARSER_MODP_768: |
|
1767 attr_II->iGroupDesc = MODP_768; |
|
1768 break; |
|
1769 case IKE_PARSER_MODP_1024: |
|
1770 attr_II->iGroupDesc = MODP_1024; |
|
1771 break; |
|
1772 case IKE_PARSER_MODP_1536: |
|
1773 attr_II->iGroupDesc = MODP_1536; |
|
1774 break; |
|
1775 case IKE_PARSER_MODP_2048: |
|
1776 attr_II->iGroupDesc = MODP_2048; |
|
1777 break; |
|
1778 default: //Shouldn't happen but the error will be detected later |
|
1779 err = KKmdIkeNoProposalErr; |
|
1780 break; |
|
1781 } |
|
1782 |
|
1783 if (err != KErrNone) |
|
1784 { |
|
1785 break; |
|
1786 } |
|
1787 } |
|
1788 |
|
1789 prop->iReplayWindowLength = spec->iReplayWindowLength; |
|
1790 |
|
1791 i ++; |
|
1792 } //while |
|
1793 |
|
1794 if (err != KErrNone) |
|
1795 { |
|
1796 delete iProposal_IIList; |
|
1797 iProposal_IIList = NULL; |
|
1798 } |
|
1799 |
|
1800 CleanupStack::PopAndDestroy(SaList); //SAList |
|
1801 |
|
1802 return err; |
|
1803 } |
|
1804 |
|
1805 TBool CIkev1Negotiation::ExamineRemoteIdentity(const TDesC8& aRemoteIdInPolicy) |
|
1806 { |
|
1807 ////////////////////////////////////////////////////////////////// |
|
1808 // |
|
1809 // This method is called when we are acting as a Quick mode responder. |
|
1810 // The purpose of this method is compare remote Identity information |
|
1811 // received in Quick Mode IKE message (=IDi) to the remote Identity |
|
1812 // information in the local Ipsec Policy. |
|
1813 // If Identitiea are NOT matching the FALSE response is returned. |
|
1814 // There is the following special "kludge" is done in these test: |
|
1815 // Identity IPv4 address and IPv4 subnet with prefix 32 are |
|
1816 // interpreted to be same as well as IPv6 address and IPv6 subnet |
|
1817 // with prefix 128. When this situation occurs a special flag |
|
1818 // (iSwapRemoteIdType = ETrue) is set in CIkev1Negotiation object |
|
1819 // |
|
1820 ////////////////////////////////////////////////////////////////// |
|
1821 TBool AddrMatch; |
|
1822 TInetAddr IpAddr; |
|
1823 TInetAddr IpMask; |
|
1824 TUint8 IdType; |
|
1825 TInt PrefixLength = 0; |
|
1826 TInetAddr* PrefixPtr = NULL; |
|
1827 |
|
1828 if ( !ProcessIdentityData(aRemoteIdInPolicy, &IdType, &IpAddr, &IpMask) ) |
|
1829 return EFalse; |
|
1830 |
|
1831 AddrMatch = IpAddr.Match(iRemoteAddr1_ID_II); |
|
1832 |
|
1833 if ( AddrMatch ) |
|
1834 { |
|
1835 if ( (IdType == ID_IPV4_ADDR_SUBNET ) || (IdType == ID_IPV6_ADDR_SUBNET) ) |
|
1836 { |
|
1837 // |
|
1838 // Identity in policy is IP subnet |
|
1839 // |
|
1840 if ( iRemoteIDType_II == IdType ) |
|
1841 { |
|
1842 // |
|
1843 // Both identity in policy and identity in IKE IDi payload are |
|
1844 // IP subnets. The subnet masks MUST match, too |
|
1845 // |
|
1846 AddrMatch = IpMask.Match(iRemoteAddr2_ID_II); |
|
1847 } |
|
1848 else |
|
1849 { |
|
1850 if ( ( (IdType == ID_IPV4_ADDR_SUBNET ) && (iRemoteIDType_II == ID_IPV4_ADDR)) || |
|
1851 ( (IdType == ID_IPV6_ADDR_SUBNET ) && (iRemoteIDType_II == ID_IPV6_ADDR))) |
|
1852 { |
|
1853 // |
|
1854 // Identity in IKE IDi payload is an IP address |
|
1855 // Do the special check: There must be full mask in the |
|
1856 // subnet identity configured in policy |
|
1857 // |
|
1858 if ( IdType == ID_IPV6_ADDR_SUBNET ) |
|
1859 PrefixLength = 128; |
|
1860 else PrefixLength = 32; |
|
1861 PrefixPtr = &IpMask; |
|
1862 DEBUG_LOG(_L("Peer is using IP address IDi, full mask subnet required in local end!")); |
|
1863 } |
|
1864 else AddrMatch = EFalse; |
|
1865 } |
|
1866 } |
|
1867 else |
|
1868 { |
|
1869 // |
|
1870 // Identity in policy is IP address. |
|
1871 // |
|
1872 if ( ( (IdType == ID_IPV4_ADDR ) && (iRemoteIDType_II == ID_IPV4_ADDR_SUBNET)) || |
|
1873 ( (IdType == ID_IPV6_ADDR ) && (iRemoteIDType_II == ID_IPV6_ADDR_SUBNET))) |
|
1874 { |
|
1875 // |
|
1876 // Identity in IKE IDi payload is an IP subnet |
|
1877 // Do the special check: There must be full mask in the |
|
1878 // subnet identity in IKE IDi payload |
|
1879 // |
|
1880 if ( IdType == ID_IPV6_ADDR ) |
|
1881 PrefixLength = 128; |
|
1882 else PrefixLength = 32; |
|
1883 PrefixPtr = &iRemoteAddr2_ID_II; |
|
1884 DEBUG_LOG(_L("An IP address ID used in local end, full mask subnet required in peer IDi!")); |
|
1885 } |
|
1886 else if ( iRemoteIDType_II != IdType ) |
|
1887 AddrMatch = EFalse; |
|
1888 |
|
1889 } |
|
1890 } |
|
1891 |
|
1892 if ( PrefixPtr ) |
|
1893 { |
|
1894 if ( PrefixLength == PrefixLen(*PrefixPtr) ) |
|
1895 { |
|
1896 iSwapRemoteIdType = ETrue; |
|
1897 DEBUG_LOG(_L("Required ID OK, modified remote IDi informed to IPsec!")); |
|
1898 } |
|
1899 else AddrMatch = EFalse; |
|
1900 } |
|
1901 |
|
1902 return AddrMatch; |
|
1903 } |
|
1904 |
|
1905 TBool CIkev1Negotiation::ProcessIdentityData(const TDesC8& aIdentity, TUint8* aToIdType, |
|
1906 TInetAddr* aToIpAddr1, TInetAddr* aToIpAddr2) |
|
1907 { |
|
1908 if ( !aToIdType || !aToIpAddr1 || !aToIpAddr2 ) |
|
1909 return EFalse; |
|
1910 |
|
1911 aToIpAddr1->Init(KAFUnspec); |
|
1912 aToIpAddr2->Init(KAFUnspec); |
|
1913 *aToIdType = 0; |
|
1914 |
|
1915 if ( aIdentity.Length() ) |
|
1916 { |
|
1917 TInt offset = aIdentity.Find(_L8("/")); |
|
1918 |
|
1919 switch (offset) |
|
1920 { |
|
1921 case KErrNotFound: //Simple address |
|
1922 { |
|
1923 #ifdef _UNICODE |
|
1924 HBufC *unibuf = HBufC::New(aIdentity.Length()); |
|
1925 if ( !unibuf ) |
|
1926 return EFalse; |
|
1927 unibuf->Des().Copy(aIdentity); |
|
1928 if ( aToIpAddr1->Input(unibuf->Des()) != KErrNone ) |
|
1929 { |
|
1930 delete unibuf; |
|
1931 DEBUG_LOG(_L("Bad IP address identity!")); |
|
1932 return EFalse; |
|
1933 } |
|
1934 delete unibuf; |
|
1935 #else |
|
1936 if (aToIpAddr1->Input(aIdentity) != KErrNone) |
|
1937 { |
|
1938 DEBUG_LOG(_L("Bad IP address identity!")); |
|
1939 return EFalse; |
|
1940 } |
|
1941 #endif |
|
1942 if ( aToIpAddr1->Family() == KAfInet ) |
|
1943 *aToIdType = ID_IPV4_ADDR; |
|
1944 else *aToIdType = ID_IPV6_ADDR; |
|
1945 break; |
|
1946 } |
|
1947 |
|
1948 default: //Subnet |
|
1949 { |
|
1950 //addr1 - subnet |
|
1951 TInt prefix_len; |
|
1952 #ifdef _UNICODE |
|
1953 HBufC *unibuf = HBufC::New(aIdentity.Length()); |
|
1954 if ( !unibuf ) |
|
1955 return EFalse; |
|
1956 unibuf->Des().Copy(aIdentity); |
|
1957 TPtrC addr_buf(unibuf->Ptr(), offset); |
|
1958 if (aToIpAddr1->Input(addr_buf) != KErrNone) |
|
1959 { |
|
1960 delete unibuf; |
|
1961 DEBUG_LOG(_L("Bad Subnet Identity address!")); |
|
1962 return EFalse; |
|
1963 } |
|
1964 TPtrC prefix_ptr(unibuf->Ptr() + offset + 1, unibuf->Length() - offset - 1); |
|
1965 #else |
|
1966 TPtrC addr_buf(aIdentity.Ptr(), offset); |
|
1967 if (aToIpAddr1->.Input(addr_buf) != KErrNone) |
|
1968 { |
|
1969 DEB(LogError(_L("Bad Subnet Identity address!"));) |
|
1970 return EFalse; |
|
1971 } |
|
1972 TPtrC prefix_ptr(aIdentity.Ptr() + offset + 1, aIdentity.Length() - offset - 1); |
|
1973 #endif |
|
1974 //addr2 - mask |
|
1975 TLex lex(prefix_ptr); |
|
1976 if (lex.Val(prefix_len) != KErrNone) |
|
1977 { |
|
1978 DEBUG_LOG(_L("Bad Subnet Identity PREFIX Length!")); |
|
1979 return EFalse; |
|
1980 } |
|
1981 #ifdef _UNICODE |
|
1982 delete unibuf; |
|
1983 #endif |
|
1984 if ( aToIpAddr1->Family() == KAfInet ) |
|
1985 { |
|
1986 if ( prefix_len > 32 ) |
|
1987 { |
|
1988 DEBUG_LOG(_L("Bad Subnet Identity: Prefix too long!")); |
|
1989 return EFalse; |
|
1990 } |
|
1991 *aToIdType = ID_IPV4_ADDR_SUBNET; |
|
1992 PrefixMask(*aToIpAddr2, prefix_len, KAfInet); |
|
1993 } |
|
1994 else //KAfInet6 |
|
1995 { |
|
1996 if ( prefix_len > 128 ) |
|
1997 { |
|
1998 DEBUG_LOG(_L("Bad Subnet Identity: Prefix too long!")); |
|
1999 return EFalse; |
|
2000 } |
|
2001 *aToIdType = ID_IPV6_ADDR_SUBNET; |
|
2002 PrefixMask(*aToIpAddr2, prefix_len, KAfInet); |
|
2003 } |
|
2004 |
|
2005 } |
|
2006 |
|
2007 } //end switch |
|
2008 } |
|
2009 |
|
2010 return ETrue; |
|
2011 } |
|
2012 |
|
2013 //First msg of PHASE_II as initiator |
|
2014 void CIkev1Negotiation::InitPhase2L() |
|
2015 { |
|
2016 //Quick mode stage 1 |
|
2017 DEBUG_LOG(_L("-------- IKE: Initiating PHASE II --------")); |
|
2018 iPhase = PHASE_II; |
|
2019 iDOI=IPSEC_DOI; |
|
2020 iStage = 1; |
|
2021 |
|
2022 GetSPIL(); |
|
2023 //the rest will be done in ReceiveSPI |
|
2024 } |
|
2025 |
|
2026 //Requests an SPI from the kernel |
|
2027 |
|
2028 void CIkev1Negotiation::GetSPIL() |
|
2029 { |
|
2030 CProposal_IIList *propII_List; |
|
2031 CProposal_II *prop=NULL; |
|
2032 TUint8 sa_type = 0; |
|
2033 |
|
2034 DEBUG_LOG1(_L("GetSPI in stage: %d"), iStage); |
|
2035 |
|
2036 iInboundSPIList = new (ELeave) CArrayFixFlat<TSPINode>(1); |
|
2037 |
|
2038 if (iRole == RESPONDER) //If Phase II proposal Chosen |
|
2039 propII_List = iChosenProp_IIList; //If RESPONDER |
|
2040 else |
|
2041 propII_List = iProposal_IIList; //If INITIATOR |
|
2042 |
|
2043 TInt i, count = propII_List->Count(); |
|
2044 for (i = 0; i < count; i++) //May have many Phase_II proposals |
|
2045 { |
|
2046 prop = propII_List->At(i); |
|
2047 if (prop->iProtocol == PROTO_IPSEC_AH) |
|
2048 sa_type = SADB_SATYPE_AH; |
|
2049 else if (prop->iProtocol == PROTO_IPSEC_ESP) |
|
2050 sa_type = SADB_SATYPE_ESP; |
|
2051 else |
|
2052 sa_type = 0; //Unknown Protocol |
|
2053 |
|
2054 TInetAddr myAddr(iLocalAddr); |
|
2055 if ( myAddr.IsUnspecified() ) |
|
2056 User::LeaveIfError( iPluginSession->GetLocalAddress( myAddr ) ); |
|
2057 TInetAddr peerAddr(iRemoteAddr); |
|
2058 peerAddr.SetPort(0); |
|
2059 TSPINode node; |
|
2060 node.iPropNum = prop->iProposalNum; |
|
2061 node.iSeq = iSeq; |
|
2062 iInboundSPIList->AppendL(node); |
|
2063 |
|
2064 |
|
2065 __ASSERT_DEBUG( iIpsecSaSpiRetriever != NULL, |
|
2066 User::Invariant() ); |
|
2067 iIpsecSaSpiRetriever->Cancel(); |
|
2068 iIpsecSaSpiRetriever->GetIpsecSaSpi( iSeq++, sa_type, peerAddr, myAddr ); |
|
2069 iPendingSPI++; //To know when all received in ReceiveSPIL() |
|
2070 } |
|
2071 |
|
2072 DEBUG_LOG1(_L("GetSPI seq= %d"), iSeq); |
|
2073 } |
|
2074 |
|
2075 //aSPI received in Network order. |
|
2076 void CIkev1Negotiation::ReceiveSPIL(TUint32 aSPI, TUint32 aSeq) |
|
2077 { |
|
2078 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
2079 |
|
2080 DEBUG_LOG2(_L("ReceiveSPIL: SPI=%x, Seq=%u"), ByteOrder::Swap32(aSPI), aSeq); |
|
2081 |
|
2082 CProposal_IIList *propII_List = iProposal_IIList; |
|
2083 TInt i; |
|
2084 for (i = 0; i < iInboundSPIList->Count(); i++) |
|
2085 { |
|
2086 if (iInboundSPIList->At(i).iSeq == aSeq) |
|
2087 { |
|
2088 iInboundSPIList->At(i).iSPI = aSPI; |
|
2089 break; |
|
2090 } |
|
2091 //prop = prop->iNext; //To assign the SPI to the correct proposal |
|
2092 } |
|
2093 if (iRole==INITIATOR) |
|
2094 propII_List->At(i)->iSPI.Copy((TUint8*)&aSPI,sizeof(TUint32)); //needed to send it to the other Peer |
|
2095 |
|
2096 if (--iPendingSPI) // Check if still waiting for some SPI |
|
2097 return; |
|
2098 |
|
2099 iExchange = IKE_QUICK_MODE; //Current mode being used. |
|
2100 //Builds and send the packet |
|
2101 |
|
2102 if ((iHostData->iCommit) && (iRole==RESPONDER)) //Responder && if commit bit used we set the flag |
|
2103 iFlags |= ISAKMP_HDR_CFLAG; //Sets the Commit bit if this side set it else |
|
2104 |
|
2105 msg->IsakmpInit(this); |
|
2106 msg->IsakmpHashL(); |
|
2107 msg->IsakmpSa(); |
|
2108 ComputeNonceL(); //Computes a new Nonce for PHASE_II |
|
2109 msg->IsakmpNonce(); |
|
2110 if (iPFS) //Only sent if PFS in use... |
|
2111 msg->IsakmpKeyL(); |
|
2112 |
|
2113 if (iStage==1) //Initiator |
|
2114 { |
|
2115 // |
|
2116 // If Internal address private extension used change iLocalAddr1_ID_II to |
|
2117 // correspond that address |
|
2118 // |
|
2119 if ( iInternalAddr ) { |
|
2120 iLocalAddr1_ID_II = iInternalAddr->iClientIntAddr; |
|
2121 iLocalIDType_II = ID_IPV4_ADDR; |
|
2122 iDefaultLocalID = ETrue; |
|
2123 } |
|
2124 DEBUG_LOG(_L("PhaseII IV:")); //New IV for phase II |
|
2125 ComputeIVL(iIV, iMessageId); |
|
2126 //IDs must be sent if TUNNEL mode or is explicitly specified in the acquire |
|
2127 if ((!iLocalAddr1_ID_II.IsUnspecified()) || (!iRemoteAddr1_ID_II.IsUnspecified()) || |
|
2128 (iIDProtocol != 0) || (iIDLocalPort != 0) || (iIDRemotePort != 0)) |
|
2129 { |
|
2130 msg->IsakmpOwnIdentL(); //Own proxy |
|
2131 msg->IsakmpPeerIdentL(); //Peer Proxy |
|
2132 } |
|
2133 } |
|
2134 else if (iStage==2) //Responder |
|
2135 { |
|
2136 if (iIDReceived) //If received we send it back, otherwise no |
|
2137 { |
|
2138 msg->IsakmpPeerIdentL(); |
|
2139 msg->IsakmpOwnIdentL(); |
|
2140 } |
|
2141 if (iHostData->iResponderLifetime) |
|
2142 CheckSendResponderLifetime(*msg); //Adds to the message the RESPONDER_LIFETIME payload if needed |
|
2143 } |
|
2144 else return; |
|
2145 |
|
2146 if (iHostData->iReplayStatus) |
|
2147 { |
|
2148 DEBUG_LOG(_L("Constructing REPLAY-STATUS")); |
|
2149 |
|
2150 TInt i; |
|
2151 CProposal_II *prop; |
|
2152 for (i = 0 ; i < iProposal_IIList->Count(); i++) |
|
2153 { |
|
2154 prop = iProposal_IIList->At(i); |
|
2155 msg->IsakmpReplayStatus(prop->iProtocol, iInboundSPIList->At(i).iSPI, prop->iReplayWindowLength); |
|
2156 } |
|
2157 } |
|
2158 msg->IsakmpHashContL(); //inserts the hash in the correct position of the buffer |
|
2159 SendL(*msg); |
|
2160 |
|
2161 iStage++; //Next stage |
|
2162 } |
|
2163 |
|
2164 void CIkev1Negotiation::AcquireSAErrorResponse(TInt aError) |
|
2165 { |
|
2166 DEBUG_LOG(_L("CIkev1Negotiation::AcquireSAErrorResponse")); |
|
2167 |
|
2168 if ( iProposal_IIList ) |
|
2169 { |
|
2170 for ( TInt j=0; j<iProposal_IIList->Count(); j++ ) |
|
2171 { |
|
2172 TIpsecSAData sa_data; |
|
2173 sa_data.iSeq = iAcquireSeq; |
|
2174 sa_data.iPid = iPfkeyAcquirePID; |
|
2175 sa_data.iSPI = 0; |
|
2176 sa_data.iDst = iRemoteAddr; |
|
2177 |
|
2178 CProposal_II* prop_II = iProposal_IIList->At( j ); |
|
2179 |
|
2180 if ( prop_II->iProtocol == PROTO_IPSEC_AH ) |
|
2181 { |
|
2182 sa_data.iSAType = SADB_SATYPE_AH; |
|
2183 } |
|
2184 else if ( prop_II->iProtocol == PROTO_IPSEC_ESP ) |
|
2185 { |
|
2186 sa_data.iSAType = SADB_SATYPE_ESP; |
|
2187 } |
|
2188 iPluginSession->AcquireSAError( sa_data, aError ); |
|
2189 } |
|
2190 } |
|
2191 iAcquirePending = EFalse; |
|
2192 } |
|
2193 |
|
2194 //Will update the outbound |
|
2195 void CIkev1Negotiation::UpdateSADatabaseL() |
|
2196 { |
|
2197 #ifdef _DEBUG |
|
2198 TBuf<40> addr_buf; |
|
2199 #endif |
|
2200 TUint8 sa_type=0; |
|
2201 TUint8 auth_alg=0; |
|
2202 TUint8 encr_alg=0; |
|
2203 TUint32 updateSPI,addSPI; |
|
2204 TIpsecSAData sa_data; |
|
2205 TBool TunnelMode; |
|
2206 // |
|
2207 // Received Phase II key (Might be Auth + Encr keys) |
|
2208 // (Buffers are allocated for max 1024 bits key material |
|
2209 HBufC8* outboundKey_II = HBufC8::NewLC(128); |
|
2210 HBufC8* inboundKey_II = HBufC8::NewLC(128); |
|
2211 TPtrC8 in_authKey(0,0), out_authKey(0,0); |
|
2212 TPtrC8 in_encrKey(0,0), out_encrKey(0,0); |
|
2213 //Identities |
|
2214 #ifdef _UNICODE |
|
2215 TBuf<80> id_work; |
|
2216 #endif |
|
2217 HBufC8* local_id = HBufC8::NewLC(128); |
|
2218 HBufC8* remote_id = HBufC8::NewLC(128); |
|
2219 // ESP UDP Encapsulation extension data |
|
2220 HBufC8* gen_ext_data = HBufC8::NewLC(128); |
|
2221 TPtr8 GenExtData((TUint8*)gen_ext_data->Ptr(), 0, gen_ext_data->Des().MaxLength()); |
|
2222 |
|
2223 DEBUG_LOG(_L("---UPDATING SAD---")); |
|
2224 |
|
2225 if ((!iDefaultLocalID) && (iLocalIDType_II != 0)) |
|
2226 { |
|
2227 switch (iLocalIDType_II) |
|
2228 { |
|
2229 case ID_IPV4_ADDR: |
|
2230 case ID_IPV6_ADDR: |
|
2231 #ifdef _UNICODE |
|
2232 iLocalAddr1_ID_II.OutputWithScope(id_work); |
|
2233 local_id->Des().Copy(id_work); |
|
2234 #else |
|
2235 iLocalAddr1_ID_II.OutputWithScope(local_id->Des()); |
|
2236 #endif |
|
2237 break; |
|
2238 |
|
2239 case ID_IPV4_ADDR_SUBNET: |
|
2240 case ID_IPV6_ADDR_SUBNET: |
|
2241 #ifdef _UNICODE |
|
2242 iLocalAddr1_ID_II.OutputWithScope(id_work); |
|
2243 local_id->Des().Copy(id_work); |
|
2244 #else |
|
2245 iLocalAddr1_ID_II.OutputWithScope(local_id->Des()); |
|
2246 #endif |
|
2247 local_id->Des().AppendFormat(_L8("/%d"),PrefixLen(iLocalAddr2_ID_II)); //PrefixLen can't fail because checked before |
|
2248 break; |
|
2249 default: //Should never come here |
|
2250 DEBUG_LOG1(_L("Local ID type %d not supported"), iLocalIDType_II); |
|
2251 CleanupStack::PopAndDestroy(5); //key buffer, identities and ESP UDP encaps data |
|
2252 return; |
|
2253 } |
|
2254 } |
|
2255 |
|
2256 if ((!iDefaultRemoteID) && (iRemoteIDType_II != 0) ) |
|
2257 { |
|
2258 switch (iRemoteIDType_II) |
|
2259 { |
|
2260 case ID_IPV4_ADDR: |
|
2261 case ID_IPV6_ADDR: |
|
2262 #ifdef _UNICODE |
|
2263 iRemoteAddr1_ID_II.OutputWithScope(id_work); |
|
2264 remote_id->Des().Copy(id_work); |
|
2265 #else |
|
2266 iRemoteAddr1_ID_II.OutputWithScope(remote_id->Des()); |
|
2267 #endif |
|
2268 if ( iSwapRemoteIdType ) |
|
2269 { |
|
2270 if ( iRemoteIDType_II == ID_IPV4_ADDR ) |
|
2271 remote_id->Des().AppendFormat(_L8("/%d"), 32); |
|
2272 else remote_id->Des().AppendFormat(_L8("/%d"), 128); |
|
2273 } |
|
2274 break; |
|
2275 |
|
2276 case ID_IPV4_ADDR_SUBNET: |
|
2277 case ID_IPV6_ADDR_SUBNET: |
|
2278 #ifdef _UNICODE |
|
2279 iRemoteAddr1_ID_II.OutputWithScope(id_work); |
|
2280 remote_id->Des().Copy(id_work); |
|
2281 #else |
|
2282 iRemoteAddr1_ID_II.OutputWithScope(remote_id->Des()); |
|
2283 #endif |
|
2284 if ( !iSwapRemoteIdType ) |
|
2285 remote_id->Des().AppendFormat(_L8("/%d"),PrefixLen(iRemoteAddr2_ID_II)); //PrefixLen can't fail because checked before |
|
2286 break; |
|
2287 |
|
2288 default: //Should never come here |
|
2289 DEBUG_LOG1(_L("Remote ID type %d not supported"), iRemoteIDType_II); |
|
2290 CleanupStack::PopAndDestroy(5); //key buffer, identities and ESP UDP encaps data |
|
2291 return; |
|
2292 } |
|
2293 } |
|
2294 |
|
2295 TUint32 flags = 0; |
|
2296 if (iPFS) |
|
2297 { |
|
2298 flags = SADB_SAFLAGS_PFS; |
|
2299 DEBUG_LOG(_L("PFS enabled")); |
|
2300 } |
|
2301 |
|
2302 TUint32 addPID; |
|
2303 if (iRole==INITIATOR) |
|
2304 addPID = iPfkeyAcquirePID; //Require to remove the Larval SA |
|
2305 else |
|
2306 addPID = iPluginSession->Uid(); |
|
2307 |
|
2308 DEBUG_LOG2(_L("SAD seq= %d , PID= %d"), iAcquireSeq, addPID); |
|
2309 |
|
2310 TInt i, j; |
|
2311 for (i = 0; i < iInboundSPIList->Count(); i++) |
|
2312 { |
|
2313 if (iInboundSPIList->At(i).iPropNum == iProposalNum) |
|
2314 break; |
|
2315 } |
|
2316 |
|
2317 CProposal_II *prop; |
|
2318 TSPINode inboundspi_node; |
|
2319 TInt key_len, encr_len, auth_len; |
|
2320 TChosenAttrib_II *attr_II; |
|
2321 TInt count = iChosenProp_IIList->Count(); |
|
2322 |
|
2323 for (j = 0 ; j < count; j++) |
|
2324 { |
|
2325 prop = iChosenProp_IIList->At(j); |
|
2326 inboundspi_node = iInboundSPIList->At(i); |
|
2327 attr_II = (TChosenAttrib_II *)prop->iAttrList->At(0); //only 1 transform is chosen no matter how many there are |
|
2328 if (prop->iProtocol == PROTO_IPSEC_AH) |
|
2329 { |
|
2330 |
|
2331 sa_type = SADB_SATYPE_AH; |
|
2332 encr_alg = 0; |
|
2333 auth_alg = attr_II->iTransformID; |
|
2334 auth_len = (TInt)HMAC_KeyLength((TUint8)auth_alg); |
|
2335 |
|
2336 TPtr8 AHOutKey((TUint8*)outboundKey_II->Ptr(), 0, outboundKey_II->Des().MaxLength()); |
|
2337 TPtr8 AHInKey((TUint8*)inboundKey_II->Ptr(), 0, inboundKey_II->Des().MaxLength()); |
|
2338 |
|
2339 ComputeKeys2L(prop, auth_len, inboundspi_node, AHOutKey, AHInKey); |
|
2340 in_encrKey.Set(NULL, 0); |
|
2341 out_encrKey.Set(NULL, 0); |
|
2342 in_authKey.Set(inboundKey_II->Ptr(), auth_len/8); |
|
2343 out_authKey.Set(outboundKey_II->Ptr(),auth_len/8); |
|
2344 } |
|
2345 else if (prop->iProtocol == PROTO_IPSEC_ESP) |
|
2346 { |
|
2347 sa_type = SADB_SATYPE_ESP; |
|
2348 encr_alg = attr_II->iTransformID; |
|
2349 if (attr_II->iKeyLength!=0) |
|
2350 encr_len = attr_II->iKeyLength; |
|
2351 else //not sent means constant size or variable and use default |
|
2352 { |
|
2353 switch ( encr_alg ) |
|
2354 { |
|
2355 case ESP_DES_CBC: |
|
2356 encr_len = 64; |
|
2357 break; |
|
2358 case ESP_3DES_CBC: |
|
2359 encr_len = 3*64; |
|
2360 break; |
|
2361 case ESP_NULL: |
|
2362 encr_len = 0; |
|
2363 break; |
|
2364 case ESP_AES_CBC: |
|
2365 encr_len = 128; |
|
2366 break; |
|
2367 default: |
|
2368 encr_len = 0; |
|
2369 break; |
|
2370 |
|
2371 } |
|
2372 } |
|
2373 |
|
2374 if (attr_II->iAuthAlg==DOI_HMAC_MD5) |
|
2375 auth_alg = SADB_AALG_MD5HMAC; |
|
2376 else if (attr_II->iAuthAlg==DOI_HMAC_SHA) |
|
2377 auth_alg = SADB_AALG_SHA1HMAC; |
|
2378 else |
|
2379 auth_alg = 0; |
|
2380 |
|
2381 auth_len = (TInt)HMAC_KeyLength((TUint8)auth_alg); |
|
2382 key_len = encr_len + auth_len; |
|
2383 |
|
2384 TPtr8 ESPOutKey((TUint8*)outboundKey_II->Ptr(), 0, outboundKey_II->Des().MaxLength()); |
|
2385 TPtr8 ESPInKey((TUint8*)inboundKey_II->Ptr(), 0, inboundKey_II->Des().MaxLength()); |
|
2386 ComputeKeys2L(prop, key_len, inboundspi_node, ESPOutKey, ESPInKey); |
|
2387 |
|
2388 in_encrKey.Set(inboundKey_II->Ptr(), encr_len/8); |
|
2389 out_encrKey.Set(outboundKey_II->Ptr(), encr_len/8); |
|
2390 |
|
2391 //If no HMAC selected the next instr does nothing because size will be 0 |
|
2392 in_authKey.Set(inboundKey_II->Ptr() + in_encrKey.Length(),auth_len/8); |
|
2393 out_authKey.Set(outboundKey_II->Ptr() + out_encrKey.Length(),auth_len/8); |
|
2394 // |
|
2395 // Nokia specific NAT traversal info (=ESP UDP tunneling) |
|
2396 // If iNAT_T_Required is true connection is over NAT:ted |
|
2397 // newtork (=local end behind NAT). |
|
2398 // |
|
2399 if ( iNAT_T_Required ) { |
|
2400 flags |= SADB_SAFLAGS_NAT_T; |
|
2401 } |
|
2402 } |
|
2403 else |
|
2404 { |
|
2405 DEBUG_LOG1(_L("Unknown IPsec protocol %d"), prop->iProtocol); |
|
2406 CleanupStack::PopAndDestroy(5); //key buffer, identities and ESP UDP encaps data |
|
2407 return; |
|
2408 } |
|
2409 |
|
2410 updateSPI = inboundspi_node.iSPI; |
|
2411 Mem::Copy((TUint8*)&addSPI, prop->iSPI.Ptr(), sizeof(TUint32)); |
|
2412 |
|
2413 TInetAddr local_addr(iLocalAddr); |
|
2414 local_addr.SetPort(iIDLocalPort); |
|
2415 TInetAddr remote_addr(iRemoteAddr); |
|
2416 remote_addr.SetPort(iIDRemotePort); |
|
2417 |
|
2418 //This will be always outbound |
|
2419 |
|
2420 TInt64 time(0), bytes(0); |
|
2421 TPtrC8 time_ptr(attr_II->iLifeDurationSecs); |
|
2422 TPtrC8 bytes_ptr(attr_II->iLifeDurationKBytes); |
|
2423 if (attr_II->iReducedLifeSecs.Length() != 0) |
|
2424 time_ptr.Set(attr_II->iReducedLifeSecs); |
|
2425 |
|
2426 if (attr_II->iReducedLifeKBytes.Length() != 0) |
|
2427 bytes_ptr.Set(attr_II->iReducedLifeKBytes); |
|
2428 |
|
2429 ComputeLifetimes_II(time_ptr, bytes_ptr, time, bytes); |
|
2430 if (time == 0) //default lifetime applied |
|
2431 time = DEFAULT_IPSEC_SA_LIFETIME; |
|
2432 |
|
2433 if (iHardLifetime > time) |
|
2434 { |
|
2435 DEBUG_LOG2(_L("Time %u, hard lifetime %d"), |
|
2436 I64LOW(time), I64LOW(iHardLifetime)); |
|
2437 time = iHardLifetime; |
|
2438 } |
|
2439 |
|
2440 if (attr_II->iEncMode==DOI_TUNNEL) |
|
2441 { |
|
2442 TunnelMode = ETrue; |
|
2443 DEBUG_LOG(_L("TUNNEL MODE")); |
|
2444 #ifdef _DEBUG |
|
2445 iLocalAddr1_ID_II.OutputWithScope(addr_buf); |
|
2446 DEBUG_LOG1(_L("Local ID: net %S"), &addr_buf); |
|
2447 |
|
2448 if ((iLocalIDType_II == ID_IPV4_ADDR_SUBNET) || (iLocalIDType_II == ID_IPV6_ADDR_SUBNET)) |
|
2449 { |
|
2450 iLocalAddr2_ID_II.OutputWithScope(addr_buf); |
|
2451 DEBUG_LOG1(_L(", mask %S"), &addr_buf); |
|
2452 } |
|
2453 DEBUG_LOG1(_L(" (port %d)"), iIDLocalPort); |
|
2454 iRemoteAddr1_ID_II.OutputWithScope(addr_buf); |
|
2455 DEBUG_LOG1(_L("Remote ID: addr %S"), &addr_buf); |
|
2456 if ((iRemoteIDType_II == ID_IPV4_ADDR_SUBNET) || (iRemoteIDType_II == ID_IPV6_ADDR_SUBNET)) |
|
2457 { |
|
2458 iRemoteAddr2_ID_II.OutputWithScope(addr_buf); |
|
2459 DEBUG_LOG1(_L(", mask %S"), &addr_buf); |
|
2460 } |
|
2461 DEBUG_LOG1(_L(" (port %d)"), iIDRemotePort); |
|
2462 #endif // _DEBUG |
|
2463 |
|
2464 } |
|
2465 else { |
|
2466 TunnelMode = EFalse; |
|
2467 DEBUG_LOG(_L("TRANSPORT MODE")); |
|
2468 } |
|
2469 DEBUG_LOG1(_L("Sec Lifetime set to %u"),I64LOW(time)); |
|
2470 DEBUG_LOG1(_L("KB Lifetime set to %u"),I64LOW(bytes)); |
|
2471 |
|
2472 //Inbound SA. |
|
2473 sa_data.iSAType = sa_type; |
|
2474 sa_data.iSeq = iAcquireSeq; |
|
2475 sa_data.iSrc = remote_addr; |
|
2476 sa_data.iDst = local_addr; |
|
2477 sa_data.iProtocol = iIDProtocol; |
|
2478 sa_data.iSrcIdType = iRemoteIDType_II; |
|
2479 sa_data.iDstIdType = iLocalIDType_II; |
|
2480 sa_data.iSrcIdent.Set((TUint8 *)remote_id->Ptr(), remote_id->Length(), remote_id->Length()); |
|
2481 sa_data.iDstIdent.Set((TUint8 *)local_id->Ptr(), local_id->Length(), local_id->Length()); |
|
2482 sa_data.iPid = iPluginSession->Uid(); |
|
2483 sa_data.iSPI = updateSPI; |
|
2484 sa_data.iAuthAlg = auth_alg; |
|
2485 sa_data.iEncrAlg = encr_alg; |
|
2486 sa_data.iAuthKey.Set(in_authKey); |
|
2487 sa_data.iEncrKey.Set(in_encrKey); |
|
2488 TIpsecSALifetime lifetime(0, bytes, time, 0); |
|
2489 sa_data.iHard = &lifetime; |
|
2490 sa_data.iReplayWindowLength = prop->iReplayWindowLength; |
|
2491 |
|
2492 if ( (sa_type == SADB_SATYPE_ESP) && (GenExtData.Length() == 0) ) { |
|
2493 // |
|
2494 // Store possible NAT traversal info for IPSEC to do ESP UDP encapsulation correctly |
|
2495 // |
|
2496 PFKeyExtDataUtil::BuildUdpEncExtensionData( GenExtData, |
|
2497 iNAT_D_Flags, |
|
2498 (flags & SADB_SAFLAGS_NAT_T), |
|
2499 iHostData->iUseNatProbing, |
|
2500 (TUint16)iHostData->iEspUdpPort, |
|
2501 UDP_KEEPALIVE_TIME, |
|
2502 iLastRemoteAddr, |
|
2503 iRemoteOriginalAddr ); |
|
2504 } |
|
2505 |
|
2506 if ( GenExtData.Length() ) { |
|
2507 sa_data.iGenericExtension.Set(GenExtData); |
|
2508 } |
|
2509 |
|
2510 if ( TunnelMode ) { |
|
2511 // |
|
2512 // Get VPN interface index |
|
2513 // |
|
2514 TUint32 vpnInterfaceIndex = iPluginSession->VpnInterfaceIndex(); |
|
2515 if ( vpnInterfaceIndex != 0 ) |
|
2516 { |
|
2517 sa_data.iInternalAddress.Init( KAfInet6 ); |
|
2518 sa_data.iInternalAddress.SetScope( vpnInterfaceIndex ); |
|
2519 flags |= SADB_SAFLAGS_INT_ADDR; |
|
2520 } |
|
2521 } |
|
2522 sa_data.iFlags = flags; |
|
2523 iPluginSession->UpdateSAL(sa_data); |
|
2524 TIpsecSPI SpiData; |
|
2525 SpiData.iProtocol = sa_type; |
|
2526 SpiData.iSrcAddr = remote_addr; |
|
2527 SpiData.iDstAddr = local_addr; |
|
2528 SpiData.iSPI = updateSPI; |
|
2529 SpiData.iInbound = ETrue; |
|
2530 iPluginSession->AddIpsecSPIToSAL(iSAId, SpiData); |
|
2531 |
|
2532 sa_data.iFlags &= ~SADB_SAFLAGS_INT_ADDR; //No VPN interface index to outbound SA |
|
2533 //Outbound SA. |
|
2534 //First check there's no other SA with the same parameters and |
|
2535 //erase it if happens (very unlikely, but still possible) |
|
2536 SpiData.iDstAddr = remote_addr; |
|
2537 SpiData.iSrcAddr = local_addr; |
|
2538 SpiData.iSPI = addSPI; |
|
2539 SpiData.iInbound = EFalse; |
|
2540 if ( iPluginSession->DeleteIpsecSpi(iSAId, addSPI, EFalse) ) |
|
2541 { |
|
2542 DEBUG_LOG(_L("Deleting previously negotiated IPsec SA")); |
|
2543 iPluginSession->DeleteIpsecSA(SpiData.iSPI, SpiData.iSrcAddr, SpiData.iDstAddr, |
|
2544 SpiData.iProtocol); |
|
2545 } |
|
2546 //Some changes in the SA, the rest is the same |
|
2547 sa_data.iSrc = local_addr; |
|
2548 sa_data.iDst = remote_addr; |
|
2549 sa_data.iSrcIdType = iLocalIDType_II; |
|
2550 sa_data.iDstIdType = iRemoteIDType_II; |
|
2551 sa_data.iSrcIdent.Set((TUint8 *)local_id->Ptr(), local_id->Length(), local_id->Length()); |
|
2552 sa_data.iDstIdent.Set((TUint8 *)remote_id->Ptr(), remote_id->Length(), remote_id->Length()); |
|
2553 sa_data.iPid = addPID; |
|
2554 sa_data.iSPI = addSPI; |
|
2555 sa_data.iAuthKey.Set(out_authKey); |
|
2556 sa_data.iEncrKey.Set(out_encrKey); |
|
2557 |
|
2558 iPluginSession->AddSAL(sa_data); |
|
2559 iPluginSession->AddIpsecSPIToSAL(iSAId, SpiData); |
|
2560 |
|
2561 i++; //To get the correct SPIs from iInboundSPIList |
|
2562 } //end for |
|
2563 |
|
2564 CleanupStack::PopAndDestroy(5); //key buffer, identities and ESP UDP encaps data |
|
2565 |
|
2566 iAcquirePending = EFalse; |
|
2567 |
|
2568 } |
|
2569 |
|
2570 void CIkev1Negotiation::ComputeLifetimes_II(const TDesC8 &aLifetime, const TDesC8 &aLifesize, TInt64 &aTime, TInt64 &aBytes) |
|
2571 { |
|
2572 TInt64 maxnum = MAKE_TINT64(0x7fffffffu, 0xffffffffu); |
|
2573 |
|
2574 if (Desc8ToTInt64(aLifetime, aTime) != KErrNone) |
|
2575 { |
|
2576 DEBUG_LOG(_L("Phase_II Lifetime(sec) Overflowed Setting to maximum value")); |
|
2577 } |
|
2578 if (Desc8ToTInt64(aLifesize, aBytes) != KErrNone) { |
|
2579 DEBUG_LOG(_L("Phase_II Lifetime(kbytes) Overflowed Setting to maximum value")); |
|
2580 } |
|
2581 else |
|
2582 { if (aBytes < maxnum / 1024) //Make sure no overflow |
|
2583 aBytes = aBytes * 1024; //KB to Bytes |
|
2584 else |
|
2585 { |
|
2586 aBytes = MAKE_TINT64(KMaxTInt, KMaxTUint); |
|
2587 DEBUG_LOG(_L("Phase_II Lifetime(kbytes) Overflowed Setting to maximum value")); |
|
2588 } |
|
2589 } |
|
2590 |
|
2591 } |
|
2592 |
|
2593 |
|
2594 TBool CIkev1Negotiation::Phase_IExchangeL(const ThdrISAKMP &aHdr) |
|
2595 { |
|
2596 if (!ProcessHeaderL(aHdr)) |
|
2597 return EFalse; |
|
2598 |
|
2599 DEBUG_LOG2(_L("---------- Phase %d - Stage %d ----------"),iPhase, iStage); |
|
2600 if (iPhase == PHASE_I) |
|
2601 { |
|
2602 if (aHdr.GetExchange() == ISAKMP_EXCHANGE_ID) |
|
2603 MainModeReplyL(); //Main Mode |
|
2604 else |
|
2605 AggressiveReplyL(); //Aggressive Mode |
|
2606 } |
|
2607 else |
|
2608 { |
|
2609 QuickModeReplyL(); |
|
2610 } |
|
2611 return ETrue; |
|
2612 } |
|
2613 |
|
2614 TBool CIkev1Negotiation::Phase_IIExchangeL(const ThdrISAKMP &aHdr) |
|
2615 { |
|
2616 if (!ProcessHeaderL(aHdr)) |
|
2617 return EFalse; |
|
2618 |
|
2619 DEBUG_LOG2(_L("---------- Phase %d - Stage %d ----------"),iPhase, iStage); |
|
2620 |
|
2621 QuickModeReplyL(); |
|
2622 |
|
2623 return ETrue; |
|
2624 } |
|
2625 |
|
2626 void CIkev1Negotiation::QuickModeReplyL() |
|
2627 { |
|
2628 |
|
2629 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
2630 switch(iStage) |
|
2631 { |
|
2632 //INITIATOR cases |
|
2633 case 3: //Send last message (if no COMMIT) |
|
2634 msg->IsakmpInit(this); |
|
2635 msg->IsakmpHashL(); |
|
2636 SendL(*msg); |
|
2637 iStage = 4; |
|
2638 |
|
2639 if (iRecvFlags & ISAKMP_HDR_CFLAG) //Commit Bit set |
|
2640 return; //Not finished yet. We wait for CONNECTED |
|
2641 |
|
2642 //No Commot bit, Update SA database |
|
2643 UpdateSADatabaseL(); |
|
2644 SetFinished(); //No more stages. |
|
2645 break; |
|
2646 case 1: |
|
2647 DEBUG_LOG(_L("QuickModeReplyL in Stage 1 ?")); |
|
2648 break; |
|
2649 case 5: //Send last message (extra message waiting for commit( |
|
2650 //No more processing required |
|
2651 SetFinished(); //No more stages. |
|
2652 break; |
|
2653 //RESPONDER cases |
|
2654 case 2: |
|
2655 GetSPIL(); |
|
2656 //rest done in receiveSPI |
|
2657 break; |
|
2658 case 4: |
|
2659 if (iRecvFlags & ISAKMP_HDR_CFLAG) //Commit Bit set |
|
2660 { |
|
2661 DEBUG_LOG(_L("Sending CONNECTED Status message")); |
|
2662 msg->IsakmpInit(this); |
|
2663 |
|
2664 //HASH Payload only if payload protected with encryption |
|
2665 if (iFlags & ISAKMP_HDR_EFLAG) |
|
2666 msg->IsakmpHashL(); |
|
2667 |
|
2668 msg->IsakmpNotification(CONNECTED, iChosenProp_IIList->At(0)->iProtocol); |
|
2669 |
|
2670 if (iFlags & ISAKMP_HDR_EFLAG) |
|
2671 msg->IsakmpHashContL(); |
|
2672 |
|
2673 SendL(*msg); |
|
2674 } |
|
2675 SetFinished(); |
|
2676 break; |
|
2677 } |
|
2678 } |
|
2679 |
|
2680 //Builds and sends a Phase I reply for Main Mode |
|
2681 void CIkev1Negotiation::MainModeReplyL() |
|
2682 { |
|
2683 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
2684 TInt vendor_type; |
|
2685 |
|
2686 switch(iStage) |
|
2687 { |
|
2688 // |
|
2689 //RESPONDER replies |
|
2690 // |
|
2691 case 2: |
|
2692 msg->IsakmpInit(this); |
|
2693 msg->IsakmpSa(); |
|
2694 if ( iHostData->iDPDHeartBeat != 0 ) |
|
2695 BuildDPDVendorId(*msg); |
|
2696 if ( iNatDiscovery ) { |
|
2697 iNatDiscovery->BuildNatVendorId(*msg); |
|
2698 iNatDiscovery->BuildRfcNatVendorId(*msg); |
|
2699 } |
|
2700 SendL(*msg); |
|
2701 iStage = 3; |
|
2702 break; |
|
2703 case 4: |
|
2704 ComputeNonceL(); //Nonce to be sent |
|
2705 msg->IsakmpInit(this); |
|
2706 msg->IsakmpKeyL(); |
|
2707 msg->IsakmpNonce(); |
|
2708 if (((iChosenProposal_I.iAttrList->iAuthMethod == RSA_SIG) || |
|
2709 (iChosenProposal_I.iAttrList->iAuthMethod == DSS_SIG)) && !iPeerX509Cert) |
|
2710 msg->IsakmpCertificateReqL(); |
|
2711 if ( iNatDiscovery ) { |
|
2712 iNatDiscovery->BuildDiscoveryPayloadsL(*msg, iChosenProposal_I.iAttrList->iHashAlg, |
|
2713 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
2714 iLocalAddr, iLastRemoteAddr); |
|
2715 } |
|
2716 SendL(*msg); |
|
2717 iStage = 5; //next stage |
|
2718 iFlags |= ISAKMP_HDR_EFLAG; //From now on encryption is used |
|
2719 if (!ComputeKeysL()) //Generates keying material for encryption stages |
|
2720 return; //error don't send reply packet |
|
2721 break; |
|
2722 case 6: |
|
2723 msg->IsakmpInit(this); |
|
2724 |
|
2725 switch(iChosenProposal_I.iAttrList->iAuthMethod) |
|
2726 { |
|
2727 case RSA_SIG: |
|
2728 case DSS_SIG: |
|
2729 msg->IsakmpOwnIdentL(); |
|
2730 msg->IsakmpCertificateL(); |
|
2731 msg->IsakmpSignatureL(); |
|
2732 break; |
|
2733 case PRE_SHARED: |
|
2734 msg->IsakmpOwnIdentL(); |
|
2735 msg->IsakmpHashL(); |
|
2736 break; |
|
2737 } |
|
2738 |
|
2739 if ( iHostData->iInitialContact && |
|
2740 iRole == INITIATOR && |
|
2741 iSARekeyInfo == NULL ) |
|
2742 { |
|
2743 DEBUG_LOG(_L("Constructing INITIAL-CONTACT")); |
|
2744 msg->IsakmpNotification(DOI_INITIAL_CONTACT, PROTO_ISAKMP); //Not protected by the hash! |
|
2745 } |
|
2746 |
|
2747 SendL(*msg); |
|
2748 |
|
2749 IsakmpPhase1CompletedL(); |
|
2750 break; |
|
2751 // |
|
2752 //INITIATOR replies |
|
2753 // |
|
2754 case 3: |
|
2755 ComputeNonceL(); //Nonce to be sent |
|
2756 msg->IsakmpInit(this); |
|
2757 msg->IsakmpKeyL(); |
|
2758 msg->IsakmpNonce(); |
|
2759 if ( iChosenProposal_I.iAttrList->iAuthMethod == IKE_A_CRACK && !iPeerX509Cert ) |
|
2760 { |
|
2761 msg->IsakmpCertificateReqL(); |
|
2762 } |
|
2763 if ( iHostData->iUseNatProbing ) |
|
2764 vendor_type = EXPANDED_VENDOR_ID; |
|
2765 else vendor_type = HASH_VENDOR_ID; |
|
2766 msg->IsakmpVendorId(vendor_type, |
|
2767 (TUint8*)iCookie_I.Ptr(), |
|
2768 (TUint8*)iCookie_R.Ptr(), iLocalAddr); |
|
2769 if ( iNatDiscovery ) |
|
2770 { |
|
2771 iNatDiscovery->BuildDiscoveryPayloadsL(*msg, iChosenProposal_I.iAttrList->iHashAlg, |
|
2772 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
2773 iLocalAddr, iLastRemoteAddr); |
|
2774 } |
|
2775 SendL(*msg); |
|
2776 iStage = 4; //next stage |
|
2777 break; |
|
2778 |
|
2779 case 5: |
|
2780 iFlags |= ISAKMP_HDR_EFLAG; //From now on encryption is used |
|
2781 if (!ComputeKeysL()) //Generates keying material for encryption stages |
|
2782 return; //error don't send reply packet |
|
2783 |
|
2784 msg->IsakmpInit(this); |
|
2785 |
|
2786 switch(iChosenProposal_I.iAttrList->iAuthMethod) |
|
2787 { |
|
2788 case RSA_SIG: |
|
2789 case DSS_SIG: |
|
2790 msg->IsakmpOwnIdentL(); //Also fills iOwnIdentPayload! |
|
2791 msg->IsakmpCertificateL(); |
|
2792 msg->IsakmpSignatureL(); |
|
2793 if (!iPeerX509Cert) |
|
2794 msg->IsakmpCertificateReqL(); |
|
2795 break; |
|
2796 case PRE_SHARED: |
|
2797 msg->IsakmpOwnIdentL(); |
|
2798 msg->IsakmpHashL(); |
|
2799 break; |
|
2800 } |
|
2801 |
|
2802 |
|
2803 if ( iFamiliarPeer && iHostData->iUseInternalAddr ) |
|
2804 msg->IsakmpIntnet(0); /* null IPV4 address as parameter */ |
|
2805 |
|
2806 if ( iHostData->iInitialContact && |
|
2807 !iPluginSession->FindIkev1SADataWithAddr(iRemoteAddr) && |
|
2808 iRole == INITIATOR && |
|
2809 iSARekeyInfo == NULL ) |
|
2810 { |
|
2811 DEBUG_LOG(_L("Constructing INITIAL-CONTACT")); |
|
2812 msg->IsakmpNotification(DOI_INITIAL_CONTACT, PROTO_ISAKMP); //Not protected by the hash! |
|
2813 } |
|
2814 |
|
2815 SendL(*msg); |
|
2816 iStage = 6; //next stage |
|
2817 |
|
2818 break; |
|
2819 case 7: |
|
2820 // CRACK authentication going. No actions required here ! |
|
2821 break; |
|
2822 default: |
|
2823 DEBUG_LOG1(_L("Main mode Wrong Phase number requested (%d) !!"),iStage); |
|
2824 } |
|
2825 |
|
2826 } |
|
2827 |
|
2828 |
|
2829 //Builds and sends a Phase I reply for Aggressive Mode |
|
2830 void CIkev1Negotiation::AggressiveReplyL() |
|
2831 { |
|
2832 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
2833 |
|
2834 switch(iStage) |
|
2835 { |
|
2836 case 2://RESPONDER Sends the 2nd msg. of the exchange |
|
2837 ComputeNonceL(); //Nonce to be sent |
|
2838 msg->IsakmpInit(this); |
|
2839 msg->IsakmpSa(); |
|
2840 msg->IsakmpKeyL(); |
|
2841 msg->IsakmpNonce(); |
|
2842 msg->IsakmpOwnIdentL(); |
|
2843 |
|
2844 if (!ComputeKeysL()) //Needed to compute hash before computing signature |
|
2845 { |
|
2846 return; |
|
2847 } |
|
2848 |
|
2849 if ( iHostData->iDPDHeartBeat != 0 ) |
|
2850 BuildDPDVendorId(*msg); |
|
2851 if ( iNatDiscovery ) { |
|
2852 iNatDiscovery->BuildNatVendorId(*msg); |
|
2853 iNatDiscovery->BuildRfcNatVendorId(*msg); |
|
2854 iNatDiscovery->BuildDiscoveryPayloadsL(*msg, iChosenProposal_I.iAttrList->iHashAlg, |
|
2855 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
2856 iLocalAddr, iLastRemoteAddr); |
|
2857 } |
|
2858 |
|
2859 switch (iChosenProposal_I.iAttrList->iAuthMethod) |
|
2860 { |
|
2861 case RSA_SIG: |
|
2862 case DSS_SIG: |
|
2863 msg->IsakmpCertificateL(); |
|
2864 msg->IsakmpSignatureL(); |
|
2865 if (!iPeerX509Cert) //No stored cert so send a CR |
|
2866 { |
|
2867 msg->IsakmpCertificateReqL(); |
|
2868 } |
|
2869 break; |
|
2870 case PRE_SHARED: |
|
2871 msg->IsakmpHashL(); |
|
2872 break; |
|
2873 } |
|
2874 SendL(*msg); |
|
2875 |
|
2876 iStage = 3; //next stage |
|
2877 |
|
2878 break; |
|
2879 case 3://INITIATOR |
|
2880 iFlags |= ISAKMP_HDR_EFLAG; //From now on encryption is used |
|
2881 msg->IsakmpInit(this); |
|
2882 if ( iNatDiscovery ) { |
|
2883 iNatDiscovery->BuildDiscoveryPayloadsL(*msg, iChosenProposal_I.iAttrList->iHashAlg, |
|
2884 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
2885 iLocalAddr, iLastRemoteAddr); |
|
2886 } |
|
2887 |
|
2888 switch (iChosenProposal_I.iAttrList->iAuthMethod) |
|
2889 { |
|
2890 case RSA_SIG: |
|
2891 case DSS_SIG: |
|
2892 msg->IsakmpCertificateL(); |
|
2893 msg->IsakmpSignatureL(); |
|
2894 break; |
|
2895 case PRE_SHARED: |
|
2896 msg->IsakmpHashL(); |
|
2897 break; |
|
2898 } |
|
2899 if ( iHostData->iInitialContact && |
|
2900 !iPluginSession->FindIkev1SADataWithAddr(iRemoteAddr) && |
|
2901 iRole == INITIATOR && |
|
2902 iSARekeyInfo == NULL ) //Only sent if no ISAKMP SA established |
|
2903 { |
|
2904 DEBUG_LOG(_L("Constructing INITIAL-CONTACT")); |
|
2905 msg->IsakmpNotification(DOI_INITIAL_CONTACT, PROTO_ISAKMP); //Not protected by the hash! |
|
2906 } |
|
2907 |
|
2908 SendL(*msg); |
|
2909 IsakmpPhase1CompletedL(); |
|
2910 break; |
|
2911 case 4: |
|
2912 // Aggressive mode as responder completed |
|
2913 DEBUG_LOG(_L("Aggressive mode as responder completed")); |
|
2914 break; |
|
2915 |
|
2916 case 7: |
|
2917 // CRACK authentication going. No actions required here ! |
|
2918 break; |
|
2919 default: |
|
2920 DEBUG_LOG1(_L("Main mode Wrong Phase number requested (%d) !! "),iStage); |
|
2921 } |
|
2922 |
|
2923 } |
|
2924 |
|
2925 void CIkev1Negotiation::SaveISAKMPSAL() |
|
2926 { |
|
2927 // |
|
2928 // Create a new IKEv1 SA object |
|
2929 // |
|
2930 TIkev1SAData SaData; |
|
2931 SaData.iCookie_I = iCookie_I; |
|
2932 SaData.iCookie_R = iCookie_R; |
|
2933 SaData.iSAId = iSAId; |
|
2934 SaData.iSAState = 0; |
|
2935 SaData.iInitiator = (iRole == INITIATOR); |
|
2936 SaData.iAutoLogin = iAutoLogin; |
|
2937 SaData.iDPDSupported = iDPDSupported; |
|
2938 SaData.iFamiliarPeer = iFamiliarPeer; |
|
2939 SaData.iNAT_T_Required = iNAT_T_Required; |
|
2940 SaData.iNAT_D_Flags = iNAT_D_Flags; |
|
2941 SaData.iIkeData = iHostData; |
|
2942 SaData.iLocalAddr = iLocalAddr; |
|
2943 SaData.iRemoteAddr = iRemoteAddr; |
|
2944 SaData.iDestinAddr = iLastRemoteAddr; |
|
2945 SaData.iVirtualIp = iInternalAddr; |
|
2946 SaData.iSeq = iSeq; |
|
2947 SaData.iPrevExchange = iPrevExchange; |
|
2948 SaData.iFlags = iFlags; |
|
2949 |
|
2950 SaData.iEncrAlg = iChosenProposal_I.iAttrList->iEncrAlg; |
|
2951 SaData.iHashAlg = iChosenProposal_I.iAttrList->iHashAlg; |
|
2952 SaData.iGroupDesc = iChosenProposal_I.iAttrList->iGroupDesc; |
|
2953 SaData.iGroupType = iChosenProposal_I.iAttrList->iGroupType; |
|
2954 SaData.iKeyLength = iChosenProposal_I.iAttrList->iKeyLength; |
|
2955 |
|
2956 TUint32 Lifetime = 0; |
|
2957 TUint Len = iChosenProposal_I.iAttrList->iLifeDurationSecs.Length(); |
|
2958 if (Len > 0) |
|
2959 { |
|
2960 if (Len > sizeof(TUint32)) |
|
2961 { |
|
2962 Lifetime = KMaxTUint32; |
|
2963 } |
|
2964 else // (len <= sizeof(TUint32)) |
|
2965 { |
|
2966 Mem::Copy(&Lifetime, iChosenProposal_I.iAttrList->iLifeDurationSecs.Ptr(), Len); |
|
2967 Lifetime = ByteOrder::Swap32(Lifetime); |
|
2968 Lifetime = Lifetime >> (sizeof(TUint32)*8 - Len*8); //To set the correct value (shift in bits) |
|
2969 } |
|
2970 } |
|
2971 SaData.iLifeTimeSecs = Lifetime; |
|
2972 |
|
2973 Lifetime = 0; |
|
2974 Len = iChosenProposal_I.iAttrList->iLifeDurationKBytes.Length(); |
|
2975 if (Len > 0) |
|
2976 { |
|
2977 if (Len > sizeof(TUint32)) |
|
2978 { |
|
2979 Lifetime = KMaxTUint32; |
|
2980 } |
|
2981 else // (len <= sizeof(TUint32)) |
|
2982 { |
|
2983 Mem::Copy(&Lifetime, iChosenProposal_I.iAttrList->iLifeDurationKBytes.Ptr(), Len); |
|
2984 Lifetime = ByteOrder::Swap32(Lifetime); |
|
2985 Lifetime = Lifetime >> (sizeof(TUint32)*8 - Len*8); //To set the correct value (shift in bits) |
|
2986 } |
|
2987 } |
|
2988 SaData.iLifeTimeKB = Lifetime; |
|
2989 |
|
2990 SaData.iSKEYID = iSKEYID; |
|
2991 SaData.iSKEYID_d = iSKEYID_d; |
|
2992 SaData.iSKEYID_a = iSKEYID_a; |
|
2993 SaData.iSKEYID_e = iSKEYID_e; |
|
2994 SaData.iLastIV = iLastIV; |
|
2995 SaData.iIV = iIV; |
|
2996 |
|
2997 if ( iDPDSupported && iHostData->iDPDHeartBeat ) |
|
2998 { |
|
2999 // |
|
3000 // Initialize DPD protocol parameters in TIkev1SAData |
|
3001 // |
|
3002 TPtr8 ptr((TUint8*)&SaData.iDPDSequence, sizeof(TUint32)); |
|
3003 ptr.SetLength(sizeof(TUint32)); |
|
3004 TRandom::RandomL(ptr); |
|
3005 SaData.iDPDSequence &= 0x7fffffff; |
|
3006 SaData.iDPDRetry = 0; |
|
3007 SaData.iPendingDPDSequence = 0; |
|
3008 SaData.iExpectedDPDSequence = 0; |
|
3009 } |
|
3010 |
|
3011 iLastIKEMsgInfo.Store(SaData.iLastIKEMsgInfo); |
|
3012 SaData.iLastMsg = iLastMsg; |
|
3013 iPluginSession->CreateIkev1SAL(SaData, iSARekeyInfo); // Add rekey info later |
|
3014 } |
|
3015 |
|
3016 TBool CIkev1Negotiation::ProcessHeaderL(const ThdrISAKMP &aHdr) |
|
3017 { |
|
3018 //checks on the header |
|
3019 if (!CheckCookies(aHdr.GetCookieI(), aHdr.GetCookieR())) |
|
3020 return EFalse; |
|
3021 |
|
3022 if (iStage == 1) |
|
3023 { |
|
3024 if (iPhase == PHASE_I) |
|
3025 { |
|
3026 iCookie_I = aHdr.GetCookieI(); //save initiator cookie |
|
3027 iCookie_R = CreateCookieL(); //create responder cookie |
|
3028 } |
|
3029 iMessageId = aHdr.GetMessageId(); |
|
3030 } |
|
3031 |
|
3032 //checks on the header |
|
3033 if (!CheckPayloadCode(aHdr.GetPayload())) |
|
3034 return EFalse; |
|
3035 |
|
3036 if (!CheckVersionL(aHdr.GetVersion())) |
|
3037 return EFalse; |
|
3038 |
|
3039 if (!CheckExchangeTypeL(aHdr.GetExchange())) |
|
3040 return EFalse; |
|
3041 |
|
3042 if (!CheckFlagsL(aHdr.GetFlags())) |
|
3043 return EFalse; |
|
3044 iRecvFlags = aHdr.GetFlags(); //Save the flags for later use |
|
3045 |
|
3046 if (!CheckMessageIdL(aHdr.GetMessageId())) |
|
3047 return EFalse; |
|
3048 |
|
3049 iLengthLeft -= ISAKMP_HEADER_SIZE; //Updates the length left in the buffer |
|
3050 |
|
3051 //EVEN stages RESPONDER, ODD ones INITIATOR |
|
3052 DEBUG_LOG(_L("Processing packet...")); |
|
3053 if (iPhase == PHASE_I) |
|
3054 { |
|
3055 switch (iStage) |
|
3056 { |
|
3057 case 1: |
|
3058 if (!ProcessStage1L(aHdr)) |
|
3059 return EFalse; |
|
3060 break; |
|
3061 case 2: |
|
3062 if (!ProcessStage2L(aHdr)) |
|
3063 return EFalse; |
|
3064 break; |
|
3065 case 3: |
|
3066 if (iExchange == ISAKMP_EXCHANGE_ID) |
|
3067 { |
|
3068 if (!ProcessStage3MainL(aHdr)) |
|
3069 return EFalse; |
|
3070 } |
|
3071 else //ISAKMP_EXCHANGE_AGGR |
|
3072 { |
|
3073 if (!ProcessStage3AggrL(aHdr)) |
|
3074 return EFalse; |
|
3075 } |
|
3076 break; |
|
3077 case 4: |
|
3078 if (!ProcessStage4L(aHdr)) |
|
3079 return EFalse; |
|
3080 break; |
|
3081 case 5: |
|
3082 if (!ProcessStage5L(aHdr)) |
|
3083 return EFalse; |
|
3084 break; |
|
3085 case 6: |
|
3086 if (!ProcessStage6L(aHdr)) |
|
3087 return EFalse; |
|
3088 break; |
|
3089 case 7: |
|
3090 if (!ProcessStage7L(aHdr)) /* For CRACK negotiation */ |
|
3091 return EFalse; |
|
3092 break; |
|
3093 default: |
|
3094 return EFalse; |
|
3095 } |
|
3096 } |
|
3097 else //PHASE_II |
|
3098 { |
|
3099 switch (iStage) |
|
3100 { |
|
3101 case 1: |
|
3102 if (!ProcessStage1Phase2L(aHdr)) |
|
3103 return EFalse; |
|
3104 break; |
|
3105 case 2: |
|
3106 if (!ProcessStage2Phase2L(aHdr)) |
|
3107 return EFalse; |
|
3108 break; |
|
3109 case 3: |
|
3110 if (!ProcessStage3Phase2L(aHdr)) |
|
3111 return EFalse; |
|
3112 break; |
|
3113 case 4: |
|
3114 if (!ProcessCONNECTEDL(aHdr)) |
|
3115 return EFalse; |
|
3116 break; |
|
3117 default: |
|
3118 DEBUG_LOG(_L("Quick Bad Stage")); |
|
3119 } |
|
3120 } |
|
3121 return ETrue; |
|
3122 } |
|
3123 |
|
3124 //Process payloads appearing in Stage 1. Responder Role |
|
3125 TBool CIkev1Negotiation::ProcessStage1L(const ThdrISAKMP &aHdr) |
|
3126 { |
|
3127 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3128 if (!payload) |
|
3129 return EFalse; |
|
3130 |
|
3131 CleanupStack::PushL(payload); |
|
3132 |
|
3133 //SA Payload processing (all modes) |
|
3134 if (!ProcessSAL(payload->iSa, NULL)) |
|
3135 { |
|
3136 CleanupStack::PopAndDestroy(); //payload |
|
3137 return EFalse; |
|
3138 } |
|
3139 |
|
3140 //Process vendor ID:s |
|
3141 ProcessVendorL(payload->iVids); |
|
3142 |
|
3143 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3144 |
|
3145 switch (auth_method) |
|
3146 { |
|
3147 case RSA_SIG: |
|
3148 case DSS_SIG: |
|
3149 //Process the possible CR payloads |
|
3150 if ( !ProcessCertificateReqArrayL(payload->iCertReqs) ) { |
|
3151 CleanupStack::PopAndDestroy(); //payload |
|
3152 return EFalse; |
|
3153 } |
|
3154 //Process the possible CERT payloads |
|
3155 if ( !ProcessCertificateArrayL(payload->iCerts) ) { |
|
3156 CleanupStack::PopAndDestroy(); //payload |
|
3157 return EFalse; |
|
3158 } |
|
3159 break; |
|
3160 |
|
3161 default: |
|
3162 break; |
|
3163 } |
|
3164 |
|
3165 |
|
3166 if (iExchange == ISAKMP_EXCHANGE_ID) |
|
3167 { |
|
3168 if ( payload->iKe || payload->iNonce || payload->iHash || payload->iSign || |
|
3169 payload->iIds->Count() ) |
|
3170 { |
|
3171 CleanupStack::PopAndDestroy(); //payload |
|
3172 return EFalse; |
|
3173 } |
|
3174 } |
|
3175 else //ISAKMP_EXCHANGE_AGGR |
|
3176 { |
|
3177 if ( !payload->iKe || !payload->iNonce || (payload->iIds->Count() != 1) ) |
|
3178 { |
|
3179 CleanupStack::PopAndDestroy(); //payload |
|
3180 return EFalse; |
|
3181 } |
|
3182 |
|
3183 //Key Payload processing (all modes) |
|
3184 if (!ProcessKeyL(payload->iKe)) |
|
3185 { |
|
3186 CleanupStack::PopAndDestroy(); //payload |
|
3187 return EFalse; |
|
3188 } |
|
3189 TIdentISAKMP* id_payload = (TIdentISAKMP*)payload->iIds->At(0); // The first ID |
|
3190 TNonceISAKMP* nonce_payload = (TNonceISAKMP*)payload->iNonce; |
|
3191 |
|
3192 //Nonce Payload processing |
|
3193 if (!ProcessNonceL(nonce_payload)) |
|
3194 { |
|
3195 CleanupStack::PopAndDestroy(); //payload |
|
3196 return EFalse; |
|
3197 } |
|
3198 //ID Payload processing |
|
3199 if (!CheckIdentL(id_payload)) |
|
3200 { |
|
3201 CleanupStack::PopAndDestroy(); //payload |
|
3202 return EFalse; |
|
3203 } |
|
3204 //Save the ident payload for HASH_I/R computing |
|
3205 delete iPeerIdentPayload; |
|
3206 iPeerIdentPayload = NULL; |
|
3207 iPeerIdentPayloadSize = id_payload->GetLength() - sizeof(TPayloadISAKMP); |
|
3208 iPeerIdentPayload = new (ELeave) TUint8[iPeerIdentPayloadSize]; |
|
3209 Mem::Copy(iPeerIdentPayload,((TUint8 *)id_payload)+sizeof(TPayloadISAKMP),iPeerIdentPayloadSize); |
|
3210 |
|
3211 if ( iNatDiscovery ) |
|
3212 { |
|
3213 if ( payload->iNatDs->Count() ) |
|
3214 { |
|
3215 iNAT_D_Flags = iNatDiscovery->CheckDiscoveryPayloadsL(payload->iNatDs, iChosenProposal_I.iAttrList->iHashAlg, |
|
3216 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
3217 iLocalAddr, iLastRemoteAddr); |
|
3218 if ( iNAT_D_Flags ) |
|
3219 iLastRemoteAddr.SetPort(FLOATED_IKE_PORT); |
|
3220 } |
|
3221 else |
|
3222 { |
|
3223 if ( iLastRemoteAddr.Port() == FLOATED_IKE_PORT ) |
|
3224 iNAT_D_Flags |= LOCAL_END_NAT; |
|
3225 } |
|
3226 } |
|
3227 |
|
3228 }//end aggressive |
|
3229 |
|
3230 |
|
3231 CleanupStack::PopAndDestroy(); //payload |
|
3232 iStage = 2; |
|
3233 return ETrue; |
|
3234 |
|
3235 } |
|
3236 |
|
3237 //Process payloads appearing in Stage 3. Initiator Role |
|
3238 TBool CIkev1Negotiation::ProcessStage2L(const ThdrISAKMP &aHdr) |
|
3239 { |
|
3240 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3241 if (!payload) |
|
3242 return EFalse; |
|
3243 |
|
3244 CleanupStack::PushL(payload); |
|
3245 |
|
3246 iCookie_R = aHdr.GetCookieR(); //Save the responder Cookie |
|
3247 |
|
3248 //SA Payload processing (all modes) |
|
3249 if (!ProcessSAL(payload->iSa, NULL)) { |
|
3250 CleanupStack::PopAndDestroy(); // payload |
|
3251 return EFalse; |
|
3252 } |
|
3253 |
|
3254 ProcessVendorL(payload->iVids); |
|
3255 |
|
3256 if ( iAutoLogin && (iLocalAddr.Family() == KAFUnspec ) ) { |
|
3257 User::LeaveIfError( iPluginSession->GetLocalAddress( iLocalAddr ) ); //No local address, get it now (used later with NAT traversal) |
|
3258 } |
|
3259 |
|
3260 //NOW we know the auth method chosen! |
|
3261 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3262 |
|
3263 switch (auth_method) |
|
3264 { |
|
3265 case RSA_SIG: |
|
3266 case DSS_SIG: |
|
3267 //Process the possible CR payloads |
|
3268 if ( !ProcessCertificateReqArrayL(payload->iCertReqs) ) |
|
3269 { |
|
3270 CleanupStack::PopAndDestroy(); //payload |
|
3271 return EFalse; |
|
3272 } |
|
3273 if (!ProcessCertificateArrayL(payload->iCerts)) |
|
3274 { |
|
3275 CleanupStack::PopAndDestroy(); //payload |
|
3276 return EFalse; |
|
3277 } |
|
3278 break; |
|
3279 |
|
3280 default: |
|
3281 break; |
|
3282 } |
|
3283 |
|
3284 if (iExchange == ISAKMP_EXCHANGE_ID) |
|
3285 { |
|
3286 if ( payload->iKe || payload->iNonce || payload->iHash || payload->iSign || |
|
3287 payload->iIds->Count() ) |
|
3288 { |
|
3289 CleanupStack::PopAndDestroy(); //payload |
|
3290 return EFalse; |
|
3291 } |
|
3292 } |
|
3293 else //ISAKMP_EXCHANGE_AGGR |
|
3294 { |
|
3295 if ( !payload->iKe || |
|
3296 !payload->iNonce || |
|
3297 (!payload->iHash && auth_method == PRE_SHARED) // hash is a must only with PSK |
|
3298 || (payload->iIds->Count() != 1) ) |
|
3299 { |
|
3300 CleanupStack::PopAndDestroy(); //payload |
|
3301 return EFalse; |
|
3302 } |
|
3303 //Key Payload processing (all modes) |
|
3304 if (!ProcessKeyL(payload->iKe)) |
|
3305 { |
|
3306 CleanupStack::PopAndDestroy(); //payload |
|
3307 return EFalse; |
|
3308 } |
|
3309 TIdentISAKMP* id_payload = (TIdentISAKMP*)payload->iIds->At(0); // The first ID |
|
3310 TNonceISAKMP* nonce_payload = (TNonceISAKMP*)payload->iNonce; |
|
3311 |
|
3312 //Nonce Payload processing |
|
3313 if (!ProcessNonceL(nonce_payload)) |
|
3314 { |
|
3315 CleanupStack::PopAndDestroy(); //payload |
|
3316 return EFalse; |
|
3317 } |
|
3318 |
|
3319 //ID Payload processing |
|
3320 if (!CheckIdentL(id_payload)) |
|
3321 { |
|
3322 CleanupStack::PopAndDestroy(); //payload |
|
3323 return EFalse; |
|
3324 } |
|
3325 |
|
3326 //Save the ident payload for HASH_I/R computing |
|
3327 delete iPeerIdentPayload; |
|
3328 iPeerIdentPayload = NULL; |
|
3329 iPeerIdentPayloadSize = id_payload->GetLength()-sizeof(TPayloadISAKMP); |
|
3330 iPeerIdentPayload = new (ELeave) TUint8[iPeerIdentPayloadSize]; |
|
3331 Mem::Copy(iPeerIdentPayload,((TUint8 *)id_payload)+sizeof(TPayloadISAKMP),iPeerIdentPayloadSize); |
|
3332 |
|
3333 if (!ComputeKeysL()) //Computes the keys to be used. Needed to compute HASH_R |
|
3334 { |
|
3335 CleanupStack::PopAndDestroy(); //payload |
|
3336 return EFalse; |
|
3337 } |
|
3338 |
|
3339 switch (auth_method) |
|
3340 { |
|
3341 case PRE_SHARED: |
|
3342 if (!ProcessHashL(payload->iHash)) |
|
3343 { |
|
3344 CleanupStack::PopAndDestroy(); //payload |
|
3345 return EFalse; |
|
3346 } |
|
3347 DEBUG_LOG(_L("HASH OK!")); |
|
3348 break; |
|
3349 case RSA_SIG: |
|
3350 case DSS_SIG: |
|
3351 case IKE_A_CRACK: |
|
3352 //Signature payload processing and checking |
|
3353 if (!ProcessSignatureL(payload->iSign)) { |
|
3354 CleanupStack::PopAndDestroy(); //payload |
|
3355 return EFalse; |
|
3356 } |
|
3357 if ( auth_method == IKE_A_CRACK ) { |
|
3358 CleanupStack::PopAndDestroy(); //payload |
|
3359 return StartCRACKAuthL(); |
|
3360 } |
|
3361 else { |
|
3362 if (!CertifyRemoteIdentityL(id_payload)) |
|
3363 { |
|
3364 DEBUG_LOG(_L("ProcessStage2L RSA_SIG CertifyRemoteIdentityL failed")); |
|
3365 DEBUG_LOG(_L("AUTHENTICATION_FAILED")); |
|
3366 SetErrorStatus( KKmdIkeAuthFailedErr ); |
|
3367 SendNotifyL(AUTHENTICATION_FAILED); |
|
3368 CleanupStack::PopAndDestroy(); //payload |
|
3369 return EFalse; |
|
3370 } |
|
3371 } |
|
3372 break; |
|
3373 |
|
3374 default: |
|
3375 break; |
|
3376 |
|
3377 } |
|
3378 |
|
3379 if ( iNatDiscovery && payload->iNatDs->Count()) { |
|
3380 iNAT_D_Flags = iNatDiscovery->CheckDiscoveryPayloadsL(payload->iNatDs, iChosenProposal_I.iAttrList->iHashAlg, |
|
3381 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
3382 iLocalAddr, iLastRemoteAddr); |
|
3383 if ( iNAT_D_Flags ) |
|
3384 iLastRemoteAddr.SetPort(FLOATED_IKE_PORT); |
|
3385 } |
|
3386 } |
|
3387 |
|
3388 CleanupStack::PopAndDestroy(); //payload |
|
3389 |
|
3390 iStage = 3; |
|
3391 return ETrue; |
|
3392 } |
|
3393 |
|
3394 // Process payloads appearing in Stage 4. Order NOT relevant. Only Main Mode |
|
3395 // Handles message: HDR, KE, [HASH(1),] <IDii>PubKey_r, <Ni>PubKey_r for RSAENCR |
|
3396 // Handles message: HDR, KE, Ni for the rest [CERTREQ] in certificates |
|
3397 TBool CIkev1Negotiation::ProcessStage3MainL(const ThdrISAKMP &aHdr) |
|
3398 { |
|
3399 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3400 if (!payload) |
|
3401 return EFalse; |
|
3402 |
|
3403 CleanupStack::PushL(payload); |
|
3404 |
|
3405 if ( payload->iSa || !payload->iNonce || payload->iHash || payload->iSign ) |
|
3406 { |
|
3407 CleanupStack::PopAndDestroy(); //payload |
|
3408 return EFalse; |
|
3409 } |
|
3410 |
|
3411 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3412 |
|
3413 //Process payloads |
|
3414 //Main mode (ONLY) |
|
3415 //Key Payload processing (all methods) |
|
3416 if (!ProcessKeyL(payload->iKe)) |
|
3417 { |
|
3418 CleanupStack::PopAndDestroy(); //payload |
|
3419 return EFalse; |
|
3420 } |
|
3421 |
|
3422 if ((auth_method == RSA_SIG) || (auth_method == DSS_SIG)) |
|
3423 { |
|
3424 //Process the possible CR payloads |
|
3425 if ( !ProcessCertificateReqArrayL(payload->iCertReqs) ) |
|
3426 { |
|
3427 CleanupStack::PopAndDestroy(); //payload |
|
3428 return EFalse; |
|
3429 } |
|
3430 } |
|
3431 |
|
3432 TNonceISAKMP* nonce_payload = (TNonceISAKMP*)payload->iNonce; |
|
3433 |
|
3434 ProcessVendorL(payload->iVids); |
|
3435 |
|
3436 if ( iNatDiscovery && payload->iNatDs->Count() ) |
|
3437 { |
|
3438 iNAT_D_Flags = iNatDiscovery->CheckDiscoveryPayloadsL(payload->iNatDs, iChosenProposal_I.iAttrList->iHashAlg, |
|
3439 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
3440 iLocalAddr, iLastRemoteAddr); |
|
3441 if ( iNAT_D_Flags ) |
|
3442 iLastRemoteAddr.SetPort(FLOATED_IKE_PORT); |
|
3443 } |
|
3444 |
|
3445 //Nonce Payload processing (all methods) |
|
3446 TBool Status = ProcessNonceL(nonce_payload); |
|
3447 if ( Status ) |
|
3448 { |
|
3449 iStage = 4; |
|
3450 } |
|
3451 CleanupStack::PopAndDestroy(); //payload |
|
3452 |
|
3453 return Status; |
|
3454 } |
|
3455 |
|
3456 |
|
3457 //Process payloads appearing in 3(Aggressive). Order NOT relevant |
|
3458 TBool CIkev1Negotiation::ProcessStage3AggrL(const ThdrISAKMP &aHdr) |
|
3459 { |
|
3460 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3461 if (!payload) |
|
3462 return EFalse; |
|
3463 |
|
3464 CleanupStack::PushL(payload); |
|
3465 |
|
3466 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3467 |
|
3468 //Mode-dependent processing |
|
3469 switch (auth_method) |
|
3470 { |
|
3471 case PRE_SHARED: |
|
3472 //Hash payload processing |
|
3473 if (!ProcessHashL(payload->iHash)) |
|
3474 { |
|
3475 CleanupStack::PopAndDestroy(); //payload |
|
3476 return EFalse; |
|
3477 } |
|
3478 DEBUG_LOG(_L("HASH OK!")); |
|
3479 break; |
|
3480 case RSA_SIG: |
|
3481 case DSS_SIG: |
|
3482 //Certificate payload processing |
|
3483 if (!ProcessCertificateArrayL(payload->iCerts)) |
|
3484 { |
|
3485 CleanupStack::PopAndDestroy(); //payload |
|
3486 return EFalse; |
|
3487 } |
|
3488 //Signature payload processing |
|
3489 if (!ProcessSignatureL(payload->iSign)) |
|
3490 { |
|
3491 CleanupStack::PopAndDestroy(); //payload |
|
3492 return EFalse; |
|
3493 } |
|
3494 break; |
|
3495 |
|
3496 default: |
|
3497 break; |
|
3498 } |
|
3499 |
|
3500 ProcessVendorL(payload->iVids); |
|
3501 |
|
3502 if ( iNatDiscovery && payload->iNatDs->Count() ) { |
|
3503 iNAT_D_Flags = iNatDiscovery->CheckDiscoveryPayloadsL(payload->iNatDs, iChosenProposal_I.iAttrList->iHashAlg, |
|
3504 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
3505 iLocalAddr, iLastRemoteAddr); |
|
3506 if ( iNAT_D_Flags ) |
|
3507 iLastRemoteAddr.SetPort(FLOATED_IKE_PORT); |
|
3508 } |
|
3509 |
|
3510 CleanupStack::PopAndDestroy(); //payload |
|
3511 |
|
3512 iFlags |= ISAKMP_HDR_EFLAG; //From now on encryption is used |
|
3513 IsakmpPhase1CompletedL(); |
|
3514 iStage = 4; |
|
3515 return ETrue; |
|
3516 |
|
3517 } |
|
3518 |
|
3519 |
|
3520 //Process payloads appearing in Stage 5. Order NOT relevant. ONLY for MAIN Mode |
|
3521 // Preshared and signatures: HDR, KE, Nr |
|
3522 // RSA Encr. : HDR, <IDir>PubKey_i, <Nr_b>PubKey_i |
|
3523 // RSA Revised Encr. : HDR, <Nr_b>PubKey_i , <KE_b>Ke_r, <IDir>Ke_r |
|
3524 TBool CIkev1Negotiation::ProcessStage4L(const ThdrISAKMP &aHdr) |
|
3525 { |
|
3526 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3527 if (!payload) |
|
3528 return EFalse; |
|
3529 |
|
3530 CleanupStack::PushL(payload); |
|
3531 |
|
3532 if ( payload->iSa || !payload->iNonce || !payload->iKe ) |
|
3533 { |
|
3534 CleanupStack::PopAndDestroy(); //payload |
|
3535 return EFalse; |
|
3536 } |
|
3537 |
|
3538 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3539 |
|
3540 if ((auth_method == RSA_SIG) || (auth_method == DSS_SIG)) |
|
3541 { |
|
3542 //Process the possible CR payloads |
|
3543 if ( !ProcessCertificateReqArrayL(payload->iCertReqs) ) |
|
3544 { |
|
3545 CleanupStack::PopAndDestroy(); //payload |
|
3546 return EFalse; |
|
3547 } |
|
3548 } |
|
3549 |
|
3550 //Key Payload processing (all methods) |
|
3551 if (!ProcessKeyL(payload->iKe)) |
|
3552 { |
|
3553 CleanupStack::PopAndDestroy(); //payload |
|
3554 return EFalse; |
|
3555 } |
|
3556 if ( auth_method != PRE_SHARED ) { |
|
3557 if (!ProcessCertificateArrayL(payload->iCerts)) { |
|
3558 CleanupStack::PopAndDestroy(); //payload |
|
3559 return EFalse; |
|
3560 } |
|
3561 } |
|
3562 TNonceISAKMP* nonce_payload = (TNonceISAKMP*)payload->iNonce; |
|
3563 |
|
3564 //Nonce Payload processing (all modes) |
|
3565 TBool Status = ProcessNonceL(nonce_payload); |
|
3566 if (!Status) |
|
3567 { |
|
3568 CleanupStack::PopAndDestroy(); //payload |
|
3569 return EFalse; |
|
3570 } |
|
3571 ProcessVendorL(payload->iVids); |
|
3572 |
|
3573 if ( iNatDiscovery && payload->iNatDs->Count() ) |
|
3574 { |
|
3575 iNAT_D_Flags = iNatDiscovery->CheckDiscoveryPayloadsL(payload->iNatDs, iChosenProposal_I.iAttrList->iHashAlg, |
|
3576 (TUint8*)iCookie_I.Ptr(), (TUint8*)iCookie_R.Ptr(), |
|
3577 iLocalAddr, iLastRemoteAddr); |
|
3578 if ( iNAT_D_Flags ) |
|
3579 iLastRemoteAddr.SetPort(FLOATED_IKE_PORT); |
|
3580 } |
|
3581 |
|
3582 if ( auth_method == IKE_A_CRACK ) |
|
3583 { |
|
3584 /*--------------------------------------------------- |
|
3585 * Process message: HDR, [CERT], KEr, Nr, SIG |
|
3586 * - Verify CRACK signature and if OK |
|
3587 * - Initialize CRACK authentication |
|
3588 *---------------------------------------------------*/ |
|
3589 Status = ComputeKeysL(); |
|
3590 if ( Status ) //Generates keying material for encryption stages |
|
3591 { |
|
3592 Status = ProcessSignatureL(payload->iSign); |
|
3593 if ( Status ) //Signature payload processing and checking |
|
3594 { |
|
3595 Status = StartCRACKAuthL(); |
|
3596 } |
|
3597 } |
|
3598 } |
|
3599 else |
|
3600 { |
|
3601 iStage = 5; |
|
3602 } |
|
3603 |
|
3604 CleanupStack::PopAndDestroy(); //payload |
|
3605 return Status; |
|
3606 } |
|
3607 |
|
3608 |
|
3609 //Process payloads appearing in Stage 6. Order NOT relevant |
|
3610 TBool CIkev1Negotiation::ProcessStage5L(const ThdrISAKMP &aHdr) |
|
3611 { |
|
3612 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3613 if (!payload) |
|
3614 return EFalse; |
|
3615 |
|
3616 CleanupStack::PushL(payload); |
|
3617 if ( payload->iSa || payload->iNonce || payload->iKe ) |
|
3618 { |
|
3619 CleanupStack::PopAndDestroy(); //payload |
|
3620 return EFalse; |
|
3621 } |
|
3622 |
|
3623 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3624 TIdentISAKMP* id_payload = NULL; |
|
3625 // ID Payload processing (all modes) |
|
3626 if ( payload->iIds->Count() != 1 ) |
|
3627 { |
|
3628 CleanupStack::PopAndDestroy(); //payload |
|
3629 return EFalse; |
|
3630 } |
|
3631 id_payload = (TIdentISAKMP*)payload->iIds->At(0); // The first ID |
|
3632 if (!CheckIdentL(id_payload)) |
|
3633 { |
|
3634 CleanupStack::PopAndDestroy(); //payload |
|
3635 return EFalse; |
|
3636 } |
|
3637 //Save the ident payload for HASH_I/R computing |
|
3638 delete iPeerIdentPayload; |
|
3639 iPeerIdentPayload = NULL; |
|
3640 iPeerIdentPayloadSize=id_payload->GetLength()-sizeof(TPayloadISAKMP); |
|
3641 iPeerIdentPayload = new (ELeave) TUint8[iPeerIdentPayloadSize]; |
|
3642 Mem::Copy(iPeerIdentPayload,((TUint8 *)id_payload)+sizeof(TPayloadISAKMP),iPeerIdentPayloadSize); |
|
3643 |
|
3644 //Mode-dependent processing |
|
3645 switch (auth_method) |
|
3646 { |
|
3647 case PRE_SHARED: |
|
3648 //Hash payload processing |
|
3649 if (!ProcessHashL(payload->iHash)) |
|
3650 { |
|
3651 CleanupStack::PopAndDestroy(); //payload |
|
3652 return EFalse; |
|
3653 } |
|
3654 DEBUG_LOG(_L("HASH OK!")); |
|
3655 break; |
|
3656 case RSA_SIG: |
|
3657 case DSS_SIG: |
|
3658 //Certificate payload processing |
|
3659 if (!ProcessCertificateArrayL(payload->iCerts)) |
|
3660 { |
|
3661 CleanupStack::PopAndDestroy(); //payload |
|
3662 return EFalse; |
|
3663 } |
|
3664 if (!CertifyRemoteIdentityL(id_payload)) |
|
3665 { |
|
3666 DEBUG_LOG(_L("ProcessStage5L RSA_SIG CertifyRemoteIdentityL failed")); |
|
3667 DEBUG_LOG(_L("AUTHENTICATION_FAILED")); |
|
3668 SetErrorStatus( KKmdIkeAuthFailedErr ); |
|
3669 SendNotifyL(AUTHENTICATION_FAILED); |
|
3670 CleanupStack::PopAndDestroy(); //payload |
|
3671 return EFalse; |
|
3672 } |
|
3673 //Signature payload processing and checking |
|
3674 if (!ProcessSignatureL(payload->iSign)) |
|
3675 { |
|
3676 CleanupStack::PopAndDestroy(); //payload |
|
3677 return EFalse; |
|
3678 } |
|
3679 //Process the possible CR payloads (needed if we are responder) |
|
3680 if ( iRole == RESPONDER ) |
|
3681 { |
|
3682 if ( !ProcessCertificateReqArrayL(payload->iCertReqs) ) |
|
3683 { |
|
3684 CleanupStack::PopAndDestroy(); //payload |
|
3685 return EFalse; |
|
3686 } |
|
3687 if ( !iOwnCert ) |
|
3688 ReadOwnCertL(); // Peer does not required a specific cert. Get any |
|
3689 } |
|
3690 break; |
|
3691 |
|
3692 default: |
|
3693 break; |
|
3694 }//end switch |
|
3695 |
|
3696 // Process notification payloads |
|
3697 TInt i = 0; |
|
3698 while ( i < payload->iNotifs->Count() ) { |
|
3699 if (!ProcessNotificationL(payload->iNotifs->At(i))) |
|
3700 { |
|
3701 CleanupStack::PopAndDestroy(); //payload |
|
3702 return EFalse; |
|
3703 } |
|
3704 i ++; |
|
3705 } |
|
3706 |
|
3707 ProcessVendorL(payload->iVids); |
|
3708 |
|
3709 CleanupStack::PopAndDestroy(); //payload |
|
3710 |
|
3711 if (iExchange == ISAKMP_EXCHANGE_ID) |
|
3712 iStage = 6; |
|
3713 else iStage = 3; |
|
3714 |
|
3715 return ETrue; |
|
3716 } |
|
3717 |
|
3718 |
|
3719 //Process payloads appearing in Stage 6(Main) Order NOT relevant |
|
3720 TBool CIkev1Negotiation::ProcessStage6L(const ThdrISAKMP &aHdr) |
|
3721 { |
|
3722 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3723 if (!payload) |
|
3724 return EFalse; |
|
3725 |
|
3726 CleanupStack::PushL(payload); |
|
3727 if ( payload->iSa || payload->iNonce || payload->iKe ) |
|
3728 { |
|
3729 CleanupStack::PopAndDestroy(); //payload |
|
3730 return EFalse; |
|
3731 } |
|
3732 |
|
3733 |
|
3734 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
3735 TIdentISAKMP* id_payload = NULL; |
|
3736 //ID Payload processing (all modes) |
|
3737 if ( payload->iIds->Count() != 1 ) |
|
3738 { |
|
3739 CleanupStack::PopAndDestroy(); //payload |
|
3740 return EFalse; |
|
3741 } |
|
3742 id_payload = (TIdentISAKMP*)payload->iIds->At(0); // The first ID |
|
3743 if (!CheckIdentL(id_payload)) |
|
3744 { |
|
3745 CleanupStack::PopAndDestroy(); //payload |
|
3746 return EFalse; |
|
3747 } |
|
3748 //Save the ident payload for HASH_I/R computing |
|
3749 delete iPeerIdentPayload; |
|
3750 iPeerIdentPayload = NULL; |
|
3751 iPeerIdentPayloadSize=id_payload->GetLength()-sizeof(TPayloadISAKMP); |
|
3752 iPeerIdentPayload = new (ELeave) TUint8[iPeerIdentPayloadSize]; |
|
3753 Mem::Copy(iPeerIdentPayload,((TUint8 *)id_payload)+sizeof(TPayloadISAKMP),iPeerIdentPayloadSize); |
|
3754 |
|
3755 //Mode-dependent processing |
|
3756 switch (auth_method) |
|
3757 { |
|
3758 case PRE_SHARED: |
|
3759 //Hash payload processing |
|
3760 if (!ProcessHashL(payload->iHash)) |
|
3761 { |
|
3762 CleanupStack::PopAndDestroy(); //payload |
|
3763 return EFalse; |
|
3764 } |
|
3765 DEBUG_LOG(_L("HASH OK!")); |
|
3766 break; |
|
3767 case RSA_SIG: |
|
3768 case DSS_SIG: |
|
3769 //Certificate payload processing |
|
3770 if (!ProcessCertificateArrayL(payload->iCerts)) |
|
3771 { |
|
3772 CleanupStack::PopAndDestroy(); //payload |
|
3773 return EFalse; |
|
3774 } |
|
3775 if (!CertifyRemoteIdentityL(id_payload)) |
|
3776 { |
|
3777 DEBUG_LOG(_L("ProcessStage6L RSA_SIG CertifyRemoteIdentityL failed")); |
|
3778 DEBUG_LOG(_L("AUTHENTICATION_FAILED")); |
|
3779 SetErrorStatus( KKmdIkeAuthFailedErr ); |
|
3780 SendNotifyL(AUTHENTICATION_FAILED); |
|
3781 CleanupStack::PopAndDestroy(); //payload |
|
3782 return EFalse; |
|
3783 } |
|
3784 //Signature payload processing and checking |
|
3785 if (!ProcessSignatureL(payload->iSign)) |
|
3786 { |
|
3787 CleanupStack::PopAndDestroy(); //payload |
|
3788 return EFalse; |
|
3789 } |
|
3790 break; |
|
3791 default: |
|
3792 break; |
|
3793 } |
|
3794 |
|
3795 // Process notification payloads |
|
3796 TInt i = 0; |
|
3797 while ( i < payload->iNotifs->Count() ) { |
|
3798 if (!ProcessNotificationL(payload->iNotifs->At(i))) |
|
3799 { |
|
3800 CleanupStack::PopAndDestroy(); //payload |
|
3801 return EFalse; |
|
3802 } |
|
3803 i ++; |
|
3804 } |
|
3805 |
|
3806 ProcessVendorL(payload->iVids); |
|
3807 // Internal address payload processing |
|
3808 ProcessIntAddrL(payload->iIaddr); |
|
3809 |
|
3810 CleanupStack::PopAndDestroy(); //payload |
|
3811 |
|
3812 return IsakmpPhase1CompletedL(); |
|
3813 |
|
3814 } |
|
3815 |
|
3816 //Process payloads appearing in Stage 7 = CRACK authentication going |
|
3817 TBool CIkev1Negotiation::ProcessStage7L(const ThdrISAKMP &aHdr) |
|
3818 { |
|
3819 TBool status = ETrue; |
|
3820 TInt crack_status; |
|
3821 |
|
3822 if ( iCRACKneg ) { |
|
3823 crack_status = iCRACKneg->ExecuteCRACKMsgL(aHdr); |
|
3824 |
|
3825 switch ( crack_status ) { |
|
3826 |
|
3827 case CRACK_SUCCESS: |
|
3828 /*------------------------------------------------------- |
|
3829 * CRACK authentication has been succesfully completed |
|
3830 * Take actions to start Quick mode negotiation |
|
3831 *------------------------------------------------------*/ |
|
3832 delete iCRACKneg; |
|
3833 iCRACKneg = NULL; |
|
3834 iLastIV.Copy(iIV); //Saves last IV in Phase 1 |
|
3835 DEBUG_LOG(_L("Last IV Saved!")); |
|
3836 IsakmpPhase1CompletedL(); |
|
3837 break; |
|
3838 |
|
3839 case CRACK_CONTINUE: |
|
3840 /*---------------------------------------------------------- |
|
3841 * CRACK authentication continues, no further actions needed |
|
3842 *----------------------------------------------------------*/ |
|
3843 break; |
|
3844 |
|
3845 case CRACK_IGNORE_MSG: |
|
3846 /*---------------------------------------------------------- |
|
3847 * CRACK authentication continues, received message ignored |
|
3848 *----------------------------------------------------------*/ |
|
3849 status = EFalse; |
|
3850 break; |
|
3851 |
|
3852 default: |
|
3853 /*---------------------------------------------------------- |
|
3854 * CRACK authentication failed, negotiation failed |
|
3855 *----------------------------------------------------------*/ |
|
3856 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
3857 R_VPN_MSG_VPN_GW_AUTH_FAIL, |
|
3858 KKmdIkeAuthFailedErr, |
|
3859 iPluginSession->VpnIapId(), |
|
3860 &iRemoteAddr ); |
|
3861 status = EFalse; |
|
3862 SetErrorStatus(KKmdIkeAuthFailedErr); |
|
3863 AcquireSAErrorResponse(KKmdIkeAuthFailedErr); |
|
3864 break; |
|
3865 |
|
3866 } |
|
3867 } |
|
3868 |
|
3869 return status; |
|
3870 } |
|
3871 |
|
3872 //Called as a RESPONDER for PHASE_II |
|
3873 //Checks HASH(1),SA,KE,NONCE,[ID,ID] from INITIATOR |
|
3874 TBool CIkev1Negotiation::ProcessStage1Phase2L(const ThdrISAKMP &aHdr) |
|
3875 { |
|
3876 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
3877 if (!payload) |
|
3878 return EFalse; |
|
3879 |
|
3880 CleanupStack::PushL(payload); |
|
3881 |
|
3882 if ( !payload->iSa || !payload->iNonce ) |
|
3883 { |
|
3884 CleanupStack::PopAndDestroy(); //payload |
|
3885 return EFalse; |
|
3886 } |
|
3887 |
|
3888 //Payload Processing |
|
3889 |
|
3890 CProposal_IIList *recv_proposals = new (ELeave) CProposal_IIList(1); //, *prop |
|
3891 CleanupStack::PushL(recv_proposals); |
|
3892 |
|
3893 //SA |
|
3894 if (!ProcessSAL(payload->iSa, (TUint8 *)recv_proposals)) |
|
3895 { |
|
3896 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
3897 return EFalse; |
|
3898 } |
|
3899 |
|
3900 //ID payloads (if existing) |
|
3901 if ( payload->iIds->Count() == 2 ) |
|
3902 { |
|
3903 if (!ProcessStage1_II_IDsL(payload->iIds->At(0), payload->iIds->At(1), recv_proposals)) |
|
3904 { |
|
3905 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
3906 return EFalse; |
|
3907 } |
|
3908 } |
|
3909 else if ( payload->iIds->Count() != 0 ) |
|
3910 { |
|
3911 DEBUG_LOG(_L("Unsupported Phase II ID payload count")); |
|
3912 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
3913 return EFalse; |
|
3914 } |
|
3915 //After ID to know what address to search in the "SAD" |
|
3916 TInt err = BuildProposals2L(); |
|
3917 if (err != KErrNone) |
|
3918 { |
|
3919 DEBUG_LOG(_L("NO_PROPOSAL_CHOSEN: No policy matching")); |
|
3920 SendNotifyL(NO_PROPOSAL_CHOSEN); |
|
3921 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
3922 return EFalse; |
|
3923 } |
|
3924 |
|
3925 //Contains the transform nums matching if multiple proposals |
|
3926 CTransModifierList *trans_array = new (ELeave) CTransModifierList(1); |
|
3927 CleanupStack::PushL(trans_array); |
|
3928 |
|
3929 TInt num = iProposal_IIList->MultiMatchL(recv_proposals, iRole == RESPONDER, trans_array);//If RESPONDER relaxed comparison (no lifetimes checked) |
|
3930 iProposalNum = num; // Set to num not 1 |
|
3931 #ifdef _DEBUG |
|
3932 TBuf<128> err_buf; |
|
3933 #endif |
|
3934 if (num < 0) |
|
3935 { |
|
3936 #ifdef _DEBUG |
|
3937 err_buf.Copy(_L("NO_PROPOSAL_CHOSEN: Phase II proposal not accepted - ")); |
|
3938 AppendAttributeError(num, err_buf); |
|
3939 DEBUG_LOG(err_buf); |
|
3940 #endif |
|
3941 SetErrorStatus( KKmdIkeNoProposalErr ); |
|
3942 SendNotifyL(NO_PROPOSAL_CHOSEN); |
|
3943 CleanupStack::PopAndDestroy(3); //transarray + recv_proposals + payload |
|
3944 return EFalse; |
|
3945 } |
|
3946 |
|
3947 //Copy the chosen transform |
|
3948 //Actually is the same one as recv_proposals because we should always receive a single proposal with a single transform. |
|
3949 CreateChosenProposalL(recv_proposals, num, trans_array); |
|
3950 |
|
3951 CleanupStack::PopAndDestroy(2); //transarray + recv_proposals |
|
3952 |
|
3953 //Process the possible NOTIFICATION payloads |
|
3954 for (TInt i = 0; i < payload->iNotifs->Count(); i++) |
|
3955 { |
|
3956 if (!ProcessNotificationL(payload->iNotifs->At(i))) |
|
3957 { |
|
3958 CleanupStack::PopAndDestroy(); //payload |
|
3959 return EFalse; |
|
3960 } |
|
3961 } |
|
3962 |
|
3963 if (!ProcessNonceL(payload->iNonce)) |
|
3964 { |
|
3965 CleanupStack::PopAndDestroy(); //payload |
|
3966 return EFalse; |
|
3967 } |
|
3968 //HASH |
|
3969 if (!ProcessHash2L(aHdr, payload->iHash, payload->iPadding)) |
|
3970 { |
|
3971 CleanupStack::PopAndDestroy(); //payload |
|
3972 return EFalse; |
|
3973 } |
|
3974 |
|
3975 if (!ProcessKeyL(payload->iKe)) |
|
3976 { |
|
3977 CleanupStack::PopAndDestroy(); //payload |
|
3978 return EFalse; |
|
3979 } |
|
3980 |
|
3981 ProcessVendorL(payload->iVids); |
|
3982 |
|
3983 if ( iNatDiscovery ) { |
|
3984 iNAT_D_Flags |= iNatDiscovery->GetPeerOriginalAddress(payload->iNatOa, iRemoteOriginalAddr, iChosenProp_IIList); |
|
3985 } |
|
3986 |
|
3987 CleanupStack::PopAndDestroy(); //notif_payload_array |
|
3988 iStage = 2; |
|
3989 return ETrue; |
|
3990 } |
|
3991 |
|
3992 //Creates a new proposal list from a selected part of another list (Certain proposal and transforms) |
|
3993 void CIkev1Negotiation::CreateChosenProposalL(CProposal_IIList* aPropList, TInt aPropNum, CTransModifierList *aTransArray) |
|
3994 { |
|
3995 |
|
3996 CProposal_II *prop, *new_propII; |
|
3997 TAttrib_II *attr_II; |
|
3998 TChosenAttrib_II *new_attr_II; |
|
3999 TInt count = aPropList->Count(); |
|
4000 TInt i = 0; |
|
4001 TInt j = 0; |
|
4002 |
|
4003 // |
|
4004 // Find selected proroposal from list |
|
4005 // |
|
4006 while ( i < count) |
|
4007 { |
|
4008 if (aPropList->At(i)->iProposalNum == aPropNum) |
|
4009 break; |
|
4010 i ++; |
|
4011 } |
|
4012 |
|
4013 TTransModifier *tmodif; |
|
4014 TInt64 own_time, own_bytes, peer_time, peer_bytes; |
|
4015 delete iChosenProp_IIList; //Must be erased because can contain data from previous retransmissions |
|
4016 iChosenProp_IIList = NULL; |
|
4017 iChosenProp_IIList = new (ELeave) CProposal_IIList(1); |
|
4018 while ( i < count ) |
|
4019 { |
|
4020 prop = aPropList->At(i); |
|
4021 if ( prop->iProposalNum != aPropNum) |
|
4022 break; // Stop, another Proposal |
|
4023 |
|
4024 new_propII = new (ELeave) CProposal_II(); |
|
4025 CleanupStack::PushL(new_propII); |
|
4026 new_propII->ConstructL(1); |
|
4027 iChosenProp_IIList->AppendL(new_propII); |
|
4028 CleanupStack::Pop(); //new_propII safe |
|
4029 |
|
4030 new_propII->iProtocol = prop->iProtocol; |
|
4031 new_propII->iNumTransforms = 1; //We only choose 1 transform for each proposal |
|
4032 new_propII->iProposalNum = (TUint8)aPropNum; |
|
4033 new_propII->iSPI.Copy(prop->iSPI); |
|
4034 tmodif = aTransArray->At(j); |
|
4035 new_propII->iReplayWindowLength = tmodif->iReplayWindowLength; |
|
4036 |
|
4037 attr_II = prop->iAttrList->At(tmodif->iTransNum); //look for the chosen transform in the prop |
|
4038 ComputeLifetimes_II(tmodif->iReducedLifeSecs, tmodif->iReducedLifeKBytes, own_time, own_bytes); |
|
4039 ComputeLifetimes_II(attr_II->iLifeDurationSecs, attr_II->iLifeDurationKBytes, peer_time, peer_bytes); |
|
4040 |
|
4041 //Only copy the chosen transform |
|
4042 new_attr_II = new (ELeave) TChosenAttrib_II(); |
|
4043 CleanupStack::PushL(new_attr_II); |
|
4044 new_attr_II->Copy(*attr_II); |
|
4045 if ((peer_time > own_time) && (own_time != 0)) |
|
4046 { |
|
4047 new_attr_II->iReducedLifeSecs.Set(tmodif->iReducedLifeSecs); |
|
4048 DEBUG_LOG1(_L("Lifetime bigger than the one set. Reducing to %d"), own_time); |
|
4049 } |
|
4050 else |
|
4051 new_attr_II->iReducedLifeSecs.Set(NULL, 0); |
|
4052 |
|
4053 if ((peer_bytes > own_bytes) && (own_bytes != 0)) |
|
4054 { |
|
4055 new_attr_II->iReducedLifeKBytes.Set(tmodif->iReducedLifeKBytes); |
|
4056 DEBUG_LOG1(_L("Lifesize bigger than the one set. Reducing to %d"), own_bytes); |
|
4057 } |
|
4058 else |
|
4059 new_attr_II->iReducedLifeKBytes.Set(NULL, 0); |
|
4060 |
|
4061 new_propII->iAttrList->AppendL(new_attr_II); |
|
4062 CleanupStack::Pop(); //new_attrII safe |
|
4063 |
|
4064 j++; // Next transform modifer |
|
4065 i++; // Next proposal |
|
4066 |
|
4067 } |
|
4068 } |
|
4069 |
|
4070 |
|
4071 //Called as a INITIATOR for PHASE_II |
|
4072 //Checks HASH(1),SA, ,NONCE,[KE] [ID,ID] from RESPONDER |
|
4073 TBool CIkev1Negotiation::ProcessStage2Phase2L(const ThdrISAKMP &aHdr) |
|
4074 { |
|
4075 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
4076 if (!payload) |
|
4077 return EFalse; |
|
4078 |
|
4079 CleanupStack::PushL(payload); |
|
4080 |
|
4081 if ( !payload->iSa || !payload->iNonce ) |
|
4082 { |
|
4083 CleanupStack::PopAndDestroy(); //payload |
|
4084 return EFalse; |
|
4085 } |
|
4086 |
|
4087 CProposal_IIList *recv_proposals = new (ELeave) CProposal_IIList(1); |
|
4088 CleanupStack::PushL(recv_proposals); |
|
4089 |
|
4090 //SA |
|
4091 if (!ProcessSAL(payload->iSa, (TUint8 *)recv_proposals)) |
|
4092 { |
|
4093 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
4094 return EFalse; |
|
4095 } |
|
4096 |
|
4097 //ID payloads (if existing) |
|
4098 if ( payload->iIds->Count() == 2 ) |
|
4099 { |
|
4100 if (!ProcessStage2_II_IDsL(payload->iIds->At(0), payload->iIds->At(1))) |
|
4101 { |
|
4102 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
4103 return EFalse; |
|
4104 } |
|
4105 } |
|
4106 else if ( payload->iIds->Count() != 0 ) |
|
4107 { |
|
4108 DEBUG_LOG(_L("Unsupported Phase II ID payload count")); |
|
4109 CleanupStack::PopAndDestroy(2); //recv_proposals + payload |
|
4110 return EFalse; |
|
4111 } |
|
4112 |
|
4113 //Contains the transform nums matching if multiple proposals |
|
4114 CTransModifierList *trans_array = new (ELeave) CTransModifierList(1); |
|
4115 CleanupStack::PushL(trans_array); |
|
4116 |
|
4117 //Check the received proposals match the proposed one (Got from |
|
4118 //acquire msg.) |
|
4119 TInt num = iProposal_IIList->MultiMatchL(recv_proposals, iRole == RESPONDER, trans_array);//If RESPONDER relaxed comparison (no lifetimes checked) |
|
4120 #ifdef _DEBUG |
|
4121 TBuf<128> err_buf; |
|
4122 #endif |
|
4123 if (num < 0) |
|
4124 { |
|
4125 #ifdef _DEBUG |
|
4126 err_buf.Copy(_L("BAD_PROPOSAL_SYNTAX: Phase II reply doesn't match proposal - ")); |
|
4127 AppendAttributeError(num, err_buf); |
|
4128 DEBUG_LOG(err_buf); |
|
4129 #endif |
|
4130 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4131 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4132 CleanupStack::PopAndDestroy(3); //transarray + recv_proposals + payload |
|
4133 return EFalse; |
|
4134 } |
|
4135 // iProposalNum set to correspond local proposal numbering |
|
4136 iProposalNum = trans_array->At(0)->iPropNum; |
|
4137 //Copy the chosen transform |
|
4138 CreateChosenProposalL(recv_proposals, num, trans_array); |
|
4139 |
|
4140 CleanupStack::PopAndDestroy(2); //transarray + recv_proposals |
|
4141 |
|
4142 //Process the possible NOTIFICATION payloads |
|
4143 for (TInt i = 0; i < payload->iNotifs->Count(); i++) |
|
4144 { |
|
4145 if (!ProcessNotificationL(payload->iNotifs->At(i))) |
|
4146 { |
|
4147 CleanupStack::PopAndDestroy(); //payload |
|
4148 return EFalse; |
|
4149 } |
|
4150 } |
|
4151 //NONCE |
|
4152 if (!ProcessNonceL(payload->iNonce)) |
|
4153 { |
|
4154 CleanupStack::PopAndDestroy(); //payload |
|
4155 return EFalse; |
|
4156 } |
|
4157 //HASH |
|
4158 if (!ProcessHash2L(aHdr, payload->iHash, payload->iPadding)) |
|
4159 { |
|
4160 CleanupStack::PopAndDestroy(); //payload |
|
4161 return EFalse; |
|
4162 } |
|
4163 //KEY (if present (PFS)) |
|
4164 if (!ProcessKeyL(payload->iKe)) |
|
4165 { |
|
4166 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4167 SendNotifyL(PAYLOAD_MALFORMED); |
|
4168 CleanupStack::PopAndDestroy(); //payload |
|
4169 return EFalse; |
|
4170 } |
|
4171 |
|
4172 ProcessVendorL(payload->iVids); |
|
4173 |
|
4174 if ( iNatDiscovery ) { |
|
4175 iNAT_D_Flags |= iNatDiscovery->GetPeerOriginalAddress(payload->iNatOa, iRemoteOriginalAddr, iChosenProp_IIList); |
|
4176 } |
|
4177 |
|
4178 if ( iRecvFlags & ISAKMP_HDR_CFLAG ) //Commit Bit set |
|
4179 { |
|
4180 iFlags |= ISAKMP_HDR_CFLAG; //Sets the Commit bit if this side set it else |
|
4181 DEBUG_LOG(_L("SAD update delayed until CONNECTED received")); |
|
4182 } |
|
4183 |
|
4184 CleanupStack::PopAndDestroy(); //payload |
|
4185 iStage = 3; |
|
4186 return ETrue; |
|
4187 |
|
4188 } |
|
4189 |
|
4190 TBool CIkev1Negotiation::ProcessStage3Phase2L(const ThdrISAKMP &aHdr) |
|
4191 { |
|
4192 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
4193 if (!payload) |
|
4194 return EFalse; |
|
4195 |
|
4196 CleanupStack::PushL(payload); |
|
4197 |
|
4198 if ( payload->iSa || payload->iNonce || payload->iKe || payload->iIds->Count() != 0 ) |
|
4199 { |
|
4200 CleanupStack::PopAndDestroy(); //payload |
|
4201 return EFalse; |
|
4202 } |
|
4203 |
|
4204 //Hash Payload |
|
4205 TBool Status = ProcessHash2L(aHdr, payload->iHash, payload->iPadding); |
|
4206 if ( Status ) |
|
4207 { |
|
4208 //END OF THE PHASE II (Quick mode) negotiation. |
|
4209 //Now we need to update the PFKEY SA database |
|
4210 ProcessVendorL(payload->iVids); |
|
4211 UpdateSADatabaseL(); |
|
4212 iStage = 4; |
|
4213 } |
|
4214 CleanupStack::PopAndDestroy(); //payload |
|
4215 return Status; |
|
4216 } |
|
4217 |
|
4218 TBool CIkev1Negotiation::ProcessCONNECTEDL(const ThdrISAKMP &aHdr) |
|
4219 { |
|
4220 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *this, iDebug); |
|
4221 if (!payload) |
|
4222 return EFalse; |
|
4223 |
|
4224 CleanupStack::PushL(payload); |
|
4225 |
|
4226 if ( !payload->iHash || (payload->iNotifs->Count() != 1) || payload->iSa || |
|
4227 payload->iNonce || payload->iKe || (payload->iIds->Count() != 0) ) |
|
4228 { |
|
4229 DEBUG_LOG(_L("PAYLOAD_MALFORMED (no hash or notfic payload)")); |
|
4230 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4231 SendNotifyL(PAYLOAD_MALFORMED); |
|
4232 CleanupStack::PopAndDestroy(); //payload |
|
4233 return EFalse; |
|
4234 } |
|
4235 |
|
4236 //Checks if the hash value is OK. Here because need the |
|
4237 //notification payload |
|
4238 const TNotificationISAKMP* notif_payload = payload->iNotifs->At(0); |
|
4239 TBool Status = VerifyInformationalHashL(payload->iHash, notif_payload, iMessageId); |
|
4240 if ( Status ) |
|
4241 { //Hash OK |
|
4242 if ((notif_payload->GetDOI() == IPSEC_DOI) && (notif_payload->GetMsgType() == CONNECTED)) |
|
4243 { |
|
4244 //END OF THE PHASE II (Quick mode) negotiation. |
|
4245 //Now we need to update the PFKEY SA database |
|
4246 DEBUG_LOG(_L("CONNECTED message received. Updating SAD")); |
|
4247 UpdateSADatabaseL(); |
|
4248 iStage = 5; |
|
4249 } |
|
4250 } |
|
4251 else |
|
4252 { |
|
4253 DEBUG_LOG(_L("AUTHENTICATION_FAILED (Informational hash)")); |
|
4254 SetErrorStatus( KKmdIkeAuthFailedErr ); |
|
4255 SendNotifyL(AUTHENTICATION_FAILED); |
|
4256 } |
|
4257 CleanupStack::PopAndDestroy(); //payload |
|
4258 return Status; |
|
4259 } |
|
4260 |
|
4261 //returns KErrNone if OK, otherwise error already treated. |
|
4262 TBool CIkev1Negotiation::ProcessSAL(const TSAISAKMP *aSA, TUint8 *aRecvProposals) |
|
4263 { |
|
4264 //payload not present |
|
4265 if (!aSA) |
|
4266 { |
|
4267 DEBUG_LOG(_L("NO SA PAYLOAD")); |
|
4268 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4269 SendNotifyL(PAYLOAD_MALFORMED); |
|
4270 return EFalse; |
|
4271 } |
|
4272 |
|
4273 //requires a special length check to know the proposals and transforms are not bigger than |
|
4274 //the size specified in th SA |
|
4275 TUint32 SALengthLeft = aSA->GetLength() - aSA->Size(); |
|
4276 |
|
4277 TUint8 next_payload = aSA->GetPayload(); |
|
4278 if ((next_payload == ISAKMP_PAYLOAD_P) || (next_payload == ISAKMP_PAYLOAD_T)) |
|
4279 { |
|
4280 DEBUG_LOG(_L("INVALID_PAYLOAD_TYPE (Bad next payload for the SA)")); |
|
4281 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4282 SendNotifyL(INVALID_PAYLOAD_TYPE); // Payloads and transforms are processed as a part of the SA, |
|
4283 return EFalse; |
|
4284 } |
|
4285 |
|
4286 TUint32 doi=aSA->GetDOI(); |
|
4287 if (!CheckDOI(doi)) |
|
4288 { |
|
4289 DEBUG_LOG(_L("DOI_NOT_SUPPORTED in SA payload")); |
|
4290 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4291 SendNotifyL(DOI_NOT_SUPPORTED); //send the informational exchange |
|
4292 return EFalse; |
|
4293 } |
|
4294 |
|
4295 if (iStage == 1) |
|
4296 iDOI = doi; |
|
4297 |
|
4298 //Process SITuation depending on DOI. In this implementation always is IPSEC DOI |
|
4299 if (!CheckSituationL(aSA->GetSIT())) |
|
4300 return EFalse; |
|
4301 |
|
4302 if (aSA->HasLDId()) //If no Labeled Domain Identifier no more processing for the SA |
|
4303 { |
|
4304 DEBUG_LOG(_L("Label Domain Identifier (LDI) not supported")); |
|
4305 return EFalse; |
|
4306 } |
|
4307 |
|
4308 if (iPhase==PHASE_I) //Only used in Phase_I. PHASE_II hashs check it directly from received paylaod |
|
4309 { |
|
4310 //Store the SA payload for further calculations in Hash. |
|
4311 if (iRole==RESPONDER) |
|
4312 { |
|
4313 iSAPayloadSize = aSA->GetLength()-sizeof(TPayloadISAKMP); |
|
4314 delete iSAPayload; |
|
4315 iSAPayload = NULL; |
|
4316 iSAPayload = new (ELeave) (TUint8[iSAPayloadSize]); //Generic payload NOT included |
|
4317 Mem::Copy(iSAPayload,(((TUint8 *)aSA)+sizeof(TPayloadISAKMP)),iSAPayloadSize); |
|
4318 } |
|
4319 } |
|
4320 const TPayloadISAKMP *payload = aSA->Payload(); |
|
4321 return ProcessProposalsL(payload, SALengthLeft, aRecvProposals); |
|
4322 } |
|
4323 |
|
4324 |
|
4325 //Do the process required for proposals and transforms. The aPayload given must be a proposal |
|
4326 TBool CIkev1Negotiation::ProcessProposalsL(const TPayloadISAKMP *aPayload, TUint32 aLengthLeft, TUint8 *aRecvProposals) |
|
4327 { |
|
4328 TProposalISAKMP *proposal; |
|
4329 const TPayloadISAKMP *ppayload=aPayload; |
|
4330 TUint8 payType = ppayload->GetPayload(); |
|
4331 TUint32 len_left; |
|
4332 CProposal_IIList *recv_proposals = (CProposal_IIList *)aRecvProposals; |
|
4333 CProposal_II *auxProp_II; |
|
4334 TBool found = EFalse; //At least 1 transform matching |
|
4335 |
|
4336 //Many Proposals. The RESPONDER MUST choose a transform for each proposal or reject the |
|
4337 //full suite of attributes. |
|
4338 do |
|
4339 { |
|
4340 //General payload check |
|
4341 if ((payType != ISAKMP_PAYLOAD_NONE) && (payType != ISAKMP_PAYLOAD_P)) |
|
4342 { |
|
4343 DEBUG_LOG(_L("INVALID_PAYLOAD_TYPE (Bad next payload for the proposal)")); |
|
4344 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4345 SendNotifyL(INVALID_PAYLOAD_TYPE); |
|
4346 return EFalse; |
|
4347 } |
|
4348 |
|
4349 if (aPayload->GetReserved() != 0) //Must be always 0 |
|
4350 { |
|
4351 DEBUG_LOG(_L("INVALID RESERVED FIELD")); |
|
4352 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4353 SendNotifyL(PAYLOAD_MALFORMED); |
|
4354 return EFalse; |
|
4355 } |
|
4356 |
|
4357 //requires special length check |
|
4358 if ((aPayload->GetLength() < MIN_ISAKMP_PAYLOAD_SIZE) || (aPayload->GetLength() > aLengthLeft)) |
|
4359 { |
|
4360 DEBUG_LOG(_L("BAD PAYLOAD SIZE")); |
|
4361 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4362 SendNotifyL(PAYLOAD_MALFORMED); |
|
4363 return EFalse; |
|
4364 } |
|
4365 |
|
4366 aLengthLeft -= aPayload->GetLength(); //dcreases the length of the prop. and its transforms |
|
4367 |
|
4368 proposal = TProposalISAKMP::Ptr(ppayload); |
|
4369 |
|
4370 |
|
4371 if (!CheckProtocolL(proposal->GetProtocol())) |
|
4372 return EFalse; |
|
4373 |
|
4374 if (!CheckSPIL(proposal)) |
|
4375 return EFalse; |
|
4376 |
|
4377 len_left = proposal->GetLength() - (proposal->Size() + proposal->GetSPISize()); |
|
4378 //len_left contains the length of the transforms only |
|
4379 |
|
4380 TInt ret = KErrNotFound; |
|
4381 if (iPhase == PHASE_I) |
|
4382 { |
|
4383 iChosenProposal_I.iProtocol = proposal->GetProtocol(); |
|
4384 iChosenProposal_I.iSPI.Copy((TUint8 *)proposal->SPI(), proposal->GetSPISize()); |
|
4385 iChosenProposal_I.iNumTransforms = 1; //Phase I only one transf chosen |
|
4386 iChosenProposal_I.iProposalNum = proposal->GetNum();//Not compulsory but preferable to speed up the search process in the peer |
|
4387 |
|
4388 ret = ProcessTransformsL(ppayload,len_left); |
|
4389 |
|
4390 if (ret == KErrNone) |
|
4391 return ETrue;//valid transform found |
|
4392 else if (ret != KErrNotFound) |
|
4393 { |
|
4394 DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED")); |
|
4395 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4396 SendNotifyL(ATTRIBUTES_NOT_SUPPORTED); |
|
4397 return EFalse; |
|
4398 } |
|
4399 //If not found there may be other proposal to check |
|
4400 } |
|
4401 else //PHASE_II |
|
4402 { |
|
4403 auxProp_II = new (ELeave) CProposal_II(); |
|
4404 CleanupStack::PushL(auxProp_II); |
|
4405 auxProp_II->ConstructL(proposal->GetNumTrans()); |
|
4406 auxProp_II->iProtocol=proposal->GetProtocol(); |
|
4407 auxProp_II->iSPI.Copy((TUint8 *)proposal->SPI(), proposal->GetSPISize()); |
|
4408 auxProp_II->iNumTransforms = proposal->GetNumTrans(); //Number of transforms in the proposal |
|
4409 auxProp_II->iProposalNum = proposal->GetNum(); //Proposal num |
|
4410 |
|
4411 ret = ProcessTransforms2L(ppayload, auxProp_II, len_left); |
|
4412 if (ret==KErrNone)//valid transform found |
|
4413 { |
|
4414 //Adds the new proposal to the list of chosen proposals |
|
4415 recv_proposals->AppendL(auxProp_II); |
|
4416 CleanupStack::Pop(); //auxProp_II safe |
|
4417 found = ETrue; |
|
4418 //go for the next proposal |
|
4419 } |
|
4420 else |
|
4421 { |
|
4422 DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED")); |
|
4423 SendNotifyL(ATTRIBUTES_NOT_SUPPORTED); |
|
4424 CleanupStack::PopAndDestroy(); //delete auxProp_II; //delete the current proposal |
|
4425 return EFalse; |
|
4426 } |
|
4427 } |
|
4428 |
|
4429 payType = ppayload->GetPayload(); |
|
4430 ppayload = ppayload->Next(); //Next payload if there's any |
|
4431 } while (payType!=ISAKMP_PAYLOAD_NONE); //Proposal loop |
|
4432 |
|
4433 if (!found) |
|
4434 { |
|
4435 DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED")); |
|
4436 SendNotifyL(ATTRIBUTES_NOT_SUPPORTED); |
|
4437 return EFalse; |
|
4438 } |
|
4439 |
|
4440 return found; |
|
4441 } |
|
4442 |
|
4443 //processes all the PHASE I transforms. The parameter payload is the proposal containing |
|
4444 //the transforms to be able to access the # of transforms. |
|
4445 //Returns if any transform accepted (KErrNone) or not (KErrNotFound) or processing error (KErrGeneral) |
|
4446 TInt CIkev1Negotiation::ProcessTransformsL(const TPayloadISAKMP *aPayload,TUint32 aLengthLeft) |
|
4447 { |
|
4448 DEBUG_LOG(_L("-> CIkev1Negotiation::ProcessTransformsL()")); |
|
4449 TUint16 reason; |
|
4450 TInt ret = KErrGeneral; |
|
4451 const TTransformISAKMP *transf; |
|
4452 const TProposalISAKMP *proposal=TProposalISAKMP::Ptr(aPayload); |
|
4453 //First transform. Not Next() because would be the next proposal or non-sa payload |
|
4454 const TPayloadISAKMP *tpayload=proposal->Payload(); |
|
4455 |
|
4456 TInt payType = tpayload->GetPayload(); //Type of the payload following the first transform |
|
4457 transf = TTransformISAKMP::Ptr(tpayload); |
|
4458 |
|
4459 TInt numTransf = (TInt)transf->GetNum(); // First transform number |
|
4460 TInt lastTransf = numTransf + (TInt)proposal->GetNumTrans(); // Last transform number |
|
4461 |
|
4462 while ( numTransf < lastTransf ) |
|
4463 { |
|
4464 //only permited payload codes |
|
4465 if ((payType != ISAKMP_PAYLOAD_NONE) && (payType != ISAKMP_PAYLOAD_T)) |
|
4466 { |
|
4467 DEBUG_LOG(_L("INVALID_PAYLOAD_TYPE (Bad next payload for the transform)")); |
|
4468 SendNotifyL(INVALID_PAYLOAD_TYPE); |
|
4469 return KErrGeneral; |
|
4470 } |
|
4471 |
|
4472 if (tpayload->GetReserved() != 0) //Must be always 0 |
|
4473 { |
|
4474 DEBUG_LOG(_L("INVALID RESERVED FIELD")); |
|
4475 SendNotifyL(PAYLOAD_MALFORMED); |
|
4476 return KErrGeneral; |
|
4477 } |
|
4478 |
|
4479 //requires special length check |
|
4480 if ((tpayload->GetLength() < MIN_ISAKMP_PAYLOAD_SIZE) || (tpayload->GetLength() > aLengthLeft)) |
|
4481 { |
|
4482 DEBUG_LOG(_L("BAD PAYLOAD SIZE")); |
|
4483 SendNotifyL(PAYLOAD_MALFORMED); |
|
4484 return KErrGeneral; |
|
4485 } |
|
4486 |
|
4487 if (!CheckTransformID(PROTO_ISAKMP,transf->GetID())) |
|
4488 { |
|
4489 DEBUG_LOG(_L(" Continue")); |
|
4490 |
|
4491 numTransf++; // Next supposed transform # |
|
4492 payType = tpayload->GetPayload(); |
|
4493 tpayload = tpayload->Next(); //next payload (transform) |
|
4494 transf = TTransformISAKMP::Ptr(tpayload); |
|
4495 |
|
4496 continue; //If fails, transform discarded!, not error |
|
4497 } |
|
4498 |
|
4499 if ( transf->GetNum() != numTransf ) //Not the correct # |
|
4500 { |
|
4501 DEBUG_LOG1(_L("BAD_PROPOSAL_SYNTAX (Non conscutive transform number (%d)"),transf->GetNum()); |
|
4502 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4503 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransformsL() KErrGeneral")); |
|
4504 return KErrGeneral; |
|
4505 } |
|
4506 |
|
4507 if (transf->GetReserved() != 0 ) //Should be always 0 |
|
4508 { |
|
4509 DEBUG_LOG(_L("INVALID RESERVED FIELD")); |
|
4510 SendNotifyL(PAYLOAD_MALFORMED); |
|
4511 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransformsL() KErrGeneral")); |
|
4512 return KErrGeneral; |
|
4513 } |
|
4514 |
|
4515 numTransf++; // Next supposed transform # |
|
4516 //Attributes to be checked depending on Transf ID |
|
4517 TAttrib attrib; |
|
4518 |
|
4519 ret = ProcessAttributesL(tpayload, &attrib); |
|
4520 |
|
4521 if (ret != KErrNone) |
|
4522 { |
|
4523 if (ret != KErrNotFound) |
|
4524 { |
|
4525 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransformsL() KErrGeneral")); |
|
4526 return KErrGeneral; //Error in the attributes. Already reported |
|
4527 } |
|
4528 //Not accepted but correct |
|
4529 } |
|
4530 else // Accepted attributes if (AttrChosen(attrib)) |
|
4531 { |
|
4532 //Checks the response or proposal is the same as one of our proposals |
|
4533 TAttrib *attr_list = iProposal_I.iAttrList; |
|
4534 TInt ret = KErrNotFound; |
|
4535 #ifdef _DEBUG |
|
4536 TBuf<256> buf; |
|
4537 #endif |
|
4538 while (attr_list && (ret != KErrNone) ) |
|
4539 { |
|
4540 ret = attrib.Compare(*attr_list, iRole==RESPONDER); //If RESPONDER relaxed comparison (no lifetimes checked) |
|
4541 if (ret != KErrNone) |
|
4542 { |
|
4543 #ifdef _DEBUG |
|
4544 DEBUG_LOG1(_L("Transform #%d not matching proposal Reason: "), attrib.iTransformNum); |
|
4545 AppendAttributeError(ret, buf); |
|
4546 DEBUG_LOG(buf); |
|
4547 #endif |
|
4548 } |
|
4549 attr_list = attr_list->iNext; //next transform proposed |
|
4550 |
|
4551 } |
|
4552 if (ret == KErrNone) |
|
4553 { |
|
4554 *iChosenProposal_I.iAttrList = attrib; |
|
4555 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransformsL() KErrNone")); |
|
4556 return KErrNone; //If the attibute are supported there's no need to check more SA |
|
4557 } |
|
4558 else //No proposal matches |
|
4559 { |
|
4560 if ( numTransf == lastTransf ) //Is there more transforms to check |
|
4561 { |
|
4562 if (iRole == INITIATOR) |
|
4563 { |
|
4564 reason = BAD_PROPOSAL_SYNTAX; |
|
4565 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Phase I reply don't match proposal)")); |
|
4566 SetErrorStatus( KKmdIkeNegotFailed ); |
|
4567 } |
|
4568 else |
|
4569 { |
|
4570 reason = NO_PROPOSAL_CHOSEN; |
|
4571 DEBUG_LOG(_L("NO_PROPOSAL_CHOSEN (Received Proposal doesn't match accepted attributes (Check own proposals))")); |
|
4572 } |
|
4573 SendNotifyL(reason); |
|
4574 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransformsL() KErrNotFound")); |
|
4575 return KErrNotFound; |
|
4576 } |
|
4577 } |
|
4578 } |
|
4579 |
|
4580 payType = tpayload->GetPayload(); |
|
4581 tpayload = tpayload->Next(); //next payload (transform) |
|
4582 transf = TTransformISAKMP::Ptr(tpayload); |
|
4583 |
|
4584 } |
|
4585 |
|
4586 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransformsL() KErrNotFound")); |
|
4587 |
|
4588 //if reaches this point meanse no transform accepted in this proposal |
|
4589 //Notifies to the upper level |
|
4590 return KErrNotFound; |
|
4591 |
|
4592 } |
|
4593 |
|
4594 |
|
4595 //Logs the error when comparing a proposal |
|
4596 //void CIkev1Negotiation::LogAttributeError(TInt aTransformNum, TInt aErr) |
|
4597 void CIkev1Negotiation::AppendAttributeError(TInt aErr, TDes &aBuf) const |
|
4598 { |
|
4599 #ifndef _DEBUG |
|
4600 (void)aErr; |
|
4601 (void)aBuf; |
|
4602 #endif |
|
4603 |
|
4604 #ifdef _DEBUG |
|
4605 switch (aErr) |
|
4606 { |
|
4607 case KErrNotFound: |
|
4608 aBuf.Append(_L("No proposals\n")); |
|
4609 break; |
|
4610 case KErrTransformID: |
|
4611 aBuf.Append(_L("Different Transform Algorithm\n")); |
|
4612 break; |
|
4613 case KErrEncrAlg: |
|
4614 aBuf.Append(_L("Different Encryption Algorithm\n")); |
|
4615 break; |
|
4616 case KErrHashAlg: |
|
4617 aBuf.Append(_L("Different Hash Algorithm\n")); |
|
4618 break; |
|
4619 case KErrAuthMethod: |
|
4620 aBuf.Append(_L("Different Authentication Method\n")); |
|
4621 break; |
|
4622 case KErrGroupDesc: |
|
4623 aBuf.Append(_L("Different Group Description\n")); |
|
4624 break; |
|
4625 case KErrGroupType: |
|
4626 aBuf.Append(_L("Different Group Type\n")); |
|
4627 break; |
|
4628 case KErrGroupPrime: |
|
4629 aBuf.Append(_L("Different Group Prime\n")); |
|
4630 break; |
|
4631 case KErrGroupGen1: |
|
4632 aBuf.Append(_L("Different Group Generator 1\n")); |
|
4633 break; |
|
4634 case KErrGroupGen2: |
|
4635 aBuf.Append(_L("Different Group Generator 2\n")); |
|
4636 break; |
|
4637 case KErrGroupCurveA: |
|
4638 aBuf.Append(_L("Different Group Curve A\n")); |
|
4639 break; |
|
4640 case KErrGroupCurveB: |
|
4641 aBuf.Append(_L("Different Group Curve A\n")); |
|
4642 break; |
|
4643 case KErrPRF: |
|
4644 aBuf.Append(_L("Different PRF\n")); |
|
4645 break; |
|
4646 case KErrKeyLength: |
|
4647 aBuf.Append(_L("Different Key Length\n")); |
|
4648 break; |
|
4649 case KErrFieldSize: |
|
4650 aBuf.Append(_L("Different Field Size\n")); |
|
4651 break; |
|
4652 case KErrGroupOrder: |
|
4653 aBuf.Append(_L("Different Group Order\n")); |
|
4654 break; |
|
4655 case KErrLifeTime: |
|
4656 aBuf.Append(_L("Different Lifetime\n")); |
|
4657 break; |
|
4658 case KErrLifeSize: |
|
4659 aBuf.Append(_L("Different LifeSize\n")); |
|
4660 break; |
|
4661 case KErrEncMode: |
|
4662 aBuf.Append(_L("Different Encapsulation Mode\n")); |
|
4663 break; |
|
4664 case KErrAuthAlg: |
|
4665 aBuf.Append(_L("Different Authentication Algorithm\n")); |
|
4666 break; |
|
4667 case KErrKeyRounds: |
|
4668 aBuf.Append(_L("Different Key Rounds\n")); |
|
4669 break; |
|
4670 case KErrComprDicSize: |
|
4671 aBuf.Append(_L("Different Compress Dictionary Size\n")); |
|
4672 break; |
|
4673 case KErrComprPrivAlg: |
|
4674 aBuf.Append(_L("Different Compress Private Algorithm\n")); |
|
4675 break; |
|
4676 case KErrTransformNum: |
|
4677 aBuf.Append(_L("Different Transform Num.\n")); |
|
4678 break; |
|
4679 case KErrPropProtocol: |
|
4680 aBuf.Append(_L("Proposals have different protocol.\n")); |
|
4681 break; |
|
4682 case KErrNoTransforms: |
|
4683 aBuf.Append(_L("Proposal has no transforms \n")); |
|
4684 break; |
|
4685 case KErrNoRemoteProposals: |
|
4686 aBuf.Append(_L("Remote Proposals list is empty\n")); |
|
4687 break; |
|
4688 case KErrNoLocalProposals: |
|
4689 aBuf.Append(_L("Local Proposals list is empty\n")); |
|
4690 break; |
|
4691 case KErrPropNumberMismatch: |
|
4692 aBuf.Append(_L("The proposals lists have diferent number of AND'd proposals")); |
|
4693 break; |
|
4694 default: |
|
4695 aBuf.Append(_L("Unknown\n")); |
|
4696 } |
|
4697 #endif |
|
4698 } |
|
4699 |
|
4700 //processes all the PHASE II transforms. The parameter payload is the proposal containing |
|
4701 //the transforms to be able to access the # of transforms. |
|
4702 //Returns if any transform accepted (KErrNone) or not (KErrNotFound) or processing error (KErrGeneral) |
|
4703 TInt CIkev1Negotiation::ProcessTransforms2L(const TPayloadISAKMP *aPayload,CProposal_II *aProp,TUint32 aLengthLeft) |
|
4704 { |
|
4705 DEBUG_LOG(_L("-> CIkev1Negotiation::ProcessTransforms2L()")); |
|
4706 |
|
4707 TInt ret; |
|
4708 const TTransformISAKMP *transf; |
|
4709 const TProposalISAKMP *proposal=TProposalISAKMP::Ptr(aPayload); |
|
4710 //First transform. Not Next() because would be the next proposal or non-sa payload |
|
4711 const TPayloadISAKMP *tpayload = proposal->Payload(); |
|
4712 |
|
4713 TAttrib_II *attr_II = NULL; |
|
4714 TInt payType = tpayload->GetPayload(); //Type of the payload following the first transform |
|
4715 transf = TTransformISAKMP::Ptr(tpayload); |
|
4716 |
|
4717 TInt numTransf = (TInt)transf->GetNum(); // First transform number |
|
4718 TInt lastTransf = numTransf + (TInt)proposal->GetNumTrans(); // Last transform number |
|
4719 |
|
4720 while ( numTransf < lastTransf ) |
|
4721 { |
|
4722 //only permited payload codes |
|
4723 if ((payType != ISAKMP_PAYLOAD_NONE) && (payType != ISAKMP_PAYLOAD_T)) |
|
4724 { |
|
4725 DEBUG_LOG(_L("INVALID_PAYLOAD_TYPE (Bad next payload for the transform)")); |
|
4726 SendNotifyL(INVALID_PAYLOAD_TYPE); |
|
4727 return KErrGeneral; |
|
4728 } |
|
4729 |
|
4730 if (tpayload->GetReserved() != 0) //Must be always 0 |
|
4731 { |
|
4732 DEBUG_LOG(_L("INVALID RESERVED FIELD")); |
|
4733 SendNotifyL(PAYLOAD_MALFORMED); |
|
4734 return KErrGeneral; |
|
4735 } |
|
4736 |
|
4737 //requires special length check |
|
4738 if ((tpayload->GetLength() < MIN_ISAKMP_PAYLOAD_SIZE) || (tpayload->GetLength() > aLengthLeft)) |
|
4739 { |
|
4740 DEBUG_LOG(_L("BAD PAYLOAD SIZE")); |
|
4741 SendNotifyL(PAYLOAD_MALFORMED); |
|
4742 return KErrGeneral; |
|
4743 } |
|
4744 |
|
4745 if (!CheckTransformID(aProp->iProtocol,transf->GetID())) |
|
4746 { |
|
4747 DEBUG_LOG(_L(" Transform doesn't match, moving on to the next one")); |
|
4748 payType = tpayload->GetPayload(); |
|
4749 tpayload = tpayload->Next(); //next payload (transform) |
|
4750 transf = TTransformISAKMP::Ptr(tpayload); |
|
4751 numTransf++; // Next supposed transform # |
|
4752 continue; //If fails, transform discarded!, not error |
|
4753 } |
|
4754 |
|
4755 if ( transf->GetNum() != numTransf ) //Not the correct #. Must be consecutive |
|
4756 { |
|
4757 DEBUG_LOG1(_L("BAD_PROPOSAL_SYNTAX (Non conscutive transform number (%d)"),transf->GetNum()); |
|
4758 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4759 return KErrGeneral; |
|
4760 } |
|
4761 |
|
4762 if (transf->GetReserved() != 0 ) //Must be always 0 |
|
4763 { |
|
4764 DEBUG_LOG(_L("INVALID RESERVED FIELD")); |
|
4765 SendNotifyL(PAYLOAD_MALFORMED); |
|
4766 return KErrGeneral; |
|
4767 } |
|
4768 |
|
4769 //Attributes to be checked depending on Transf ID |
|
4770 attr_II = new (ELeave) TAttrib_II(); |
|
4771 CleanupStack::PushL(attr_II); |
|
4772 ret = ProcessAttributes2L(tpayload, attr_II, aProp->iProtocol); |
|
4773 if (ret != KErrNone) //Some invalid attribute |
|
4774 { |
|
4775 DEBUG_LOG(_L(" Invalid attribute")); |
|
4776 CleanupStack::PopAndDestroy(); //delete attr_II; |
|
4777 if (ret != KErrNotFound) |
|
4778 return KErrGeneral; //Error in the attributes. Already reported |
|
4779 else //Invalid transform- Ignored |
|
4780 { |
|
4781 DEBUG_LOG2(_L("Transform %d of proposal %d ignored"), transf->GetNum(), aProp->iProposalNum); |
|
4782 } |
|
4783 } |
|
4784 else //Accepted, must check if really proposed or if matches the configuration if RESPONDER |
|
4785 { |
|
4786 DEBUG_LOG(_L(" Adding new attribute")); |
|
4787 aProp->iAttrList->AppendL(attr_II); //Add the new attribute |
|
4788 CleanupStack::Pop(); //attr_II saf |
|
4789 } |
|
4790 payType = tpayload->GetPayload(); |
|
4791 tpayload = tpayload->Next(); //next payload (transform) |
|
4792 transf = TTransformISAKMP::Ptr(tpayload); |
|
4793 numTransf++; // Next supposed transform # |
|
4794 |
|
4795 } |
|
4796 |
|
4797 //No valid transform found |
|
4798 if (aProp->iAttrList->Count() == 0) |
|
4799 { |
|
4800 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransforms2L() KErrNotFound")); |
|
4801 return KErrNotFound; |
|
4802 } |
|
4803 |
|
4804 DEBUG_LOG(_L("<- CIkev1Negotiation::ProcessTransforms2L() KErrNone")); |
|
4805 return KErrNone; |
|
4806 } |
|
4807 |
|
4808 |
|
4809 //Copies and checks the values of the attributes. The parameter aPayload must be a transform |
|
4810 //aAttrib will contain the sent attributes if the return value is KErrNone, otherwise should be |
|
4811 //ignore because there was an error reading them (KErrGeneral) or the transform was not accepted (KErrNotFound) |
|
4812 TInt CIkev1Negotiation::ProcessAttributesL(const TPayloadISAKMP *aPayload, TAttrib *aAttrib) |
|
4813 { |
|
4814 const TTransformISAKMP *transf = TTransformISAKMP::Ptr(aPayload); |
|
4815 TInt length= aPayload->GetLength() - sizeof(*transf); //To process the attribs |
|
4816 TDataISAKMP *attr= transf->SAAttrib(); |
|
4817 |
|
4818 aAttrib->iTransformNum = transf->GetNum(); |
|
4819 aAttrib->iTransformID = transf->GetID(); |
|
4820 // |
|
4821 // Store parameters for extended authentication |
|
4822 // |
|
4823 aAttrib->iXauthUsed = iHostData->iUseXauth; |
|
4824 aAttrib->iRole = iRole; |
|
4825 |
|
4826 TUint16 lifeType = 0; //No type assigned yet |
|
4827 TUint32 lifeValue = 0; //No value assigned yet |
|
4828 TUint16 val; |
|
4829 |
|
4830 while ( length>0 ) |
|
4831 { |
|
4832 length = length - attr->Size(); |
|
4833 if (length<0) //Mismatch between lengths!!! |
|
4834 { |
|
4835 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Length mismatch in the attibutes)")); |
|
4836 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4837 return KErrGeneral; |
|
4838 } |
|
4839 switch (attr->Type()) |
|
4840 { |
|
4841 case OAKLEY_ATTR_TYPE_ENCR_ALG: |
|
4842 if (!CheckEncrAlg(attr->Value())) |
|
4843 return KErrNotFound; |
|
4844 aAttrib->iEncrAlg=attr->Value(); |
|
4845 break; |
|
4846 case OAKLEY_ATTR_TYPE_HASH_ALG: |
|
4847 if (!CheckHashAlg(attr->Value())) |
|
4848 return KErrNotFound; |
|
4849 aAttrib->iHashAlg = attr->Value(); |
|
4850 break; |
|
4851 case OAKLEY_ATTR_TYPE_AUTH_METH: |
|
4852 val = CTransNegotiation::GetAuthMethod(attr->Value(), iHostData->iUseXauth, iRole); |
|
4853 if (!CheckAuthMethod(val)) |
|
4854 return KErrNotFound; |
|
4855 aAttrib->iAuthMethod = val; |
|
4856 break; |
|
4857 case OAKLEY_ATTR_TYPE_GROUP_DESC: |
|
4858 if (!CheckGroupDesc(attr->Value())) |
|
4859 return KErrNotFound; |
|
4860 aAttrib->iGroupDesc = attr->Value(); |
|
4861 break; |
|
4862 case OAKLEY_ATTR_TYPE_GROUP_TYPE: |
|
4863 if (!CheckGroupType(attr->Value())) |
|
4864 return KErrNotFound; |
|
4865 aAttrib->iGroupType = attr->Value(); |
|
4866 break; |
|
4867 case OAKLEY_ATTR_TYPE_GROUP_PRIME: |
|
4868 if (attr->IsBasic()) |
|
4869 { |
|
4870 val = attr->Value(); |
|
4871 aAttrib->iGroupPrime.Copy((TUint8*)&val, sizeof(val)); |
|
4872 } |
|
4873 else |
|
4874 aAttrib->iGroupPrime.Copy(attr->VarValue(),attr->Length()); |
|
4875 break; |
|
4876 case OAKLEY_ATTR_TYPE_GROUP_GEN1: |
|
4877 if (attr->IsBasic()) |
|
4878 { |
|
4879 val = attr->Value(); |
|
4880 aAttrib->iGroupGen1.Copy((TUint8*)&val, sizeof(val)); |
|
4881 } |
|
4882 else |
|
4883 aAttrib->iGroupGen1.Copy(attr->VarValue(),attr->Length()); |
|
4884 break; |
|
4885 case OAKLEY_ATTR_TYPE_GROUP_GEN2: |
|
4886 if (attr->IsBasic()) |
|
4887 { |
|
4888 val = attr->Value(); |
|
4889 aAttrib->iGroupGen2.Copy((TUint8*)&val, sizeof(val)); |
|
4890 } |
|
4891 else |
|
4892 aAttrib->iGroupGen2.Copy(attr->VarValue(),attr->Length()); |
|
4893 break; |
|
4894 case OAKLEY_ATTR_TYPE_GROUP_CRVA: |
|
4895 if (attr->IsBasic()) |
|
4896 { |
|
4897 val = attr->Value(); |
|
4898 aAttrib->iGroupCurveA.Copy((TUint8*)&val, sizeof(val)); |
|
4899 } |
|
4900 else |
|
4901 aAttrib->iGroupCurveA.Copy(attr->VarValue(),attr->Length()); |
|
4902 break; |
|
4903 case OAKLEY_ATTR_TYPE_GROUP_CRVB: |
|
4904 if (attr->IsBasic()) |
|
4905 { |
|
4906 val = attr->Value(); |
|
4907 aAttrib->iGroupCurveB.Copy((TUint8*)&val, sizeof(val)); |
|
4908 } |
|
4909 else |
|
4910 aAttrib->iGroupCurveB.Copy(attr->VarValue(),attr->Length()); |
|
4911 break; |
|
4912 case OAKLEY_ATTR_TYPE_LIFE_TYPE: |
|
4913 lifeType = attr->Value(); |
|
4914 if (!CheckLifeType(lifeType)) |
|
4915 { |
|
4916 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Invalid lifetime type)")); |
|
4917 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4918 return KErrGeneral; |
|
4919 } |
|
4920 break; |
|
4921 case OAKLEY_ATTR_TYPE_LIFE_DUR: |
|
4922 if (attr->IsBasic()) |
|
4923 { |
|
4924 lifeValue = ByteOrder::Swap32(attr->Value()); |
|
4925 if (lifeType == SECONDS) |
|
4926 aAttrib->iLifeDurationSecs.Copy((TUint8 *)&lifeValue, sizeof(lifeValue)); |
|
4927 else if (lifeType == KBYTES) |
|
4928 aAttrib->iLifeDurationKBytes.Copy((TUint8 *)&lifeValue, sizeof(lifeValue)); |
|
4929 else |
|
4930 { |
|
4931 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Invalid lifetime type)")); |
|
4932 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4933 return KErrGeneral; |
|
4934 } |
|
4935 } |
|
4936 else //Not basic |
|
4937 { |
|
4938 if (lifeType == SECONDS) |
|
4939 aAttrib->iLifeDurationSecs.Copy(attr->VarValue(),attr->Length()); |
|
4940 else if (lifeType == KBYTES) |
|
4941 aAttrib->iLifeDurationKBytes.Copy(attr->VarValue(),attr->Length()); |
|
4942 else |
|
4943 { |
|
4944 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Invalid lifetime type)")); |
|
4945 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
4946 return KErrGeneral; |
|
4947 } |
|
4948 } |
|
4949 break; |
|
4950 case OAKLEY_ATTR_TYPE_PRF: |
|
4951 if (!CheckPRF(attr->Value())) |
|
4952 return KErrNotFound; |
|
4953 aAttrib->iPRF=attr->Value(); |
|
4954 break; |
|
4955 case OAKLEY_ATTR_TYPE_KEY_LEN: |
|
4956 aAttrib->iKeyLength = attr->Value(); |
|
4957 break; |
|
4958 case OAKLEY_ATTR_TYPE_FIELD_SIZE: |
|
4959 if (!CheckFieldSize(attr->Value())) |
|
4960 return KErrNotFound; |
|
4961 aAttrib->iFieldSize=attr->Value(); |
|
4962 break; |
|
4963 case OAKLEY_ATTR_TYPE_GROUP_ORDER: |
|
4964 if (attr->IsBasic()) |
|
4965 { |
|
4966 val = attr->Value(); |
|
4967 aAttrib->iGroupOrder.Copy((TUint8*)&val, sizeof(val)); |
|
4968 } |
|
4969 else |
|
4970 aAttrib->iGroupOrder.Copy(attr->VarValue(),attr->Length()); |
|
4971 break; |
|
4972 default: |
|
4973 DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED (Invalid attribute number)")); |
|
4974 SendNotifyL(ATTRIBUTES_NOT_SUPPORTED); |
|
4975 return KErrGeneral; |
|
4976 } |
|
4977 attr = attr->Next(); |
|
4978 } |
|
4979 |
|
4980 //Done here to ensure both received |
|
4981 if (aAttrib->iKeyLength !=0) |
|
4982 if (!CheckKeyLength(aAttrib->iKeyLength, (TUint8)aAttrib->iEncrAlg ,PROTO_ISAKMP)) |
|
4983 return KErrNotFound; |
|
4984 |
|
4985 return KErrNone; |
|
4986 } |
|
4987 |
|
4988 //Copies and checks the values of the attributes. The parameter aPayload must be a transform |
|
4989 //aAttrib will contain the sent attributes if the return value is KErrNone, otherwise should be |
|
4990 //ignore because there was an error reading them (KErrGeneral) or the transform was not accepted (KErrNotFound) |
|
4991 TInt CIkev1Negotiation::ProcessAttributes2L(const TPayloadISAKMP *aPayload, TAttrib_II *aAttrib,TUint8 aProtocol) |
|
4992 { |
|
4993 const TTransformISAKMP *transf = TTransformISAKMP::Ptr(aPayload); |
|
4994 TInt length= aPayload->GetLength() - sizeof(*transf); //To process the attribs |
|
4995 |
|
4996 aAttrib->iTransformNum = transf->GetNum(); |
|
4997 aAttrib->iTransformID = transf->GetID(); |
|
4998 TDataISAKMP *attr= transf->SAAttrib(); |
|
4999 TUint16 lifeType = 0; //No type assigned yet |
|
5000 TUint32 lifeValue = 0; |
|
5001 while (length>0) |
|
5002 { |
|
5003 length = length - attr->Size(); |
|
5004 if (length<0) //Mismatch between lengths!!! |
|
5005 { |
|
5006 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Length mismatch in the attibutes)")); |
|
5007 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
5008 return KErrGeneral; |
|
5009 } |
|
5010 switch (attr->Type()) |
|
5011 { |
|
5012 case DOI_ATTR_TYPE_LIFE_TYPE: |
|
5013 lifeType=attr->Value(); |
|
5014 if (!CheckLifeType(lifeType)) |
|
5015 { |
|
5016 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Invalid lifetime type)")); |
|
5017 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
5018 return KErrGeneral; |
|
5019 } |
|
5020 break; |
|
5021 case DOI_ATTR_TYPE_LIFE_DUR: |
|
5022 if (attr->IsBasic()) |
|
5023 { |
|
5024 lifeValue = ByteOrder::Swap32(attr->Value()); |
|
5025 if (lifeType==SECONDS) |
|
5026 aAttrib->iLifeDurationSecs.Copy((TUint8 *)&lifeValue, sizeof(lifeValue)); |
|
5027 else if (lifeType==KBYTES) |
|
5028 aAttrib->iLifeDurationKBytes.Copy((TUint8 *)&lifeValue, sizeof(lifeValue)); |
|
5029 else |
|
5030 { |
|
5031 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (No lifetime type received)")); |
|
5032 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
5033 return KErrGeneral; |
|
5034 } |
|
5035 } |
|
5036 else |
|
5037 { |
|
5038 if (lifeType==SECONDS) |
|
5039 aAttrib->iLifeDurationSecs.Copy(attr->VarValue(),attr->Length()); |
|
5040 else if (lifeType==KBYTES) |
|
5041 aAttrib->iLifeDurationKBytes.Copy(attr->VarValue(),attr->Length()); |
|
5042 else |
|
5043 { |
|
5044 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (No lifetime type received)")); |
|
5045 SendNotifyL(BAD_PROPOSAL_SYNTAX); |
|
5046 return KErrGeneral; |
|
5047 } |
|
5048 } |
|
5049 lifeType = 0; //Cannot received another lifetime without setting the type again |
|
5050 break; |
|
5051 case DOI_ATTR_TYPE_GROUP_DESC: |
|
5052 if (!CheckGroupDesc(attr->Value())) |
|
5053 return KErrNotFound; |
|
5054 aAttrib->iGroupDesc=attr->Value(); |
|
5055 break; |
|
5056 case DOI_ATTR_TYPE_ENC_MODE: //Encapsulation Mode |
|
5057 if (!CheckEncMode(attr->Value())) |
|
5058 return KErrNotFound; |
|
5059 aAttrib->iEncMode=attr->Value(); |
|
5060 if ( aAttrib->iEncMode == UDP_ENC_TUNNEL || aAttrib->iEncMode == UDP_RFC_ENC_TUNNEL ) |
|
5061 aAttrib->iEncMode = DOI_TUNNEL; |
|
5062 if ( aAttrib->iEncMode == UDP_ENC_TRANSPORT || aAttrib->iEncMode == UDP_RFC_ENC_TRANSPORT) |
|
5063 aAttrib->iEncMode = DOI_TRANSPORT; |
|
5064 break; |
|
5065 case DOI_ATTR_TYPE_AUTH_ALG: |
|
5066 if (!CheckAuthAlg(attr->Value())) |
|
5067 return KErrNotFound; |
|
5068 aAttrib->iAuthAlg=attr->Value(); |
|
5069 break; |
|
5070 case DOI_ATTR_TYPE_KEY_LEN: |
|
5071 aAttrib->iKeyLength = attr->Value(); |
|
5072 break; |
|
5073 case DOI_ATTR_TYPE_KEY_ROUNDS: |
|
5074 aAttrib->iKeyRounds=attr->Value(); |
|
5075 break; |
|
5076 /* |
|
5077 case DOI_ATTR_TYPE_COMP_DIC_SIZE: //Compress Dictionary size |
|
5078 aAttrib->iComprDicSize=attr->Value(); |
|
5079 break; |
|
5080 case DOI_ATTR_TYPE_COMP_PRIV_ALG: //Compress Dictionary size |
|
5081 aAttrib->iComprPrivAlg=attr->Value(); |
|
5082 break; |
|
5083 */ |
|
5084 default: |
|
5085 DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED (Invalid attribute number)")); |
|
5086 SendNotifyL(ATTRIBUTES_NOT_SUPPORTED); |
|
5087 return KErrGeneral; |
|
5088 } |
|
5089 attr = attr->Next(); |
|
5090 } |
|
5091 |
|
5092 if (lifeType != 0) //Type set but not sent |
|
5093 { |
|
5094 DEBUG_LOG(_L("Lifetime type set but value not sent!")); |
|
5095 return KErrNotFound; |
|
5096 } |
|
5097 |
|
5098 if (aAttrib->iKeyLength !=0) |
|
5099 if (!CheckKeyLength(aAttrib->iKeyLength,transf->GetID(),aProtocol)) //Check key length correct |
|
5100 return KErrNotFound; |
|
5101 |
|
5102 return KErrNone; |
|
5103 } |
|
5104 |
|
5105 |
|
5106 //returns KErrNone if OK, otherwise error already treated. |
|
5107 TBool CIkev1Negotiation::ProcessKeyL(const TKeyISAKMP *aKey) |
|
5108 { |
|
5109 //const TKeyISAKMP *key = TKeyISAKMP::Ptr(aPayload); |
|
5110 |
|
5111 //payload not present |
|
5112 if (iPhase==PHASE_I) |
|
5113 { |
|
5114 if (!aKey) |
|
5115 { |
|
5116 DEBUG_LOG(_L("NO KEY Payload")); |
|
5117 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5118 SendNotifyL(PAYLOAD_MALFORMED); |
|
5119 return EFalse; |
|
5120 } |
|
5121 //Doesn't return yet because it needs to copy the received key |
|
5122 } |
|
5123 else //PHASE_II |
|
5124 { |
|
5125 if (!aKey) |
|
5126 { |
|
5127 if (iPFS) |
|
5128 { |
|
5129 DEBUG_LOG(_L("KEY Payload Expected (PFS is enabled)")); |
|
5130 return EFalse; |
|
5131 } |
|
5132 |
|
5133 return ETrue; |
|
5134 |
|
5135 } |
|
5136 else // Key present |
|
5137 { |
|
5138 if (!iPFS) |
|
5139 { |
|
5140 DEBUG_LOG(_L("KEY Payload NOT Expected (PFS is disabled)")); |
|
5141 return EFalse; |
|
5142 } |
|
5143 //Doesn't return yet because it needs to copy the received key |
|
5144 } |
|
5145 } |
|
5146 |
|
5147 //stores the public key sent by the other peer. Only if key received and PFS enabled (PHASE II only) |
|
5148 iPeerPublicKey.Copy(aKey->KeyData(), aKey->GetLength() - sizeof(*aKey)); |
|
5149 return ETrue; |
|
5150 } |
|
5151 |
|
5152 |
|
5153 TBool CIkev1Negotiation::ProcessNonceL(const TPayloadISAKMP *aPayload) |
|
5154 { |
|
5155 const TNonceISAKMP *nonce = TNonceISAKMP::Ptr(aPayload); |
|
5156 |
|
5157 //payload not present |
|
5158 if (!nonce) |
|
5159 { |
|
5160 DEBUG_LOG(_L("NO NONCE PAYLOAD")); |
|
5161 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5162 SendNotifyL(PAYLOAD_MALFORMED); |
|
5163 return EFalse; |
|
5164 } |
|
5165 |
|
5166 //stores the nonce sent by the other peer |
|
5167 if (iRole==RESPONDER) |
|
5168 iNONCE_I.Copy(nonce->NonceData(),nonce->NonceDataLen()); |
|
5169 else |
|
5170 iNONCE_R.Copy(nonce->NonceData(),nonce->NonceDataLen()); |
|
5171 |
|
5172 return ETrue; |
|
5173 |
|
5174 } |
|
5175 |
|
5176 TBool CIkev1Negotiation::ProcessStage1_II_IDsL(const TIdentISAKMP *aInit_ID_payload,const TIdentISAKMP *aResp_ID_payload, CProposal_IIList *aRecv_proposals) |
|
5177 { |
|
5178 //IDci |
|
5179 //First we check the received IDs to be able to build the proposals for phase_II |
|
5180 TInt32 addr; //Contains a numeric IPv4 addr to be sent |
|
5181 TBuf<40> addr_buf; //Contains a text IPv4/IPv6 addr to be sent |
|
5182 |
|
5183 TIp6Addr ip6addr; //IPV6 raw address |
|
5184 |
|
5185 //We receive the peer proxy address or gateway client |
|
5186 TAttrib_II *attr_II = aRecv_proposals->At(0)->iAttrList->At(0); |
|
5187 if (aInit_ID_payload) //ID Payload received |
|
5188 { |
|
5189 iIDReceived = ETrue; |
|
5190 if (!CheckIdentL(aInit_ID_payload)) |
|
5191 return EFalse; |
|
5192 |
|
5193 iIDRemotePort = aInit_ID_payload->GetPort(); |
|
5194 iIDProtocol = aInit_ID_payload->GetProtocol(); |
|
5195 iRemoteIDType_II = aInit_ID_payload->GetIDType(); |
|
5196 |
|
5197 switch (aInit_ID_payload->GetIDType()) |
|
5198 { |
|
5199 case ID_IPV4_ADDR: |
|
5200 Mem::Copy((TUint8 *)&addr, aInit_ID_payload->IDData(),sizeof(TInt32)); |
|
5201 iRemoteAddr1_ID_II.SetAddress(ByteOrder::Swap32(addr)); |
|
5202 DEBUG_LOG(_L("Remote ID received")); |
|
5203 DEBUG_LOG(_L("Setting Remote ID to:")); |
|
5204 iRemoteAddr1_ID_II.OutputWithScope(addr_buf); |
|
5205 DEBUG_LOG(addr_buf); |
|
5206 if (iRemoteAddr.Match(iRemoteAddr1_ID_II)) |
|
5207 iDefaultRemoteID = ETrue; //Must be sent but won't be used when updating the SAD |
|
5208 else if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5209 { |
|
5210 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Received ID MUST match the Remote addr in Transport mode)")); |
|
5211 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5212 return EFalse; |
|
5213 } |
|
5214 break; |
|
5215 case ID_IPV4_ADDR_SUBNET: |
|
5216 Mem::Copy((TUint8 *)&addr, aInit_ID_payload->IDData(),sizeof(TInt32)); //Address |
|
5217 iRemoteAddr1_ID_II.SetAddress(ByteOrder::Swap32(addr)); |
|
5218 Mem::Copy((TUint8 *)&addr, aInit_ID_payload->IDData() + sizeof(TInt32),sizeof(TInt32)); //Mask |
|
5219 iRemoteAddr2_ID_II.SetAddress(ByteOrder::Swap32(addr)); |
|
5220 iRemoteAddr1_ID_II.OutputWithScope(addr_buf); |
|
5221 DEBUG_LOG(_L("Setting Remote ID to: addr = ")); |
|
5222 DEBUG_LOG(addr_buf); |
|
5223 iRemoteAddr2_ID_II.OutputWithScope(addr_buf); |
|
5224 DEBUG_LOG(_L(" mask = ")); |
|
5225 DEBUG_LOG(addr_buf); |
|
5226 if (PrefixLen(iRemoteAddr2_ID_II) < KErrNone) //Invalid Mask (can't be > 32 bec. we get only 4 bytes) |
|
5227 { |
|
5228 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Invalid peer proxy mask for type ID_IPV4_ADDR_SUBNET)")); |
|
5229 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5230 SendNotifyL(INVALID_ID_INFORMATION); |
|
5231 return EFalse; |
|
5232 } |
|
5233 if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5234 { |
|
5235 if (!iRemoteAddr.Match(iRemoteAddr1_ID_II, iRemoteAddr2_ID_II)) |
|
5236 { |
|
5237 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Remote ID MUST match the net & mask received)")); |
|
5238 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5239 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5240 return EFalse; |
|
5241 } |
|
5242 } |
|
5243 break; |
|
5244 case ID_IPV6_ADDR: |
|
5245 Mem::Copy(&ip6addr.u.iAddr8, aInit_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); |
|
5246 iRemoteAddr1_ID_II.SetAddress(ip6addr); |
|
5247 DEBUG_LOG(_L("Remote ID received")); |
|
5248 DEBUG_LOG(_L("Setting Remote ID to:")); |
|
5249 iRemoteAddr1_ID_II.OutputWithScope(addr_buf); |
|
5250 DEBUG_LOG(addr_buf); |
|
5251 if (iRemoteAddr.Match(iRemoteAddr1_ID_II)) |
|
5252 iDefaultRemoteID = ETrue; //Must be sent but won't be used when updating the SAD |
|
5253 else if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5254 { |
|
5255 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Remote ID doesn't match received IDi in Transport mode)")); |
|
5256 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5257 return EFalse; |
|
5258 } |
|
5259 break; |
|
5260 case ID_IPV6_ADDR_SUBNET: |
|
5261 Mem::Copy(&ip6addr.u.iAddr8, aInit_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); //Address |
|
5262 iRemoteAddr1_ID_II.SetAddress(ip6addr); |
|
5263 Mem::Copy(&ip6addr.u.iAddr8, aInit_ID_payload->IDData() + sizeof(ip6addr.u.iAddr8), sizeof(ip6addr.u.iAddr8)); //Mask |
|
5264 iRemoteAddr2_ID_II.SetAddress(ip6addr); |
|
5265 DEBUG_LOG(_L("Remote ID (subnet) received")); |
|
5266 DEBUG_LOG(_L("Setting Remote ID to: addr = ")); |
|
5267 iRemoteAddr1_ID_II.OutputWithScope(addr_buf); |
|
5268 DEBUG_LOG(addr_buf); |
|
5269 DEBUG_LOG(_L(" mask = ")); |
|
5270 iRemoteAddr2_ID_II.OutputWithScope(addr_buf); |
|
5271 DEBUG_LOG(addr_buf); |
|
5272 if (PrefixLen(iRemoteAddr2_ID_II) < 0) //Invalid Mask |
|
5273 { |
|
5274 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Invalid peer proxy mask for type ID_IPV6_ADDR_SUBNET)")); |
|
5275 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5276 SendNotifyL(INVALID_ID_INFORMATION); |
|
5277 return EFalse; |
|
5278 } |
|
5279 if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5280 { |
|
5281 if (!iRemoteAddr.Match(iRemoteAddr1_ID_II, iRemoteAddr2_ID_II)) |
|
5282 { |
|
5283 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Remote ID MUST match the net & mask received)")); |
|
5284 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5285 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5286 return EFalse; |
|
5287 } |
|
5288 } |
|
5289 break; |
|
5290 default: //redundant. Detected in CheckIdentL() |
|
5291 DEBUG_LOG(_L("INVALID_ID_INFORMATION (ID Type not supported)")); |
|
5292 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5293 SendNotifyL(INVALID_ID_INFORMATION); |
|
5294 return EFalse; |
|
5295 }//switch |
|
5296 } |
|
5297 else //No id received (That means we're negotiating directly with the end host) (RFC 2409 5.5) |
|
5298 { |
|
5299 //For TRANSPORT we don't need to do anything |
|
5300 iIDLocalPort = 0; |
|
5301 iIDRemotePort = 0; |
|
5302 iIDProtocol = 0; |
|
5303 return ETrue; //No need to check the Responder ID if no Initiator ID received |
|
5304 } |
|
5305 |
|
5306 //IDcr |
|
5307 //Receive our proxy. We don't know it because we are responders so the other peer tells us who does it |
|
5308 //want to communicate with |
|
5309 if (aResp_ID_payload) //ID Payload received |
|
5310 { |
|
5311 if (!CheckIdentL(aResp_ID_payload)) |
|
5312 return EFalse; |
|
5313 |
|
5314 iIDLocalPort = aResp_ID_payload->GetPort(); |
|
5315 iLocalIDType_II = aResp_ID_payload->GetIDType(); |
|
5316 if (iIDProtocol != aResp_ID_payload->GetProtocol()) //Must be the same sent in the IDCi |
|
5317 { |
|
5318 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Local ID Protocol different from Remote ID Protocol. Must be the same)")); |
|
5319 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5320 SendNotifyL(INVALID_ID_INFORMATION); |
|
5321 return EFalse; |
|
5322 } |
|
5323 |
|
5324 switch (aResp_ID_payload->GetIDType()) |
|
5325 { |
|
5326 case ID_IPV4_ADDR: |
|
5327 Mem::Copy((TUint8 *)&addr, aResp_ID_payload->IDData(),sizeof(TInt32)); |
|
5328 iLocalAddr1_ID_II.SetAddress(ByteOrder::Swap32(addr)); |
|
5329 DEBUG_LOG(_L("Local ID received")); |
|
5330 DEBUG_LOG(_L("Setting Local ID to:")); |
|
5331 iLocalAddr1_ID_II.OutputWithScope(addr_buf); |
|
5332 DEBUG_LOG(addr_buf); |
|
5333 if ( iInternalAddr ) { |
|
5334 // |
|
5335 // Check ID against internal address instead of local address |
|
5336 // |
|
5337 if (iInternalAddr->iClientIntAddr.Match(iLocalAddr1_ID_II)) |
|
5338 iDefaultLocalID = ETrue; //Must be sent but won't be used when updating the SAD |
|
5339 } |
|
5340 else { |
|
5341 if (iLocalAddr.Match(iLocalAddr1_ID_II)) |
|
5342 iDefaultLocalID = ETrue; //Must be sent but won't be used when updating the SAD |
|
5343 else if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5344 { |
|
5345 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Local ID MUST match the net & mask received)")); |
|
5346 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5347 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5348 return EFalse; |
|
5349 } |
|
5350 } |
|
5351 break; |
|
5352 case ID_IPV4_ADDR_SUBNET: |
|
5353 Mem::Copy((TUint8 *)&addr, aResp_ID_payload->IDData(),sizeof(TInt32)); //Address |
|
5354 iLocalAddr1_ID_II.SetAddress(ByteOrder::Swap32(addr)); |
|
5355 Mem::Copy((TUint8 *)&addr, aResp_ID_payload->IDData() + sizeof(TInt32),sizeof(TInt32)); //Mask |
|
5356 iLocalAddr2_ID_II.SetAddress(ByteOrder::Swap32(addr)); |
|
5357 DEBUG_LOG(_L("Setting Local ID to: addr = ")); |
|
5358 iLocalAddr1_ID_II.OutputWithScope(addr_buf); |
|
5359 DEBUG_LOG(addr_buf); |
|
5360 DEBUG_LOG(_L(" mask = ")); |
|
5361 iLocalAddr2_ID_II.OutputWithScope(addr_buf); |
|
5362 DEBUG_LOG(addr_buf); |
|
5363 if (PrefixLen(iLocalAddr2_ID_II) < 0) //Invalid Mask |
|
5364 { |
|
5365 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Invalid Remote ID mask for type ID_IPV4_ADDR_SUBNET)")); |
|
5366 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5367 SendNotifyL(INVALID_ID_INFORMATION); |
|
5368 return EFalse; |
|
5369 } |
|
5370 if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5371 { |
|
5372 if (!iLocalAddr.Match(iLocalAddr1_ID_II, iLocalAddr2_ID_II)) |
|
5373 { |
|
5374 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Local ID MUST match the net & mask received)")); |
|
5375 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5376 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5377 return EFalse; |
|
5378 } |
|
5379 } |
|
5380 break; |
|
5381 case ID_IPV6_ADDR: |
|
5382 Mem::Copy(&ip6addr.u.iAddr8, aResp_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); |
|
5383 //iOwnProxyAddr.SetAddress(ip6addr); |
|
5384 iLocalAddr1_ID_II.SetAddress(ip6addr); |
|
5385 DEBUG_LOG(_L("Own Proxy received")); |
|
5386 DEBUG_LOG(_L("Setting Own Proxy address to:")); |
|
5387 iLocalAddr1_ID_II.OutputWithScope(addr_buf); |
|
5388 DEBUG_LOG(addr_buf); |
|
5389 if (iLocalAddr.Match(iLocalAddr1_ID_II)) |
|
5390 iDefaultLocalID = ETrue; //Must be sent but won't be used when updating the SAD |
|
5391 else if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5392 { |
|
5393 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Local ID MUST match the net & mask received)")); |
|
5394 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5395 return EFalse; |
|
5396 } |
|
5397 break; |
|
5398 case ID_IPV6_ADDR_SUBNET: |
|
5399 Mem::Copy(&ip6addr.u.iAddr8, aResp_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); //Address |
|
5400 iLocalAddr1_ID_II.SetAddress(ip6addr); |
|
5401 Mem::Copy(&ip6addr.u.iAddr8, aResp_ID_payload->IDData() + sizeof(ip6addr.u.iAddr8), sizeof(ip6addr.u.iAddr8)); //Mask |
|
5402 iLocalAddr2_ID_II.SetAddress(ip6addr); |
|
5403 DEBUG_LOG(_L("Setting Own Proxy to: addr = ")); |
|
5404 iLocalAddr1_ID_II.OutputWithScope(addr_buf); |
|
5405 DEBUG_LOG(addr_buf); |
|
5406 DEBUG_LOG(_L(" mask = ")); |
|
5407 iLocalAddr2_ID_II.OutputWithScope(addr_buf); |
|
5408 DEBUG_LOG(addr_buf); |
|
5409 if (PrefixLen(iLocalAddr2_ID_II) < 0) //Invalid Mask |
|
5410 { |
|
5411 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Invalid Remote ID mask for type ID_IPV6_ADDR_SUBNET)")); |
|
5412 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5413 SendNotifyL(INVALID_ID_INFORMATION); |
|
5414 return EFalse; |
|
5415 } |
|
5416 if (attr_II->iEncMode == DOI_TRANSPORT) |
|
5417 { |
|
5418 if (!iLocalAddr.Match(iLocalAddr1_ID_II, iLocalAddr2_ID_II)) |
|
5419 { |
|
5420 DEBUG_LOG(_L("ADDRESS_NOTIFICATION (Local ID MUST match the net & mask received)")); |
|
5421 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5422 SendNotifyL(ADDRESS_NOTIFICATION); |
|
5423 return EFalse; |
|
5424 } |
|
5425 } |
|
5426 break; |
|
5427 default: |
|
5428 DEBUG_LOG(_L("INVALID_ID_INFORMATION (ID Type not supported)")); |
|
5429 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5430 SendNotifyL(INVALID_ID_INFORMATION); |
|
5431 return EFalse; |
|
5432 }//switch |
|
5433 } |
|
5434 |
|
5435 return ETrue; |
|
5436 } |
|
5437 |
|
5438 |
|
5439 TBool CIkev1Negotiation::ProcessStage2_II_IDsL(const TIdentISAKMP *aInit_ID_payload,const TIdentISAKMP *aResp_ID_payload)//, CProposal_IIList *aRecv_proposals) |
|
5440 { |
|
5441 TInt32 addr4_int; //Contains a numeric IPv4 addr to be sent |
|
5442 TIp6Addr ip6addr; //IPV6 raw address |
|
5443 TInetAddr tmp_addr; |
|
5444 //Here we check the initator proxy (Our client) sent by us has been received correctly |
|
5445 if (aInit_ID_payload) //ID Payload received |
|
5446 { |
|
5447 if (!CheckIdentL(aInit_ID_payload)) |
|
5448 return EFalse; |
|
5449 |
|
5450 if (aInit_ID_payload->GetPort() != iIDLocalPort) |
|
5451 { |
|
5452 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Local ID Port different from the one sent)")); |
|
5453 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5454 SendNotifyL(INVALID_ID_INFORMATION); |
|
5455 return EFalse; |
|
5456 } |
|
5457 |
|
5458 if (aInit_ID_payload->GetProtocol() != iIDProtocol) |
|
5459 { |
|
5460 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Local ID Protocol different from the one sent)")); |
|
5461 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5462 SendNotifyL(INVALID_ID_INFORMATION); |
|
5463 return EFalse; |
|
5464 } |
|
5465 |
|
5466 switch (aInit_ID_payload->GetIDType()) |
|
5467 { |
|
5468 case ID_IPV4_ADDR: |
|
5469 Mem::Copy((TUint8 *)&addr4_int,aInit_ID_payload->IDData(),sizeof(TInt32)); |
|
5470 tmp_addr.SetAddress(ByteOrder::Swap32(addr4_int)); |
|
5471 if (!tmp_addr.Match(iLocalAddr1_ID_II)) |
|
5472 { |
|
5473 DEBUG_LOG(_L("Wrong Own ID received (Different from the one sent)")); |
|
5474 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5475 SendNotifyL(INVALID_ID_INFORMATION); |
|
5476 return EFalse; |
|
5477 } |
|
5478 break; |
|
5479 case ID_IPV4_ADDR_SUBNET: |
|
5480 //Subnet |
|
5481 Mem::Copy((TUint8 *)&addr4_int,aInit_ID_payload->IDData(),sizeof(TInt32)); |
|
5482 tmp_addr.SetAddress(ByteOrder::Swap32(addr4_int)); |
|
5483 if (!tmp_addr.Match(iLocalAddr1_ID_II)) |
|
5484 { |
|
5485 //The ID subnet is not the one we sent! |
|
5486 DEBUG_LOG(_L("Wrong Own ID subnet received (Different from the one sent)")); |
|
5487 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5488 SendNotifyL(INVALID_ID_INFORMATION); |
|
5489 return EFalse; |
|
5490 } |
|
5491 //Mask |
|
5492 Mem::Copy((TUint8 *)&addr4_int,aInit_ID_payload->IDData() + sizeof(TInt32),sizeof(TInt32)); |
|
5493 tmp_addr.SetAddress(ByteOrder::Swap32(addr4_int)); |
|
5494 if (!tmp_addr.Match(iLocalAddr2_ID_II)) |
|
5495 { |
|
5496 //The ID mask is not the one we sent! |
|
5497 DEBUG_LOG(_L("Wrong Own ID mask received (Different from the one sent)")); |
|
5498 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5499 SendNotifyL(INVALID_ID_INFORMATION); |
|
5500 return EFalse; |
|
5501 } |
|
5502 break; |
|
5503 case ID_IPV6_ADDR: |
|
5504 Mem::Copy(&ip6addr.u.iAddr8, aInit_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); |
|
5505 tmp_addr.SetAddress(ip6addr); |
|
5506 if (!tmp_addr.Match(iLocalAddr1_ID_II)) |
|
5507 { |
|
5508 //The ID is not the one we sent! |
|
5509 DEBUG_LOG(_L("Wrong Local ID received (Different from the one sent)")); |
|
5510 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5511 SendNotifyL(INVALID_ID_INFORMATION); |
|
5512 return EFalse; |
|
5513 } |
|
5514 break; |
|
5515 case ID_IPV6_ADDR_SUBNET: |
|
5516 //subnet |
|
5517 Mem::Copy(&ip6addr.u.iAddr8, aInit_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); |
|
5518 tmp_addr.SetAddress(ip6addr); |
|
5519 if (!tmp_addr.Match(iLocalAddr1_ID_II)) |
|
5520 { |
|
5521 //The ID is not the one we sent! |
|
5522 DEBUG_LOG(_L("Wrong Local ID subnet received (Different from the one sent)")); |
|
5523 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5524 SendNotifyL(INVALID_ID_INFORMATION); |
|
5525 return EFalse; |
|
5526 } |
|
5527 //mask |
|
5528 Mem::Copy(&ip6addr.u.iAddr8, aInit_ID_payload->IDData() + sizeof(ip6addr.u.iAddr8), sizeof(ip6addr.u.iAddr8)); |
|
5529 tmp_addr.SetAddress(ip6addr); |
|
5530 if (!tmp_addr.Match(iLocalAddr2_ID_II)) |
|
5531 { |
|
5532 //The ID is not the one we sent! |
|
5533 DEBUG_LOG(_L("Wrong Local ID mask received (Different from the one sent)")); |
|
5534 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5535 SendNotifyL(INVALID_ID_INFORMATION); |
|
5536 return EFalse; |
|
5537 } |
|
5538 break; |
|
5539 default: |
|
5540 DEBUG_LOG(_L("INVALID_ID_INFORMATION (ID Type not supported)")); |
|
5541 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5542 SendNotifyL(INVALID_ID_INFORMATION); |
|
5543 return EFalse; |
|
5544 }//switch |
|
5545 } |
|
5546 else //No id sent (That means we're negotiating directly with the end host |
|
5547 { |
|
5548 if (!iLocalAddr1_ID_II.IsUnspecified()) |
|
5549 { |
|
5550 DEBUG_LOG(_L("IDci expected and not received!")); |
|
5551 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5552 SendNotifyL(INVALID_ID_INFORMATION); |
|
5553 return EFalse; |
|
5554 } |
|
5555 } |
|
5556 |
|
5557 //We receive the peer (responder) proxy address or gateway client |
|
5558 if (aResp_ID_payload) //ID Payload received |
|
5559 { |
|
5560 if (!CheckIdentL(aResp_ID_payload)) |
|
5561 return EFalse; |
|
5562 |
|
5563 if (aResp_ID_payload->GetPort() != iIDRemotePort) |
|
5564 { |
|
5565 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Remote Port different from the one sent)")); |
|
5566 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5567 SendNotifyL(INVALID_ID_INFORMATION); |
|
5568 return EFalse; |
|
5569 } |
|
5570 |
|
5571 if (aResp_ID_payload->GetProtocol() != iIDProtocol) |
|
5572 { |
|
5573 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Responder ID Protocol different from the one sent)")); |
|
5574 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5575 SendNotifyL(INVALID_ID_INFORMATION); |
|
5576 return EFalse; |
|
5577 } |
|
5578 |
|
5579 switch (aResp_ID_payload->GetIDType()) |
|
5580 { |
|
5581 case ID_IPV4_ADDR: |
|
5582 Mem::Copy((TUint8 *)&addr4_int,aResp_ID_payload->IDData(),sizeof(TInt32)); |
|
5583 tmp_addr.SetAddress(ByteOrder::Swap32(addr4_int)); |
|
5584 DEBUG_LOG(_L("IDcr received")); |
|
5585 if (!iRemoteAddr1_ID_II.Match(tmp_addr)) |
|
5586 { |
|
5587 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Wrong Remote ID, doesn't match sent one)")); |
|
5588 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5589 SendNotifyL(INVALID_ID_INFORMATION); |
|
5590 return EFalse; |
|
5591 } |
|
5592 break; |
|
5593 case ID_IPV4_ADDR_SUBNET: |
|
5594 //subnet address |
|
5595 Mem::Copy((TUint8 *)&addr4_int,aResp_ID_payload->IDData(),sizeof(TInt32)); |
|
5596 tmp_addr.SetAddress(ByteOrder::Swap32(addr4_int)); |
|
5597 if (!tmp_addr.Match(iRemoteAddr1_ID_II)) |
|
5598 { |
|
5599 //The ID subnet is not the one we sent! |
|
5600 DEBUG_LOG(_L("Wrong Remote ID subnet received (Different from the one sent)")); |
|
5601 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5602 SendNotifyL(INVALID_ID_INFORMATION); |
|
5603 return EFalse; |
|
5604 } |
|
5605 //Mask address |
|
5606 Mem::Copy((TUint8 *)&addr4_int,aResp_ID_payload->IDData() + sizeof(TInt32),sizeof(TInt32)); |
|
5607 tmp_addr.SetAddress(ByteOrder::Swap32(addr4_int)); |
|
5608 if (!tmp_addr.Match(iRemoteAddr2_ID_II)) |
|
5609 { |
|
5610 //The ID mask is not the one we sent! |
|
5611 DEBUG_LOG(_L("Wrong Remote ID mask received (Different from the one sent)")); |
|
5612 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5613 SendNotifyL(INVALID_ID_INFORMATION); |
|
5614 return EFalse; |
|
5615 } |
|
5616 break; |
|
5617 case ID_IPV6_ADDR: |
|
5618 Mem::Copy(&ip6addr.u.iAddr8,aResp_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); |
|
5619 tmp_addr.SetAddress(ip6addr); |
|
5620 DEBUG_LOG(_L("IDcr received")); |
|
5621 if (!iRemoteAddr1_ID_II.Match(tmp_addr)) |
|
5622 { |
|
5623 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Wrong ID, doesn't match sent proxy)")); |
|
5624 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5625 SendNotifyL(INVALID_ID_INFORMATION); |
|
5626 return EFalse; |
|
5627 } |
|
5628 break; |
|
5629 case ID_IPV6_ADDR_SUBNET: |
|
5630 //subnet |
|
5631 Mem::Copy(&ip6addr.u.iAddr8, aResp_ID_payload->IDData(), sizeof(ip6addr.u.iAddr8)); |
|
5632 tmp_addr.SetAddress(ip6addr); |
|
5633 if (!tmp_addr.Match(iRemoteAddr1_ID_II)) |
|
5634 { |
|
5635 //The ID is not the one we sent! |
|
5636 DEBUG_LOG(_L("Wrong Remote ID subnet received (Different from the one sent)")); |
|
5637 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5638 SendNotifyL(INVALID_ID_INFORMATION); |
|
5639 return EFalse; |
|
5640 } |
|
5641 //mask |
|
5642 Mem::Copy(&ip6addr.u.iAddr8, aResp_ID_payload->IDData() + sizeof(ip6addr.u.iAddr8), sizeof(ip6addr.u.iAddr8)); |
|
5643 tmp_addr.SetAddress(ip6addr); |
|
5644 if (!tmp_addr.Match(iRemoteAddr2_ID_II)) |
|
5645 { |
|
5646 //The ID is not the one we sent! |
|
5647 DEBUG_LOG(_L("Wrong Remote ID mask received (Different from the one sent)")); |
|
5648 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5649 SendNotifyL(INVALID_ID_INFORMATION); |
|
5650 return EFalse; |
|
5651 } |
|
5652 break; |
|
5653 default: //Only these 2 modes make sense no reason for subnets or range |
|
5654 DEBUG_LOG(_L("INVALID_ID_INFORMATION (Remote ID Type not supported)")); |
|
5655 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5656 SendNotifyL(INVALID_ID_INFORMATION); |
|
5657 return EFalse; |
|
5658 }//switch |
|
5659 } |
|
5660 else //No id sent (That means we're negotiating directly with the end host. We check it's TRUE! |
|
5661 { |
|
5662 if (!iRemoteAddr1_ID_II.IsUnspecified()) |
|
5663 { |
|
5664 DEBUG_LOG(_L("IDcr expected and not received!")); |
|
5665 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5666 SendNotifyL(INVALID_ID_INFORMATION); |
|
5667 return EFalse; |
|
5668 } |
|
5669 } |
|
5670 |
|
5671 return ETrue; |
|
5672 } |
|
5673 |
|
5674 |
|
5675 TBool CIkev1Negotiation::CheckIdentL(const TPayloadISAKMP *aPayload) |
|
5676 { |
|
5677 const TIdentISAKMP *ident = TIdentISAKMP::Ptr(aPayload); |
|
5678 |
|
5679 //payload not present |
|
5680 if (!ident) |
|
5681 { |
|
5682 DEBUG_LOG(_L("NO ID PAYLOAD")); |
|
5683 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5684 SendNotifyL(PAYLOAD_MALFORMED); |
|
5685 return EFalse; |
|
5686 } |
|
5687 |
|
5688 if (iPhase == PHASE_I) |
|
5689 { |
|
5690 TUint8 protocol = ident->GetProtocol(); |
|
5691 if ((protocol != KProtocolInetUdp) && (protocol != 0)) |
|
5692 { |
|
5693 DEBUG_LOG(_L("INVALID_ID_INFORMATION: Bad Phase I Protocol (Only UDP(17) or 0 accepted)")); |
|
5694 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5695 SendNotifyL(INVALID_ID_INFORMATION); |
|
5696 return EFalse; |
|
5697 } |
|
5698 TUint16 port = ident->GetPort(); |
|
5699 if ((port != 0) && (port != IKE_PORT) && (port != FLOATED_IKE_PORT) ) |
|
5700 { |
|
5701 DEBUG_LOG(_L("INVALID_ID_INFORMATION: Invalid Bad Phase I Port. (Only 0, 500 or 4500 accepted)")); |
|
5702 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5703 SendNotifyL(INVALID_ID_INFORMATION); |
|
5704 return EFalse; |
|
5705 } |
|
5706 switch (ident->GetIDType()) |
|
5707 { |
|
5708 case ID_IPV4_ADDR: |
|
5709 case ID_IPV6_ADDR: |
|
5710 case ID_FQDN: |
|
5711 case ID_USER_FQDN: |
|
5712 case ID_DER_ASN1_DN: |
|
5713 break; |
|
5714 default: |
|
5715 DEBUG_LOG(_L("INVALID_ID_INFORMATION: Invalid Type (Only IPV4/IPV6/User FQDN and DER ASN1 DN accepted in PHASE I)")); |
|
5716 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5717 SendNotifyL(INVALID_ID_INFORMATION); |
|
5718 return EFalse; |
|
5719 } |
|
5720 } |
|
5721 |
|
5722 return ETrue; |
|
5723 } |
|
5724 |
|
5725 |
|
5726 //Certificate Request Payload processing (all modes). |
|
5727 TBool CIkev1Negotiation::ProcessCertificateReqL(const TCertificateReqISAKMP *aCertReq) |
|
5728 { |
|
5729 if (iChosenProposal_I.iAttrList->iAuthMethod == IKE_A_CRACK) |
|
5730 { |
|
5731 DEBUG_LOG(_L("CR ignored when CRACK auth !)")); |
|
5732 return ETrue; |
|
5733 } |
|
5734 |
|
5735 TInt ret = CheckEncodingL(aCertReq->GetEncoding()); |
|
5736 switch (ret) |
|
5737 { |
|
5738 case KErrGeneral: |
|
5739 return EFalse; |
|
5740 case KErrNotSupported: //Not supported but not an error, just ignored |
|
5741 return ETrue; |
|
5742 } |
|
5743 |
|
5744 if ( !iPkiService ) |
|
5745 return EFalse; |
|
5746 TBool Status = EFalse; |
|
5747 // |
|
5748 // No specific CA asked. Find a certificate using own trusted CA list |
|
5749 // |
|
5750 if ( ReadOwnCertL()) |
|
5751 { |
|
5752 Status = ETrue; |
|
5753 } |
|
5754 |
|
5755 return Status; |
|
5756 |
|
5757 } |
|
5758 |
|
5759 |
|
5760 //Certificate Request Payload(s) processing (all modes). |
|
5761 TBool CIkev1Negotiation::ProcessCertificateReqArrayL(const CArrayFixFlat<const TCertificateReqISAKMP *> *aCRPayloadArray) |
|
5762 { |
|
5763 |
|
5764 TInt count = aCRPayloadArray->Count(); |
|
5765 if ( count == 0 ) |
|
5766 { |
|
5767 return ETrue; // No Certificate requests |
|
5768 } |
|
5769 |
|
5770 if ( ProcessCertificateReqL(aCRPayloadArray->At(0)) ) |
|
5771 { |
|
5772 DEBUG_LOG(_L("User Certificate required by peer found")); |
|
5773 iSendCert = ETrue; //Requires sending our cert in next interchange where allowed/expected, otherwise not sent |
|
5774 return ETrue; |
|
5775 } |
|
5776 HBufC8* CAName = NULL; |
|
5777 CIkeCaList* trustedCaList = iPkiService->CaList(); |
|
5778 |
|
5779 TInt Status=0; |
|
5780 |
|
5781 for (TInt i=0; i < trustedCaList->Count(); i++) |
|
5782 { |
|
5783 CIkeCaElem* CaElem = (*trustedCaList)[i]; |
|
5784 |
|
5785 CAName = IkeCert::GetCertificateFieldDERL(CaElem->Certificate(), KSubjectName); |
|
5786 CleanupStack::PushL(CAName); |
|
5787 |
|
5788 TRAP_IGNORE(Status=iPkiService->ReadChainL(iHostData, CAName)); |
|
5789 |
|
5790 CleanupStack::PopAndDestroy(CAName); |
|
5791 CAName=NULL; |
|
5792 |
|
5793 if ( Status == KErrNone ) |
|
5794 { |
|
5795 delete iOwnCert; |
|
5796 iOwnCert = iPkiService->GetCertificate(); |
|
5797 |
|
5798 iICA1 = iPkiService->GetTrustedICA1(); |
|
5799 |
|
5800 iICA2 = iPkiService->GetTrustedICA2(); |
|
5801 |
|
5802 iPeerTrustedCA = iPkiService->GetTrustedCA(); |
|
5803 |
|
5804 iSendCert = ETrue; //Requires sending our cert in next interchange where allowed/expected, otherwise not sent |
|
5805 |
|
5806 DEBUG_LOG(_L("Certificate chain Found!")); |
|
5807 return ETrue; |
|
5808 } |
|
5809 } |
|
5810 |
|
5811 |
|
5812 if ( Status == KVpnErrInvalidCaCertFile) |
|
5813 { |
|
5814 SetErrorStatus(KVpnErrInvalidCaCertFile); |
|
5815 |
|
5816 SendNotifyL(CERTIFICATE_UNAVAILABLE); |
|
5817 |
|
5818 DEBUG_LOG(_L("Certificate chain read failed!")); |
|
5819 |
|
5820 return EFalse; |
|
5821 } |
|
5822 |
|
5823 SetErrorStatus(KKmdIkeNoCertFoundErr); |
|
5824 SendNotifyL(CERTIFICATE_UNAVAILABLE); |
|
5825 DEBUG_LOG(_L("Certificate Chain r!")); |
|
5826 |
|
5827 return EFalse; |
|
5828 } |
|
5829 |
|
5830 //Certificate Payload(s) processing (all modes). |
|
5831 TBool CIkev1Negotiation::ProcessCertificateArrayL(CArrayFixFlat<const TCertificateISAKMP *>* aCertArray) |
|
5832 { |
|
5833 TBool Status; |
|
5834 if ( iCertRequested ) |
|
5835 Status = EFalse; |
|
5836 else Status = ETrue; |
|
5837 |
|
5838 if ( iPkiService && aCertArray->Count() ) |
|
5839 { |
|
5840 const CIkeCaList* trustedCaList = iPkiService->CaList(); |
|
5841 CX509Certificate* PeerCert = IkePkiUtils::VerifyCertificateL(*aCertArray, |
|
5842 *trustedCaList); |
|
5843 if ( PeerCert ) |
|
5844 { |
|
5845 delete iPeerX509Cert; |
|
5846 iPeerX509Cert = PeerCert; |
|
5847 DEBUG_LOG(_L("Peer Certificate is OK")); |
|
5848 Status = ETrue; |
|
5849 } |
|
5850 else |
|
5851 { |
|
5852 Status = EFalse; |
|
5853 DEBUG_LOG(_L("Peer Certificate is rejected")); |
|
5854 } |
|
5855 } |
|
5856 |
|
5857 return Status; |
|
5858 } |
|
5859 |
|
5860 //Checks the signature sent by the peer host |
|
5861 TBool CIkev1Negotiation::ProcessSignatureL(const TSignatureISAKMP *aSigPayload) |
|
5862 { |
|
5863 TBool ret; |
|
5864 //payload not present |
|
5865 if (!aSigPayload || !iPeerX509Cert ) |
|
5866 { |
|
5867 DEBUG_LOG(_L("NO SIG PAYLOAD")); |
|
5868 SetErrorStatus(KKmdIkePeerAuthFailed); |
|
5869 SendNotifyL(PAYLOAD_MALFORMED); |
|
5870 return EFalse; |
|
5871 } |
|
5872 |
|
5873 //DSS only allows SHA1 as hash |
|
5874 TUint16 tmp = iChosenProposal_I.iAttrList->iHashAlg; |
|
5875 if (iChosenProposal_I.iAttrList->iAuthMethod==DSS_SIG) |
|
5876 iChosenProposal_I.iAttrList->iHashAlg = HASH_SHA1; |
|
5877 |
|
5878 TBuf8<ISAKMP_HASH_SIZE> hash; |
|
5879 //Verify the peer signature |
|
5880 if (iRole==RESPONDER) |
|
5881 { |
|
5882 ComputeHash1L(hash); //Computes the value of iHASH_I the signature checking |
|
5883 //Nothing else to compute. |
|
5884 } |
|
5885 else //Initiator |
|
5886 { |
|
5887 ComputeHashrL(hash); //Computes the value of CRACK digest for signature checking |
|
5888 } |
|
5889 |
|
5890 ret = VerifySignatureL(iPeerX509Cert, (TUint8 *)hash.Ptr(), hash.Length(), aSigPayload->SigData(),aSigPayload->GetDataLength()); |
|
5891 |
|
5892 //restores the value of the Hash alg. |
|
5893 iChosenProposal_I.iAttrList->iHashAlg = tmp; |
|
5894 |
|
5895 if (!ret) |
|
5896 { |
|
5897 DEBUG_LOG(_L("INVALID_SIGNATURE 2")); |
|
5898 SetErrorStatus(KKmdIkePeerAuthFailed); |
|
5899 SendNotifyL(INVALID_SIGNATURE); |
|
5900 return EFalse; |
|
5901 } |
|
5902 |
|
5903 DEBUG_LOG(_L("Peer Signature is OK")); |
|
5904 return ETrue; |
|
5905 } |
|
5906 |
|
5907 |
|
5908 TBool CIkev1Negotiation::ProcessHashL(const THashISAKMP *aHashPayload) |
|
5909 { |
|
5910 TBool Status = EFalse; |
|
5911 if (aHashPayload) |
|
5912 { |
|
5913 //Compute peer's hash |
|
5914 TBuf8<ISAKMP_HASH_SIZE> hash; |
|
5915 if ( (iStage == 6) || ((iStage == 2) && (iExchange == ISAKMP_EXCHANGE_AGGR))) |
|
5916 ComputeHashrL(hash); |
|
5917 else ComputeHash1L(hash); |
|
5918 Status = (Mem::Compare((TUint8 *)hash.Ptr(), hash.Length(), aHashPayload->Data(), aHashPayload->DataLen()) == 0 ); |
|
5919 if ( !Status ) |
|
5920 { |
|
5921 DEBUG_LOG(_L("INVALID_HASH_INFORMATION")); |
|
5922 SendNotifyL(INVALID_HASH_INFORMATION); |
|
5923 } |
|
5924 } |
|
5925 |
|
5926 return Status; |
|
5927 } |
|
5928 |
|
5929 |
|
5930 TBool CIkev1Negotiation::ProcessHash2L(const ThdrISAKMP &aHdr, const THashISAKMP *aHashPayload, TUint aPadding) |
|
5931 { |
|
5932 TBool Status = EFalse; |
|
5933 if ( aHashPayload ) |
|
5934 { |
|
5935 TUint8* hashMsg = (TUint8*)aHashPayload->Next(); |
|
5936 TInt hashMsgLen = aHdr.GetLength() - sizeof(aHdr) - aHashPayload->GetLength() - aPadding; |
|
5937 Status = VerifyHash2L(aHashPayload, hashMsg, hashMsgLen); |
|
5938 if (!Status) |
|
5939 { |
|
5940 DEBUG_LOG(_L("INVALID_HASH_INFORMATION")); |
|
5941 SendNotifyL(INVALID_HASH_INFORMATION); |
|
5942 } |
|
5943 } |
|
5944 else |
|
5945 { |
|
5946 DEBUG_LOG(_L("PAYLOAD_MALFORMED")); |
|
5947 SendNotifyL(PAYLOAD_MALFORMED); |
|
5948 } |
|
5949 |
|
5950 return Status; |
|
5951 } |
|
5952 |
|
5953 |
|
5954 //Check a notification Payload inserted in a normal exchange (MAIN , AGGR, QUICK) |
|
5955 TBool CIkev1Negotiation::ProcessNotificationL(const TNotificationISAKMP *aNotifPayload) |
|
5956 { |
|
5957 if (!aNotifPayload) |
|
5958 return ETrue; //optional so noting happens |
|
5959 |
|
5960 if (!CheckDOI(aNotifPayload->GetDOI())) |
|
5961 { |
|
5962 DEBUG_LOG(_L("Bad DOI in the NOT payload")); |
|
5963 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5964 SendNotifyL(DOI_NOT_SUPPORTED); //send the informational exchange |
|
5965 return EFalse; |
|
5966 } |
|
5967 |
|
5968 switch(aNotifPayload->GetMsgType()) |
|
5969 { |
|
5970 case DOI_RESPONDER_LIFETIME: |
|
5971 return ProcessResponderLifetimeL(aNotifPayload); |
|
5972 case DOI_REPLAY_STATUS: |
|
5973 return ProcessReplayStatus(aNotifPayload); |
|
5974 case DOI_INITIAL_CONTACT: |
|
5975 return ProcessInitialContactL(aNotifPayload); |
|
5976 default: |
|
5977 DEBUG_LOG(_L("INVALID MESSAGE TYPE in NOT payload")); |
|
5978 SetErrorStatus( KKmdIkeNegotFailed ); |
|
5979 SendNotifyL(PAYLOAD_MALFORMED); |
|
5980 return EFalse; |
|
5981 } |
|
5982 |
|
5983 } |
|
5984 |
|
5985 |
|
5986 //Processes a RESPONDER-LIFETIME NOT payload |
|
5987 TBool CIkev1Negotiation::ProcessResponderLifetimeL(const TNotificationISAKMP *aNotifPayload) |
|
5988 { |
|
5989 TBuf8<2 * ISAKMP_COOKIE_SIZE> spi, own_neg_spi; |
|
5990 DEBUG_LOG(_L("Processing RESPONDER-LIFETIME")); |
|
5991 |
|
5992 |
|
5993 if (!((iPhase == PHASE_II) && (iStage == 2))) |
|
5994 { |
|
5995 if ( iPhase == PHASE_I ) { |
|
5996 DEBUG_LOG(_L("RESPONDER-LIFETIME payload in phase 1, ignored !!")); |
|
5997 return ETrue; |
|
5998 } |
|
5999 else { |
|
6000 DEBUG_LOG(_L("Unexpected RESPONDER-LIFETIME payload (Bad stage)")); |
|
6001 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6002 SendNotifyL(INVALID_PAYLOAD_TYPE); |
|
6003 return EFalse; |
|
6004 } |
|
6005 } |
|
6006 |
|
6007 TUint8 protocol = aNotifPayload->GetProtocol(); |
|
6008 if ((protocol != PROTO_IPSEC_AH) && (protocol != PROTO_IPSEC_ESP) && |
|
6009 (protocol != PROTO_ISAKMP) && (protocol != 0)) |
|
6010 { |
|
6011 DEBUG_LOG(_L("Bad protocol in the RESPONDER-LIFETIME payload")); |
|
6012 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6013 SendNotifyL(INVALID_PROTOCOL_ID); |
|
6014 return EFalse; |
|
6015 } |
|
6016 |
|
6017 TUint8 spi_size = aNotifPayload->GetSPISize(); |
|
6018 CProposal_II *prop; |
|
6019 TInt i; |
|
6020 //If SPI sent |
|
6021 switch (spi_size) |
|
6022 { |
|
6023 case 2 * ISAKMP_COOKIE_SIZE: //ISAKMP spi |
|
6024 spi.Copy(aNotifPayload->GetSPI(), aNotifPayload->GetSPISize()); |
|
6025 own_neg_spi.Copy(iCookie_I); |
|
6026 own_neg_spi.Append(iCookie_R); |
|
6027 |
|
6028 if (spi.Compare(own_neg_spi) != 0) |
|
6029 { |
|
6030 DEBUG_LOG(_L("Invalid SPI size in the RESPONDER-LIFETIME payload. Payload ignored")); |
|
6031 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6032 SendNotifyL(INVALID_SPI); |
|
6033 return EFalse; |
|
6034 } |
|
6035 if (iChosenProp_IIList->Count() > 1) |
|
6036 { |
|
6037 DEBUG_LOG(_L("RESPONDER-LIFETIME ignored. More than one SA (need a IPsec SPI to know which one to use) ")); |
|
6038 return EFalse; |
|
6039 } |
|
6040 prop = iChosenProp_IIList->At(0); //Only one proposal |
|
6041 break; |
|
6042 case 0: //Compatibility with Alchemy cc500 |
|
6043 if (iChosenProp_IIList->Count() > 1) |
|
6044 { |
|
6045 DEBUG_LOG(_L("RESPONDER-LIFETIME ignored. More than one SA (need a IPsec SPI to know which one to use) ")); |
|
6046 return EFalse; |
|
6047 } |
|
6048 |
|
6049 prop = iChosenProp_IIList->At(0); //Only one proposal |
|
6050 break; |
|
6051 case sizeof(TUint32): //IPSEC SPI |
|
6052 spi.Copy(aNotifPayload->GetSPI(), aNotifPayload->GetSPISize()); |
|
6053 prop = NULL; //Only for the debugger, the loop will have at least one proposal |
|
6054 for (i = 0; i < iChosenProp_IIList->Count(); i++) |
|
6055 { |
|
6056 prop = iChosenProp_IIList->At(i); //Only one proposal |
|
6057 if (((prop->iSPI.Compare(spi) == 0) && prop->iProtocol == protocol)) //right prop |
|
6058 break; |
|
6059 } |
|
6060 |
|
6061 if (i == iChosenProp_IIList->Count()) //No prop matches |
|
6062 { |
|
6063 DEBUG_LOG(_L("RESPONDER-LIFETIME ignored. IPsec SPI doesn't match any chosen proposal")); |
|
6064 return EFalse; |
|
6065 } |
|
6066 break; |
|
6067 default: |
|
6068 DEBUG_LOG(_L("Bad SPI size in the RESPONDER-LIFETIME payload")); |
|
6069 return EFalse; |
|
6070 } |
|
6071 TAttrib_II *transform = prop->iAttrList->At(0); //Only one transform |
|
6072 TInt data_len = aNotifPayload->GetNotifDataSize(); |
|
6073 TUint8 *data_ptr = aNotifPayload->GetNotifData(); |
|
6074 TUint16 lifeType = 0; //No type assigned yet |
|
6075 TInt64 lifeValue = 0; //No type assigned yet |
|
6076 TInt64 lifeValue32; |
|
6077 TInt64 curr_lifeValue = 0; |
|
6078 TInt32 duration; |
|
6079 |
|
6080 TDataISAKMP *attr = (TDataISAKMP*)data_ptr; |
|
6081 while (data_len > 0) |
|
6082 { |
|
6083 data_len = data_len - attr->Size(); |
|
6084 if (data_len < 0) //Mismatch between lengths!!! |
|
6085 { |
|
6086 DEBUG_LOG(_L("RESPONDER-LIFETIME (Length mismatch in the attibutes)")); |
|
6087 return EFalse; |
|
6088 } |
|
6089 switch (attr->Type()) |
|
6090 { |
|
6091 case DOI_ATTR_TYPE_LIFE_TYPE: |
|
6092 case OAKLEY_ATTR_TYPE_LIFE_TYPE: |
|
6093 lifeType = attr->Value(); |
|
6094 if (!CheckLifeType(lifeType)) |
|
6095 { |
|
6096 DEBUG_LOG(_L("RESPONDER-LIFETIME (Invalid lifetime type)")); |
|
6097 return EFalse; |
|
6098 } |
|
6099 break; |
|
6100 case DOI_ATTR_TYPE_LIFE_DUR: |
|
6101 case OAKLEY_ATTR_TYPE_LIFE_DUR: |
|
6102 if (attr->IsBasic()) |
|
6103 { |
|
6104 duration = ByteOrder::Swap32(attr->Value()); |
|
6105 lifeValue = MAKE_TINT64(0, duration); |
|
6106 lifeValue32 = I64LOW(lifeValue); |
|
6107 if (lifeType == SECONDS) |
|
6108 { |
|
6109 Desc8ToTInt64(transform->iLifeDurationSecs, curr_lifeValue); //can't fail |
|
6110 if (lifeValue < curr_lifeValue) |
|
6111 transform->iLifeDurationSecs.Copy((TUint8 *)&lifeValue32, sizeof(lifeValue32)); |
|
6112 } |
|
6113 else if (lifeType == KBYTES) |
|
6114 { |
|
6115 Desc8ToTInt64(transform->iLifeDurationKBytes, curr_lifeValue); //can't fail |
|
6116 if (lifeValue < curr_lifeValue) |
|
6117 transform->iLifeDurationKBytes.Copy((TUint8 *)&lifeValue32, sizeof(lifeValue32)); |
|
6118 } |
|
6119 else |
|
6120 { |
|
6121 DEBUG_LOG(_L("RESPONDER-LIFETIME (Invalid lifetime type)")); |
|
6122 return EFalse; |
|
6123 } |
|
6124 } |
|
6125 else //Not basic |
|
6126 { |
|
6127 TPtrC8 ptr(attr->VarValue(),attr->Length()); |
|
6128 |
|
6129 if (lifeType == SECONDS) |
|
6130 { |
|
6131 if (Desc8ToTInt64(ptr, lifeValue) != KErrNone) |
|
6132 { |
|
6133 DEBUG_LOG(_L("RESPONDER-LIFETIME Lifetime(Sec) Overflowed Setting to maximum value")); |
|
6134 } |
|
6135 Desc8ToTInt64(transform->iLifeDurationSecs, curr_lifeValue); //can't fail |
|
6136 if (lifeValue < curr_lifeValue) |
|
6137 transform->iLifeDurationSecs.Copy(attr->VarValue(),attr->Length()); |
|
6138 } |
|
6139 else if (lifeType == KBYTES) |
|
6140 { |
|
6141 if (Desc8ToTInt64(ptr, lifeValue) != KErrNone) |
|
6142 { |
|
6143 DEBUG_LOG(_L("RESPONDER-LIFETIME Lifetime(KBytes) Overflowed Setting to maximum value")); |
|
6144 } |
|
6145 Desc8ToTInt64(transform->iLifeDurationKBytes, curr_lifeValue); //can't fail |
|
6146 if (lifeValue < curr_lifeValue) |
|
6147 transform->iLifeDurationKBytes.Copy(attr->VarValue(),attr->Length()); |
|
6148 } |
|
6149 else |
|
6150 { |
|
6151 DEBUG_LOG(_L("RESPONDER-LIFETIME (Invalid lifetime type)")); |
|
6152 return EFalse; |
|
6153 } |
|
6154 } |
|
6155 break; |
|
6156 default: |
|
6157 DEBUG_LOG1(_L("RESPONDER-LIFETIME (Invalid attribute (%d) received)"), attr->Type()); |
|
6158 return EFalse; |
|
6159 }//switch |
|
6160 attr = attr->Next(); |
|
6161 }//while |
|
6162 |
|
6163 return ETrue; |
|
6164 } |
|
6165 |
|
6166 //Processes a REPLAY-STATUS NOT payload |
|
6167 TBool CIkev1Negotiation::ProcessReplayStatus(const TNotificationISAKMP *aNotifPayload) |
|
6168 { |
|
6169 TBuf8<2 * ISAKMP_COOKIE_SIZE> spi, own_neg_spi; |
|
6170 |
|
6171 DEBUG_LOG(_L("Processing REPLAY-STATUS")); |
|
6172 |
|
6173 if (!((iPhase == PHASE_II) && ((iStage == 1) || (iStage == 2)))) |
|
6174 { |
|
6175 DEBUG_LOG(_L("Unexpected REPLAY-STATUS payload (Bad stage)")); |
|
6176 return EFalse; |
|
6177 } |
|
6178 |
|
6179 TUint8 protocol = aNotifPayload->GetProtocol(); |
|
6180 if ((protocol != PROTO_IPSEC_AH) && (protocol != PROTO_IPSEC_ESP) && |
|
6181 (protocol != PROTO_ISAKMP) && (protocol != 0)) |
|
6182 { |
|
6183 DEBUG_LOG(_L("Bad protocol in the REPLAY-STATUS payload")); |
|
6184 return EFalse; |
|
6185 } |
|
6186 |
|
6187 TInt i; |
|
6188 TUint8 spi_size = aNotifPayload->GetSPISize(); |
|
6189 CProposal_II *prop; |
|
6190 //If SPI sent |
|
6191 switch (spi_size) |
|
6192 { |
|
6193 case 2 * ISAKMP_COOKIE_SIZE: //ISAKMP spi |
|
6194 spi.Copy(aNotifPayload->GetSPI(), aNotifPayload->GetSPISize()); |
|
6195 own_neg_spi.Copy(iCookie_I); |
|
6196 own_neg_spi.Append(iCookie_R); |
|
6197 if (spi.Compare(own_neg_spi) != 0) |
|
6198 { |
|
6199 DEBUG_LOG(_L("Invalid SPI size in the REPLAY-STATUS payload. Payload ignored")); |
|
6200 return EFalse; |
|
6201 } |
|
6202 if (iChosenProp_IIList->Count() > 1) |
|
6203 { |
|
6204 DEBUG_LOG(_L("REPLAY-STATUS ignored. More than one IPsec SA (need an IPsec SPI to know which one to use) ")); |
|
6205 return EFalse; |
|
6206 } |
|
6207 break; |
|
6208 case 0: //Compatibility with Alchemy cc500 |
|
6209 if (iChosenProp_IIList->Count() > 1) |
|
6210 { |
|
6211 DEBUG_LOG(_L("RESPONDER-LIFETIME ignored. More than one SA (need a IPsec SPI to know which one to use) ")); |
|
6212 return EFalse; |
|
6213 } |
|
6214 prop = iChosenProp_IIList->At(0); //Only one proposal |
|
6215 break; |
|
6216 case sizeof(TUint32): //IPSEC SPI |
|
6217 spi.Copy(aNotifPayload->GetSPI(), aNotifPayload->GetSPISize()); |
|
6218 for (i = 0; i < iChosenProp_IIList->Count(); i++) |
|
6219 { |
|
6220 prop = iChosenProp_IIList->At(i); //Only one proposal |
|
6221 if (((prop->iSPI.Compare(spi) == 0) && prop->iProtocol == protocol)) //right prop |
|
6222 break; |
|
6223 } |
|
6224 if (i == iChosenProp_IIList->Count()) //No prop matches |
|
6225 { |
|
6226 DEBUG_LOG(_L("REPLAY-STATUS ignored. IPsec SPI doesn't match any chosen proposal")); |
|
6227 return EFalse; |
|
6228 } |
|
6229 break; |
|
6230 default: |
|
6231 DEBUG_LOG(_L("Bad SPI size in the REPLAY-STATUS payload")); |
|
6232 return EFalse; |
|
6233 } |
|
6234 |
|
6235 TInt data_len = aNotifPayload->GetNotifDataSize(); |
|
6236 TUint32 *data = (TUint32 *)aNotifPayload->GetNotifData(); |
|
6237 if (STATIC_CAST(TUint, data_len) < sizeof(*data)) |
|
6238 { |
|
6239 DEBUG_LOG(_L("REPLAY-STATUS (Length mismatch in the attibutes)")); |
|
6240 return EFalse; |
|
6241 } |
|
6242 |
|
6243 #ifdef _DEBUG |
|
6244 if (ByteOrder::Swap32(*data) == 0) |
|
6245 DEBUG_LOG(_L("Anti-Replay Disabled on Peer Host")); |
|
6246 else |
|
6247 DEBUG_LOG(_L("Anti-Replay Enabled on Peer Host")); |
|
6248 #endif |
|
6249 return ETrue; |
|
6250 } |
|
6251 |
|
6252 |
|
6253 TBool CIkev1Negotiation::ProcessInitialContactL(const TNotificationISAKMP *aNotifPayload) |
|
6254 { |
|
6255 TBuf8<2 * ISAKMP_COOKIE_SIZE> spi, neg_spi; |
|
6256 |
|
6257 DEBUG_LOG(_L("Processing INITIAL-CONTACT")); |
|
6258 // 7 = CRACK |
|
6259 if (!(iPhase == PHASE_I && (iStage == 5 || iStage == 6 || iStage == 7))) |
|
6260 { |
|
6261 DEBUG_LOG(_L("Unexpected INITIAL-CONTACT payload (Bad stage)")); |
|
6262 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6263 SendNotifyL(INVALID_PAYLOAD_TYPE); |
|
6264 return EFalse; |
|
6265 } |
|
6266 |
|
6267 if (aNotifPayload->GetProtocol() != PROTO_ISAKMP && |
|
6268 aNotifPayload->GetProtocol() != 0 ) |
|
6269 |
|
6270 { |
|
6271 DEBUG_LOG(_L("Bad protocol in the INITIAL_CONTACT payload")); |
|
6272 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6273 SendNotifyL(INVALID_PROTOCOL_ID); |
|
6274 return EFalse; |
|
6275 } |
|
6276 |
|
6277 if (aNotifPayload->GetSPISize() != 2 * ISAKMP_COOKIE_SIZE) |
|
6278 { |
|
6279 DEBUG_LOG(_L("Bad SPI size in the INITIAL_CONTACT payload")); |
|
6280 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6281 SendNotifyL(INVALID_SPI); |
|
6282 return EFalse; |
|
6283 } |
|
6284 spi.Copy(aNotifPayload->GetSPI(), aNotifPayload->GetSPISize()); |
|
6285 neg_spi.Copy(iCookie_I); |
|
6286 neg_spi.Append(iCookie_R); |
|
6287 |
|
6288 if (spi.Compare(neg_spi) != 0) |
|
6289 { |
|
6290 DEBUG_LOG(_L("Invalid SPI size in the INITIAL_CONTACT payload")); |
|
6291 SetErrorStatus( KKmdIkeNegotFailed ); |
|
6292 SendNotifyL(INVALID_SPI); |
|
6293 return EFalse; |
|
6294 } |
|
6295 |
|
6296 if ( iRole == RESPONDER ) |
|
6297 { |
|
6298 // Expired SAs are not returned. |
|
6299 TIkev1SAData* sa = iPluginSession->FindIkev1SADataWithAddr( iRemoteAddr ); |
|
6300 while ( sa != NULL ) |
|
6301 { |
|
6302 iPluginSession->UpdateIkev1SAL( sa->iSAId, ETrue ); |
|
6303 sa = iPluginSession->FindIkev1SADataWithAddr( iRemoteAddr ); |
|
6304 } |
|
6305 |
|
6306 // Delete other ongoing negotiations. |
|
6307 CIkev1Negotiation* next = iPluginSession->FirstNegotiation(); |
|
6308 while ( next != NULL ) |
|
6309 { |
|
6310 CIkev1Negotiation* current = next; |
|
6311 next = current->iNext; |
|
6312 if ( current != this ) |
|
6313 { |
|
6314 delete current; |
|
6315 } |
|
6316 } |
|
6317 } |
|
6318 |
|
6319 return ETrue; |
|
6320 } |
|
6321 |
|
6322 |
|
6323 |
|
6324 void CIkev1Negotiation::ProcessVendorL(CArrayFixFlat<const TVendorISAKMP*>* aVids) |
|
6325 { |
|
6326 TBool result; |
|
6327 TInt i = 0; |
|
6328 |
|
6329 while ( i < aVids->Count() ) |
|
6330 { |
|
6331 TVendorISAKMP* VendorPayload = (TVendorISAKMP*)aVids->At(i); |
|
6332 DEBUG_LOG(_L("Vendor ID received!\nHex: ")); |
|
6333 DEBUG_LOG_ARRAY(VendorPayload->VIDData(), VendorPayload->GetLength() - sizeof(*VendorPayload)); |
|
6334 |
|
6335 if ( iLocalAddr.Family() == KAFUnspec ) |
|
6336 User::LeaveIfError( iPluginSession->GetLocalAddress( iLocalAddr ) ); // No local address info, get it ! |
|
6337 |
|
6338 result = EFalse; |
|
6339 iNAT_T_Required = ProcessVendorId(&result, |
|
6340 (TUint8*)iCookie_I.Ptr(), |
|
6341 (TUint8*)iCookie_R.Ptr(), |
|
6342 iLocalAddr, |
|
6343 VendorPayload); |
|
6344 if ( result ) |
|
6345 { |
|
6346 iFamiliarPeer = result; |
|
6347 #ifdef _DEBUG |
|
6348 DEBUG_LOG(_L("Nokia VPN gateway in peer!")); |
|
6349 if ( iNAT_T_Required ) { |
|
6350 DEBUG_LOG(_L("NAT Traversal needed!")); |
|
6351 if ( !iHostData->iUseNatProbing ) |
|
6352 DEBUG_LOG(_L(" NAT probe not requested! NAT-T not used!")); |
|
6353 } |
|
6354 #endif // _DEBUG |
|
6355 iNAT_T_Required = iNAT_T_Required & iHostData->iUseNatProbing; |
|
6356 } |
|
6357 else |
|
6358 { |
|
6359 if ( CheckDPDVendorId(VendorPayload) ) |
|
6360 { |
|
6361 DEBUG_LOG(_L("Peer supports IETF Dead Peer Detection!")); |
|
6362 iDPDSupported = ETrue; |
|
6363 } |
|
6364 else if ( iNatDiscovery ) |
|
6365 { |
|
6366 result = iNatDiscovery->CheckNatVendorId(VendorPayload); |
|
6367 if ( result ) |
|
6368 { |
|
6369 DEBUG_LOG(_L("Peer supports IETF (draft-03) NAT Traversal!")); |
|
6370 } |
|
6371 else |
|
6372 { |
|
6373 result = iNatDiscovery->CheckRfcNatVendorId(VendorPayload); |
|
6374 if ( result ) |
|
6375 { |
|
6376 iVendorIDRfc=ETrue; |
|
6377 DEBUG_LOG(_L("Peer supports IETF NAT Traversal!")); |
|
6378 } |
|
6379 } |
|
6380 } |
|
6381 } |
|
6382 |
|
6383 i ++; |
|
6384 } |
|
6385 |
|
6386 } |
|
6387 |
|
6388 // |
|
6389 //Process Internal address payload received |
|
6390 // |
|
6391 void CIkev1Negotiation::ProcessIntAddrL(const TINTNETISAKMP *aIntnetPayload) |
|
6392 { |
|
6393 if ( aIntnetPayload && iFamiliarPeer && iHostData->iUseInternalAddr ) { |
|
6394 delete iInternalAddr; //delete if already exists (old) |
|
6395 iInternalAddr = NULL; |
|
6396 iInternalAddr = ProcessIntNetL((TINTNETISAKMP*) aIntnetPayload); |
|
6397 #ifdef _DEBUG |
|
6398 if ( iInternalAddr) { |
|
6399 TBuf<80> buf; |
|
6400 TBuf<40> txt_addr; |
|
6401 iInternalAddr->iClientIntAddr.OutputWithScope(txt_addr); |
|
6402 DEBUG_LOG1(_L("Internal address received: %S"),&txt_addr); |
|
6403 } |
|
6404 #endif |
|
6405 } |
|
6406 } |
|
6407 |
|
6408 //Computes the hash for phase II |
|
6409 void CIkev1Negotiation::ComputeHash2L(TDes8& aHash, TInt aStage, const TUint8 *aHashMsg, TInt aHashMsgLen) |
|
6410 { |
|
6411 |
|
6412 HBufC8* prf_data = |
|
6413 HBufC8::NewLC(((aHashMsgLen + iNONCE_I.Length() + iNONCE_R.Length() + (2*sizeof(TUint32))) | 0x3) + 1); |
|
6414 |
|
6415 if (aStage == 3) |
|
6416 prf_data->Des().Append(0); |
|
6417 |
|
6418 TUint32 id = ByteOrder::Swap32(iMessageId); |
|
6419 prf_data->Des().Append((TUint8*)&id,sizeof(iMessageId)); |
|
6420 DEBUG_LOG(_L("ID")); |
|
6421 switch (aStage) |
|
6422 { |
|
6423 case 2: |
|
6424 prf_data->Des().Append(iNONCE_I); |
|
6425 //No break is intended |
|
6426 case 1: |
|
6427 prf_data->Des().Append(aHashMsg,aHashMsgLen); |
|
6428 break; |
|
6429 case 3: |
|
6430 |
|
6431 prf_data->Des().Append(iNONCE_I); |
|
6432 DEBUG_LOG(_L("iNONCE_I")); |
|
6433 prf_data->Des().Append(iNONCE_R); |
|
6434 DEBUG_LOG(_L("iNONCE_R")); |
|
6435 break; |
|
6436 default: |
|
6437 CleanupStack::PopAndDestroy(); //prf_data |
|
6438 return; |
|
6439 } |
|
6440 |
|
6441 DEBUG_LOG1(_L("Hash_II(%d) prf"),aStage); |
|
6442 |
|
6443 ComputePRFL(aHash, iSKEYID_a, prf_data->Des()); |
|
6444 |
|
6445 DEBUG_LOG(_L("HASH")); |
|
6446 |
|
6447 CleanupStack::PopAndDestroy(); //prf_data |
|
6448 |
|
6449 } |
|
6450 |
|
6451 //Computes the hash for a protected informational exchange |
|
6452 void CIkev1Negotiation::ComputeHashInfL(TDes8& aHash, const TUint8 *aHashMsg, TInt aHashMsgLen) |
|
6453 { |
|
6454 |
|
6455 HBufC8* prf_data = |
|
6456 HBufC8::NewLC(((aHashMsgLen + sizeof(iMessageId)) | 0x3) + 1); |
|
6457 |
|
6458 //prf(SKEYID_a, M_ID | N/D) |
|
6459 TUint32 id = ByteOrder::Swap32(iMessageId); |
|
6460 prf_data->Des().Append((TUint8*)&id, sizeof(iMessageId)); |
|
6461 |
|
6462 prf_data->Des().Append(aHashMsg, aHashMsgLen); |
|
6463 |
|
6464 DEBUG_LOG(_L("Hash_NOT prf")); |
|
6465 |
|
6466 ComputePRFL(aHash, iSKEYID_a, prf_data->Des()); |
|
6467 |
|
6468 DEBUG_LOG(_L("HASH")); |
|
6469 |
|
6470 CleanupStack::PopAndDestroy(); //prf_data |
|
6471 |
|
6472 } |
|
6473 |
|
6474 //Verifies that aHash is correct |
|
6475 TBool CIkev1Negotiation::VerifyHash2L(const THashISAKMP *aHash,const TUint8 *aHashMsg, TInt aHashMsgLen) |
|
6476 { |
|
6477 TBuf8<ISAKMP_HASH_SIZE> tmp_hash; |
|
6478 |
|
6479 ComputeHash2L(tmp_hash, iStage, aHashMsg, aHashMsgLen); //Computes the specified phase II hash |
|
6480 |
|
6481 TBool Status = (Mem::Compare((TUint8*)tmp_hash.Ptr(), tmp_hash.Length(), aHash->Data(), aHash->DataLen()) == 0); |
|
6482 |
|
6483 return Status; |
|
6484 } |
|
6485 |
|
6486 //Verifies the hash of a Notification or Delete payload |
|
6487 // Used also to verify the hash of Transaction exchange (Attribute payload) |
|
6488 TBool CIkev1Negotiation::VerifyInformationalHashL(const THashISAKMP *aHash,const TPayloadISAKMP *aPayload, TUint32 aMessageId) |
|
6489 { |
|
6490 TBuf8<MAX_PRF_LENGTH> tmp_hash; |
|
6491 |
|
6492 TUint32 tmp_id = ByteOrder::Swap32(aMessageId); |
|
6493 HBufC8 *prf_buf = HBufC8::NewLC(sizeof(tmp_id) + aPayload->GetLength()); |
|
6494 prf_buf->Des().Copy((TUint8 *)&tmp_id , sizeof(tmp_id)); |
|
6495 prf_buf->Des().Append((TUint8 *)aPayload, aPayload->GetLength()); |
|
6496 |
|
6497 ComputePRFL(tmp_hash, iSKEYID_a, prf_buf->Des()); |
|
6498 TPtrC8 hash_ptr(aHash->Data(),aHash->DataLen()); |
|
6499 TBool b = (tmp_hash.Compare(hash_ptr)==0); |
|
6500 CleanupStack::PopAndDestroy(); //prf_buf |
|
6501 return (b); |
|
6502 } |
|
6503 |
|
6504 |
|
6505 //Computes Own Nonce using current time a seed |
|
6506 void CIkev1Negotiation::ComputeNonceL() |
|
6507 { |
|
6508 DEBUG_LOG(_L("Computed NONCE.")); |
|
6509 if (iRole==INITIATOR) |
|
6510 { |
|
6511 iNONCE_I.SetLength(OAKLEY_DEFAULT_NONCE_SIZE); |
|
6512 TRandom::RandomL(iNONCE_I); |
|
6513 } |
|
6514 else |
|
6515 { |
|
6516 iNONCE_R.SetLength(OAKLEY_DEFAULT_NONCE_SIZE); |
|
6517 TRandom::RandomL(iNONCE_R); |
|
6518 } |
|
6519 } |
|
6520 |
|
6521 //Computes HASH_R value |
|
6522 void CIkev1Negotiation::ComputeHashrL(TDes8 &aHash) |
|
6523 { |
|
6524 TInt id_size = 0; |
|
6525 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
6526 |
|
6527 DEBUG_LOG(_L("Computing HASH_R")); |
|
6528 |
|
6529 if ( auth_method != IKE_A_CRACK ) { |
|
6530 if (iRole==INITIATOR) |
|
6531 { //peer id. payload |
|
6532 id_size = iPeerIdentPayloadSize; |
|
6533 DEBUG_LOG(_L("PeerID")); |
|
6534 } |
|
6535 else |
|
6536 { //Own identification payload |
|
6537 id_size = iOwnIdentPayloadSize; |
|
6538 DEBUG_LOG(_L("OwnID")); |
|
6539 } |
|
6540 } |
|
6541 |
|
6542 DEBUG_LOG(_L("SKEYID")); |
|
6543 |
|
6544 HBufC8 *prf_data; |
|
6545 if (iRole==INITIATOR) //peer id. payload |
|
6546 { |
|
6547 prf_data = HBufC8::NewLC(iPeerPublicKey.Length() + iOwnPublicKey_ptr.Length() + iCookie_R.Length() |
|
6548 + iCookie_I.Length() + iSAPayloadSize + id_size); |
|
6549 prf_data->Des().Copy(iPeerPublicKey); |
|
6550 prf_data->Des().Append(iOwnPublicKey_ptr); |
|
6551 prf_data->Des().Append(iCookie_R); |
|
6552 prf_data->Des().Append(iCookie_I); |
|
6553 prf_data->Des().Append(iSAPayload,iSAPayloadSize); //stored at the begining |
|
6554 if ( auth_method != IKE_A_CRACK ) |
|
6555 prf_data->Des().Append(iPeerIdentPayload, iPeerIdentPayloadSize); |
|
6556 } |
|
6557 else //RESPONDER |
|
6558 { |
|
6559 prf_data = HBufC8::NewLC(iOwnPublicKey_ptr.Length() + iPeerPublicKey.Length() + iCookie_R.Length() |
|
6560 + iCookie_I.Length() + iSAPayloadSize + id_size); |
|
6561 prf_data->Des().Copy(iOwnPublicKey_ptr); |
|
6562 prf_data->Des().Append(iPeerPublicKey); |
|
6563 prf_data->Des().Append(iCookie_R); |
|
6564 prf_data->Des().Append(iCookie_I); |
|
6565 prf_data->Des().Append(iSAPayload,iSAPayloadSize); //stored at the begining |
|
6566 if ( auth_method != IKE_A_CRACK ) |
|
6567 prf_data->Des().Append(iOwnIdentPayload, iOwnIdentPayloadSize); |
|
6568 } |
|
6569 |
|
6570 DEBUG_LOG(_L("PRF")); |
|
6571 |
|
6572 ComputePRFL(aHash, iSKEYID, prf_data->Des()); |
|
6573 |
|
6574 CleanupStack::PopAndDestroy(); //prf_data |
|
6575 |
|
6576 DEBUG_LOG(_L("HASH_R")); |
|
6577 |
|
6578 } |
|
6579 |
|
6580 |
|
6581 //Computes the value of iHASH_I |
|
6582 void CIkev1Negotiation::ComputeHash1L(TDes8 &aHash) |
|
6583 { |
|
6584 TInt id_size = 0; |
|
6585 TUint16 auth_method = iChosenProposal_I.iAttrList->iAuthMethod; |
|
6586 |
|
6587 DEBUG_LOG(_L("Computing HASH_I")); |
|
6588 |
|
6589 if ( auth_method != IKE_A_CRACK ) { |
|
6590 if (iRole==INITIATOR) //Own identification payload |
|
6591 { |
|
6592 id_size = iOwnIdentPayloadSize; |
|
6593 DEBUG_LOG(_L("OwnID")); |
|
6594 } |
|
6595 else //peer id. payload |
|
6596 { |
|
6597 id_size = iPeerIdentPayloadSize; |
|
6598 DEBUG_LOG(_L("PeerID")); |
|
6599 } |
|
6600 } |
|
6601 |
|
6602 |
|
6603 DEBUG_LOG(_L("SKEYID")); |
|
6604 |
|
6605 HBufC8 *prf_data; |
|
6606 if (iRole==INITIATOR) |
|
6607 { |
|
6608 prf_data = HBufC8::NewLC(iOwnPublicKey_ptr.Length() + iPeerPublicKey.Length() + iCookie_I.Length() |
|
6609 + iCookie_R.Length() + iSAPayloadSize + id_size); |
|
6610 prf_data->Des().Copy(iOwnPublicKey_ptr); |
|
6611 prf_data->Des().Append(iPeerPublicKey); |
|
6612 prf_data->Des().Append(iCookie_I); |
|
6613 prf_data->Des().Append(iCookie_R); |
|
6614 prf_data->Des().Append(iSAPayload,iSAPayloadSize); //stored at the begining |
|
6615 if ( auth_method != IKE_A_CRACK ) |
|
6616 prf_data->Des().Append(iOwnIdentPayload,iOwnIdentPayloadSize); |
|
6617 } |
|
6618 else //RESPONDER |
|
6619 { |
|
6620 prf_data = HBufC8::NewLC(iPeerPublicKey.Length() + iOwnPublicKey_ptr.Length() + iCookie_I.Length() |
|
6621 + iCookie_R.Length() + iSAPayloadSize + id_size); |
|
6622 prf_data->Des().Copy(iPeerPublicKey); |
|
6623 prf_data->Des().Append(iOwnPublicKey_ptr); |
|
6624 prf_data->Des().Append(iCookie_I); |
|
6625 prf_data->Des().Append(iCookie_R); |
|
6626 prf_data->Des().Append(iSAPayload,iSAPayloadSize); //stored at the begining |
|
6627 |
|
6628 if ( auth_method != IKE_A_CRACK ) |
|
6629 prf_data->Des().Append(iPeerIdentPayload, iPeerIdentPayloadSize); |
|
6630 } |
|
6631 |
|
6632 DEBUG_LOG(_L("PRF")); |
|
6633 |
|
6634 ComputePRFL(aHash, iSKEYID, prf_data->Des()); |
|
6635 CleanupStack::PopAndDestroy(); //prf_buf |
|
6636 DEBUG_LOG(_L("HASH_I")); |
|
6637 } |
|
6638 |
|
6639 |
|
6640 //Checks the encryption alg is valid |
|
6641 TBool CIkev1Negotiation::CheckEncrAlg(TUint16 aValue) |
|
6642 { |
|
6643 switch (aValue) |
|
6644 { |
|
6645 case DES_CBC: |
|
6646 case DES3_CBC: |
|
6647 case AES_CBC: |
|
6648 return ETrue; |
|
6649 case IDEA_CBC: |
|
6650 case BLOWFISH_CBC: |
|
6651 case RC5_R16_B64_CBC: |
|
6652 case CAST_CBC: |
|
6653 DEBUG_LOG(_L("Not implemented Encr algorithm")); |
|
6654 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6655 } |
|
6656 DEBUG_LOG(_L("Bad Encr algorithm")); |
|
6657 |
|
6658 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6659 } |
|
6660 |
|
6661 |
|
6662 |
|
6663 TBool CIkev1Negotiation::CheckHashAlg(TUint16 aValue) |
|
6664 { |
|
6665 switch (aValue) |
|
6666 { |
|
6667 case HASH_MD5: |
|
6668 case HASH_SHA1: |
|
6669 return ETrue; |
|
6670 case HASH_TIGER: |
|
6671 DEBUG_LOG(_L("Not implemented Hash algorithm")); |
|
6672 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6673 } |
|
6674 DEBUG_LOG(_L("Bad Hash algorithm")); |
|
6675 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6676 |
|
6677 } |
|
6678 |
|
6679 |
|
6680 TBool CIkev1Negotiation::CheckAuthMethod(TUint16 aValue) |
|
6681 { |
|
6682 switch (aValue) |
|
6683 { |
|
6684 case PRE_SHARED: |
|
6685 if (iHostData->iPresharedKey.iKey.Length()==0) //No preshared key defined |
|
6686 { |
|
6687 DEBUG_LOG(_L("Authentication method error (No Preshared key available")); |
|
6688 return EFalse; |
|
6689 } |
|
6690 return ETrue; |
|
6691 case RSA_SIG: |
|
6692 case DSS_SIG: |
|
6693 case IKE_A_CRACK: |
|
6694 return ETrue; |
|
6695 } |
|
6696 DEBUG_LOG(_L("Bad Authentication method")); |
|
6697 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6698 |
|
6699 } |
|
6700 |
|
6701 TBool CIkev1Negotiation::CheckGroupDesc(TUint16 aValue) |
|
6702 { |
|
6703 switch (aValue) |
|
6704 { |
|
6705 case MODP_768: |
|
6706 case MODP_1024: |
|
6707 case MODP_1536: |
|
6708 case MODP_2048: |
|
6709 return ETrue; |
|
6710 case EC2N_155: |
|
6711 case EC2N_185: |
|
6712 break; |
|
6713 } |
|
6714 |
|
6715 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6716 } |
|
6717 |
|
6718 |
|
6719 TBool CIkev1Negotiation::CheckGroupType(TUint16 aValue) |
|
6720 { |
|
6721 switch(aValue) |
|
6722 { |
|
6723 case MODP: |
|
6724 return ETrue; |
|
6725 case ECP: |
|
6726 case EC2N: |
|
6727 break; |
|
6728 } |
|
6729 |
|
6730 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6731 |
|
6732 } |
|
6733 |
|
6734 TBool CIkev1Negotiation::CheckGroupPrime(const TUint8* /* aValue */, TUint16 /* length */) |
|
6735 { |
|
6736 return ETrue; |
|
6737 } |
|
6738 |
|
6739 TBool CIkev1Negotiation::CheckGroupGen(const TUint8* /* aValue */, TUint16 /* length */) |
|
6740 { |
|
6741 return ETrue; |
|
6742 } |
|
6743 |
|
6744 TBool CIkev1Negotiation::CheckGroupCurve(const TUint8* /* aValue */, TUint16 /* length */) |
|
6745 { |
|
6746 return ETrue; |
|
6747 } |
|
6748 |
|
6749 //Used for Phase I and II |
|
6750 TBool CIkev1Negotiation::CheckLifeType(TUint16 aValue) |
|
6751 { |
|
6752 switch(aValue) |
|
6753 { |
|
6754 case SECONDS: |
|
6755 case KBYTES: |
|
6756 return ETrue; |
|
6757 } |
|
6758 return EFalse; |
|
6759 } |
|
6760 |
|
6761 TBool CIkev1Negotiation::CheckLifeDuration(const TUint8* /* aValue */, TUint16 /* length */) |
|
6762 { |
|
6763 return ETrue; |
|
6764 } |
|
6765 |
|
6766 TBool CIkev1Negotiation::CheckPRF(TUint16 aValue) |
|
6767 { |
|
6768 if (aValue!=OAKLEY_PRF_3DES_CBC_MAC) |
|
6769 { |
|
6770 DEBUG_LOG(_L("Bad PRF")); |
|
6771 return EFalse; |
|
6772 } |
|
6773 return ETrue; |
|
6774 } |
|
6775 |
|
6776 TBool CIkev1Negotiation::CheckKeyLength(TUint16 /*aValue*/,TUint8 aID,TUint8 aProtocol) |
|
6777 { |
|
6778 TBool Status = ETrue; |
|
6779 switch (aProtocol) |
|
6780 { |
|
6781 case PROTO_ISAKMP: |
|
6782 if ( aID != AES_CBC ) |
|
6783 { |
|
6784 Status = EFalse; //all other supported algs have fixed size |
|
6785 DEBUG_LOG(_L("Key length specified with fixed ISAKMP encryption algorithm")); |
|
6786 } |
|
6787 break; |
|
6788 case PROTO_IPSEC_AH: |
|
6789 Status = EFalse; //Supported algorithms have fixed key length |
|
6790 DEBUG_LOG(_L("Key length specified with fixed AH integrity algorithm")); |
|
6791 break; |
|
6792 case PROTO_IPSEC_ESP: |
|
6793 if ( aID != ESP_AES_CBC ) |
|
6794 { |
|
6795 Status = EFalse; |
|
6796 DEBUG_LOG(_L("Key length specified with fixed ESP encryption algorithm")); |
|
6797 } |
|
6798 break; |
|
6799 default: //Unsupported SA type |
|
6800 Status = EFalse; //Supported algorithms have fixed key length |
|
6801 break; |
|
6802 } |
|
6803 |
|
6804 return Status; |
|
6805 } |
|
6806 |
|
6807 TBool CIkev1Negotiation::CheckFieldSize(TUint16 /* aValue */) |
|
6808 { |
|
6809 DEBUG_LOG(_L("Field size not supported")); |
|
6810 return EFalse; |
|
6811 } |
|
6812 |
|
6813 TBool CIkev1Negotiation::CheckGroupOrder(const TUint8* /* aValue */, TUint16 /* length */) |
|
6814 { |
|
6815 DEBUG_LOG(_L("Group Order not supported ")); |
|
6816 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6817 } |
|
6818 |
|
6819 //Encapsulation mode |
|
6820 TBool CIkev1Negotiation::CheckEncMode(TUint16 aValue) |
|
6821 { |
|
6822 switch (aValue) |
|
6823 { |
|
6824 case DOI_TUNNEL: |
|
6825 case DOI_TRANSPORT: |
|
6826 return ETrue; |
|
6827 case UDP_ENC_TUNNEL: |
|
6828 case UDP_RFC_ENC_TUNNEL: |
|
6829 // case UDP_ENC_TRANSPORT: |
|
6830 if ( iNAT_D_Flags ) |
|
6831 return ETrue; |
|
6832 break; |
|
6833 } |
|
6834 |
|
6835 DEBUG_LOG(_L("Bad Encapsulation mode")); |
|
6836 return EFalse; |
|
6837 |
|
6838 } |
|
6839 |
|
6840 //defined authentication algorithm types. Other are invalid. |
|
6841 TBool CIkev1Negotiation::CheckAuthAlg(TUint16 aValue) |
|
6842 { |
|
6843 switch (aValue) |
|
6844 { |
|
6845 case DOI_HMAC_MD5: |
|
6846 case DOI_HMAC_SHA: |
|
6847 return ETrue; |
|
6848 case DOI_DES_MAC: |
|
6849 case DOI_KPDK: |
|
6850 DEBUG_LOG(_L("Unimplemented Auhentication Algorithm")); |
|
6851 } |
|
6852 DEBUG_LOG(_L("Bad Auhentication Algorithm")); |
|
6853 return ETrue; // Unknown attribute value NOT a fatal error ! |
|
6854 } |
|
6855 |
|
6856 //By now only X509_CERT_SIG. Tristate error codes: |
|
6857 //KErrNone -> accepted |
|
6858 //KErrNotSupported ignored but no error Notification. |
|
6859 //KErrGeneral: NOT accepted |
|
6860 TInt CIkev1Negotiation::CheckEncodingL(TUint8 aEncoding) |
|
6861 { |
|
6862 switch (aEncoding) |
|
6863 { |
|
6864 case X509_CERT_SIG://X.509 Certificate - Signature |
|
6865 break; |
|
6866 case CRL://Certificate Revocation List (CRL) |
|
6867 DEBUG_LOG(_L("WARNING: CRL ignored because not supported")); |
|
6868 return KErrNotSupported; //No notification, just ignored! |
|
6869 case PKCS://PKCS #7 wrapped X.509 certificate |
|
6870 case PGP://PGP Certificate |
|
6871 case DNS ://DNS Signed Key |
|
6872 case X509_CERT_KE://X.509 Certificate - Key Exchange |
|
6873 case KERBEROS://Kerberos Tokens |
|
6874 case ARL://Authority Revocation List (ARL) |
|
6875 case SPKI://SPKI Certificate |
|
6876 case X509_CERT_ATTR://X.509 Certificate - Attribute |
|
6877 DEBUG_LOG(_L("CERT_TYPE_UNSUPPORTED (not supported CERT type)")); |
|
6878 SendNotifyL(CERT_TYPE_UNSUPPORTED); |
|
6879 return KErrNotSupported; // No notification, just ignored! |
|
6880 |
|
6881 default://Invalid encoding type |
|
6882 DEBUG_LOG(_L("INVALID_CERT_ENCODING (not existent CERT type)")); |
|
6883 SendNotifyL(INVALID_CERT_ENCODING); |
|
6884 return KErrNotSupported; // No notification, just ignored! |
|
6885 |
|
6886 } |
|
6887 |
|
6888 return KErrNone; |
|
6889 } |
|
6890 |
|
6891 |
|
6892 //Provisional (Uses as a seed time, Address and port) |
|
6893 TCookie CIkev1Negotiation::CreateCookieL() const |
|
6894 { |
|
6895 TCookie c; |
|
6896 //Cookie generation is Random no longer uses known data like addr |
|
6897 //or port (wrong?) |
|
6898 c.SetLength(ISAKMP_COOKIE_SIZE); |
|
6899 TRandom::RandomL(c); |
|
6900 return c; |
|
6901 } |
|
6902 |
|
6903 TInt32 CIkev1Negotiation::RandomMessageId() |
|
6904 { |
|
6905 TTime tmp_time; |
|
6906 tmp_time.UniversalTime(); |
|
6907 TInt64 seed = tmp_time.Int64(); |
|
6908 TInt32 rand = Math::Rand(seed); |
|
6909 return rand; |
|
6910 } |
|
6911 |
|
6912 TBool CIkev1Negotiation::CheckCookies(const TCookie& aInit, const TCookie& aResp) |
|
6913 { |
|
6914 TCookie NULL_COOKIE; |
|
6915 NULL_COOKIE.FillZ(ISAKMP_COOKIE_SIZE); |
|
6916 |
|
6917 if ( iCookie_I.Compare(NULL_COOKIE) != 0 && |
|
6918 iCookie_I.Compare(aInit) != 0 ) |
|
6919 { |
|
6920 DEBUG_LOG(_L("Initiator COOKIE incorrect")); |
|
6921 return EFalse; |
|
6922 } |
|
6923 if ( iCookie_R.Compare(NULL_COOKIE) != 0 && |
|
6924 iCookie_R.Compare(aResp) != 0 ) |
|
6925 { |
|
6926 DEBUG_LOG(_L("Responder COOKIE incorrect")); |
|
6927 return EFalse; |
|
6928 } |
|
6929 |
|
6930 return ETrue; |
|
6931 } |
|
6932 |
|
6933 //Checks if the payload value is correct |
|
6934 TBool CIkev1Negotiation::CheckPayloadCode(TUint8 aPayload) |
|
6935 { |
|
6936 switch (aPayload) |
|
6937 { |
|
6938 case ISAKMP_PAYLOAD_NONE: |
|
6939 case ISAKMP_PAYLOAD_SA: |
|
6940 case ISAKMP_PAYLOAD_P: |
|
6941 case ISAKMP_PAYLOAD_T: |
|
6942 case ISAKMP_PAYLOAD_KE: |
|
6943 case ISAKMP_PAYLOAD_ID: |
|
6944 case ISAKMP_PAYLOAD_CERT: |
|
6945 case ISAKMP_PAYLOAD_CR: |
|
6946 case ISAKMP_PAYLOAD_HASH: |
|
6947 case ISAKMP_PAYLOAD_SIG: |
|
6948 case ISAKMP_PAYLOAD_NONCE: |
|
6949 case ISAKMP_PAYLOAD_NOTIF: |
|
6950 case ISAKMP_PAYLOAD_D: |
|
6951 case ISAKMP_PAYLOAD_VID: |
|
6952 case ISAKMP_PAYLOAD_ATTRIBUTES: |
|
6953 case ISAKMP_PAYLOAD_CHRE: |
|
6954 case ISAKMP_INT_NETWORK: |
|
6955 case IETF_NAT_DISCOVERY: |
|
6956 case IETF_RFC_NAT_DISCOVERY: |
|
6957 case IETF_NAT_ORIG_ADDR: |
|
6958 case IETF_RFC_NAT_ORIG_ADDR: |
|
6959 return ETrue; //supported payload type |
|
6960 } |
|
6961 DEBUG_LOG1(_L("INVALID_PAYLOAD_TYPE (%x)"),aPayload); |
|
6962 return EFalse; |
|
6963 |
|
6964 } |
|
6965 |
|
6966 |
|
6967 //Checks if the version (major,minor) is supported |
|
6968 TBool CIkev1Negotiation::CheckVersionL(TUint8 aVersion) |
|
6969 { |
|
6970 if (aVersion >> 4 > MAJOR) |
|
6971 { |
|
6972 DEBUG_LOG(_L("INVALID_MAJOR_VERSION")); |
|
6973 SendNotifyL(INVALID_MAJOR_VERSION); |
|
6974 return EFalse; |
|
6975 } |
|
6976 |
|
6977 if (aVersion & (0x0f) > MINOR) |
|
6978 { |
|
6979 DEBUG_LOG(_L("INVALID_MINOR_VERSION")); |
|
6980 SendNotifyL(INVALID_MINOR_VERSION); |
|
6981 return EFalse; |
|
6982 } |
|
6983 |
|
6984 return ETrue; //version correct |
|
6985 } |
|
6986 |
|
6987 //Checks if the exchange type is valid and the same as in the negotiation |
|
6988 TBool CIkev1Negotiation::CheckExchangeTypeL(TUint8 aType) |
|
6989 { |
|
6990 switch (aType) |
|
6991 { |
|
6992 case ISAKMP_EXCHANGE_ID: //Main |
|
6993 case ISAKMP_EXCHANGE_AGGR: // Agressive |
|
6994 case ISAKMP_EXCHANGE_INFO: |
|
6995 case IKE_QUICK_MODE: |
|
6996 //invalid Exchange Type Not the same being used and not an error notification |
|
6997 if (aType != iExchange) |
|
6998 { |
|
6999 DEBUG_LOG(_L("INVALID_EXCHANGE_TYPE")); //send the informational exchange |
|
7000 SendNotifyL(INVALID_EXCHANGE_TYPE); //send the informational exchange |
|
7001 return EFalse; //invalid Exchange Type |
|
7002 } |
|
7003 break; |
|
7004 case ISAKMP_EXCHANGE_BASE: // Base |
|
7005 case ISAKMP_EXCHANGE_NONE: // Identity Protection (Main mode in IKE) |
|
7006 case ISAKMP_EXCHANGE_AUTH: // Authentication Only |
|
7007 case IKE_NEW_GROUP_MODE: // New Group Mode |
|
7008 DEBUG_LOG(_L("INVALID_EXCHANGE_TYPE")); //send the informational exchange |
|
7009 SendNotifyL(UNSUPPORTED_EXCHANGE_TYPE); //send the informational exchange |
|
7010 return EFalse; |
|
7011 } |
|
7012 |
|
7013 return ETrue; |
|
7014 } |
|
7015 |
|
7016 //Checks the non-relevant bits are 0. Other comprovations are done when needed |
|
7017 TBool CIkev1Negotiation::CheckFlagsL(TUint8 aFlags) |
|
7018 { |
|
7019 if (aFlags >> 3 != 0) |
|
7020 { |
|
7021 DEBUG_LOG(_L("INVALID_FLAGS")); //send the informational exchange |
|
7022 SendNotifyL(INVALID_FLAGS); //send the informational exchange |
|
7023 return EFalse; |
|
7024 } |
|
7025 |
|
7026 return ETrue; |
|
7027 } |
|
7028 |
|
7029 //Checks the Id has a correct value. 0 in Phase I, the correct one in Phase II |
|
7030 TBool CIkev1Negotiation::CheckMessageIdL(TUint32 aId) |
|
7031 { |
|
7032 if (aId != iMessageId) //iMessageId will be 0 during Phase I |
|
7033 { |
|
7034 DEBUG_LOG2(_L("INVALID_MESSAGE_ID %u (neg=%u)"),aId, iMessageId); |
|
7035 SendNotifyL(INVALID_MESSAGE_ID); //send the informational exchange |
|
7036 return EFalse; |
|
7037 } |
|
7038 return ETrue; |
|
7039 } |
|
7040 |
|
7041 //Checks the DOI is valid |
|
7042 TBool CIkev1Negotiation::CheckDOI(TUint32 aDOI) |
|
7043 { |
|
7044 if (aDOI > IPSEC_DOI) //Not IPSEC nor ISAKMP DOI |
|
7045 return EFalse; |
|
7046 |
|
7047 return ETrue; |
|
7048 } |
|
7049 |
|
7050 //Checks the SIT is valid |
|
7051 TBool CIkev1Negotiation::CheckSituationL(TUint32 aSIT) |
|
7052 { |
|
7053 //Secrecy and integrity not yet supported |
|
7054 if ((aSIT & IPSEC_SIT_SECRECY) || (aSIT & IPSEC_SIT_INTEGRITY)) |
|
7055 { |
|
7056 DEBUG_LOG(_L("SITUATION_NOT_SUPPORTED")); //send the informational exchange |
|
7057 SendNotifyL(SITUATION_NOT_SUPPORTED); //send the informational exchange |
|
7058 return EFalse; |
|
7059 } |
|
7060 |
|
7061 return ETrue; |
|
7062 } |
|
7063 //check the generic payload is OK. Correct payload + Reserved==0 |
|
7064 TBool CIkev1Negotiation::CheckGenericPayloadL(const TPayloadISAKMP *aPayload) |
|
7065 { |
|
7066 if (!CheckPayloadCode(aPayload->GetPayload())) |
|
7067 return EFalse; |
|
7068 |
|
7069 if (aPayload->GetReserved() != 0) //Must be always 0 |
|
7070 { |
|
7071 DEBUG_LOG(_L("INVALID RESERVED FIELD")); |
|
7072 SendNotifyL(PAYLOAD_MALFORMED); |
|
7073 return EFalse; |
|
7074 } |
|
7075 |
|
7076 if ((aPayload->GetLength() < MIN_ISAKMP_PAYLOAD_SIZE) || (aPayload->GetLength() > iLengthLeft)) |
|
7077 { |
|
7078 DEBUG_LOG(_L("BAD PAYLOAD SIZE")); |
|
7079 SendNotifyL(PAYLOAD_MALFORMED); |
|
7080 return EFalse; |
|
7081 } |
|
7082 |
|
7083 iLengthLeft -= aPayload->GetLength(); //Updates the length left in the buffer |
|
7084 |
|
7085 return ETrue; |
|
7086 |
|
7087 } |
|
7088 |
|
7089 //checks if protocol supported |
|
7090 TBool CIkev1Negotiation::CheckProtocolL(TUint8 aProtocol) |
|
7091 { |
|
7092 switch (aProtocol) |
|
7093 { |
|
7094 //PHASE_I Protocol |
|
7095 case PROTO_ISAKMP: //Only when establishing own SA?? |
|
7096 if (iPhase != PHASE_I) |
|
7097 { |
|
7098 DEBUG_LOG(_L("INVALID_PROTOCOL_ID (ISAKMP only allowed in Phase I)")); |
|
7099 SendNotifyL(INVALID_PROTOCOL_ID); |
|
7100 return EFalse; |
|
7101 } |
|
7102 return ETrue; |
|
7103 |
|
7104 //PHASE_II Protocols |
|
7105 case PROTO_IPSEC_AH: |
|
7106 case PROTO_IPSEC_ESP: |
|
7107 if (iPhase != PHASE_II) |
|
7108 { |
|
7109 DEBUG_LOG1(_L("INVALID_PROTOCOL_ID (Prot (%u) only allowed in Phase II)"),aProtocol); |
|
7110 SendNotifyL(INVALID_PROTOCOL_ID); |
|
7111 return EFalse; |
|
7112 } |
|
7113 return ETrue; |
|
7114 } |
|
7115 DEBUG_LOG1(_L("INVALID_PROTOCOL_ID (Unknown Protocol (%u))"),aProtocol); |
|
7116 SendNotifyL(INVALID_PROTOCOL_ID); |
|
7117 return EFalse; |
|
7118 } |
|
7119 |
|
7120 TBool CIkev1Negotiation::CheckSPIL(const TProposalISAKMP *aProposal) |
|
7121 { |
|
7122 |
|
7123 TUint size=aProposal->GetSPISize(); |
|
7124 if (iPhase == PHASE_I) |
|
7125 { |
|
7126 if (size > MAX_SPI_SIZE) |
|
7127 { |
|
7128 DEBUG_LOG(_L("INVALID_SPI (Bad Size)")); |
|
7129 SendNotifyL(INVALID_SPI); |
|
7130 return EFalse; |
|
7131 } |
|
7132 } |
|
7133 else //Phase II |
|
7134 { |
|
7135 TUint32 spi = 0; |
|
7136 if (aProposal->GetSPISize() > sizeof(TUint32)) |
|
7137 { |
|
7138 DEBUG_LOG(_L("INVALID_SPI (Too big. Max. is 32 bits)")); |
|
7139 SendNotifyL(INVALID_SPI); |
|
7140 return EFalse; |
|
7141 } |
|
7142 Mem::Copy((TUint8 *)&spi, ((TProposalISAKMP *)aProposal)->SPI(), aProposal->GetSPISize()); |
|
7143 spi = ByteOrder::Swap32(spi); |
|
7144 if (spi < 256) //The first 256 are reserved |
|
7145 { |
|
7146 DEBUG_LOG(_L("INVALID_SPI (spi's < 256 are RESERVED)")); |
|
7147 SendNotifyL(INVALID_SPI); |
|
7148 return EFalse; |
|
7149 } |
|
7150 } |
|
7151 return ETrue; |
|
7152 } |
|
7153 |
|
7154 //Checks for transform payloads. MUST NOT abort processing, just discard the payload |
|
7155 TBool CIkev1Negotiation::CheckTransformID(TUint8 aProtocol,TUint8 aID) |
|
7156 { |
|
7157 switch (aProtocol) |
|
7158 { |
|
7159 case PROTO_ISAKMP: |
|
7160 if (aID != KEY_IKE) |
|
7161 return EFalse; |
|
7162 break; |
|
7163 |
|
7164 case PROTO_IPSEC_AH: |
|
7165 if ( (aID != AH_MD5) && (aID != AH_SHA)) |
|
7166 { |
|
7167 DEBUG_LOG(_L("Unsupported Authentication Algorithm")); |
|
7168 return EFalse; |
|
7169 } |
|
7170 break; |
|
7171 case PROTO_IPSEC_ESP: |
|
7172 switch ( aID ) |
|
7173 { |
|
7174 case ESP_DES_CBC: |
|
7175 case ESP_3DES_CBC: |
|
7176 case ESP_NULL: |
|
7177 case ESP_AES_CBC: |
|
7178 break; |
|
7179 default: |
|
7180 DEBUG_LOG(_L("Unsupported Encryption Algorithm")); |
|
7181 return EFalse; |
|
7182 } |
|
7183 break; |
|
7184 |
|
7185 default: |
|
7186 return EFalse; |
|
7187 } |
|
7188 |
|
7189 return ETrue; |
|
7190 } |
|
7191 |
|
7192 |
|
7193 //Diffie-Hellman key exchange |
|
7194 //The info in iNegotiation MUST be correct |
|
7195 TBool CIkev1Negotiation::ComputeDHPublicValueL() |
|
7196 { |
|
7197 TUint desc; |
|
7198 if (iPhase == PHASE_I) |
|
7199 { |
|
7200 //If aggressive sends the SA and KE at the same time b4 knowing the chosen group. |
|
7201 //The group in the first proposed transform is chosen. Shouldn't be transforms with |
|
7202 //different groups sent. Checked when using the configuration tool? |
|
7203 if ((iExchange == ISAKMP_EXCHANGE_AGGR) && (iRole == INITIATOR)) |
|
7204 desc = iProposal_I.iAttrList->iGroupDesc; |
|
7205 else |
|
7206 desc = iChosenProposal_I.iAttrList->iGroupDesc; |
|
7207 } |
|
7208 else |
|
7209 { |
|
7210 if (iRole == INITIATOR) //We have to use one of the proposals because we don't have the reply yet |
|
7211 //Anyay only one group can be specified for phase II so it's fine |
|
7212 desc = iProposal_IIList->At(0)->iAttrList->At(0)->iGroupDesc; |
|
7213 else //RESPONDER |
|
7214 desc = iChosenProp_IIList->At(0)->iAttrList->At(0)->iGroupDesc; |
|
7215 } |
|
7216 |
|
7217 delete iOwnKeys; //Happens in phase II because we may recalculate the DH value. |
|
7218 iOwnKeys = NULL; |
|
7219 delete iOwnPublicKey; // Happens in phase II because we may recalculate the DH value. |
|
7220 iOwnPublicKey = NULL; |
|
7221 |
|
7222 iOwnKeys = GeneratePubPrivKeysL(desc); |
|
7223 if (!iOwnKeys) |
|
7224 { |
|
7225 DEBUG_LOG(_L("Error generating DH public and private keys")); |
|
7226 return EFalse; |
|
7227 } |
|
7228 iOwnPublicKey = iOwnKeys->GetPubKey(); //save the public key in a buffer to have easy access |
|
7229 iOwnPublicKey_ptr.Set(iOwnPublicKey->Des()); |
|
7230 return ETrue; |
|
7231 } |
|
7232 |
|
7233 |
|
7234 //Initial IV computation |
|
7235 //Pre:Requires correct Public keys alredy stored!!! |
|
7236 TBool CIkev1Negotiation::InitIVL() |
|
7237 { |
|
7238 HBufC8* prf_data = |
|
7239 HBufC8::NewLC(((iOwnPublicKey_ptr.Length() + iPeerPublicKey.Length()) | 0x3) + 1); |
|
7240 |
|
7241 if (iRole == INITIATOR) |
|
7242 { |
|
7243 prf_data->Des().Copy(iOwnPublicKey_ptr); |
|
7244 prf_data->Des().Append(iPeerPublicKey); |
|
7245 |
|
7246 } |
|
7247 else //RESPONDER |
|
7248 { |
|
7249 prf_data->Des().Copy(iPeerPublicKey); |
|
7250 prf_data->Des().Append(iOwnPublicKey_ptr); |
|
7251 } |
|
7252 if (iChosenProposal_I.iAttrList->iHashAlg == HASH_MD5) |
|
7253 MD5HashL(prf_data->Des(), iIV); |
|
7254 else SHA1HashL(prf_data->Des(), iIV); |
|
7255 |
|
7256 if (iChosenProposal_I.iAttrList->iEncrAlg == AES_CBC ) |
|
7257 iIVSize = 16; |
|
7258 else iIVSize = 8; |
|
7259 iIV.SetLength(iIVSize); |
|
7260 DEBUG_LOG(_L("Init")); |
|
7261 |
|
7262 CleanupStack::PopAndDestroy(); //prf_data |
|
7263 |
|
7264 return ETrue; |
|
7265 } |
|
7266 |
|
7267 |
|
7268 |
|
7269 //subsequent IV computations. Like when send notifications or beginning of Phase II |
|
7270 TBool CIkev1Negotiation::ComputeIVL(TDes8 &aIV, TInt32 aMessageId) |
|
7271 { |
|
7272 HBufC8* prf_data = |
|
7273 HBufC8::NewLC(((aIV.Length() + sizeof(aMessageId)) | 0x3) + 1); |
|
7274 |
|
7275 if ((iChosenProposal_I.iAttrList->iEncrAlg != DES3_CBC) && |
|
7276 (iChosenProposal_I.iAttrList->iEncrAlg != AES_CBC) && |
|
7277 (iChosenProposal_I.iAttrList->iEncrAlg != DES_CBC)) |
|
7278 { |
|
7279 return EFalse; |
|
7280 } |
|
7281 //former IV |
|
7282 prf_data->Des().Copy(aIV); |
|
7283 //Message ID |
|
7284 TInt32 id = ByteOrder::Swap32(aMessageId); //Needed to add it |
|
7285 |
|
7286 prf_data->Des().Append((TUint8 *)&id, sizeof(id)); |
|
7287 |
|
7288 DEBUG_LOG(_L("prf")); |
|
7289 if (iChosenProposal_I.iAttrList->iHashAlg == HASH_MD5) |
|
7290 MD5HashL(prf_data->Des(), aIV); |
|
7291 else SHA1HashL(prf_data->Des(), aIV); |
|
7292 |
|
7293 DEBUG_LOG(_L("Computed IV")); |
|
7294 |
|
7295 CleanupStack::PopAndDestroy(); //prf_data |
|
7296 return ETrue; |
|
7297 } |
|
7298 |
|
7299 //Generates all the keying material SKEYID,SKEYID_d,SKEYID_a,SKEYID_e |
|
7300 TBool CIkev1Negotiation::ComputeKeysL() |
|
7301 { |
|
7302 TUint desc; |
|
7303 //If aggressive sends the SA and KE at the same time b4 knowing the chosen group. |
|
7304 //The group in the first proposed transform is chosen. Shouldn't be transforms with |
|
7305 //different groups sent |
|
7306 if ((iExchange == ISAKMP_EXCHANGE_AGGR) && (iRole == INITIATOR)) |
|
7307 desc = iProposal_I.iAttrList->iGroupDesc; |
|
7308 else |
|
7309 desc = iChosenProposal_I.iAttrList->iGroupDesc; |
|
7310 // |
|
7311 //Computes agreed key |
|
7312 // |
|
7313 HBufC8* agreedKey = ComputeAgreedKeyL(desc, iPeerPublicKey, iOwnKeys); //(gxy) |
|
7314 if ( !agreedKey ) { |
|
7315 DEBUG_LOG(_L("DH secret creation failed (ComputeAgreedKeyL)")); |
|
7316 SetErrorStatus( KKmdIkeNegotFailed ); |
|
7317 SendNotifyL(INVALID_KEY_INFORMATION); |
|
7318 return EFalse; |
|
7319 } |
|
7320 CleanupStack::PushL(agreedKey); //agreedKey |
|
7321 |
|
7322 // Use prf and agreed DH-key to generate keying material |
|
7323 HBufC8* prf_data = |
|
7324 HBufC8::NewLC(((iNONCE_I.Length() + iNONCE_R.Length() + 2*ISAKMP_COOKIE_SIZE) | 0x3) + 1); |
|
7325 HBufC8* prf_key = |
|
7326 HBufC8::NewLC(((iNONCE_I.Length() + iNONCE_R.Length() ) | 0x3) + 1); |
|
7327 |
|
7328 DEBUG_LOG(_L("Agreed Key.")); |
|
7329 |
|
7330 switch(iChosenProposal_I.iAttrList->iAuthMethod) |
|
7331 { |
|
7332 case RSA_SIG: |
|
7333 case DSS_SIG: |
|
7334 case IKE_A_CRACK: |
|
7335 //For signatures: |
|
7336 //SKEYID = prf(Ni_b|Nr_b, g^xy) |
|
7337 //key |
|
7338 prf_key->Des().Copy(iNONCE_I); |
|
7339 prf_key->Des().Append(iNONCE_R); |
|
7340 ComputePRFL(iSKEYID, prf_key->Des(), agreedKey->Des()); |
|
7341 break; |
|
7342 case PRE_SHARED: |
|
7343 { |
|
7344 //pre-shared keys: |
|
7345 //SKEYID=prf(pre_shared key, Ni_b | Nr_b); |
|
7346 //data |
|
7347 prf_data->Des().Copy(iNONCE_I.Ptr(),iNONCE_I.Length()); |
|
7348 prf_data->Des().Append(iNONCE_R.Ptr(),iNONCE_R.Length()); |
|
7349 DEBUG_LOG(_L("Pre-shared Key")); |
|
7350 #ifdef _UNICODE |
|
7351 HBufC8 *preshared_key_buf = HBufC8::NewLC(iHostData->iPresharedKey.iKey.Length()); |
|
7352 preshared_key_buf->Des().Copy(iHostData->iPresharedKey.iKey); |
|
7353 TPtrC8 preshared_key_ptr(preshared_key_buf->Des()); |
|
7354 #else |
|
7355 TPtrC8 preshared_key_ptr(iHostData->iPresharedKey.iKey); |
|
7356 #endif |
|
7357 ComputePRFL(iSKEYID, preshared_key_ptr, prf_data->Des()); |
|
7358 #ifdef _UNICODE |
|
7359 CleanupStack::PopAndDestroy(); //presharedkey_buf |
|
7360 #endif |
|
7361 } |
|
7362 break; |
|
7363 default://method not implemented |
|
7364 DEBUG_LOG1(_L("ATTRIBUTES_NOT_SUPPORTED:Auth Method %d not supported "),iChosenProposal_I.iAttrList->iAuthMethod); |
|
7365 SetErrorStatus( KKmdIkeNegotFailed ); |
|
7366 SendNotifyL(ATTRIBUTES_NOT_SUPPORTED); |
|
7367 return EFalse; |
|
7368 } |
|
7369 |
|
7370 CleanupStack::PopAndDestroy(2); //prf_data and prf_key |
|
7371 prf_data = |
|
7372 HBufC8::NewLC(((agreedKey->Length() + iSKEYID.Length() + 2*ISAKMP_COOKIE_SIZE + 4) | 0x3) + 1); |
|
7373 |
|
7374 prf_data->Des().Copy(agreedKey->Des()); |
|
7375 prf_data->Des().Append(iCookie_I); |
|
7376 prf_data->Des().Append(iCookie_R); |
|
7377 prf_data->Des().Append(0); |
|
7378 ComputePRFL(iSKEYID_d, iSKEYID, prf_data->Des()); |
|
7379 |
|
7380 prf_data->Des().Copy(iSKEYID_d); |
|
7381 prf_data->Des().Append(agreedKey->Des()); |
|
7382 prf_data->Des().Append(iCookie_I); |
|
7383 prf_data->Des().Append(iCookie_R); |
|
7384 prf_data->Des().Append(1); |
|
7385 ComputePRFL(iSKEYID_a, iSKEYID, prf_data->Des()); |
|
7386 |
|
7387 prf_data->Des().Copy(iSKEYID_a); |
|
7388 prf_data->Des().Append(agreedKey->Des()); |
|
7389 prf_data->Des().Append(iCookie_I); |
|
7390 prf_data->Des().Append(iCookie_R); |
|
7391 prf_data->Des().Append(2); |
|
7392 ComputePRFL(iSKEYID_e, iSKEYID, prf_data->Des()); |
|
7393 |
|
7394 agreedKey->Des().FillZ(); // Zeroe DH secret g^xy |
|
7395 |
|
7396 //Builds the IV |
|
7397 if (!InitIVL()) |
|
7398 { |
|
7399 DEBUG_LOG(_L("Error Computing IV")); |
|
7400 return EFalse; |
|
7401 } |
|
7402 if (iExchange == ISAKMP_EXCHANGE_AGGR) |
|
7403 { |
|
7404 iLastIV.Copy(iIV); //Saves last IV in Phase 1 |
|
7405 iLastIV.SetLength(iIVSize); |
|
7406 DEBUG_LOG(_L("Last IV Saved!")); |
|
7407 } |
|
7408 |
|
7409 //if key extension required: |
|
7410 TUint8 *key; |
|
7411 TInt key_len=0; |
|
7412 TInt total_key_len = ISAKMPEncrKeyLength((TUint8)iChosenProposal_I.iAttrList->iEncrAlg); |
|
7413 if (iSKEYID_e.Length() < total_key_len) |
|
7414 { |
|
7415 DEBUG_LOG(_L("Extending encrytion key...")); |
|
7416 key = new (ELeave) TUint8[total_key_len*2]; |
|
7417 CleanupStack::PushL(key); |
|
7418 key[0] = 0; |
|
7419 TPtr8 kx0_ptr(key, 1, 1); |
|
7420 TPtr8 kx1_ptr(key, 0, total_key_len * 2); |
|
7421 ComputePRFL(kx1_ptr, iSKEYID_e, kx0_ptr); //K1=prf(SKEYID_e,0) |
|
7422 key_len += kx1_ptr.Length(); |
|
7423 |
|
7424 while (key_len < total_key_len) |
|
7425 { |
|
7426 kx0_ptr.Set(&key[key_len - kx1_ptr.Length()], kx1_ptr.Length(), total_key_len); |
|
7427 kx1_ptr.Set(&key[key_len], 0, total_key_len); |
|
7428 ComputePRFL(kx1_ptr, iSKEYID_e, kx0_ptr); //Kx=prf(SKEYID_e,K<x-1>) |
|
7429 key_len += kx1_ptr.Length(); |
|
7430 } |
|
7431 iSKEYID_e.Copy(key, total_key_len); |
|
7432 CleanupStack::PopAndDestroy(); //key |
|
7433 DEBUG_LOG(_L(" SKEYID_e (EXTENDED)")); |
|
7434 } |
|
7435 else |
|
7436 { |
|
7437 iSKEYID_e.SetLength(total_key_len); |
|
7438 DEBUG_LOG(_L(" SKEYID_e")); |
|
7439 } |
|
7440 |
|
7441 DEBUG_LOG(_L(" Init IV")); |
|
7442 |
|
7443 CleanupStack::PopAndDestroy(2); //prf_data and agreedKey |
|
7444 |
|
7445 return ETrue; |
|
7446 } |
|
7447 |
|
7448 //Computes the IPSEC keys needed for each IPSEC SA |
|
7449 //KEYMAT = prf(SKEY_ID, protocol | SPI | Ni_b | Nr_b) |
|
7450 //if PFS: |
|
7451 //KEYMAT = prf(SKEY_ID, g(qm)^xy | protocol | SPI | Ni_b | Nr_b) |
|
7452 void CIkev1Negotiation::ComputeKeys2L(const CProposal_II *aProp, TInt aKeyLen, TSPINode &aInboundSpiNode, TDes8& aOutboundKey_II, TDes8& aInboundKey_II) |
|
7453 { |
|
7454 DEBUG_LOG(_L("Computing PHASE II keys ")); |
|
7455 |
|
7456 aOutboundKey_II.SetLength(0); |
|
7457 aInboundKey_II.SetLength(0); |
|
7458 DEBUG_LOG(_L("Total Computed Key Length=")); |
|
7459 DEBUG_LOG_NUM(aKeyLen); |
|
7460 |
|
7461 HBufC8* agreedKey = NULL; //g(qm)^xy |
|
7462 TInt prf_len = iSKEYID_d.Length() + iNONCE_I.Length() + iNONCE_R.Length() + 8; // 8 for protocol and SPI |
|
7463 |
|
7464 if (iPFS) |
|
7465 { |
|
7466 agreedKey = ComputeAgreedKeyL(iChosenProp_IIList->At(0)->iAttrList->At(0)->iGroupDesc, iPeerPublicKey, iOwnKeys); |
|
7467 if ( !agreedKey ) |
|
7468 User::Leave(KErrGeneral); |
|
7469 CleanupStack::PushL(agreedKey); |
|
7470 prf_len += agreedKey->Length(); |
|
7471 DEBUG_LOG(_L(" Agreed Key")); |
|
7472 } |
|
7473 #ifdef _DEBUG |
|
7474 else DEBUG_LOG(_L("(NO PFS)")); |
|
7475 #endif // _DEBUG |
|
7476 |
|
7477 DEBUG_LOG(_L("Protocol:")); |
|
7478 DEBUG_LOG_NUM(aProp->iProtocol); |
|
7479 |
|
7480 TUint32 in_spi = aInboundSpiNode.iSPI; //inbound spi in Network Order |
|
7481 DEBUG_LOG(_L("InSPI:")); |
|
7482 DEBUG_LOG_NUM(ByteOrder::Swap32(in_spi)); |
|
7483 TUint32 out_spi; |
|
7484 Mem::Copy((TUint8 *)&out_spi, aProp->iSPI.Ptr(), aProp->iSPI.Length()); |
|
7485 DEBUG_LOG1(_L("OutSPI: %x"), out_spi); |
|
7486 //Inbound and outbound calculations only differ in the SPI |
|
7487 //If the key is not long enough we need to extend it |
|
7488 TPtr8 key_ptr((TUint8 *)aOutboundKey_II.Ptr() + aOutboundKey_II.Length(), 0, aOutboundKey_II.MaxLength()); |
|
7489 |
|
7490 HBufC8* prf_data = HBufC8::NewLC((prf_len | 0x3) + 1); |
|
7491 |
|
7492 while ((aOutboundKey_II.Length() * 8) < aKeyLen) //include the key extension algorithm |
|
7493 { |
|
7494 prf_data->Des().Copy(key_ptr); |
|
7495 if (agreedKey)//Only used if PFS |
|
7496 { |
|
7497 prf_data->Des().Append(agreedKey->Des()); |
|
7498 } |
|
7499 prf_data->Des().Append(&aProp->iProtocol, sizeof(aProp->iProtocol)); |
|
7500 prf_data->Des().Append(aProp->iSPI.Ptr(),aProp->iSPI.Length()); |
|
7501 prf_data->Des().Append(iNONCE_I); |
|
7502 prf_data->Des().Append(iNONCE_R); |
|
7503 key_ptr.Set((TUint8 *)aOutboundKey_II.Ptr() + aOutboundKey_II.Length(), 0, aOutboundKey_II.MaxLength() - aOutboundKey_II.Length()); |
|
7504 ComputePRFL(key_ptr, iSKEYID_d, prf_data->Des()); |
|
7505 aOutboundKey_II.SetLength(aOutboundKey_II.Length() + key_ptr.Length()); |
|
7506 } |
|
7507 |
|
7508 key_ptr.Set((TUint8 *)aInboundKey_II.Ptr() + aInboundKey_II.Length(), 0, aOutboundKey_II.MaxLength()); |
|
7509 while ((aInboundKey_II.Length() * 8) < aKeyLen) //include the key extension algorithm |
|
7510 { |
|
7511 prf_data->Des().Copy(key_ptr); |
|
7512 if (agreedKey)//Only used if PFS |
|
7513 { |
|
7514 prf_data->Des().Append(agreedKey->Des()); |
|
7515 } |
|
7516 prf_data->Des().Append(&aProp->iProtocol,sizeof(aProp->iProtocol)); |
|
7517 prf_data->Des().Append((TUint8 *)&in_spi, sizeof(TUint32)); |
|
7518 prf_data->Des().Append(iNONCE_I); |
|
7519 prf_data->Des().Append(iNONCE_R); |
|
7520 |
|
7521 key_ptr.Set((TUint8 *)aInboundKey_II.Ptr() + aInboundKey_II.Length(), 0, aInboundKey_II.MaxLength() - aInboundKey_II.Length()); |
|
7522 ComputePRFL(key_ptr, iSKEYID_d, prf_data->Des()); |
|
7523 aInboundKey_II.SetLength(aInboundKey_II.Length() + key_ptr.Length()); |
|
7524 } |
|
7525 |
|
7526 if ( agreedKey ) |
|
7527 CleanupStack::PopAndDestroy(2); //prf_data and agreedKey |
|
7528 else CleanupStack::PopAndDestroy(); //prf_data |
|
7529 |
|
7530 } |
|
7531 |
|
7532 |
|
7533 /* This function is called by oakley module to do pseudo random computation for |
|
7534 given data */ |
|
7535 //IMPORTANT: If some func added or modified check MAX_PRF_LENGTH is correct in ike.h |
|
7536 |
|
7537 void CIkev1Negotiation::ComputePRFL(TDes8 &prf_output, const TDesC8 &prf_key, const TDesC8 &prf_data) |
|
7538 { |
|
7539 // All actions taken are moved into the crypto module IKE_CRYPTO.CPP |
|
7540 |
|
7541 if ( iChosenProposal_I.iAttrList->iPRF == OAKLEY_PRF_3DES_CBC_MAC) |
|
7542 { |
|
7543 DEBUG_LOG(_L("PRF (3DES_CBC_MAC)")); |
|
7544 Hmac3DesCbcL(prf_data, prf_output, prf_key); |
|
7545 } |
|
7546 else |
|
7547 { |
|
7548 // Use HMAC version of the negotiated hash function as default PRF |
|
7549 if ( iChosenProposal_I.iAttrList->iHashAlg == HASH_MD5 ) { |
|
7550 DEBUG_LOG(_L("PRF (MD5)")); |
|
7551 MD5HmacL(prf_data, prf_output, prf_key); |
|
7552 } |
|
7553 else { |
|
7554 if ( iChosenProposal_I.iAttrList->iHashAlg == HASH_SHA1 ) { |
|
7555 DEBUG_LOG(_L("PRF (SHA1)")); |
|
7556 SHA1HmacL(prf_data, prf_output, prf_key); |
|
7557 } |
|
7558 } |
|
7559 } |
|
7560 |
|
7561 } |
|
7562 |
|
7563 |
|
7564 //NOTE: Must be called after ProcessCertificate() !!! |
|
7565 TBool CIkev1Negotiation::CertifyRemoteIdentityL(const TIdentISAKMP *aIdPayload) |
|
7566 { |
|
7567 TBool Status = EFalse; |
|
7568 TInt id_len = aIdPayload->IDDataLen(); |
|
7569 |
|
7570 if ( id_len && iPkiService && iPeerX509Cert ) |
|
7571 { |
|
7572 TPtrC8 IdData((TUint8 *)aIdPayload->IDData(), id_len); |
|
7573 |
|
7574 // Leave is trapped and handled here because the event log is easily accessible |
|
7575 // and in the upper layers it would not be possible to identify the |
|
7576 // cause of the error based on the generic leave code. |
|
7577 TRAPD(err, Status = IkePkiUtils::CertifyIdentityL(iPeerX509Cert, IdData, (TInt)aIdPayload->GetIDType())); |
|
7578 |
|
7579 if( KErrNotSupported == err ) |
|
7580 { |
|
7581 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
7582 R_VPN_MSG_CERT_ERROR, |
|
7583 KErrNotSupported, |
|
7584 iPluginSession->VpnIapId(), |
|
7585 &iRemoteAddr ); |
|
7586 } |
|
7587 |
|
7588 #ifdef _DEBUG |
|
7589 if (Status) |
|
7590 DEBUG_LOG(_L("Remote identity has been certified")); |
|
7591 #endif // _DEBUG |
|
7592 } |
|
7593 |
|
7594 return Status; |
|
7595 } |
|
7596 |
|
7597 |
|
7598 //Digests aHash with the key in aCert and compares it to the stored value aSig |
|
7599 //Needs to be check after the Signature payload has been processed |
|
7600 TBool CIkev1Negotiation::VerifySignatureL(CX509Certificate *aCert,TUint8 *aHash, TInt aHashLength,TUint8 *aSig, TUint aSigLength) |
|
7601 { |
|
7602 |
|
7603 TBool ret = EFalse; |
|
7604 if ( iPkiService ) |
|
7605 { |
|
7606 TPtrC8 Signature(aSig, aSigLength); |
|
7607 TPtrC8 RefHash(aHash, aHashLength); |
|
7608 ret = IkePkiUtils::VerifyIkev1SignatureL(Signature, RefHash, *aCert); |
|
7609 } |
|
7610 |
|
7611 return ret; |
|
7612 |
|
7613 |
|
7614 } |
|
7615 |
|
7616 //NOTE!!! The func sets iFinished to TRUE always so after detecting an error the communication finishes. |
|
7617 //If it doesn't have to iFinished should be set outside the function. |
|
7618 void CIkev1Negotiation::SendNotifyL(TUint16 aError) |
|
7619 { |
|
7620 SetFinished(); //Ends the negotiation (error condition detected) If CONNECTED also should end |
|
7621 |
|
7622 #ifdef _DEBUG |
|
7623 TBuf<60> buf; |
|
7624 DEBUG_LOG(_L("SendNotifyL(), Reason: ")); |
|
7625 buf.Append(TextNotifyType(aError)); |
|
7626 DEBUG_LOG(buf); |
|
7627 #endif // _DEBUG |
|
7628 TUint8 protocol = PROTO_ISAKMP; |
|
7629 TUint8 tmp_exchange = iExchange; |
|
7630 TUint32 tmp_msg_id = iMessageId; |
|
7631 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
7632 //If configured to send notification payloads for errors |
|
7633 if (iHostData->iNotify) |
|
7634 { |
|
7635 iExchange = ISAKMP_EXCHANGE_INFO; |
|
7636 iMessageId = RandomMessageId(); |
|
7637 msg->IsakmpInit(this); |
|
7638 |
|
7639 //HASH Payload only if payload protected with encyption |
|
7640 if (iFlags & ISAKMP_HDR_EFLAG) |
|
7641 msg->IsakmpHashL(); |
|
7642 |
|
7643 if (iPhase == PHASE_I) |
|
7644 protocol = iChosenProposal_I.iProtocol; |
|
7645 else |
|
7646 { |
|
7647 if (iChosenProp_IIList) //May be the begining of PHASE_II when still not decided |
|
7648 protocol = iChosenProp_IIList->At(0)->iProtocol; |
|
7649 } |
|
7650 msg->IsakmpNotification(aError, protocol); |
|
7651 |
|
7652 if (iFlags & ISAKMP_HDR_EFLAG) |
|
7653 { |
|
7654 msg->IsakmpHashContL(); |
|
7655 } |
|
7656 |
|
7657 iExchange = tmp_exchange; |
|
7658 iMessageId = tmp_msg_id; |
|
7659 |
|
7660 SendL(*msg); |
|
7661 |
|
7662 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
7663 R_VPN_MSG_SENT_ERROR_RESPONSE, |
|
7664 aError, |
|
7665 iPluginSession->VpnIapId(), |
|
7666 &iRemoteAddr ); |
|
7667 } |
|
7668 |
|
7669 } |
|
7670 |
|
7671 |
|
7672 //Hash function key length (in bytes) |
|
7673 TInt CIkev1Negotiation::HashLength() |
|
7674 { |
|
7675 if (iChosenProposal_I.iAttrList->iPRF == OAKLEY_PRF_3DES_CBC_MAC) |
|
7676 return 24; |
|
7677 |
|
7678 //If no PRF hash alg used instead. |
|
7679 if (iChosenProposal_I.iAttrList->iPRF==0) |
|
7680 { |
|
7681 if (iChosenProposal_I.iAttrList->iHashAlg==HASH_MD5) |
|
7682 return HMAC_MD5_SIZE/8; //16 bytes |
|
7683 //return MD5_DIGEST_LENGTH; |
|
7684 else if (iChosenProposal_I.iAttrList->iHashAlg==HASH_SHA1) |
|
7685 return HMAC_SHA1_SIZE/8; |
|
7686 //return SHA_DIGEST_LENGTH; |
|
7687 } |
|
7688 |
|
7689 return 0; |
|
7690 } |
|
7691 |
|
7692 |
|
7693 //Could be done using directly iEncrAlg from the chosen transform (in bytes) |
|
7694 TUint32 CIkev1Negotiation::ISAKMPEncrKeyLength(TUint8 aAlgId) const |
|
7695 { |
|
7696 TUint32 KeyLth = 0; |
|
7697 switch (aAlgId) { |
|
7698 case DES_CBC: |
|
7699 KeyLth = 8; |
|
7700 break; |
|
7701 case DES3_CBC: |
|
7702 KeyLth = 24; |
|
7703 break; |
|
7704 case AES_CBC: |
|
7705 if ( iChosenProposal_I.iAttrList->iKeyLength ) |
|
7706 KeyLth = (TUint32)(iChosenProposal_I.iAttrList->iKeyLength/8); |
|
7707 else KeyLth = 16; // default |
|
7708 break; |
|
7709 default: |
|
7710 break; |
|
7711 } |
|
7712 |
|
7713 return KeyLth; |
|
7714 } |
|
7715 |
|
7716 TIkev1IsakmpStream* CIkev1Negotiation::SaveIkeMsgBfr(TIkev1IsakmpStream* aMsg) |
|
7717 { |
|
7718 delete iSavedIkeMsgBfr; |
|
7719 iSavedIkeMsgBfr = aMsg; |
|
7720 return aMsg; |
|
7721 } |
|
7722 |
|
7723 //Returns the key length (in bits) of an algorithm for iAuth (TAttrib_II) field when protocol is AH |
|
7724 TUint32 CIkev1Negotiation::HMAC_KeyLength(TUint8 aId) const |
|
7725 { |
|
7726 if (aId == SADB_AALG_MD5HMAC) |
|
7727 return (HMAC_MD5_SIZE); |
|
7728 else if (aId == SADB_AALG_SHA1HMAC) |
|
7729 return (HMAC_SHA1_SIZE); |
|
7730 |
|
7731 return (0); // Error |
|
7732 } |
|
7733 |
|
7734 //Exchange Type |
|
7735 TPtrC CIkev1Negotiation::TextNotifyType(TUint16 aNotif) |
|
7736 { |
|
7737 #ifndef _DEBUG |
|
7738 (void)aNotif; |
|
7739 #endif |
|
7740 |
|
7741 #ifdef _DEBUG |
|
7742 //TBuf<35> err; |
|
7743 switch(aNotif) |
|
7744 { |
|
7745 case INVALID_PAYLOAD_TYPE: |
|
7746 return _L("INVALID_PAYLOAD_TYPE"); |
|
7747 case DOI_NOT_SUPPORTED: |
|
7748 return _L("DOI_NOT_SUPPORTED"); |
|
7749 case SITUATION_NOT_SUPPORTED: |
|
7750 return _L("SITUATION_NOT_SUPPORTED"); |
|
7751 case INVALID_COOKIE: |
|
7752 return _L("INVALID_COOKIE"); |
|
7753 case INVALID_MAJOR_VERSION: |
|
7754 return _L("INVALID_MAJOR_VERSION"); |
|
7755 case INVALID_MINOR_VERSION: |
|
7756 return _L("INVALID_MINOR_VERSION"); |
|
7757 case INVALID_EXCHANGE_TYPE: |
|
7758 return _L("INVALID_EXCHANGE_TYPE"); |
|
7759 case INVALID_FLAGS: |
|
7760 return _L("INVALID_FLAGS"); |
|
7761 case INVALID_MESSAGE_ID: |
|
7762 return _L("INVALID_MESSAGE_ID"); |
|
7763 case INVALID_PROTOCOL_ID: |
|
7764 return _L("INVALID_PROTOCOL_ID"); |
|
7765 case INVALID_SPI: |
|
7766 return _L("INVALID_SPI"); |
|
7767 case INVALID_TRANSFORM_ID: |
|
7768 return _L("INVALID_TRANSFORM_ID"); |
|
7769 case ATTRIBUTES_NOT_SUPPORTED: |
|
7770 return _L("ATTRIBUTES_NOT_SUPPORTED"); |
|
7771 case NO_PROPOSAL_CHOSEN: |
|
7772 return _L("NO_PROPOSAL_CHOSEN"); |
|
7773 case BAD_PROPOSAL_SYNTAX: |
|
7774 return _L("BAD_PROPOSAL_SYNTAX"); |
|
7775 case PAYLOAD_MALFORMED: |
|
7776 return _L("PAYLOAD_MALFORMED"); |
|
7777 case INVALID_KEY_INFORMATION: |
|
7778 return _L("INVALID_KEY_INFORMATION"); |
|
7779 case INVALID_ID_INFORMATION: |
|
7780 return _L("INVALID_ID_INFORMATION"); |
|
7781 case INVALID_CERT_ENCODING: |
|
7782 return _L("INVALID_CERT_ENCODING"); |
|
7783 case INVALID_CERTIFICATE: |
|
7784 return _L("INVALID_CERTIFICATE"); |
|
7785 case CERT_TYPE_UNSUPPORTED: |
|
7786 return _L("CERT_TYPE_UNSUPPORTED"); |
|
7787 case INVALID_CERT_AUTHORITY: |
|
7788 return _L("INVALID_CERT_AUTHORITY"); |
|
7789 case INVALID_HASH_INFORMATION: |
|
7790 return _L("INVALID_HASH_INFORMATION"); |
|
7791 case AUTHENTICATION_FAILED: |
|
7792 return _L("AUTHENTICATION_FAILED"); |
|
7793 case INVALID_SIGNATURE: |
|
7794 return _L("INVALID_SIGNATURE"); |
|
7795 case ADDRESS_NOTIFICATION: |
|
7796 return _L("ADDRESS_NOTIFICATION"); |
|
7797 case NOTIFY_SA_LIFETIME: |
|
7798 return _L("NOTIFY_SA_LIFETIME"); |
|
7799 case CERTIFICATE_UNAVAILABLE: |
|
7800 return _L("CERTIFICATE_UNAVAILABLE"); |
|
7801 case UNSUPPORTED_EXCHANGE_TYPE: |
|
7802 return _L("UNSUPPORTED_EXCHANGE_TYPE"); |
|
7803 case UNEQUAL_PAYLOAD_LENGTHS: |
|
7804 return _L("UNEQUAL_PAYLOAD_LENGTHS"); |
|
7805 case CONNECTED: |
|
7806 return _L("CONNECTED"); |
|
7807 case DOI_RESPONDER_LIFETIME: |
|
7808 return _L("RESPONDER_LIFETIME"); |
|
7809 case DOI_REPLAY_STATUS: |
|
7810 return _L("REPLAY_STATUS"); |
|
7811 case DOI_INITIAL_CONTACT: |
|
7812 return _L("INITIAL_CONTACT"); |
|
7813 } |
|
7814 return _L("Unknown "); |
|
7815 #else |
|
7816 return NULL; |
|
7817 #endif |
|
7818 } |
|
7819 |
|
7820 |
|
7821 void CIkev1Negotiation::TextPayload(TDes &aBuf, TUint8 aPayload) |
|
7822 { |
|
7823 #ifndef _DEBUG |
|
7824 (void)aBuf; |
|
7825 (void)aPayload; |
|
7826 #endif |
|
7827 |
|
7828 #ifdef _DEBUG |
|
7829 switch(aPayload) |
|
7830 { |
|
7831 case ISAKMP_PAYLOAD_NONE:// (Terminator) |
|
7832 aBuf = _L("ISAKMP_PAYLOAD_NONE"); |
|
7833 break; |
|
7834 case ISAKMP_PAYLOAD_SA:// Security Association |
|
7835 aBuf = _L("ISAKMP_PAYLOAD_SA"); |
|
7836 break; |
|
7837 case ISAKMP_PAYLOAD_P:// Proposal |
|
7838 aBuf = _L("ISAKMP_PAYLOAD_P"); |
|
7839 break; |
|
7840 case ISAKMP_PAYLOAD_T:// Transform |
|
7841 aBuf = _L("ISAKMP_PAYLOAD_T"); |
|
7842 break; |
|
7843 case ISAKMP_PAYLOAD_KE:// Key Exchange |
|
7844 aBuf = _L("ISAKMP_PAYLOAD_KE"); |
|
7845 break; |
|
7846 case ISAKMP_PAYLOAD_ID:// Identification |
|
7847 aBuf = _L("ISAKMP_PAYLOAD_ID"); |
|
7848 break; |
|
7849 case ISAKMP_PAYLOAD_CERT:// Certificate |
|
7850 aBuf = _L("ISAKMP_PAYLOAD_CERT"); |
|
7851 break; |
|
7852 case ISAKMP_PAYLOAD_CR:// Certificate Request |
|
7853 aBuf = _L("ISAKMP_PAYLOAD_CR"); |
|
7854 break; |
|
7855 case ISAKMP_PAYLOAD_HASH:// Hash |
|
7856 aBuf = _L("ISAKMP_PAYLOAD_HASH"); |
|
7857 break; |
|
7858 case ISAKMP_PAYLOAD_SIG:// Signature |
|
7859 aBuf = _L("ISAKMP_PAYLOAD_SIG"); |
|
7860 break; |
|
7861 case ISAKMP_PAYLOAD_NONCE:// Nonce |
|
7862 aBuf = _L("ISAKMP_PAYLOAD_NONCE"); |
|
7863 break; |
|
7864 case ISAKMP_PAYLOAD_NOTIF:// Notification |
|
7865 aBuf = _L("ISAKMP_PAYLOAD_NOTIF"); |
|
7866 break; |
|
7867 case ISAKMP_PAYLOAD_D:// Delete |
|
7868 aBuf = _L("ISAKMP_PAYLOAD_D"); |
|
7869 break; |
|
7870 case ISAKMP_PAYLOAD_VID:// Vendor ID |
|
7871 aBuf = _L("ISAKMP_PAYLOAD_VID"); |
|
7872 break; |
|
7873 case ISAKMP_PAYLOAD_PRIVATE:// Private use (up to 255) |
|
7874 aBuf = _L("ISAKMP_PAYLOAD_PRIVATE"); |
|
7875 break; |
|
7876 default: |
|
7877 aBuf.Format(_L("Unknown (%d) "),aPayload); |
|
7878 } |
|
7879 #endif |
|
7880 } |
|
7881 |
|
7882 //Sends the built message through the socket |
|
7883 void CIkev1Negotiation::SendL(TIkev1IsakmpStream &aMsg) |
|
7884 { |
|
7885 if (aMsg.iError) |
|
7886 { |
|
7887 DEBUG_LOG(_L("Error Building message")); |
|
7888 return; |
|
7889 } |
|
7890 TBuf8<IKEV1_MAX_IV_SIZE> tmp_IV; |
|
7891 |
|
7892 ThdrISAKMP *hdr = (ThdrISAKMP *)aMsg.iBuf.Ptr(); |
|
7893 hdr->SetLength(aMsg.iBuf.Length()); |
|
7894 DEBUG_LOG(_L("Sending (clear)...")); |
|
7895 |
|
7896 TBool FloatedPort = EFalse; |
|
7897 if ( iNAT_D_Flags & (REMOTE_END_NAT + LOCAL_END_NAT) ) |
|
7898 FloatedPort = ETrue; |
|
7899 |
|
7900 #ifdef _DEBUG |
|
7901 const TPtrC8 ikeMsgPtr( aMsg.iBuf.Ptr(), aMsg.iBuf.Length() ); |
|
7902 TInetAddr localAddr; |
|
7903 iPluginSession->GetLocalAddress( localAddr ); |
|
7904 TInt port = ( FloatedPort ? IkeSocket::KIkePort4500 : IkeSocket::KIkePort500 ); |
|
7905 localAddr.SetPort( port ); |
|
7906 TRACE_MSG_IKEV1( ikeMsgPtr, localAddr, iLastRemoteAddr ); |
|
7907 #endif // _DEBUG |
|
7908 |
|
7909 TPtr8 lastMsg(iLastMsg->Des()); |
|
7910 |
|
7911 if (hdr->GetFlags() & ISAKMP_HDR_EFLAG) |
|
7912 { |
|
7913 DEBUG_LOG(_L("Encrypting...")); |
|
7914 |
|
7915 if (hdr->GetExchange()==ISAKMP_EXCHANGE_INFO || hdr->GetExchange()==ISAKMP_EXCHANGE_TRANSACT ) |
|
7916 { |
|
7917 if ( hdr->GetExchange()==ISAKMP_EXCHANGE_TRANSACT ) |
|
7918 { |
|
7919 // |
|
7920 // Get current IV via CTransNegotiation object linked into |
|
7921 // CIkev1Negotiation |
|
7922 // |
|
7923 if ( !iTransactionNeg || |
|
7924 !iTransactionNeg->GetIV(hdr->GetMessageId(), tmp_IV) ) |
|
7925 { |
|
7926 DEBUG_LOG(_L("Send error ! Cannot get Transaction IV !")); |
|
7927 return; |
|
7928 } |
|
7929 DEBUG_LOG(_L("Transaction IV")); |
|
7930 EncryptL(aMsg.iBuf, lastMsg, tmp_IV, iSKEYID_e, iChosenProposal_I.iAttrList->iEncrAlg); |
|
7931 iTransactionNeg->SetIV(hdr->GetMessageId(), tmp_IV); |
|
7932 } |
|
7933 else |
|
7934 { |
|
7935 if (iLastIV.Length() != 0) |
|
7936 tmp_IV.Copy(iLastIV); |
|
7937 else //iLastIV not yet computed so current iIV is used |
|
7938 tmp_IV.Copy(iIV); |
|
7939 ComputeIVL(tmp_IV, hdr->GetMessageId()); |
|
7940 DEBUG_LOG(_L("Notif IV")); |
|
7941 EncryptL(aMsg.iBuf, lastMsg, tmp_IV, iSKEYID_e, iChosenProposal_I.iAttrList->iEncrAlg); |
|
7942 } |
|
7943 |
|
7944 } |
|
7945 else //Normal exchange MAIN, AGGR or QUICK |
|
7946 { |
|
7947 DEBUG_LOG(_L("IV")); |
|
7948 EncryptL(aMsg.iBuf, lastMsg, iIV, iSKEYID_e, iChosenProposal_I.iAttrList->iEncrAlg); |
|
7949 DEBUG_LOG(_L("New IV (dec)")); |
|
7950 //Saves last iIV in Phase 1 |
|
7951 if (((iStage==6) && (iExchange == ISAKMP_EXCHANGE_ID)) || |
|
7952 ((iStage==3) && (iExchange == ISAKMP_EXCHANGE_AGGR))) |
|
7953 { |
|
7954 iLastIV.Copy(iIV); |
|
7955 DEBUG_LOG(_L("Last IV Saved!")); |
|
7956 } |
|
7957 } |
|
7958 |
|
7959 DEBUG_LOG(_L("Sending ...")); |
|
7960 DEBUG_LOG1(_L("EncrLen = %d"), lastMsg.Length()); |
|
7961 } |
|
7962 else |
|
7963 { |
|
7964 lastMsg.Copy(aMsg.iBuf); |
|
7965 } |
|
7966 |
|
7967 hdr = (ThdrISAKMP *)lastMsg.Ptr(); |
|
7968 hdr->SetLength(lastMsg.Length()); //Set the total length!!! |
|
7969 |
|
7970 if (hdr->GetExchange() == ISAKMP_EXCHANGE_INFO) |
|
7971 { |
|
7972 SendAndSaveIkeMsgL(lastMsg, iLastRemoteAddr, FloatedPort); //No timers! |
|
7973 } |
|
7974 else //Normal msg. |
|
7975 { |
|
7976 iTimer->Cancel(); //Cancel previous timer because reply received & processed |
|
7977 DEBUG_LOG(_L("Timer Cancelled!")); |
|
7978 iRetryNum = 0; |
|
7979 SendAndSaveIkeMsgL(lastMsg, iLastRemoteAddr, FloatedPort); |
|
7980 iTimer->IssueRequest(MAX_RETRANS_TIMER * 1000000); // 1000000 = 1 second |
|
7981 } |
|
7982 |
|
7983 } |
|
7984 |
|
7985 |
|
7986 void CIkev1Negotiation::ReSendL() |
|
7987 { |
|
7988 //Will resend a packet in the interval (MAX_RETRANS_TIMER/2 , MAX_RETRANS_TIMER) |
|
7989 if ( iRetryNum < MAX_RETRANS_COUNT ) |
|
7990 { |
|
7991 DEBUG_LOG2(_L("---------- Phase %d - Stage %d ----------"),iPhase, iStage - 1); |
|
7992 DEBUG_LOG1(_L("ReSending(%d)..."), iRetryNum); |
|
7993 TBool FloatedPort = EFalse; |
|
7994 if ( iNAT_D_Flags & (REMOTE_END_NAT + LOCAL_END_NAT) ) |
|
7995 FloatedPort = ETrue; |
|
7996 TPtr8 lastMsg(iLastMsg->Des()); |
|
7997 iPluginSession->SendIkeMsgL(lastMsg, iLastRemoteAddr, FloatedPort); |
|
7998 //next retransmission between MAX_RETRANS_TIMER/2 and MAX_RETRANS_TIMER seconds |
|
7999 TTime tmp_time; |
|
8000 TReal secs = 0; |
|
8001 tmp_time.UniversalTime(); |
|
8002 TInt64 seed = tmp_time.Int64(); |
|
8003 TInt rand = Math::Rand(seed); |
|
8004 TInt err = Math::Round(secs, rand / (KMaxTInt / MAX_RETRANS_TIMER/2), 0); |
|
8005 secs = Math::Round(secs, secs + MAX_RETRANS_TIMER/2, 0); |
|
8006 if ((!secs) || (err != KErrNone)) |
|
8007 secs = MAX_RETRANS_TIMER/2; |
|
8008 iTimer->IssueRequest((TInt)secs * 1000000); // 1000000 = 1 second |
|
8009 iRetryNum++; |
|
8010 } |
|
8011 else |
|
8012 { |
|
8013 SendDeleteL(PROTO_ISAKMP); |
|
8014 if ( iPhase == PHASE_I ) |
|
8015 { |
|
8016 DEBUG_LOG(_L("Max num retries reached!!!")); |
|
8017 } |
|
8018 else |
|
8019 { |
|
8020 DEBUG_LOG(_L("Quick mode failed, Max num retries reached!!!")); |
|
8021 } |
|
8022 |
|
8023 if ( iPhase == PHASE_I && |
|
8024 iPluginSession->FindIkev1SA() == NULL ) |
|
8025 { |
|
8026 // Set error status in Phase 1, if there are no IKE SAs. |
|
8027 if ( GetNotifyStatus() ) |
|
8028 SetErrorStatus(KKmdIkeNoProposalErr); |
|
8029 else SetErrorStatus(KKmdIkeNoResponseErr); |
|
8030 } |
|
8031 |
|
8032 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
8033 R_VPN_MSG_VPN_GW_NO_RESP, |
|
8034 ErrorStatus(), |
|
8035 iPluginSession->VpnIapId(), |
|
8036 &iRemoteAddr ); |
|
8037 iPluginSession->DeleteNegotiation( this ); |
|
8038 } |
|
8039 } |
|
8040 |
|
8041 void CIkev1Negotiation::SendDeleteL(TUint8 aProtocol, TUint32 aIpsecSPI) |
|
8042 { |
|
8043 TIkev1IsakmpStream* msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
8044 |
|
8045 TBuf8<MAX_SPI_SIZE> SPI; |
|
8046 |
|
8047 DEBUG_LOG(_L("Sending Delete payload...")); |
|
8048 |
|
8049 //Creates a DUMMY negotiation with the info to send the packet |
|
8050 TUint8 tmp_exchange = iExchange; |
|
8051 iExchange=ISAKMP_EXCHANGE_INFO; //Set the exchange type as info |
|
8052 |
|
8053 msg->IsakmpInit(this); |
|
8054 |
|
8055 //HASH Payload only if payload protected with encyption |
|
8056 if (iFlags & ISAKMP_HDR_EFLAG) |
|
8057 msg->IsakmpHashL(); |
|
8058 |
|
8059 if (aProtocol == PROTO_ISAKMP) //ISAKMP SPI are the cookies |
|
8060 { |
|
8061 SPI.Copy(iCookie_I); |
|
8062 SPI.Append(iCookie_R); |
|
8063 } |
|
8064 else //IPSECSPI |
|
8065 { |
|
8066 SPI.Copy((TUint8 *)&aIpsecSPI, sizeof(TUint32)); |
|
8067 } |
|
8068 msg->IsakmpDelete(SPI, aProtocol); |
|
8069 |
|
8070 if (iFlags & ISAKMP_HDR_EFLAG) |
|
8071 { |
|
8072 msg->IsakmpHashContL(); |
|
8073 } |
|
8074 DEBUG_LOG(_L("Sending Delete Payload...")); |
|
8075 SendL(*msg); |
|
8076 |
|
8077 iExchange = tmp_exchange; |
|
8078 } |
|
8079 |
|
8080 void CIkev1Negotiation::CheckSendResponderLifetime(TIkev1IsakmpStream &aMsg) |
|
8081 { |
|
8082 TInt count = iChosenProp_IIList->Count(); |
|
8083 CProposal_II *prop; |
|
8084 TChosenAttrib_II *attr_II; |
|
8085 TSPINode inboundspi_node; |
|
8086 TInt j; |
|
8087 for (j = 0 ; j < count; j++) //Check all the chosen proposals (Probably one) |
|
8088 { |
|
8089 prop = iChosenProp_IIList->At(j); |
|
8090 inboundspi_node = iInboundSPIList->At(j); |
|
8091 attr_II = (TChosenAttrib_II *)prop->iAttrList->At(0); //only 1 transform is chosen no matter how many there are |
|
8092 |
|
8093 if ((attr_II->iReducedLifeSecs.Length() != 0) || (attr_II->iReducedLifeKBytes.Length() != 0)) //Any lifetime to update |
|
8094 aMsg.IsakmpResponderLifetime(prop->iProtocol, inboundspi_node.iSPI, attr_II->iReducedLifeSecs, attr_II->iReducedLifeKBytes); |
|
8095 |
|
8096 } |
|
8097 } |
|
8098 |
|
8099 |
|
8100 /**-------------------------------------------------------------------- |
|
8101 * |
|
8102 * The following methods are used to implement the Dead Peer Detection |
|
8103 * protocol defined in <draft-ietf-ipsec-dpd-04.txt> |
|
8104 * When timeout expires the R-U-THERE notify message is transmitted |
|
8105 * if there has not been any activity during the last timeout |
|
8106 * |
|
8107 *--------------------------------------------------------------------*/ |
|
8108 void CIkev1Negotiation::DpdNotifyMessageReceivedL(TIkev1SAData* aSa, TUint16 aMsgType, TUint32 aSequence) |
|
8109 { |
|
8110 |
|
8111 if ( aMsgType == DPD_R_U_THERE ) |
|
8112 { |
|
8113 // |
|
8114 // -- Assure that sequence number in notify data is what expected |
|
8115 // -- If ok, transmit a R-U-THERE-ACK |
|
8116 // |
|
8117 DEBUG_LOG(_L("DPD R-U-THERE Notify received")); |
|
8118 if ( (aSa->iExpectedDPDSequence == aSequence) || (aSa->iExpectedDPDSequence == 0) ) |
|
8119 { |
|
8120 aSa->iExpectedDPDSequence = GetNextSequence(aSequence); |
|
8121 DEBUG_LOG(_L("Sending DPD R-U-THERE_ACK notify")); |
|
8122 SendDpdNotifyMessageL(DPD_R_U_THERE_ACK, aSequence); |
|
8123 iPluginSession->UpdateIkev1SAL(aSa->iSAId, EFalse, aSa); |
|
8124 } |
|
8125 #ifdef _DEBUG |
|
8126 else DEBUG_LOG(_L("Wrong sequence number in DPD notify message")); |
|
8127 #endif // _DEBUG |
|
8128 } |
|
8129 else if ( aMsgType == DPD_R_U_THERE_ACK ) |
|
8130 { |
|
8131 // |
|
8132 // -- Assure that sequence number in notify data is corresponds |
|
8133 // current pending sequence |
|
8134 // |
|
8135 DEBUG_LOG(_L("DPD R-U-THERE-ACK Notify received")); |
|
8136 if ( aSa->iPendingDPDSequence == aSequence ) |
|
8137 { |
|
8138 aSa->iPendingDPDSequence = 0; |
|
8139 aSa->iDPDRetry = 0; |
|
8140 iPluginSession->UpdateIkev1SAL(aSa->iSAId, EFalse, aSa); |
|
8141 } |
|
8142 #ifdef _DEBUG |
|
8143 else DEBUG_LOG(_L("Wrong sequence number in DPD notify ack message")); |
|
8144 #endif // _DEBUG |
|
8145 } |
|
8146 } |
|
8147 |
|
8148 void CIkev1Negotiation::SendKeepAliveMsgL(TIkev1SAData* aSa) |
|
8149 { |
|
8150 if ( aSa->iDPDRetry > KMaxDpdRetryCount ) |
|
8151 { |
|
8152 // |
|
8153 // DPD Retry count exhausted, current IKE SA in interpreted to |
|
8154 // be closed |
|
8155 // |
|
8156 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogError, |
|
8157 R_VPN_MSG_VPN_GW_NO_RESP, |
|
8158 KKmdIkeNoResponseErr, |
|
8159 iPluginSession->VpnIapId(), |
|
8160 &iRemoteAddr ); |
|
8161 |
|
8162 iPluginSession->DeleteIpsecSAs(aSa->iSAId); |
|
8163 iPluginSession->UpdateIkev1SAL(aSa->iSAId, ETrue); |
|
8164 } |
|
8165 else |
|
8166 { |
|
8167 // |
|
8168 // Send DPD R-U-THERE notify message |
|
8169 // |
|
8170 if ( aSa->iPendingDPDSequence == 0 ) |
|
8171 { |
|
8172 aSa->iPendingDPDSequence = aSa->iDPDSequence; |
|
8173 aSa->iDPDSequence = GetNextSequence(aSa->iDPDSequence); |
|
8174 } |
|
8175 else |
|
8176 { |
|
8177 aSa->iDPDRetry ++; |
|
8178 } |
|
8179 DEBUG_LOG(_L("Sending DPD R-U-THERE notify")); |
|
8180 SendDpdNotifyMessageL(DPD_R_U_THERE, aSa->iPendingDPDSequence); |
|
8181 } |
|
8182 SetFinished(); |
|
8183 } |
|
8184 |
|
8185 MKmdEventLoggerIf& CIkev1Negotiation::EventLogger() |
|
8186 { |
|
8187 return iPluginSession->EventLogger(); |
|
8188 } |
|
8189 |
|
8190 void CIkev1Negotiation::IpsecSaSpiRetrieved(TUint32 aSpiRequestId, |
|
8191 TInt aStatus, |
|
8192 TUint32 aSpi) |
|
8193 { |
|
8194 DEBUG_LOG3(_L("IPsec SA SPI retrieved, seq=%d, SPI=%d, status=%d"), |
|
8195 aSpiRequestId, aSpi, aStatus); |
|
8196 if ( aStatus == KErrNone ) |
|
8197 { |
|
8198 TRAP( aStatus, ReceiveSPIL( aSpi, aSpiRequestId ) ); |
|
8199 } |
|
8200 else |
|
8201 { |
|
8202 iPluginSession->HandleError( aStatus ); |
|
8203 } |
|
8204 } |
|
8205 |
|
8206 TBool CIkev1Negotiation::IsRekeyingIkeSa() |
|
8207 { |
|
8208 return ( iSARekeyInfo != NULL ); |
|
8209 } |
|
8210 |
|
8211 void CIkev1Negotiation::PreparePhase2L(const TPfkeyMessage &aReq) |
|
8212 { |
|
8213 DEBUG_LOG(_L("Prepare for Phase II")); |
|
8214 GetAcquireDataL(aReq); |
|
8215 iPhaseIIAfterIkeSaRekey = ETrue; |
|
8216 } |
|
8217 |
|
8218 TUint32 CIkev1Negotiation::GetNextSequence(TUint32 aSequence) |
|
8219 { |
|
8220 aSequence ++; |
|
8221 if ( aSequence == 0 ) |
|
8222 aSequence = 1; |
|
8223 return aSequence; |
|
8224 } |
|
8225 |
|
8226 void CIkev1Negotiation::SendDpdNotifyMessageL(TUint16 aMsgType, TUint32 aSequence) |
|
8227 { |
|
8228 iExchange = ISAKMP_EXCHANGE_INFO; |
|
8229 iMessageId = RandomMessageId(); |
|
8230 TIkev1IsakmpStream* Msg = SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
8231 Msg->IsakmpInit(this); |
|
8232 Msg->IsakmpHashL(); |
|
8233 TUint32 NotifData = ByteOrder::Swap32(aSequence); |
|
8234 Msg->IsakmpNotification(aMsgType, PROTO_ISAKMP, (TUint8*)&NotifData, sizeof(NotifData)); |
|
8235 Msg->IsakmpHashContL(); |
|
8236 SendL(*Msg); |
|
8237 } |
|
8238 |
|
8239 TInt CIkev1Negotiation::ErrorStatus() |
|
8240 { |
|
8241 TInt ret( KErrNone ); |
|
8242 if ( iPluginSession ) |
|
8243 { |
|
8244 ret = iPluginSession->ErrorStatus(); |
|
8245 } |
|
8246 return ret; |
|
8247 } |
|
8248 |
|
8249 void CIkev1Negotiation::SetErrorStatus(TInt aStatus) |
|
8250 { |
|
8251 SetFinished(); |
|
8252 iPluginSession->SetErrorStatus(aStatus); |
|
8253 } |
|
8254 |
|
8255 void CIkev1Negotiation::SendAndSaveIkeMsgL( const TDesC8& aIkeMsg, |
|
8256 TInetAddr& aDestAddr, |
|
8257 TBool aUseNatPort ) |
|
8258 { |
|
8259 iPluginSession->SendIkeMsgL( aIkeMsg, aDestAddr, aUseNatPort ); |
|
8260 SaveLastMsgL(); |
|
8261 } |
|
8262 |
|
8263 |
|
8264 TBool CIkev1Negotiation::IsRetransmit(TLastIKEMsg& aRef) |
|
8265 { |
|
8266 TBool isRetransmit(EFalse); |
|
8267 if (iLastIKEMsgInfo.IsUninitialized()) |
|
8268 { |
|
8269 TIkev1SAData* ikev1SAData = iPluginSession->FindIkev1SAData(iSAId); |
|
8270 if (ikev1SAData && ikev1SAData->iLastIKEMsgInfo.IsReTransmit(aRef)) |
|
8271 { |
|
8272 isRetransmit = ETrue; |
|
8273 } |
|
8274 } |
|
8275 else |
|
8276 { |
|
8277 isRetransmit = iLastIKEMsgInfo.IsReTransmit(aRef); |
|
8278 } |
|
8279 return isRetransmit; |
|
8280 } |
|
8281 |
|
8282 void CIkev1Negotiation::SaveRetransmitInfo(TLastIKEMsg& aRef) |
|
8283 { |
|
8284 aRef.Store(iLastIKEMsgInfo); |
|
8285 TIkev1SAData* ikev1SAData = iPluginSession->FindIkev1SAData(iSAId); |
|
8286 if (ikev1SAData != NULL) |
|
8287 { |
|
8288 aRef.Store(ikev1SAData->iLastIKEMsgInfo); |
|
8289 } |
|
8290 } |
|
8291 |
|
8292 void CIkev1Negotiation::SaveLastMsgL() |
|
8293 { |
|
8294 if ( iLastMsg != NULL ) |
|
8295 { |
|
8296 TIkev1SAData* ikev1SAData = iPluginSession->FindIkev1SAData(iSAId); |
|
8297 if ( ikev1SAData != NULL ) |
|
8298 { |
|
8299 delete ikev1SAData->iLastMsg; |
|
8300 ikev1SAData->iLastMsg = iLastMsg->AllocL(); |
|
8301 } |
|
8302 } |
|
8303 } |
|
8304 |
|
8305 |
|
8306 |