vpnengine/ikev1lib/src/ikev1crack.cpp
changeset 0 33413c0669b9
child 17 d1a0d37b52a1
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     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