|
1 /* |
|
2 * Copyright (c) 1999-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: Security policy module |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <es_sock.h> |
|
20 #include <in_sock.h> |
|
21 #include <networking/ipsecerr.h> |
|
22 #include <vpnlogmessages.rsg> |
|
23 #include "ikedebug.h" |
|
24 #include "kmdeventloggerif.h" |
|
25 #include "secpolpayload.h" |
|
26 |
|
27 // CLASS HEADER |
|
28 #include "secpolreader.h" |
|
29 |
|
30 // ======== LOCAL FUNCTIONS ======== |
|
31 |
|
32 #ifdef _DEBUG |
|
33 |
|
34 // --------------------------------------------------------------------------- |
|
35 // Returns error description. |
|
36 // --------------------------------------------------------------------------- |
|
37 // |
|
38 static const TPtrC IpsecError( TInt aReason ) |
|
39 { |
|
40 switch ( aReason ) |
|
41 { |
|
42 case EIpsec_RMBUF: return _L("RMBUF operation failed unexcpectedly"); |
|
43 // |
|
44 // AH and ESP |
|
45 // |
|
46 case EIpsec_CorruptPacketIn: return _L("Truncated or corrupt packet or header"); |
|
47 case EIpsec_CorruptPacketOut: return _L("Corrupt packet after IPSEC operations"); |
|
48 case EIpsec_EspInboundSA: return _L("The inbound SA for ESP does not exist"); |
|
49 case EIpsec_EspAuthentication: return _L("Authentication check failed in ESP"); |
|
50 case EIpsec_EspAuthAlg: return _L("Required auth algorithm for ESP not available/installed"); |
|
51 case EIpsec_EspEncrAlg: return _L("Required encrypt algorithm for ESP not available/installed"); |
|
52 case EIpsec_AhAuthAlg: return _L("Required auth algorithm for AH not available/installed"); |
|
53 case EIpsec_AhInboundSA: return _L("The inbound SA for AH does not exist"); |
|
54 case EIpsec_AhIcvLength: return _L("ICV length in packet does not match algorithm"); |
|
55 case EIpsec_AhAuthentication: return _L("Authentication check failed in AH"); |
|
56 case EIpsec_PacketLength: return _L("Invalid/corrupt length of the packet"); |
|
57 case EIpsec_DataAlignment: return _L("Data not aligned by block size (ESP)"); |
|
58 case EIpsec_EspPadByte: return _L("The ESP pad byte content is invalid"); |
|
59 case EIpsec_EspPadLength: return _L("The ESP pad length is corrupt (probably wrong key)"); |
|
60 case EIpsec_ReplayDuplicate: return _L("Duplicate packet (replay window test)"); |
|
61 // |
|
62 // SECPOL |
|
63 // |
|
64 case EIpsec_OutboundNotFound: return _L("Outbound SA does not exist, ACQUIRE started"); |
|
65 case EIpsec_OutboundPending: return _L("Outbooud SA does not exits, ACQUIRE pending"); |
|
66 case EIpsec_NoSelectorMatch: return _L("None of the policy selectors matched"); |
|
67 case EIpsec_MaxTransforms: return _L("Incoming packet exceed configured max limit of transforms"); |
|
68 case EIpsec_TooFewTransforms: return _L("Policy requires IPSEC, none or too little was present"); |
|
69 case EIpsec_TunnelMismatch: return _L("Tunnelmode does not match the policy"); |
|
70 case EIpsec_MismatchedSA: return _L("Applied SA does not match the policy"); |
|
71 case EIpsec_UnrequiredSA: return _L("Applied SA where policy has none"); |
|
72 case EIpsec_TooManyTransforms: return _L("Incoming packet had more transforms than policy requires"); |
|
73 case EIpsec_NoBundle: return _L("Incoming packet had transforms, but policy doesn't require any"); |
|
74 // |
|
75 // IPv6 additions |
|
76 // |
|
77 case EIpsec_AhRMBufSplit: return _L("Inbound AH processing failed (Memory?)"); |
|
78 case EIpsec_AhPacketTooLong: return _L("Outbound packet would exeed 2**16-1 with AH"); |
|
79 case EIpsec_AhSequenceWrap: return _L("Outbound sequence # wrapped around for this SA"); |
|
80 case EIpsec_EspSequenceWrap: return _L("Outbound sequence # wrapped around for this SA"); |
|
81 case EIpsec_EspBadCipherBlockSize: return _L("Configuration error, cipher block size must be < 256"); |
|
82 case EIpsec_AcquireFailed: return _L("Acquiring SA failed (no SA available or negotiated)"); |
|
83 // |
|
84 // Detail reasons for SA not matching the SA spec in the policy |
|
85 // (replace one EIpsec_MismatchedSA with multiple detail errors) |
|
86 // |
|
87 case EIpsec_MismatchedDestination: return _L("SA destination does not match (internal error?)"); |
|
88 case EIpsec_MismatchedType: return _L("SA Type (AH/ESP) does not match"); |
|
89 case EIpsec_MismatchedPFS: return _L("PFS bit is not same"); |
|
90 case EIpsec_MismatchedAuthAlg: return _L("Auth algorithm doesn't match"); |
|
91 case EIpsec_MismatchedEncryptAlg: return _L("Encrypt algorithm doesn't match"); |
|
92 case EIpsec_MismatchReplayWindow: return _L("ReplayWindow length is shorter than required"); |
|
93 case EIpsec_MismatchSource: return _L("source address does not match"); |
|
94 case EIpsec_MismatchProxy: return _L("proxy address does not match"); |
|
95 case EIpsec_MismatchSourcePort: return _L("source port does not match"); |
|
96 case EIpsec_MismatchDestinationPort:return _L("destination port does not match"); |
|
97 case EIpsec_MismatchProtocol: return _L("protocol does not match"); |
|
98 case EIpsec_MismatchSourceIdentity: return _L("source identity does not match"); |
|
99 case EIpsec_MismatchDestinationIdentity: return _L("destination identity does not match"); |
|
100 |
|
101 case EIpsec_BadCipherKey: return _L("Key in SA is too short (for the algorithm) or is weak"); |
|
102 case EIpsec_UnknownCipherNumber: return _L("Attempting to use algorithm number that is not known"); |
|
103 case EIpsec_UnknownDigestNumber: return _L("Attempting to use algorithm number that is not known"); |
|
104 case EIpsec_UnavailableCipher: return _L("No installed library implements the cipher"); |
|
105 case EIpsec_UnavailableDigest: return _L("No installed library implements the digest"); |
|
106 // |
|
107 // Temporary place for new errors |
|
108 // |
|
109 case EIpsec_IcmpError: return _L("An ICMP error report containing AH or ESP (for INET6)"); |
|
110 case EIpsec_LostSA: return _L("An SA has been lost between Apply and Verify, expired? (for SECPOL)"); |
|
111 case EIpsec_NoInnerSource: return _L("Cannot find inner-src for outbound packet when tunneling (for SECPOL)"); |
|
112 // |
|
113 // Special code for NAT Traversal |
|
114 // |
|
115 case EIpsec_NotANATTPacket: return _L("UDP packet is NOT a NAT Taversal packet"); |
|
116 case EIpsec_FragmentMismatch: return _L("IPSEC on fragment is not same as before, packet dropped"); |
|
117 |
|
118 default: |
|
119 return _L("Unknown reason"); |
|
120 } |
|
121 } |
|
122 |
|
123 #endif |
|
124 |
|
125 // ======== MEMBER FUNCTIONS ======== |
|
126 |
|
127 // --------------------------------------------------------------------------- |
|
128 // Two-phased constructor. |
|
129 // --------------------------------------------------------------------------- |
|
130 // |
|
131 CSecpolReader* CSecpolReader::NewL( MKmdEventLoggerIf& aEventLogger, |
|
132 MIkeDebug& aDebug ) |
|
133 { |
|
134 CSecpolReader* self = new (ELeave) CSecpolReader( aEventLogger, |
|
135 aDebug ); |
|
136 CleanupStack::PushL( self ); |
|
137 self->ConstructL(); |
|
138 CleanupStack::Pop( self ); |
|
139 return self; |
|
140 } |
|
141 |
|
142 // --------------------------------------------------------------------------- |
|
143 // Destructor. |
|
144 // --------------------------------------------------------------------------- |
|
145 // |
|
146 CSecpolReader::~CSecpolReader() |
|
147 { |
|
148 DEBUG_LOG(_L("CSecpolReader::~CSecpolReader")); |
|
149 Cancel(); |
|
150 iSocket.Close(); |
|
151 iSocketServer.Close(); |
|
152 } |
|
153 |
|
154 // --------------------------------------------------------------------------- |
|
155 // Constructor. |
|
156 // --------------------------------------------------------------------------- |
|
157 // |
|
158 CSecpolReader::CSecpolReader( MKmdEventLoggerIf& aEventLogger, |
|
159 MIkeDebug& aDebug ) |
|
160 : CActive( EPriorityStandard ), |
|
161 iEventLogger( aEventLogger ), |
|
162 iDebug( aDebug ) |
|
163 { |
|
164 CActiveScheduler::Add( this ); |
|
165 } |
|
166 |
|
167 // --------------------------------------------------------------------------- |
|
168 // Second phase construction. |
|
169 // --------------------------------------------------------------------------- |
|
170 // |
|
171 void CSecpolReader::ConstructL() |
|
172 { |
|
173 TInetAddr addr; |
|
174 User::LeaveIfError( iSocketServer.Connect() ); |
|
175 User::LeaveIfError( iSocket.Open( iSocketServer, _L("secpol6") ) ); |
|
176 addr.SetAddress( KInetAddrNone ); |
|
177 addr.SetPort( 0 ); |
|
178 User::LeaveIfError( iSocket.Bind( addr ) ); |
|
179 iSocket.RecvFrom( iMsg, iAddr, 0, iStatus ); |
|
180 SetActive(); |
|
181 DEBUG_LOG(_L("CSecpolReader::ConstructL - constructed")); |
|
182 } |
|
183 |
|
184 // --------------------------------------------------------------------------- |
|
185 // Returns event logger. |
|
186 // --------------------------------------------------------------------------- |
|
187 // |
|
188 MKmdEventLoggerIf& CSecpolReader::EventLogger() |
|
189 { |
|
190 return iEventLogger; |
|
191 } |
|
192 |
|
193 |
|
194 // --------------------------------------------------------------------------- |
|
195 // From class CActive |
|
196 // Handles completion of asynchronous reading. |
|
197 // --------------------------------------------------------------------------- |
|
198 // |
|
199 void CSecpolReader::RunL() |
|
200 { |
|
201 #ifdef _DEBUG |
|
202 TBuf<40> buf; |
|
203 TBuf<1000> str; |
|
204 TInt protocol = -1; |
|
205 #endif // _DEBUG |
|
206 TInt len = 0; |
|
207 TBool processEvent; |
|
208 TSecpolPayload packet( iMsg.Ptr() ); |
|
209 |
|
210 DEBUG_LOG1(_L("Secpol read, status=%d"), iStatus.Int()); |
|
211 __ASSERT_DEBUG( iStatus.Int() == KErrNone, |
|
212 User::Invariant() ); |
|
213 if ( iStatus.Int() == KErrNone ) |
|
214 { |
|
215 switch ( packet.iIP4->Version() ) |
|
216 { |
|
217 case 4: |
|
218 processEvent = ((THdrIP4 *)packet.iRaw)->IsUnicast(); |
|
219 if ( processEvent ) |
|
220 { |
|
221 #ifdef _DEBUG |
|
222 ((THdrIP4 *)packet.iRaw)->Dump( str, iMsg.Length() ); |
|
223 protocol = packet.iIP4->Protocol(); |
|
224 #endif // _DEBUG |
|
225 len = packet.iIP4->HeaderLength(); |
|
226 } |
|
227 break; |
|
228 case 6: |
|
229 processEvent = ((THdrIP6 *)packet.iRaw)->IsUnicast(); |
|
230 if ( processEvent ) |
|
231 { |
|
232 #ifdef _DEBUG |
|
233 ((THdrIP6 *)packet.iRaw)->Dump( str, iMsg.Length() ); |
|
234 protocol = packet.iIP6->NextHeader(); |
|
235 #endif // _DEBUG |
|
236 len = packet.iIP6->HeaderLength(); |
|
237 } |
|
238 break; |
|
239 default: |
|
240 processEvent = ETrue; |
|
241 #ifdef _DEBUG |
|
242 str.Format( _L("Unknown IP protocol version %d"), |
|
243 (TInt)packet.iIP4->Version() ); |
|
244 #endif // _DEBUG |
|
245 break; |
|
246 } |
|
247 |
|
248 if ( processEvent ) |
|
249 { |
|
250 if ( len ) |
|
251 { |
|
252 packet.iRaw += len; |
|
253 #ifdef _DEBUG |
|
254 packet.Dump( str, iMsg.Length()-len, protocol ); |
|
255 #endif // _DEBUG |
|
256 } |
|
257 #ifdef _DEBUG |
|
258 str.Append( _L(" from ") ); |
|
259 (TInetAddr::Cast(iAddr)).OutputWithScope( buf ); |
|
260 str.Append( buf ); |
|
261 str.Append( _L(" because ") ); |
|
262 str.Append( IpsecError( iAddr.Port() ) ); |
|
263 str.AppendFormat( _L(" (%d)"), iAddr.Port() ); |
|
264 DEBUG_LOG(str); |
|
265 #endif // _DEBUG |
|
266 |
|
267 LOG_KMD_EVENT( MKmdEventLoggerIf::KLogWarning, |
|
268 R_VPN_MSG_DATA_DROPPED_DUE_POLICY, |
|
269 (TInt)iAddr.Port(), |
|
270 0, |
|
271 &iAddr ); |
|
272 } |
|
273 } |
|
274 |
|
275 iSocket.RecvFrom( iMsg, iAddr, 0, iStatus ); // start a new read |
|
276 SetActive(); |
|
277 } |
|
278 |
|
279 // --------------------------------------------------------------------------- |
|
280 // From class CActive |
|
281 // Handles cancellation of asynchronous reading. |
|
282 // --------------------------------------------------------------------------- |
|
283 // |
|
284 void CSecpolReader::DoCancel() |
|
285 { |
|
286 iSocket.CancelRecv(); |
|
287 } |