|
1 /* |
|
2 * Copyright (c) 2008-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: Implementation of VPN PFKEY socket interface |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <es_sock.h> |
|
20 #include <in_sock.h> |
|
21 #include <eikenv.h> |
|
22 #include <pfkey_send.h> |
|
23 #include <random.h> |
|
24 #include "pfkeysocketif.h" |
|
25 #include "pfkeymsg.h" |
|
26 #include "ipsecsadata.h" |
|
27 #include "ipsecsalifetime.h" |
|
28 #include "ikedebug.h" |
|
29 |
|
30 const TInt KDefaultPID( 0x2001E609 ); // UID3 of ikeutils.dll |
|
31 |
|
32 // ======== MEMBER FUNCTIONS ======== |
|
33 |
|
34 EXPORT_C CPFKeySocketIf* CPFKeySocketIf::NewL( MPFKeyMessageListener* aListener, |
|
35 MIkeDebug& aDebug ) |
|
36 { |
|
37 CPFKeySocketIf* reader = new ( ELeave ) CPFKeySocketIf( aListener, aDebug ); |
|
38 CleanupStack::PushL( reader ); |
|
39 reader->ConstructL(); |
|
40 CleanupStack::Pop( reader ); |
|
41 return reader; |
|
42 } |
|
43 |
|
44 // |
|
45 // CPFKeySocketIf::~CPFKeySocketIf |
|
46 // |
|
47 CPFKeySocketIf::~CPFKeySocketIf() |
|
48 { |
|
49 Cancel(); |
|
50 iPendingSpiRequests.Close(); |
|
51 iSadb.Close(); |
|
52 iSocketServer.Close(); |
|
53 } |
|
54 |
|
55 // |
|
56 // CPFKeySocketIf::CPFKeySocketIf |
|
57 // |
|
58 CPFKeySocketIf::CPFKeySocketIf( MPFKeyMessageListener* aListener, |
|
59 MIkeDebug& aDebug ) |
|
60 : CActive( EPriorityNormal ), |
|
61 iListener( aListener ), |
|
62 iSeq( 0 ), |
|
63 iDebug( aDebug ) |
|
64 { |
|
65 CActiveScheduler::Add( this ); |
|
66 } |
|
67 |
|
68 // |
|
69 // CPFKeySocketIf::ConstructL() |
|
70 // Open and activate the socket input |
|
71 // |
|
72 void CPFKeySocketIf::ConstructL() |
|
73 { |
|
74 TPtr8 ptr( (TUint8*)&iSpiBase, sizeof( iSpiBase ) ); |
|
75 ptr.SetLength( sizeof( iSpiBase ) ); |
|
76 TRandom::RandomL( ptr ); |
|
77 iSpiBase &= 0x7fffffff; |
|
78 |
|
79 User::LeaveIfError( iSocketServer.Connect() ); |
|
80 User::LeaveIfError( iSadb.Open( iSocketServer ) ); |
|
81 |
|
82 // |
|
83 // Register for ACQUIRE messages |
|
84 // |
|
85 TPfkeySendMsg reg( SADB_REGISTER, SADB_SATYPE_ESP, ++iSeq, KDefaultPID ); |
|
86 TRequestStatus status; |
|
87 iSadb.FinalizeAndSend( reg, status ); |
|
88 User::WaitForRequest( status ); |
|
89 DEBUG_LOG1( _L("Register for ESP, status=%d"), iStatus.Int() ); |
|
90 |
|
91 iMsg.Reset(); |
|
92 iSadb.ReadRequest( iMsg, iStatus ); |
|
93 SetActive(); |
|
94 } |
|
95 |
|
96 |
|
97 void CPFKeySocketIf::GetSpi( const TUint8 aType, |
|
98 const TUint32 aSeq, |
|
99 const TInetAddr& aSrc, |
|
100 const TInetAddr& aDst, |
|
101 TUint32& aSpi, |
|
102 TRequestStatus& aClientStatus) |
|
103 { |
|
104 /*Params: |
|
105 aType:SADB_SATYPE_AH,SADB_SATYPE_ESP from prop_II |
|
106 aSeq: Seq number for the message |
|
107 aSrc,aDst: Src & dst addresses |
|
108 */ |
|
109 TRequestStatus status; |
|
110 TUint32 start = NewSpi(); |
|
111 |
|
112 TPfkeySendMsg msg( SADB_GETSPI, aType, aSeq, (TUint32)&aClientStatus ); |
|
113 msg.Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSrc ); |
|
114 msg.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDst ); |
|
115 msg.Add( Int2Type<SADB_EXT_SPIRANGE>(), start ); |
|
116 |
|
117 aClientStatus = KRequestPending; |
|
118 TPendingSpiRequest pendingSpiRequest(aSpi, aClientStatus); |
|
119 TInt err = iPendingSpiRequests.Append(pendingSpiRequest); |
|
120 |
|
121 if (err == KErrNone) |
|
122 { |
|
123 iSadb.FinalizeAndSend( msg, status ); |
|
124 User::WaitForRequest( status ); |
|
125 } |
|
126 else |
|
127 { |
|
128 TRequestStatus* status = &aClientStatus; |
|
129 User::RequestComplete(status, err); |
|
130 } |
|
131 } |
|
132 |
|
133 |
|
134 void CPFKeySocketIf::CancelGetSpi(TRequestStatus& aClientStatus) |
|
135 { |
|
136 for (TInt i = 0; i < iPendingSpiRequests.Count(); ++i) |
|
137 { |
|
138 TPendingSpiRequest& pendingSpiRequest = iPendingSpiRequests[i]; |
|
139 if (&pendingSpiRequest.iClientStatus == &aClientStatus) |
|
140 { |
|
141 pendingSpiRequest.iSpi = 0; |
|
142 TRequestStatus* status = &pendingSpiRequest.iClientStatus; |
|
143 iPendingSpiRequests.Remove(i); |
|
144 User::RequestComplete(status, KErrCancel); |
|
145 break; |
|
146 } |
|
147 } |
|
148 } |
|
149 |
|
150 |
|
151 // Sends Acquire with errno informing about key management failure. |
|
152 EXPORT_C void CPFKeySocketIf::AcquireSAError( const TIpsecSAData& aSAData, |
|
153 const TInt aError ) |
|
154 { |
|
155 TRequestStatus status; |
|
156 TInt err = -aError; |
|
157 TPfkeySendMsg msg( SADB_ACQUIRE, |
|
158 aSAData.iSAType, |
|
159 aSAData.iSeq, |
|
160 aSAData.iPid ); |
|
161 |
|
162 struct sadb_msg& msgHdr = msg.MsgHdr(); |
|
163 msgHdr.sadb_msg_errno = (TUint8) err; |
|
164 msgHdr.sadb_msg_reserved = (TUint16) ( err>>8 ); |
|
165 |
|
166 msg.Add( Int2Type<SADB_EXT_SA>(), aSAData.iSPI ); |
|
167 msg.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aSAData.iDst ); |
|
168 iSadb.FinalizeAndSend( msg, status ); |
|
169 User::WaitForRequest( status ); |
|
170 } |
|
171 |
|
172 EXPORT_C void CPFKeySocketIf::UpdateSAL( const TIpsecSAData& aSAData ) |
|
173 { |
|
174 AddUpdateSAL( SADB_UPDATE, aSAData ); |
|
175 } |
|
176 |
|
177 EXPORT_C void CPFKeySocketIf::AddSAL( const TIpsecSAData& aSAData ) |
|
178 { |
|
179 AddUpdateSAL( SADB_ADD, aSAData ); |
|
180 } |
|
181 |
|
182 EXPORT_C void CPFKeySocketIf::DeleteSA( const TUint32 aSPI, |
|
183 const TInetAddr& aSrc, |
|
184 const TInetAddr& aDst, |
|
185 const TUint8 aProtocol ) |
|
186 { |
|
187 TRequestStatus status; |
|
188 TPfkeySendMsg msg( SADB_DELETE, |
|
189 aProtocol ); |
|
190 msg.Add( Int2Type<SADB_EXT_SA>(), aSPI ); |
|
191 msg.Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSrc ); |
|
192 msg.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDst ); |
|
193 iSadb.FinalizeAndSend( msg, status ); |
|
194 User::WaitForRequest( status ); |
|
195 } |
|
196 |
|
197 EXPORT_C void CPFKeySocketIf::FlushSAs() |
|
198 { |
|
199 TRequestStatus status; |
|
200 TPfkeySendMsg msg( SADB_FLUSH, |
|
201 SADB_SATYPE_UNSPEC, |
|
202 ++iSeq, |
|
203 KDefaultPID ); |
|
204 iSadb.FinalizeAndSend( msg, status ); |
|
205 User::WaitForRequest( status ); |
|
206 DEBUG_LOG1( _L("Request FLUSH, iStatus=%d"), iStatus.Int() ); |
|
207 } |
|
208 |
|
209 //Updates an SA from the SA database. |
|
210 //SPI in Net order. |
|
211 void CPFKeySocketIf::AddUpdateSAL( const TUint8 aType, |
|
212 const TIpsecSAData &aSAData ) |
|
213 { |
|
214 TRequestStatus status; |
|
215 TPfkeySendMsg* msg = new( ELeave ) TPfkeySendMsg( aType, |
|
216 aSAData.iSAType, |
|
217 aSAData.iSeq, |
|
218 aSAData.iPid ); |
|
219 msg->Add( Int2Type<SADB_EXT_SA>(), |
|
220 aSAData.iSPI, |
|
221 aSAData.iAuthAlg, |
|
222 aSAData.iEncrAlg, |
|
223 SADB_SASTATE_MATURE, |
|
224 aSAData.iReplayWindowLength, |
|
225 aSAData.iFlags ); |
|
226 |
|
227 if( aSAData.iHard ) |
|
228 { |
|
229 msg->Add( Int2Type<SADB_EXT_LIFETIME_HARD>(), |
|
230 aSAData.iHard->iAllocations, |
|
231 aSAData.iHard->iBytes, |
|
232 aSAData.iHard->iAddtime, |
|
233 aSAData.iHard->iUsetime); |
|
234 } |
|
235 if( aSAData.iSoft ) |
|
236 { |
|
237 msg->Add( Int2Type<SADB_EXT_LIFETIME_SOFT>(), |
|
238 aSAData.iSoft->iAllocations, |
|
239 aSAData.iSoft->iBytes, |
|
240 aSAData.iSoft->iAddtime, |
|
241 aSAData.iSoft->iUsetime); |
|
242 } |
|
243 msg->Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), |
|
244 aSAData.iSrc, |
|
245 aSAData.iProtocol ); |
|
246 msg->Add( Int2Type<SADB_EXT_ADDRESS_DST>(), |
|
247 aSAData.iDst, |
|
248 aSAData.iProtocol ); |
|
249 |
|
250 // Deliver internal address for IPSEC4 |
|
251 if ( aSAData.iFlags & SADB_SAFLAGS_INT_ADDR ) |
|
252 msg->Add( Int2Type<SADB_EXT_ADDRESS_PROXY>(), |
|
253 aSAData.iInternalAddress ); |
|
254 |
|
255 if ( aSAData.iAuthKey.Length() > 0 ) |
|
256 { |
|
257 msg->Add( Int2Type<SADB_EXT_KEY_AUTH>(), |
|
258 aSAData.iAuthKey ); |
|
259 } |
|
260 if ( aSAData.iEncrKey.Length() > 0 ) |
|
261 { |
|
262 msg->Add( Int2Type<SADB_EXT_KEY_ENCRYPT>(), |
|
263 aSAData.iEncrKey ); |
|
264 } |
|
265 if ( aSAData.iSrcIdent.Length() > 0 ) |
|
266 { |
|
267 msg->Add( Int2Type<SADB_EXT_IDENTITY_SRC>(), |
|
268 aSAData.iSrcIdent, |
|
269 aSAData.iSrcIdType ); |
|
270 } |
|
271 if ( aSAData.iDstIdent.Length() > 0 ) |
|
272 { |
|
273 msg->Add( Int2Type<SADB_EXT_IDENTITY_DST>(), |
|
274 aSAData.iDstIdent, |
|
275 aSAData.iDstIdType ); |
|
276 } |
|
277 |
|
278 // Deliver generic private PFKEY API extension, if exist. |
|
279 // In this phase extension can consists NAT traversal information for ESP UDP encapsulation (done by IPSEC) |
|
280 if ( aSAData.iGenericExtension.Length() ) |
|
281 { |
|
282 msg->Add( Int2Type<SADB_PRIV_GENERIC_EXT>(), |
|
283 aSAData.iGenericExtension ); |
|
284 } |
|
285 |
|
286 iSadb.FinalizeAndSend( *msg, status ); |
|
287 User::WaitForRequest( status ); |
|
288 delete msg; |
|
289 } |
|
290 |
|
291 TUint32 CPFKeySocketIf::NewSpi() |
|
292 { |
|
293 iSpiBase++; |
|
294 return iSpiBase; |
|
295 } |
|
296 |
|
297 // |
|
298 // SocketReader::ShowMessage |
|
299 // Output actual "payload" messages (e.g. PFKEY) |
|
300 // |
|
301 #ifdef _DEBUG |
|
302 void CPFKeySocketIf::ShowMessageL( TPfkeyRecvMsg &aMsg ) |
|
303 { |
|
304 HBufC* buffer = HBufC::NewL( 1000 ); |
|
305 TPtr str( buffer->Des() ); |
|
306 TPfkeyMessage msg( aMsg ); |
|
307 |
|
308 if ( msg.iError ) |
|
309 { |
|
310 str.Format( _L("Received malformed PFKEY msg of %d bytes: %d\n"), |
|
311 aMsg.Length(), msg.iError ); |
|
312 } |
|
313 else |
|
314 { |
|
315 msg.iBase.String( str, _L(" ") ); |
|
316 msg.iSa.String( str, _L(" ") ); |
|
317 msg.iCurrent.String( str, _L(" C=") ); |
|
318 msg.iHard.String( str, _L(" H=") ); |
|
319 msg.iSoft.String( str, _L(" S=") ); |
|
320 msg.iSrcAddr.String( str, _L(" SRC=") ); |
|
321 msg.iDstAddr.String( str, _L(" DST=") ); |
|
322 msg.iProxyAddr.String( str, _L(" PROXY=") ); |
|
323 msg.iAuthKey.String( str, _L(" AUTHKEY=") ); |
|
324 msg.iEncryptKey.String( str, _L(" ENCRYPTKEY=") ); |
|
325 msg.iSrcIdent.String( str, _L(" SRCI=") ); |
|
326 msg.iDstIdent.String( str, _L(" DSTI=") ); |
|
327 msg.iSensitivity.String( str, _L(" SENS=") ); |
|
328 msg.iProposal.String( str, _L(" PROP=") ); |
|
329 msg.iAuthAlgs.String( str, _L(" AUTH=") ); |
|
330 msg.iEncryptAlgs.String( str, _L(" ENCR=") ); |
|
331 msg.iSpirange.String( str, _L(" SPIR=") ); |
|
332 msg.iTs.String( str, _L(" TS=") ); |
|
333 msg.iPrivateExtension.String( str, _L(" GEN_EXT=") ); |
|
334 } |
|
335 DEBUG_LOG( str ); |
|
336 |
|
337 delete buffer; |
|
338 buffer = NULL; |
|
339 } |
|
340 #endif |
|
341 |
|
342 // |
|
343 // CPFKeySocketIf::RunL |
|
344 // Called when request completed |
|
345 // |
|
346 void CPFKeySocketIf::RunL() |
|
347 { |
|
348 if ( iStatus.Int() != KErrNone ) |
|
349 { |
|
350 DEBUG_LOG1( _L("Socket read, iStatus=%d"), iStatus.Int() ); |
|
351 } |
|
352 |
|
353 #ifdef _DEBUG |
|
354 TRAP_IGNORE( ShowMessageL( iMsg ) ); |
|
355 #endif |
|
356 |
|
357 TPfkeyMessage msg(iMsg); |
|
358 if ( ( msg.iError == KErrNone ) && |
|
359 ( msg.iBase.iMsg->sadb_msg_errno == KErrNone ) ) // No error |
|
360 { |
|
361 switch ( msg.iBase.iMsg->sadb_msg_type ) |
|
362 { |
|
363 case SADB_GETSPI: |
|
364 for (TInt i = 0; i < iPendingSpiRequests.Count(); ++i) |
|
365 { |
|
366 TPendingSpiRequest& pendingSpiRequest = iPendingSpiRequests[i]; |
|
367 if ((TUint32)&pendingSpiRequest.iClientStatus == msg.iBase.iMsg->sadb_msg_pid) |
|
368 { |
|
369 pendingSpiRequest.iSpi = msg.iSa.iExt->sadb_sa_spi; |
|
370 TRequestStatus* status = &pendingSpiRequest.iClientStatus; |
|
371 iPendingSpiRequests.Remove(i); |
|
372 User::RequestComplete(status, KErrNone); |
|
373 break; |
|
374 } |
|
375 } |
|
376 break; |
|
377 case SADB_ADD: // Fall through |
|
378 case SADB_UPDATE: // Fall through |
|
379 case SADB_ACQUIRE: // Fall through |
|
380 case SADB_EXPIRE: // Fall through |
|
381 iListener->PfkeyMessageReceived( msg ); |
|
382 break; |
|
383 |
|
384 default: |
|
385 break; |
|
386 } |
|
387 } |
|
388 else |
|
389 { |
|
390 DEBUG_LOG2( _L("Error in Pfkey message, iError=%d, sadb_msg_errno=%d"), |
|
391 iStatus.Int(), msg.iBase.iMsg->sadb_msg_errno ); |
|
392 } |
|
393 iMsg.Reset(); |
|
394 iSadb.ReadRequest( iMsg, iStatus ); // Start a new read |
|
395 SetActive(); |
|
396 } |
|
397 |
|
398 // |
|
399 // CPFKeySocketIf::DoCancel |
|
400 // Called when a pending request should be cancelled |
|
401 // |
|
402 void CPFKeySocketIf::DoCancel() |
|
403 { |
|
404 iSadb.CancelRecv(); |
|
405 } |
|
406 |
|
407 // |
|
408 // CPFKeySocketIf::RunError |
|
409 // Called when RunL() leaves |
|
410 // |
|
411 TInt CPFKeySocketIf::RunError( TInt aError ) |
|
412 { |
|
413 DEBUG_LOG1( _L("CPFKeySocketIf::RunError() aError=%d, PFKEY message lost"), |
|
414 aError ); |
|
415 aError = aError; |
|
416 |
|
417 iMsg.Reset(); |
|
418 iSadb.ReadRequest( iMsg, iStatus ); // Start a new read. |
|
419 SetActive(); |
|
420 |
|
421 return KErrNone; // Active scheduler Error() method NOT called |
|
422 } |
|
423 |