diff -r 000000000000 -r af10295192d8 linklayerprotocols/pppnif/SPPP/PPPAUTH.CPP --- /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 +#include "PPPAUTH.H" + +#include "ppppap.h" +#include "chapmd5.h" +#include "MSCHAP.H" +#include "mschap2.h" +#include +#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); + }