|
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 Crack authentication |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "ikev1crack.h" |
|
20 #include "ikedebug.h" |
|
21 #include "ikev1pluginsession.h" |
|
22 #include "ikev1timeout.h" |
|
23 #include "ikev1negotiation.h" |
|
24 #include "ikev1payload.h" |
|
25 #include "ikev1isakmpstream.h" |
|
26 #include "ikepolparser.h" |
|
27 |
|
28 |
|
29 // |
|
30 // Class that implements IKE CRACK authentication method |
|
31 // |
|
32 |
|
33 CIKECRACKNegotiation::CIKECRACKNegotiation( MIkeDebug& aDebug ) |
|
34 : iState( 0 ), |
|
35 iDebug( aDebug ) |
|
36 { |
|
37 } |
|
38 |
|
39 CIKECRACKNegotiation::~CIKECRACKNegotiation() |
|
40 { |
|
41 /*------------------------------------------------------------------- |
|
42 * |
|
43 * Delete pending dialog - and dialog info objects |
|
44 * |
|
45 *-------------------------------------------------------------------*/ |
|
46 #ifdef _DEBUG |
|
47 if ( iNegotiation ) DEBUG_LOG(_L("CRACK object deleted")); |
|
48 #endif // _DEBUG |
|
49 |
|
50 delete iDialog; |
|
51 delete iDialogInfo; |
|
52 delete iUserName; |
|
53 delete iDomain; |
|
54 } |
|
55 |
|
56 |
|
57 TInt CIKECRACKNegotiation::ConstructL(TInt aLAMType, CIkev1Negotiation *aNegotiation, const TDesC &aDomain) |
|
58 { |
|
59 /*------------------------------------------------------------------------ |
|
60 * |
|
61 * This method initializes actions to get authencation information from user. |
|
62 * The authentication information is requested from user with LAM type |
|
63 * specific dialog. |
|
64 * |
|
65 *------------------------------------------------------------------------*/ |
|
66 if ( aLAMType != CRACK_PASSWORD || !aNegotiation ) |
|
67 { |
|
68 #ifdef _DEBUG |
|
69 if ( aNegotiation ) |
|
70 DEBUG_LOG(_L("CRACK object construction failed, unsupported LAM type")); |
|
71 #endif // _DEBUG |
|
72 return CRACK_FAILED; |
|
73 } |
|
74 iNegotiation = aNegotiation; |
|
75 iPluginSession = aNegotiation->iPluginSession; |
|
76 iLAMType = aLAMType; |
|
77 if ( aDomain.Length() > 0 ) |
|
78 { |
|
79 // |
|
80 // Allocate buffer for domain name attribute |
|
81 // (to convey Group Name information) |
|
82 // |
|
83 iDomain = HBufC8::NewL(aDomain.Length()); |
|
84 iDomain->Des().Copy(aDomain); |
|
85 DEBUG_LOG(_L("CRACK Domain attribute saved")); |
|
86 } |
|
87 |
|
88 DEBUG_LOG(_L("CRACK authentication started")); |
|
89 |
|
90 return GetDataL(NULL); /* No challenge data */ |
|
91 } |
|
92 |
|
93 |
|
94 TInt CIKECRACKNegotiation::ExecuteCRACKMsgL(const ThdrISAKMP &aHdr) |
|
95 { |
|
96 /*--------------------------------------------------------------------------- |
|
97 * |
|
98 * IKE message received during CRACK authentication phase: |
|
99 * <--- HDRx*, CHRE or <--- HDRx*, NOTIFICATION |
|
100 * Process CHRE/Notification payload in IKE message |
|
101 * |
|
102 *--------------------------------------------------------------------------*/ |
|
103 if ( ( iState & WAITING_PEER_RSP ) == 0 ) { |
|
104 /*-------------------------------------------------------- |
|
105 * Not waiting a response from gateway, ignore packet |
|
106 *--------------------------------------------------------*/ |
|
107 return CRACK_IGNORE_MSG; |
|
108 } |
|
109 iState &= ~WAITING_PEER_RSP; |
|
110 |
|
111 CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *iNegotiation, iDebug); |
|
112 if (!payload) |
|
113 { |
|
114 return CRACK_FAILED; |
|
115 } |
|
116 CleanupStack::PushL(payload); |
|
117 TInt status; |
|
118 |
|
119 if ( payload->iChre ) |
|
120 { |
|
121 TInt i = 0; |
|
122 while ( i < payload->iNotifs->Count() ) |
|
123 { |
|
124 /*---------------------------------------------------------------------- |
|
125 * |
|
126 * A Notification payload received in IKE main/aggressive/information |
|
127 * exchange. If this is not a INITIAL-CONTACT notification it is |
|
128 * interpreted as a CRACK authentication failure indicated by the gateway. |
|
129 * |
|
130 *----------------------------------------------------------------------*/ |
|
131 if ( !iNegotiation->ProcessNotificationL(payload->iNotifs->At(i)) ) { |
|
132 CleanupStack::PopAndDestroy(); //payload |
|
133 return CrackAuthenticationFailedL(payload->iNotifs->At(i)); |
|
134 } |
|
135 i ++; |
|
136 } |
|
137 |
|
138 if ( payload->iIaddr ) { |
|
139 /*---------------------------------------------------------------------- |
|
140 * |
|
141 * An Internal Address payload received in IKE main/aggressive exchange. |
|
142 * |
|
143 *----------------------------------------------------------------------*/ |
|
144 iNegotiation->ProcessIntAddrL(payload->iIaddr); |
|
145 } |
|
146 /*---------------------------------------------------------------------- |
|
147 * |
|
148 * Process attributes in CHRE payload |
|
149 * |
|
150 *----------------------------------------------------------------------*/ |
|
151 status = ProcessCHREAttibutesL(payload->iChre); |
|
152 } |
|
153 else { |
|
154 status = CRACK_CONTINUE; |
|
155 DEBUG_LOG(_L("No CHRE payload in IKE CRACK message")); |
|
156 } |
|
157 |
|
158 CleanupStack::PopAndDestroy(); //payload |
|
159 return status; |
|
160 |
|
161 } |
|
162 |
|
163 TInt CIKECRACKNegotiation::ProcessUserResponseL(CAuthDialogInfo *aDialogInfo ) |
|
164 { |
|
165 /*--------------------------------------------------------------------------- |
|
166 * |
|
167 * A response received from client user (through asynchronous dialog) |
|
168 * Build an IKE message with an appropriate CHRE payload attributes |
|
169 * and send message it to gateway. |
|
170 * |
|
171 *-------------------------------------------------------------------------*/ |
|
172 if ( iState & WAITING_USER_RSP ) |
|
173 { |
|
174 iState &= ~(WAITING_USER_RSP + SECURID_NEXT_PIN_MODE); |
|
175 delete iDialog; /* delete dialog object */ |
|
176 iDialog = NULL; |
|
177 |
|
178 TUint16 attr1 = 0; |
|
179 TUint16 attr2 = 0; |
|
180 TUint16 attr3 = 0; |
|
181 HBufC8* bfr1 = NULL; |
|
182 HBufC8* bfr2 = NULL; |
|
183 HBufC8* bfr3 = NULL; |
|
184 |
|
185 /*-------------------------------------------------------- |
|
186 * |
|
187 * Store attributes according to LAM type |
|
188 * |
|
189 *--------------------------------------------------------*/ |
|
190 switch ( iLAMType ) |
|
191 { |
|
192 case CRACK_PASSWORD: |
|
193 /*-------------------------------------------------- |
|
194 * Possible attributes: User name, Secret, Domain |
|
195 *-------------------------------------------------*/ |
|
196 attr1 = CRACK_T_USERNAME; |
|
197 bfr1 = aDialogInfo->iUsername; |
|
198 attr2 = CRACK_T_SECRET; |
|
199 bfr2 = aDialogInfo->iSecret; |
|
200 bfr3 = iDomain; |
|
201 if ( bfr3 ) |
|
202 attr3 = CRACK_T_DOMAIN; |
|
203 break; |
|
204 |
|
205 default: |
|
206 break; |
|
207 } |
|
208 |
|
209 SendCredentialsL(attr1, attr2, attr3, bfr1, bfr2, bfr3); |
|
210 } |
|
211 |
|
212 delete aDialogInfo; /* release dialog info object */ |
|
213 iDialogInfo = NULL; /* reset dialog info pointer */ |
|
214 |
|
215 return CRACK_CONTINUE; |
|
216 } |
|
217 |
|
218 TInt CIKECRACKNegotiation::GetDataL(HBufC8* aChallenge) |
|
219 { |
|
220 if ( iLAMType == CRACK_PASSWORD && |
|
221 iNegotiation->iHostData->iCRACKLAMUserName && |
|
222 iNegotiation->iHostData->iCRACKLAMPassword) |
|
223 { |
|
224 return GetUNPWDFromPolicyL(); |
|
225 } |
|
226 else |
|
227 { |
|
228 return GetDatafromUserL(aChallenge); |
|
229 } |
|
230 } |
|
231 |
|
232 TInt CIKECRACKNegotiation::GetDatafromUserL(HBufC8* /*aChallenge*/) |
|
233 { |
|
234 TInt status = CRACK_CONTINUE; |
|
235 /*--------------------------------------------------------------- |
|
236 * |
|
237 * Get CRACK authentication information from user according to |
|
238 * current LAM type |
|
239 * |
|
240 *---------------------------------------------------------------*/ |
|
241 iDialog = CIkev1Dialog::NewL( iPluginSession, iPluginSession->DialogAnchor(), iDebug ); |
|
242 iDialogInfo = new(ELeave) CAuthDialogInfo(iPluginSession, DIALOG_INFO_ID, iNegotiation->SAId(), 0); |
|
243 iNegotiation->iTimer->Cancel(); //Cancel previous timer because reply received & processed |
|
244 DEBUG_LOG(_L("Timer Cancelled!")); |
|
245 iNegotiation->iRetryNum = 0; |
|
246 |
|
247 switch ( iLAMType ) |
|
248 { |
|
249 case CRACK_PASSWORD: |
|
250 /*-------------------------------------------------- |
|
251 * Request User name and password (domain) from user |
|
252 *-------------------------------------------------*/ |
|
253 iDialog->GetAsyncUNPWDialogL(iDialogInfo, (MIkeDialogComplete*)this); |
|
254 break; |
|
255 |
|
256 default: |
|
257 status = CRACK_FAILED; |
|
258 break; |
|
259 } |
|
260 |
|
261 iState |= WAITING_USER_RSP + SHOW_ERROR_DIALOG; |
|
262 |
|
263 return status; |
|
264 } |
|
265 |
|
266 TInt CIKECRACKNegotiation::GetUNPWDFromPolicyL() |
|
267 { |
|
268 ASSERT(iLAMType == CRACK_PASSWORD); |
|
269 |
|
270 iNegotiation->iTimer->Cancel(); //Cancel previous timer because reply received & processed |
|
271 DEBUG_LOG(_L("Timer Cancelled!")); |
|
272 iNegotiation->iRetryNum = 0; |
|
273 |
|
274 /*-------------------------------------------------------- |
|
275 * |
|
276 * Store attributes: User name, Secret, Domain |
|
277 * |
|
278 *--------------------------------------------------------*/ |
|
279 |
|
280 TUint16 attr1 = CRACK_T_USERNAME; |
|
281 HBufC8* bfr1 = iNegotiation->iHostData->iCRACKLAMUserName->GetAsciiDataL(); |
|
282 CleanupStack::PushL(bfr1); |
|
283 TUint16 attr2 = CRACK_T_SECRET; |
|
284 HBufC8* bfr2 = iNegotiation->iHostData->iCRACKLAMPassword->GetAsciiDataL(); |
|
285 CleanupStack::PushL(bfr2); |
|
286 HBufC8* bfr3 = iDomain; |
|
287 TUint16 attr3 = 0; |
|
288 if ( bfr3 ) |
|
289 { |
|
290 attr3 = CRACK_T_DOMAIN; |
|
291 } |
|
292 |
|
293 SendCredentialsL(attr1, attr2, attr3, bfr1, bfr2, bfr3); |
|
294 |
|
295 CleanupStack::PopAndDestroy(2); // bfr1, bfr2 |
|
296 |
|
297 return CRACK_CONTINUE; |
|
298 } |
|
299 |
|
300 void CIKECRACKNegotiation::SendCredentialsL(TUint16 aAttr1, TUint16 aAttr2, TUint16 aAttr3, |
|
301 HBufC8* aBfr1, HBufC8* aBfr2, HBufC8* aBfr3) |
|
302 { |
|
303 TIkev1IsakmpStream* msg = iNegotiation->SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) ); |
|
304 msg->IsakmpInit(iNegotiation); |
|
305 msg->IsakmpOwnIdentL(); /* Dummy ID for Crypto Cluster */ |
|
306 msg->IsakmpChre((TUint16)iLAMType, aAttr1, aBfr1, aAttr2, aBfr2, aAttr3, aBfr3); |
|
307 |
|
308 if ( iNegotiation->iFamiliarPeer && iNegotiation->iHostData->iUseInternalAddr ) |
|
309 { |
|
310 // |
|
311 // Request Internal address from gateway |
|
312 // |
|
313 msg->IsakmpIntnet(0); /* null IPV4 address as parameter */ |
|
314 } |
|
315 |
|
316 if ( iNegotiation->iHostData->iInitialContact ) |
|
317 { |
|
318 // |
|
319 // Initial contact notification added as the last payload into IKE message |
|
320 // |
|
321 if (!iPluginSession->FindIkev1SADataWithAddr(iNegotiation->iRemoteAddr)) //Only sent if no ISAKMP SA established |
|
322 { |
|
323 DEBUG_LOG(_L("Constructing INITIAL-CONTACT")); |
|
324 msg->IsakmpNotification(DOI_INITIAL_CONTACT, PROTO_ISAKMP); |
|
325 } |
|
326 } |
|
327 |
|
328 iNegotiation->SendL(*msg); |
|
329 |
|
330 // |
|
331 // Take a copy of user name buffer in dialog info. This user name |
|
332 // is cached into user name file if current CRACK negotiation is |
|
333 // succeeded |
|
334 // |
|
335 if ( aBfr1 ) |
|
336 { |
|
337 delete iUserName; // Delete old user name buffer for sure |
|
338 iUserName = NULL; |
|
339 iUserName = HBufC8::New(aBfr1->Length() + 16); // 16 bytes space for padding |
|
340 if ( iUserName ) |
|
341 { |
|
342 iUserName->Des().Copy(aBfr1->Des()); |
|
343 } |
|
344 } |
|
345 |
|
346 iState |= WAITING_PEER_RSP; |
|
347 iMsgCount++; |
|
348 } |
|
349 |
|
350 TInt CIKECRACKNegotiation::ProcessCHREAttibutesL(const TCHREISAKMP *aCHRE) |
|
351 { |
|
352 /*--------------------------------------------------------------------------- |
|
353 * |
|
354 * CHRE payload received from gateway. Process attributes in payload |
|
355 * according to current LAM type. |
|
356 * Assure first that LAM type in payload corresponds configured LAM type |
|
357 * in CRACK object |
|
358 * |
|
359 *--------------------------------------------------------------------------*/ |
|
360 TInt length = (TInt)aCHRE->GetLength(); |
|
361 if ( STATIC_CAST(TUint, length) < sizeof(TCHREISAKMP) ) { |
|
362 return CRACK_FAILED; |
|
363 } |
|
364 |
|
365 length -= sizeof(TCHREISAKMP); /* Attribute data lengt in payload */ |
|
366 if ( (aCHRE->GetCHREReserved() != 0) || (aCHRE->GetLAMtype() != iLAMType )) { |
|
367 return CRACK_FAILED; |
|
368 } |
|
369 |
|
370 TDataISAKMP *attr = aCHRE->CHREAttrib(); |
|
371 HBufC8 *challenge = NULL; |
|
372 TInt status = CRACK_CONTINUE; |
|
373 TBool get_user_data = EFalse; |
|
374 TUint16 fin; |
|
375 |
|
376 while ( length > 0 ) { |
|
377 |
|
378 length = length - attr->Size(); |
|
379 if ( length < 0 ) { |
|
380 DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Length mismatch in the attibutes)")); |
|
381 return CRACK_FAILED; |
|
382 } |
|
383 switch ( attr->Type() ) { |
|
384 |
|
385 case CRACK_T_MESSAGE: |
|
386 if ( attr->IsBasic() ) { /* MUST be variable */ |
|
387 return CRACK_FAILED; |
|
388 } |
|
389 break; |
|
390 |
|
391 case CRACK_T_FIN: |
|
392 if ( !attr->IsBasic() ) { /* MUST be basic */ |
|
393 return CRACK_FAILED; |
|
394 } |
|
395 fin = attr->Value(); |
|
396 if ( fin == CRACK_FIN_SUCCESS ) { |
|
397 DEBUG_LOG(_L("CRACK authentication OK")); |
|
398 status = CRACK_SUCCESS; |
|
399 if ( iUserName ) { |
|
400 // |
|
401 // Cache user name into user name file |
|
402 // |
|
403 CIkev1Dialog* Dialog = CIkev1Dialog::NewL(iPluginSession, iPluginSession->DialogAnchor(), iDebug); |
|
404 CleanupStack::PushL(Dialog); |
|
405 TInt err(KErrNone); |
|
406 TRAP(err, Dialog->StoreUserNameL(iUserName->Des())); |
|
407 #ifdef _DEBUG |
|
408 if (err == KErrNone) |
|
409 DEBUG_LOG(_L("User Name caching succeeded")); |
|
410 DEBUG_LOG(_L("User Name caching failed")); |
|
411 #endif |
|
412 CleanupStack::PopAndDestroy(); |
|
413 } |
|
414 } |
|
415 else { |
|
416 if ( fin == CRACK_FIN_MORE ) { |
|
417 iState |= SECURID_NEXT_PIN_MODE; |
|
418 DEBUG_LOG(_L("CRACK SecurID Next pin mode entered")); |
|
419 get_user_data = ETrue; /* SecurID "Next code2 */ |
|
420 } |
|
421 else { |
|
422 status = CRACK_FAILED; /* Illegal FIN value */ |
|
423 } |
|
424 } |
|
425 break; |
|
426 |
|
427 default: |
|
428 DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED (Invalid attribute in CHRE)")); |
|
429 return CRACK_FAILED; |
|
430 } |
|
431 |
|
432 attr = attr->Next(); |
|
433 } |
|
434 |
|
435 if ( get_user_data ) { |
|
436 /*--------------------------------------------------- |
|
437 * Get information from user |
|
438 *---------------------------------------------------*/ |
|
439 status = GetDatafromUserL(challenge); |
|
440 if ( challenge ) |
|
441 CleanupStack::PopAndDestroy(); /* delete challenge */ |
|
442 } |
|
443 |
|
444 return status; |
|
445 |
|
446 } |
|
447 |
|
448 |
|
449 TInt CIKECRACKNegotiation::CrackAuthenticationFailedL(const TNotificationISAKMP *aNotifPayload) |
|
450 { |
|
451 (void)aNotifPayload; |
|
452 /*--------------------------------------------------------------------------- |
|
453 * |
|
454 * The gateway has sent a Notification payload which indicates that CRACK |
|
455 * authentication is failed. |
|
456 * Display proper error dialog and return CRACK_FAILED status |
|
457 * |
|
458 *--------------------------------------------------------------------------*/ |
|
459 iNegotiation->iTimer->Cancel(); //Cancel timer because authentication failed |
|
460 DEBUG_LOG(_L("CRACK authentication failed!")); |
|
461 |
|
462 if ( (iState & (CRACK_AUTHENTICATED + WAITING_USER_RSP + SHOW_ERROR_DIALOG)) == |
|
463 SHOW_ERROR_DIALOG ) { |
|
464 // Dialog object shall be delete in Dialog->RunL when dialog completed |
|
465 CIkev1Dialog* Dialog = CIkev1Dialog::NewL(iPluginSession, iPluginSession->DialogAnchor(), iDebug); |
|
466 Dialog->ShowErrorDialogL(TVpnNoteDialog::EKmdAuthenticationFailed, NULL, NULL); |
|
467 iState &= ~SHOW_ERROR_DIALOG; |
|
468 } |
|
469 |
|
470 return CRACK_FAILED; |
|
471 |
|
472 } |
|
473 |
|
474 // |
|
475 // The implementation for class MIkeDialogComplete virtual function |
|
476 // |
|
477 TInt CIKECRACKNegotiation::DialogCompleteL(CIkev1Dialog* /*aDialog*/, TAny* aUserInfo, |
|
478 HBufC8* aUsername, HBufC8* aSecret, HBufC8* aDomain) |
|
479 { |
|
480 /*--------------------------------------------------------------------------- |
|
481 * |
|
482 * A response received from client user (through asynchronous dialog) |
|
483 * This method is introduced as a TUserCallback for CGetIKEPassword dialog |
|
484 * object is created. When the dialog is completed this callback function |
|
485 * is called to deliver Credentials data for CHRE payload attributes. |
|
486 * Store credential buffers to CAuthDialogInfo object and call engine |
|
487 * entry |
|
488 * |
|
489 *-------------------------------------------------------------------------*/ |
|
490 TUint32 obj_id = 1; |
|
491 CAuthDialogInfo* info = (CAuthDialogInfo*)aUserInfo; |
|
492 DEBUG_LOG1(_L("CIKECRACKNegotiation::DialogCompleteL(), aUserInfo = %x"), aUserInfo); |
|
493 |
|
494 if ( info ) |
|
495 { |
|
496 obj_id = info->GetObjId(); |
|
497 DEBUG_LOG1(_L("Preparing to call AuthDialogCompletedL(), ObjId = %x"), obj_id); |
|
498 if ( obj_id == DIALOG_INFO_ID ) |
|
499 { |
|
500 info->iUsername = aUsername; |
|
501 info->iSecret = aSecret; |
|
502 info->iDomain = aDomain; |
|
503 obj_id = info->PluginSession()->AuthDialogCompletedL(info); |
|
504 } |
|
505 } |
|
506 |
|
507 return obj_id; |
|
508 } |
|
509 |
|
510 |