--- /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;
+}
+
+