linklayerprotocols/pppnif/SPPP/PPPAUTH.CPP
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linklayerprotocols/pppnif/SPPP/PPPAUTH.CPP	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,449 @@
+// Copyright (c) 1997-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:
+//
+
+
+#include <in_iface.h>
+#include "PPPAUTH.H"
+
+#include "ppppap.h"
+#include "chapmd5.h"
+#include "MSCHAP.H"
+#include "mschap2.h"
+#include <commsdattypeinfov1_1.h>
+#include "PPPConfig.h"
+
+#if defined(_DEBUG)
+const TInt KLCPConfigOptionTypeFieldSize = 1;
+const TInt KLCPConfigOptionLengthFieldSize = 1;
+#endif
+const TInt KAuthenticationProtocolOptionFieldSize = 2;
+const TInt KChapAlgorithmFieldSize = 1;
+
+
+//
+
+void CPppAuthentication::InitL(
+	CPppLcp* aPppLcp)
+/**
+Initializes the authentication protocol.
+@param aPppLcp Parent LCP instance
+@leave The method does not leave */			
+	{
+	MPppRecvr::Init(aPppLcp, PppPhase(), PppId());
+	}
+
+CPppAuthentication::~CPppAuthentication()
+/**
+Destructor, generates a CancelAuthenticate notification to the 
+parent LCP instance */			
+	{
+	if (iPppLcp != 0)
+		iPppLcp->CancelAuthenticate(this);
+	}
+
+void CPppAuthentication::AuthenticateRequest()
+/**
+Generates an Authenticate notification to the parent LCP instance */			
+	{
+	ASSERT(iPppLcp != 0);
+	iPppLcp->Authenticate(this);
+	}
+
+void CPppAuthentication::CallAuthenticateComplete(
+	TInt aRes)
+/**
+Notifies the derived class that the LCP authentication is completed
+@param aRes Code describing the authentication result 
+	(KErrNone: authentication OK) */			
+	{
+	ASSERT(iPppLcp != 0);
+	iFlags |= KPppApAuthReqDone;
+	AuthenticateComplete(aRes);
+	}
+
+void CPppAuthentication::DoFail(
+	TInt aErrorCode)
+/**
+Notifies the parent LCP instance of an error encountered 
+during authentication
+@param aErrorCode Describes the authentication failure */			
+	{
+	ASSERT(iPppLcp != 0);
+	iPppLcp->Progress(EPppProgressAuthenticationComplete, aErrorCode);
+	iPppLcp->PhaseAborted(aErrorCode);
+	}
+
+
+void CPppAuthentication::DoSucceed()
+/**
+Notifies the parent LCP instance that the 
+authentication phase completed successfully */			
+	{
+	ASSERT(iPppLcp != 0);
+
+	iPppLcp->Progress(EPppProgressAuthenticationComplete, KErrNone);
+	iPppLcp->PhaseComplete();
+	}
+
+
+//
+
+static const TInt KOptionListLen = 1;
+static const TUint8 OptionList[KOptionListLen] =
+	{
+	KPppLcpOptAuthenticationProtocol
+	};
+			
+CPppAcp* CPppAcp::NewL(
+	CPppLcp* aLcp)
+/**
+Creates a new CPppAcp instance
+@param aLcp Parent LCP instance
+@return Newly created CPppAcp instance */		
+	{
+	CPppAcp* acp = new (ELeave) CPppAcp(aLcp);
+	return acp;
+	}
+
+CPppAcp::CPppAcp(
+	CPppLcp* aLcp)
+	: MPppOptionHandler()
+/**
+Constructor, register the current instance as a handler 
+for the authentication option type
+@param aLcp Parent LCP instance */		
+	{
+	iPppLcp = aLcp;
+	OptRegister(aLcp, OptionList, KOptionListLen);
+	}
+
+CPppAcp::~CPppAcp()
+/**
+Destructor, deletes the protocol objects created by this instance */		
+	{
+	DeleteProtocols();
+	}
+
+void CPppAcp::DeleteProtocols()
+/**
+Deletes the member protocol objects if valid. */		
+	{
+	if (iServerProtocol)
+		{
+		delete iServerProtocol;
+		iServerProtocol = NULL;
+		}
+	if (iClientProtocol)
+		{
+		delete iClientProtocol;
+		iClientProtocol = NULL;
+		}
+	}
+	
+void CPppAcp::OptNegotiationStarted()
+/**
+Initializes the option handler for a new LCP negotiation session */		
+	{
+	DeleteProtocols();
+		
+	iClientId = KPppIdUnknown;
+	iClientSubId = KPppIdUnknown;
+	iServerId = KPppIdUnknown;
+	iServerSubId = KPppIdUnknown;
+
+	iProtocolOffered = 0;
+	iCHAPTypeOffered = 0;
+	
+	// default to fallback
+	}
+
+void CPppAcp::OptNegotiationAborted()
+/**
+Executed when the negotiation is aborted, 
+resets the negotiable options */		
+	{
+	iClientId = KPppIdUnknown;
+	iClientSubId = KPppIdUnknown;
+	iServerId = KPppIdUnknown;
+	iServerSubId = KPppIdUnknown;
+	}
+
+void CPppAcp::OptNegotiationComplete()
+/**
+Executed when the negotiation is finalized, 
+creates the protocol objects according to the 
+negotiated options */		
+	{
+	TRAPD(ret, 
+	 switch (iClientId)
+		 {
+	 case KPppIdPap:
+		 iClientProtocol = CPppPap::NewL();
+		 break;
+
+	 case KPppIdChap:
+		 switch (iClientSubId)
+			 {
+		 case KPppChapMd5AlgorithmNumber:
+			 iClientProtocol = CPppChapMd5::NewL();
+			 break;
+
+		 case KPppMsChapAlgorithmNumber:
+			 iClientProtocol = CPppMsChap::NewL();
+			 break;
+
+		 case KPppMsChap2AlgorithmNumber:
+			 iClientProtocol = CPppMsChap2::NewL();
+			 break;
+			 }
+		 break;
+		 }
+
+	 if (iClientProtocol)
+		 {
+		 iClientProtocol->iFlags = KPppApIsClient;
+		 if (iClientId==iServerId)
+			 iClientProtocol->iFlags |= KPppApIsServer;
+		 iClientProtocol->InitL(iPppLcp);
+		 }
+
+	 if (iClientId!=iServerId)
+		 {
+		 switch (iServerId)
+			 {
+		 case KPppIdPap:
+			 iServerProtocol = CPppPap::NewL();
+			 break;
+
+		 case KPppIdChap:
+			 switch (iServerSubId)
+				 {
+			 case KPppChapMd5AlgorithmNumber:
+				 iServerProtocol = CPppChapMd5::NewL();
+				 break;
+
+			 case KPppMsChapAlgorithmNumber:
+				 iServerProtocol = CPppMsChap::NewL();
+				 break;
+
+			 case KPppMsChap2AlgorithmNumber:
+				 iServerProtocol = CPppMsChap2::NewL();
+				 break;
+				 }
+			 break;
+			 }
+
+		 if (iServerProtocol)
+			 {
+			 iServerProtocol->iFlags = KPppApIsServer;
+			 iServerProtocol->InitL(iPppLcp);
+			 }
+		 }
+		); // TRAPD
+
+	if (ret!=KErrNone)
+		{
+		iPppLcp->PhaseAborted(ret);
+		return;
+		}
+	}
+
+void CPppAcp::OptFillinConfigRequestL(
+	RPppOptionList& /*aRequestList*/)
+/**
+Called when the LCP state machine prepares the initial 
+configuration request. No authentication protocol is proposed
+here.
+@param aRequestList Not used */	
+	{
+	// do not add anything to the list
+	}
+	
+TPppOptResponse CPppAcp::ProposeChap(
+	RPppOption& aOption)
+/**
+Sets the option argument to CHAP and the next supported algorithm. 
+The order of negotiation of PPP CHAP algorithms:
+
+MS-CHAP-V2
+MS-CHAP-V1
+CHAP with MD5
+
+When all algorithms were tried the method returns EPppOptReject.
+@param aOption Returns the updated option
+@return EPppOptNak if aOption contains valid info 
+		EPppOptReject otherwise */	
+	{
+	switch (iCHAPTypeOffered)
+		{
+	case 0:
+		iCHAPTypeOffered = KPppMsChap2AlgorithmNumber;
+		break;			
+	case KPppMsChap2AlgorithmNumber:
+		iCHAPTypeOffered = KPppMsChapAlgorithmNumber;
+		break;			
+	case KPppMsChapAlgorithmNumber:
+		iCHAPTypeOffered = KPppChapMd5AlgorithmNumber;
+		break;
+	case KPppChapMd5AlgorithmNumber:			
+	default:
+		return EPppOptReject;
+		}
+		
+	TUint8* p = aOption.ValuePtr();
+	
+	BigEndian::Put16(p, (TUint16)KPppIdChap);
+
+	// There is a problem here due to using aOption as an input/output
+	// parameter if the size of the Data field in the
+	// Authentication-Protocol Configuration Option received in the
+	// aOption parameter is not large enough to allow suggesting CHAP
+	// (i.e. the size is of Data field is 0).  This is outside the scope
+	// of the current work, so it is assumed here that RPppOption/RMBuf
+	// meets the requirements.
+	ASSERT(aOption.First()->Size() >= 
+				KLCPConfigOptionTypeFieldSize +
+				KLCPConfigOptionLengthFieldSize +
+				KAuthenticationProtocolOptionFieldSize + 
+				KChapAlgorithmFieldSize);
+
+	aOption.SetValueLength(
+		KAuthenticationProtocolOptionFieldSize + 
+		KChapAlgorithmFieldSize);
+	p[2] = iCHAPTypeOffered;
+		
+	return EPppOptNak;		
+	}		
+		
+TPppOptResponse CPppAcp::ProposePap(
+	RPppOption& aOption)
+/**
+Sets the option argument to PAP. 
+@param aOption Returns the updated option
+@return EPppOptNak if aOption contains valid info 
+		EPppOptReject otherwise */	
+	{
+	aOption.SetValueLength(KAuthenticationProtocolOptionFieldSize);
+
+	TUint8* p = aOption.ValuePtr();
+	BigEndian::Put16(p, (TUint16)KPppIdPap);
+
+	return EPppOptNak;
+	}	
+
+TPppOptResponse CPppAcp::OptCheckConfigRequest(
+	RPppOption& aOption)
+/**
+Checks the specified authentication option. The currently supported 
+authentication mode/protocol is specified in the CDMA_SIMIP_AUTH_ALGORITHM
+field in the packet service table (TCommDbCdmaSimpIpAuthAlgorithm enum).
+@param aOption Returns the updated option
+@return EPppOptAck if the proposed authentication option is accepted
+		EPppOptNak if the option is not accepted and another option is being proposed
+		EPppOptReject if the option is not accepted and no other option is proposed */	
+	{	
+	// MobileIP, Don't negotiate PAP or CHAP if CDMA MIP.
+	if (iPppLcp->QueryExternalIPConfiguration())
+		{
+		// Check if we must authenticate always, regardless of the mode.
+		// If the SERVICE_IF_EXTERN_IP_CONFIG_ALWAYS_REJECT_AUTH field is not in CommDB, 
+		// doAlwaysAuthenticate remains EFalse.
+		}
+
+	TUint8* p = aOption.ValuePtr();
+	
+	if (aOption.ValueLength() < 
+		KAuthenticationProtocolOptionFieldSize)
+		return EPppOptReject;
+
+	// always return from every conditional branch of the following
+	switch (BigEndian::Get16(p))
+		{
+	case KPppIdPap:
+	    if (aOption.ValueLength() !=
+	        KAuthenticationProtocolOptionFieldSize)
+	        {      
+            // malformed PAP Authentication-Protocol Option - reject
+            return EPppOptReject;
+            }
+	    break;
+	case KPppIdChap:
+		if (aOption.ValueLength() != 
+			KAuthenticationProtocolOptionFieldSize + 
+			KChapAlgorithmFieldSize)
+			{		
+			// malformed CHAP Authentication-Protocol Option - reject
+			return EPppOptReject;
+			}
+            break;
+	default:
+		// unrecognized authentication protocol
+
+		break;
+		}
+	#ifndef SYMBIAN_EXCLUDE_CDMA
+		return TPppOptResponse();
+	#endif				
+	}
+
+void CPppAcp::OptApplyConfigRequest(
+	RPppOption& aOption)
+/**
+The specified configuration option from the server config request
+has been accepted, the negotiation result is stored.
+@param aOption Accepted authentication option */	
+	{
+	iClientId = BigEndian::Get16(aOption.ValuePtr());
+	TInt n = aOption.ValueLength()-2;
+	if (n>0)
+		iClientSubId = *(aOption.ValuePtr()+2);
+	}
+
+void CPppAcp::OptRecvConfigAck(
+	RPppOption& aOption)
+/**
+The specified configuration option has been acked by the server, 
+the negotiation result is stored.
+@param aOption Acked authentication option */
+	{
+	iServerId = BigEndian::Get16(aOption.ValuePtr());
+	TInt n = aOption.ValueLength()-2;
+	if (n>0)
+		iServerSubId = *(aOption.ValuePtr()+2);
+	}
+
+void CPppAcp::OptRecvConfigNak(
+	RPppOption& aOption, 
+	RPppOptionList& aReqList)
+/**
+The specified configuration option has been nacked by the server,
+the option is replaced in the option list
+@param aOption Nacked authentication option 
+@param aReqList List to be updated */	
+	{
+	aReqList.ReplaceOption(aOption);
+	}
+
+void CPppAcp::OptRecvConfigReject(
+	RPppOption& aOption, 
+	RPppOptionList& aReqList)
+/**
+The specified configuration option has been rejected by the server,
+the option is removed from the option list
+@param aOption Rejected authentication option 
+@param aReqList List to be updated */	
+	{
+	aReqList.RemoveOption(aOption);
+	}