vpnengine/ikev1lib/src/ikev1crack.cpp
changeset 0 33413c0669b9
child 23 d1a0d37b52a1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev1lib/src/ikev1crack.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,510 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   IKEv1 Crack authentication
+*
+*/
+
+
+#include "ikev1crack.h"
+#include "ikedebug.h"
+#include "ikev1pluginsession.h"
+#include "ikev1timeout.h"
+#include "ikev1negotiation.h"
+#include "ikev1payload.h"
+#include "ikev1isakmpstream.h"
+#include "ikepolparser.h"
+
+
+//
+// Class that implements IKE CRACK authentication method
+//
+
+CIKECRACKNegotiation::CIKECRACKNegotiation( MIkeDebug& aDebug )
+ : iState( 0 ),
+   iDebug( aDebug )
+    {
+    }
+
+CIKECRACKNegotiation::~CIKECRACKNegotiation()
+{
+/*-------------------------------------------------------------------
+ *
+ *  Delete pending dialog - and dialog info objects
+ *
+ *-------------------------------------------------------------------*/
+#ifdef _DEBUG
+	if ( iNegotiation ) DEBUG_LOG(_L("CRACK object deleted"));
+#endif // _DEBUG	
+            
+    delete iDialog;
+    delete iDialogInfo;
+	delete iUserName;
+	delete iDomain;
+}
+
+
+TInt CIKECRACKNegotiation::ConstructL(TInt aLAMType, CIkev1Negotiation *aNegotiation, const TDesC &aDomain)
+{
+/*------------------------------------------------------------------------
+ *
+ *  This method initializes actions to get authencation information from user.
+ *  The authentication information is requested from user with LAM type
+ *  specific dialog.
+ *  
+ *------------------------------------------------------------------------*/
+    if ( aLAMType != CRACK_PASSWORD || !aNegotiation ) 
+    {
+#ifdef _DEBUG    
+	   if (	aNegotiation )
+		   DEBUG_LOG(_L("CRACK object construction failed, unsupported LAM type"));
+#endif // _DEBUG		   
+       return CRACK_FAILED;
+    }
+    iNegotiation = aNegotiation;
+    iPluginSession      = aNegotiation->iPluginSession;   
+    iLAMType     = aLAMType;
+	if ( aDomain.Length() > 0 )
+	{
+		//
+		// Allocate buffer for domain name attribute 
+		// (to convey Group Name information)
+		// 
+		iDomain = HBufC8::NewL(aDomain.Length()); 
+		iDomain->Des().Copy(aDomain);
+		DEBUG_LOG(_L("CRACK Domain attribute saved"));		
+	}	
+
+    DEBUG_LOG(_L("CRACK authentication started"));
+    
+    return GetDataL(NULL); /* No challenge data */
+}
+
+
+TInt CIKECRACKNegotiation::ExecuteCRACKMsgL(const ThdrISAKMP &aHdr)
+{
+/*---------------------------------------------------------------------------
+ *
+ *  IKE message received during CRACK authentication phase:
+ *  <--- HDRx*, CHRE or  <--- HDRx*, NOTIFICATION
+ *  Process CHRE/Notification payload in IKE message
+ *  
+ *--------------------------------------------------------------------------*/
+    if ( ( iState & WAITING_PEER_RSP ) == 0 ) {
+       /*--------------------------------------------------------
+        * Not waiting a response from gateway, ignore packet
+        *--------------------------------------------------------*/ 
+       return CRACK_IGNORE_MSG;  
+    }
+    iState &= ~WAITING_PEER_RSP;
+
+	CIkev1Payloads* payload = CIkev1Payloads::NewL(aHdr, *iNegotiation, iDebug);
+	if (!payload)
+	{	
+		return CRACK_FAILED;    
+	}
+	CleanupStack::PushL(payload);
+	TInt status;
+	
+	if ( payload->iChre )
+	{
+		TInt i = 0;
+		while ( i < payload->iNotifs->Count() )
+		{
+    	   /*----------------------------------------------------------------------
+            *
+            * A Notification payload received in IKE main/aggressive/information
+            * exchange. If this is not a INITIAL-CONTACT notification it is
+            * interpreted as a CRACK authentication failure indicated by the gateway.
+            *
+            *----------------------------------------------------------------------*/
+			if ( !iNegotiation->ProcessNotificationL(payload->iNotifs->At(i)) ) {
+			   CleanupStack::PopAndDestroy();  //payload
+			   return CrackAuthenticationFailedL(payload->iNotifs->At(i)); 
+			}      
+			i ++;
+		}
+		
+		if ( payload->iIaddr ) {
+    	   /*----------------------------------------------------------------------
+            *
+            * An Internal Address payload received in IKE main/aggressive exchange. 
+            *
+            *----------------------------------------------------------------------*/
+			iNegotiation->ProcessIntAddrL(payload->iIaddr);       			
+		}	
+	   /*----------------------------------------------------------------------
+        *
+        * Process attributes in CHRE payload
+        *
+        *----------------------------------------------------------------------*/
+		status = ProcessCHREAttibutesL(payload->iChre);
+	}
+	else {
+	   status = CRACK_CONTINUE;		
+	   DEBUG_LOG(_L("No CHRE payload in IKE CRACK message")); 	  
+	}        
+
+    CleanupStack::PopAndDestroy();  //payload		
+    return status;  
+
+}
+
+TInt CIKECRACKNegotiation::ProcessUserResponseL(CAuthDialogInfo *aDialogInfo )
+{
+/*---------------------------------------------------------------------------
+ *  
+ *  A response received from client user (through asynchronous dialog)
+ *  Build an IKE message with an appropriate CHRE payload attributes
+ *  and send message it to gateway.
+ *  
+ *-------------------------------------------------------------------------*/
+    if ( iState & WAITING_USER_RSP ) 
+    {    
+       iState &= ~(WAITING_USER_RSP + SECURID_NEXT_PIN_MODE);
+       delete iDialog;  /* delete dialog object */
+       iDialog = NULL;
+       
+       TUint16 attr1 = 0;
+       TUint16 attr2 = 0; 
+       TUint16 attr3 = 0;
+       HBufC8* bfr1 = NULL;
+       HBufC8* bfr2 = NULL;
+       HBufC8* bfr3 = NULL;
+       
+       /*--------------------------------------------------------
+        *
+        *  Store attributes according to LAM type
+        *
+        *--------------------------------------------------------*/
+       switch ( iLAMType ) 
+       {    
+           case CRACK_PASSWORD:
+               /*--------------------------------------------------
+                *  Possible attributes: User name, Secret, Domain
+                *-------------------------------------------------*/
+                attr1 = CRACK_T_USERNAME;
+                bfr1  = aDialogInfo->iUsername;
+                attr2 = CRACK_T_SECRET;
+                bfr2  = aDialogInfo->iSecret;
+                bfr3  = iDomain;
+                if ( bfr3 )
+                   attr3 = CRACK_T_DOMAIN;                  
+                break;
+
+           default:
+                break;
+       }       
+
+       SendCredentialsL(attr1, attr2, attr3, bfr1, bfr2, bfr3);
+    }
+    
+    delete aDialogInfo;  /* release dialog info object */
+    iDialogInfo = NULL;  /* reset dialog info pointer  */
+     
+    return CRACK_CONTINUE;
+}
+
+TInt CIKECRACKNegotiation::GetDataL(HBufC8* aChallenge)
+{
+    if ( iLAMType == CRACK_PASSWORD &&
+         iNegotiation->iHostData->iCRACKLAMUserName &&
+         iNegotiation->iHostData->iCRACKLAMPassword)
+        {
+        return GetUNPWDFromPolicyL();
+        }
+    else
+        {
+        return GetDatafromUserL(aChallenge); 
+        }
+}
+
+TInt CIKECRACKNegotiation::GetDatafromUserL(HBufC8* /*aChallenge*/)
+{
+    TInt status = CRACK_CONTINUE;
+    /*---------------------------------------------------------------
+     *
+     *  Get CRACK authentication information from user according to
+     *  current LAM type
+     *
+     *---------------------------------------------------------------*/
+    iDialog     = CIkev1Dialog::NewL( iPluginSession, iPluginSession->DialogAnchor(), iDebug );
+    iDialogInfo = new(ELeave) CAuthDialogInfo(iPluginSession, DIALOG_INFO_ID, iNegotiation->SAId(), 0);
+    iNegotiation->iTimer->Cancel();   //Cancel previous timer because reply received & processed
+    DEBUG_LOG(_L("Timer Cancelled!"));
+    iNegotiation->iRetryNum = 0;
+                  
+    switch ( iLAMType ) 
+    {
+        case CRACK_PASSWORD:
+             /*--------------------------------------------------
+              * Request User name and password (domain) from user
+              *-------------------------------------------------*/
+             iDialog->GetAsyncUNPWDialogL(iDialogInfo, (MIkeDialogComplete*)this);
+             break;
+
+        default:     
+             status = CRACK_FAILED;
+             break;
+    }
+
+    iState |= WAITING_USER_RSP + SHOW_ERROR_DIALOG;
+
+    return status;
+}
+
+TInt CIKECRACKNegotiation::GetUNPWDFromPolicyL()
+{
+    ASSERT(iLAMType == CRACK_PASSWORD);
+    
+    iNegotiation->iTimer->Cancel();   //Cancel previous timer because reply received & processed
+    DEBUG_LOG(_L("Timer Cancelled!"));
+    iNegotiation->iRetryNum = 0;
+
+    /*--------------------------------------------------------
+    *
+    *  Store attributes: User name, Secret, Domain
+    *
+    *--------------------------------------------------------*/
+
+    TUint16 attr1 = CRACK_T_USERNAME;
+    HBufC8* bfr1  = iNegotiation->iHostData->iCRACKLAMUserName->GetAsciiDataL();
+    CleanupStack::PushL(bfr1);
+    TUint16 attr2 = CRACK_T_SECRET;
+    HBufC8* bfr2  = iNegotiation->iHostData->iCRACKLAMPassword->GetAsciiDataL();
+    CleanupStack::PushL(bfr2);
+    HBufC8* bfr3  = iDomain;
+    TUint16 attr3 = 0;
+    if ( bfr3 )
+        {
+        attr3 = CRACK_T_DOMAIN;                  
+        }
+
+    SendCredentialsL(attr1, attr2, attr3, bfr1, bfr2, bfr3);
+    
+	CleanupStack::PopAndDestroy(2); // bfr1, bfr2
+	
+    return CRACK_CONTINUE;
+}
+
+void CIKECRACKNegotiation::SendCredentialsL(TUint16 aAttr1, TUint16 aAttr2, TUint16 aAttr3,
+                                            HBufC8* aBfr1, HBufC8* aBfr2, HBufC8* aBfr3)
+{
+    TIkev1IsakmpStream* msg = iNegotiation->SaveIkeMsgBfr( new (ELeave) TIkev1IsakmpStream(iDebug) );
+    msg->IsakmpInit(iNegotiation);
+    msg->IsakmpOwnIdentL();    /* Dummy ID for Crypto Cluster */
+    msg->IsakmpChre((TUint16)iLAMType, aAttr1, aBfr1, aAttr2, aBfr2, aAttr3, aBfr3);
+
+    if ( iNegotiation->iFamiliarPeer && iNegotiation->iHostData->iUseInternalAddr )
+    {
+        //
+        // Request Internal address from gateway
+        //
+        msg->IsakmpIntnet(0);  /* null IPV4 address as parameter */
+    }
+
+    if ( iNegotiation->iHostData->iInitialContact ) 
+    {
+        //
+        // Initial contact notification added as the last payload into IKE  message
+        //
+        if (!iPluginSession->FindIkev1SADataWithAddr(iNegotiation->iRemoteAddr))  //Only sent if no ISAKMP SA established
+        {
+            DEBUG_LOG(_L("Constructing INITIAL-CONTACT"));
+            msg->IsakmpNotification(DOI_INITIAL_CONTACT, PROTO_ISAKMP); 
+        }
+    }
+   
+    iNegotiation->SendL(*msg);
+
+    //
+    // Take a copy of user name buffer in dialog info. This user name
+    // is cached into user name file if current CRACK negotiation is
+    // succeeded
+    //
+    if ( aBfr1 ) 
+    {
+	    delete iUserName;  // Delete old user name buffer for sure
+	    iUserName = NULL;  
+	    iUserName = HBufC8::New(aBfr1->Length() + 16); // 16 bytes space for padding
+	    if ( iUserName ) 
+	    {
+		    iUserName->Des().Copy(aBfr1->Des()); 
+	    } 	   
+    }
+   
+    iState |= WAITING_PEER_RSP;
+    iMsgCount++;
+}
+    
+TInt CIKECRACKNegotiation::ProcessCHREAttibutesL(const TCHREISAKMP *aCHRE)
+{
+/*---------------------------------------------------------------------------
+ *
+ *  CHRE payload received from gateway. Process attributes in payload
+ *  according to current LAM type.
+ *  Assure first that LAM type in payload corresponds configured LAM type
+ *  in CRACK object
+ *  
+ *--------------------------------------------------------------------------*/
+    TInt length = (TInt)aCHRE->GetLength();
+    if ( STATIC_CAST(TUint, length) < sizeof(TCHREISAKMP) ) {
+       return CRACK_FAILED; 
+    }
+    
+    length -= sizeof(TCHREISAKMP);  /* Attribute data lengt in payload */
+    if ( (aCHRE->GetCHREReserved() != 0) || (aCHRE->GetLAMtype() != iLAMType )) {
+       return CRACK_FAILED;         
+    }
+    
+    TDataISAKMP *attr     = aCHRE->CHREAttrib();
+    HBufC8  *challenge    = NULL;
+    TInt    status        = CRACK_CONTINUE;
+    TBool   get_user_data = EFalse;
+    TUint16 fin;
+    
+    while ( length > 0 ) {
+        
+        length = length - attr->Size();
+        if ( length < 0 ) {
+           DEBUG_LOG(_L("BAD_PROPOSAL_SYNTAX (Length mismatch in the attibutes)"));
+           return CRACK_FAILED;
+        }
+        switch ( attr->Type() ) {
+            
+           case CRACK_T_MESSAGE:
+                if ( attr->IsBasic() ) {   /* MUST be variable */
+                   return CRACK_FAILED;                 
+                }
+                break;
+        
+           case CRACK_T_FIN:
+                if ( !attr->IsBasic() ) {   /* MUST be basic */
+                   return CRACK_FAILED;                 
+                }
+                fin = attr->Value();
+                if ( fin == CRACK_FIN_SUCCESS ) {
+                   DEBUG_LOG(_L("CRACK authentication OK"));                     
+                   status = CRACK_SUCCESS;
+				   if ( iUserName ) {
+					  //
+					  // Cache user name into user name file
+					  //
+				      CIkev1Dialog* Dialog = CIkev1Dialog::NewL(iPluginSession, iPluginSession->DialogAnchor(), iDebug);		  			 
+					  CleanupStack::PushL(Dialog);
+					  TInt err(KErrNone);	 
+					  TRAP(err, Dialog->StoreUserNameL(iUserName->Des()));
+#ifdef _DEBUG					  
+					  if (err == KErrNone)
+						  DEBUG_LOG(_L("User Name caching succeeded"));
+						  DEBUG_LOG(_L("User Name caching failed"));
+#endif						  
+					  CleanupStack::PopAndDestroy();		  
+				   }	   
+                }    
+                else {
+                   if ( fin == CRACK_FIN_MORE ) {
+                      iState |= SECURID_NEXT_PIN_MODE; 
+                      DEBUG_LOG(_L("CRACK SecurID Next pin mode entered"));                                            
+                      get_user_data = ETrue;     /* SecurID "Next code2  */
+                   }        
+                   else {
+                      status = CRACK_FAILED;     /* Illegal FIN value */
+                   }      
+                }   
+                break;
+            
+           default:
+                DEBUG_LOG(_L("ATTRIBUTES_NOT_SUPPORTED (Invalid attribute in CHRE)"));
+                return CRACK_FAILED;
+        }
+        
+        attr = attr->Next();
+    }
+
+    if ( get_user_data ) {
+       /*---------------------------------------------------
+        * Get information from user
+        *---------------------------------------------------*/
+       status = GetDatafromUserL(challenge);
+       if ( challenge )
+          CleanupStack::PopAndDestroy();  /* delete challenge */       
+    }
+
+    return status;
+    
+}   
+
+
+TInt CIKECRACKNegotiation::CrackAuthenticationFailedL(const TNotificationISAKMP *aNotifPayload)
+{
+	(void)aNotifPayload;		
+/*---------------------------------------------------------------------------
+ *
+ *  The gateway has sent a Notification payload which indicates that CRACK 
+ *  authentication is failed.
+ *  Display proper error dialog and return CRACK_FAILED status
+ *  
+ *--------------------------------------------------------------------------*/
+    iNegotiation->iTimer->Cancel();   //Cancel timer because authentication failed
+    DEBUG_LOG(_L("CRACK authentication failed!"));
+
+    if ( (iState & (CRACK_AUTHENTICATED + WAITING_USER_RSP + SHOW_ERROR_DIALOG)) ==
+                    SHOW_ERROR_DIALOG ) {       
+       // Dialog object shall be delete in Dialog->RunL when dialog completed
+       CIkev1Dialog* Dialog = CIkev1Dialog::NewL(iPluginSession, iPluginSession->DialogAnchor(), iDebug);
+       Dialog->ShowErrorDialogL(TVpnNoteDialog::EKmdAuthenticationFailed, NULL, NULL);
+       iState &= ~SHOW_ERROR_DIALOG;
+    }
+    
+    return CRACK_FAILED;
+
+}
+
+//
+// The implementation for class MIkeDialogComplete virtual function
+//
+TInt CIKECRACKNegotiation::DialogCompleteL(CIkev1Dialog* /*aDialog*/, TAny* aUserInfo,
+                                            HBufC8* aUsername, HBufC8* aSecret, HBufC8* aDomain)
+{
+/*---------------------------------------------------------------------------
+ *  
+ *  A response received from client user (through asynchronous dialog)
+ *  This method is introduced as a TUserCallback for CGetIKEPassword dialog
+ *  object is created. When the dialog is completed this callback function
+ *  is called to deliver Credentials data for CHRE payload attributes.
+ *  Store credential buffers to CAuthDialogInfo object and call engine
+ *  entry  
+ *  
+ *-------------------------------------------------------------------------*/
+    TUint32 obj_id = 1;
+    CAuthDialogInfo* info = (CAuthDialogInfo*)aUserInfo;
+	DEBUG_LOG1(_L("CIKECRACKNegotiation::DialogCompleteL(), aUserInfo =  %x"), aUserInfo);
+			
+    if ( info )
+	{
+       obj_id = info->GetObjId();
+	   DEBUG_LOG1(_L("Preparing to call AuthDialogCompletedL(), ObjId = %x"), obj_id);
+       if ( obj_id == DIALOG_INFO_ID )
+	   {
+          info->iUsername = aUsername;
+          info->iSecret   = aSecret;
+          info->iDomain   = aDomain;
+          obj_id = info->PluginSession()->AuthDialogCompletedL(info);
+       }   
+    }
+
+    return obj_id;
+}
+
+