diff -r 000000000000 -r 33413c0669b9 vpnengine/ikev2lib/src/ikev2natt.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/ikev2lib/src/ikev2natt.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,145 @@ +/* +* 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: +* Class CIkev2NatT implements NAT Traversal functionality specified in IKEv2. +* +*/ +#include +#include "ikev2natt.h" +#include "ikev2SAdata.h" +#include "ikev2payloads.h" +#include "ikev2const.h" +#include "ikecrypto.h" + +CIkev2NatT* CIkev2NatT::NewL(const TInetAddr& aSourceAddr, const TInetAddr& aDestinationAddr, TUint16 aPort, + const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi) +{ + CIkev2NatT* self = new (ELeave)CIkev2NatT(); + CleanupStack::PushL(self); + self->ConstructL(aSourceAddr, aDestinationAddr, aPort, aInitiatorSpi, aResponderSpi); + CleanupStack::Pop(self); + + return self; +} + +void CIkev2NatT::ConstructL(const TInetAddr& aSourceAddr, const TInetAddr& aDestinationAddr, TUint16 aPort, + const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi) +{ + iSrcNotify = GenerateNatDetectionHashL(aInitiatorSpi, aResponderSpi, + aSourceAddr, aPort); + + iDstNotify = GenerateNatDetectionHashL(aInitiatorSpi, aResponderSpi, + aDestinationAddr, aPort); +} + +TUint32 CIkev2NatT::CheckPeerNotifysL(const CArrayFixFlat& aNotifys, + const TInetAddr& aLocalAddr, const TInetAddr& aRemoteAddr, TUint16 aPort, + const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi, TBool& aSupported) +{ + // + // Check does there exists NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP + // Notify payload. If found compare payload data to local end NAT + // traversal data as follows: + // -- NAT_DETECTION_SOURCE_IP Notifys are examined against local Notify + // payload iDstIdentiy data: If no match found + // ==> Peer is behind NAT + // -- NAT_DETECTION_DESTINATION_IP Notify is examined against local Notify + // payload iSrcIdentiy data: If no match found + // ==> Local end behind NAT + // + aSupported = EFalse; + TInt Count = aNotifys.Count(); + + CIkev2NatT* RefObj = CIkev2NatT::NewL(aLocalAddr, aRemoteAddr, aPort, + aInitiatorSpi, aResponderSpi); + + TNotifPayloadIkev2* PeerNotify; + TUint32 PeerLth; + TBool SrcMatch = EFalse; + TBool DstMatch = EFalse; + TUint32 NatFlags = 0; + TInt i = 0; + + while ( i < Count ) + { + PeerNotify = aNotifys.At(i); + if ( (PeerNotify->GetMsgType() == NAT_DETECTION_SOURCE_IP) && !SrcMatch ) + { + NatFlags |= REMOTE_END_NAT; + PeerLth = TPayloadIkev2::Cast(PeerNotify)->GetLength() - (TUint32)(PeerNotify->Size() + PeerNotify->GetSPISize()); + const TPtrC8 peerNotify(PeerNotify->NotifData(), PeerLth); + if ( RefObj->DestinNofify().Compare(peerNotify) == 0) + { + SrcMatch = ETrue; + NatFlags &= ~REMOTE_END_NAT; + } + } + else if ( (PeerNotify->GetMsgType() == NAT_DETECTION_DESTINATION_IP) && !DstMatch ) + { + aSupported = ETrue; + NatFlags |= LOCAL_END_NAT; + PeerLth = TPayloadIkev2::Cast(PeerNotify)->GetLength() - (TUint32)(PeerNotify->Size() + PeerNotify->GetSPISize()); + const TPtrC8 peerNotify(PeerNotify->NotifData(), PeerLth); + if ( RefObj->SourceNofify().Compare(peerNotify) == 0 ) + { + DstMatch = ETrue; + NatFlags &= ~LOCAL_END_NAT; + } + } + i ++; + } + + delete RefObj; + return NatFlags; +} + +HBufC8* CIkev2NatT::GenerateNatDetectionHashL(const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi, + TInetAddr aIpAddress, TUint16 aPort ) const +{ + __ASSERT_DEBUG( aInitiatorSpi.Length() == IKEV2_SPI_SIZE, User::Invariant()); + __ASSERT_DEBUG( aResponderSpi.Length() == IKEV2_SPI_SIZE, User::Invariant()); + + // + // Calculate HASH = SHA1(SPIS | IP | Port) both for local- and remote IP address/port + // + TBuf8<64> hashInData; + + hashInData.Append(aInitiatorSpi); + hashInData.Append(aResponderSpi); + + if ( aIpAddress.Family() == KAfInet ) + { + TUint32 ipv4addr = ByteOrder::Swap32(aIpAddress.Address());//Put in network order + hashInData.Append(reinterpret_cast(&ipv4addr), sizeof(ipv4addr)); + } + else + { + if ( aIpAddress.IsV4Mapped() ) + { + aIpAddress.ConvertToV4(); // IPv4 format + TUint32 ipv4addr = ByteOrder::Swap32(aIpAddress.Address());//Put in network order + hashInData.Append(reinterpret_cast(&ipv4addr), sizeof(ipv4addr)); + } + else + { + const TUint8* addr = &aIpAddress.Ip6Address().u.iAddr8[0]; //Address in a bytestream + hashInData.Append(addr, 16); + } + } + + aPort = ByteOrder::Swap16(aPort); + hashInData.Append(reinterpret_cast(&aPort), sizeof(aPort)); + + return IkeCrypto::PrfL(hashInData, PRF_HMAC_SHA1); +}