|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Class CIkev2NatT implements NAT Traversal functionality specified in IKEv2. |
|
16 * |
|
17 */ |
|
18 #include <in_sock.h> |
|
19 #include "ikev2natt.h" |
|
20 #include "ikev2SAdata.h" |
|
21 #include "ikev2payloads.h" |
|
22 #include "ikev2const.h" |
|
23 #include "ikecrypto.h" |
|
24 |
|
25 CIkev2NatT* CIkev2NatT::NewL(const TInetAddr& aSourceAddr, const TInetAddr& aDestinationAddr, TUint16 aPort, |
|
26 const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi) |
|
27 { |
|
28 CIkev2NatT* self = new (ELeave)CIkev2NatT(); |
|
29 CleanupStack::PushL(self); |
|
30 self->ConstructL(aSourceAddr, aDestinationAddr, aPort, aInitiatorSpi, aResponderSpi); |
|
31 CleanupStack::Pop(self); |
|
32 |
|
33 return self; |
|
34 } |
|
35 |
|
36 void CIkev2NatT::ConstructL(const TInetAddr& aSourceAddr, const TInetAddr& aDestinationAddr, TUint16 aPort, |
|
37 const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi) |
|
38 { |
|
39 iSrcNotify = GenerateNatDetectionHashL(aInitiatorSpi, aResponderSpi, |
|
40 aSourceAddr, aPort); |
|
41 |
|
42 iDstNotify = GenerateNatDetectionHashL(aInitiatorSpi, aResponderSpi, |
|
43 aDestinationAddr, aPort); |
|
44 } |
|
45 |
|
46 TUint32 CIkev2NatT::CheckPeerNotifysL(const CArrayFixFlat<TNotifPayloadIkev2*>& aNotifys, |
|
47 const TInetAddr& aLocalAddr, const TInetAddr& aRemoteAddr, TUint16 aPort, |
|
48 const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi, TBool& aSupported) |
|
49 { |
|
50 // |
|
51 // Check does there exists NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP |
|
52 // Notify payload. If found compare payload data to local end NAT |
|
53 // traversal data as follows: |
|
54 // -- NAT_DETECTION_SOURCE_IP Notifys are examined against local Notify |
|
55 // payload iDstIdentiy data: If no match found |
|
56 // ==> Peer is behind NAT |
|
57 // -- NAT_DETECTION_DESTINATION_IP Notify is examined against local Notify |
|
58 // payload iSrcIdentiy data: If no match found |
|
59 // ==> Local end behind NAT |
|
60 // |
|
61 aSupported = EFalse; |
|
62 TInt Count = aNotifys.Count(); |
|
63 |
|
64 CIkev2NatT* RefObj = CIkev2NatT::NewL(aLocalAddr, aRemoteAddr, aPort, |
|
65 aInitiatorSpi, aResponderSpi); |
|
66 |
|
67 TNotifPayloadIkev2* PeerNotify; |
|
68 TUint32 PeerLth; |
|
69 TBool SrcMatch = EFalse; |
|
70 TBool DstMatch = EFalse; |
|
71 TUint32 NatFlags = 0; |
|
72 TInt i = 0; |
|
73 |
|
74 while ( i < Count ) |
|
75 { |
|
76 PeerNotify = aNotifys.At(i); |
|
77 if ( (PeerNotify->GetMsgType() == NAT_DETECTION_SOURCE_IP) && !SrcMatch ) |
|
78 { |
|
79 NatFlags |= REMOTE_END_NAT; |
|
80 PeerLth = TPayloadIkev2::Cast(PeerNotify)->GetLength() - (TUint32)(PeerNotify->Size() + PeerNotify->GetSPISize()); |
|
81 const TPtrC8 peerNotify(PeerNotify->NotifData(), PeerLth); |
|
82 if ( RefObj->DestinNofify().Compare(peerNotify) == 0) |
|
83 { |
|
84 SrcMatch = ETrue; |
|
85 NatFlags &= ~REMOTE_END_NAT; |
|
86 } |
|
87 } |
|
88 else if ( (PeerNotify->GetMsgType() == NAT_DETECTION_DESTINATION_IP) && !DstMatch ) |
|
89 { |
|
90 aSupported = ETrue; |
|
91 NatFlags |= LOCAL_END_NAT; |
|
92 PeerLth = TPayloadIkev2::Cast(PeerNotify)->GetLength() - (TUint32)(PeerNotify->Size() + PeerNotify->GetSPISize()); |
|
93 const TPtrC8 peerNotify(PeerNotify->NotifData(), PeerLth); |
|
94 if ( RefObj->SourceNofify().Compare(peerNotify) == 0 ) |
|
95 { |
|
96 DstMatch = ETrue; |
|
97 NatFlags &= ~LOCAL_END_NAT; |
|
98 } |
|
99 } |
|
100 i ++; |
|
101 } |
|
102 |
|
103 delete RefObj; |
|
104 return NatFlags; |
|
105 } |
|
106 |
|
107 HBufC8* CIkev2NatT::GenerateNatDetectionHashL(const TDesC8& aInitiatorSpi, const TDesC8& aResponderSpi, |
|
108 TInetAddr aIpAddress, TUint16 aPort ) const |
|
109 { |
|
110 __ASSERT_DEBUG( aInitiatorSpi.Length() == IKEV2_SPI_SIZE, User::Invariant()); |
|
111 __ASSERT_DEBUG( aResponderSpi.Length() == IKEV2_SPI_SIZE, User::Invariant()); |
|
112 |
|
113 // |
|
114 // Calculate HASH = SHA1(SPIS | IP | Port) both for local- and remote IP address/port |
|
115 // |
|
116 TBuf8<64> hashInData; |
|
117 |
|
118 hashInData.Append(aInitiatorSpi); |
|
119 hashInData.Append(aResponderSpi); |
|
120 |
|
121 if ( aIpAddress.Family() == KAfInet ) |
|
122 { |
|
123 TUint32 ipv4addr = ByteOrder::Swap32(aIpAddress.Address());//Put in network order |
|
124 hashInData.Append(reinterpret_cast<TUint8*>(&ipv4addr), sizeof(ipv4addr)); |
|
125 } |
|
126 else |
|
127 { |
|
128 if ( aIpAddress.IsV4Mapped() ) |
|
129 { |
|
130 aIpAddress.ConvertToV4(); // IPv4 format |
|
131 TUint32 ipv4addr = ByteOrder::Swap32(aIpAddress.Address());//Put in network order |
|
132 hashInData.Append(reinterpret_cast<TUint8*>(&ipv4addr), sizeof(ipv4addr)); |
|
133 } |
|
134 else |
|
135 { |
|
136 const TUint8* addr = &aIpAddress.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
137 hashInData.Append(addr, 16); |
|
138 } |
|
139 } |
|
140 |
|
141 aPort = ByteOrder::Swap16(aPort); |
|
142 hashInData.Append(reinterpret_cast<TUint8*>(&aPort), sizeof(aPort)); |
|
143 |
|
144 return IkeCrypto::PrfL(hashInData, PRF_HMAC_SHA1); |
|
145 } |