|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Name : CIpSecSadbHandler.cpp |
|
15 // Part of : SIPSec |
|
16 // Version : SIP/4.0 |
|
17 // |
|
18 |
|
19 |
|
20 |
|
21 #include <pfkey_send.h> |
|
22 #include <lib_pfkey.h> |
|
23 |
|
24 #include "siprequest.h" |
|
25 #include "sipresponse.h" |
|
26 #include "sipsecurityclientheader.h" |
|
27 #include "sipsecurityserverheader.h" |
|
28 #include "sipsecurityverifyheader.h" |
|
29 |
|
30 #include "CIpSecSadbHandler.h" |
|
31 #include "MSipSecSaDbSendReceiveObserver.h" |
|
32 #include "SipSecIpsecParams.h" |
|
33 #include "SipSecUtils.h" |
|
34 #include "CSipSecSaDbMsgSender.h" |
|
35 #include "CSipSecSaDbMsgReceiver.h" |
|
36 #include "MIpSecMechanismParams.h" |
|
37 #include "MSipSecSadbObserver.h" |
|
38 |
|
39 const TInt KOngoingAddsGranularity = 4; |
|
40 |
|
41 // ---------------------------------------------------------------------------- |
|
42 // CIpSecSadbHandler::NewL |
|
43 // ---------------------------------------------------------------------------- |
|
44 // |
|
45 CIpSecSadbHandler* CIpSecSadbHandler::NewL( |
|
46 MSipSecSadbObserver& aObserver, |
|
47 RSADB& aSADB ) |
|
48 { |
|
49 CIpSecSadbHandler* self = new ( ELeave ) CIpSecSadbHandler( aObserver ); |
|
50 CleanupStack::PushL( self ); |
|
51 self->ConstructL( aSADB ); |
|
52 CleanupStack::Pop( self ); |
|
53 return self; |
|
54 } |
|
55 |
|
56 // ---------------------------------------------------------------------------- |
|
57 // CIpSecSadbHandler::ConstructL |
|
58 // ---------------------------------------------------------------------------- |
|
59 // |
|
60 void CIpSecSadbHandler::ConstructL( RSADB& aSADB ) |
|
61 { |
|
62 iSaDbMsgSender = CSipSecSaDbMsgSender::NewL( *this, aSADB ); |
|
63 } |
|
64 |
|
65 |
|
66 // ---------------------------------------------------------------------------- |
|
67 // CIpSecSadbHandler::CIpSecSadbHandler |
|
68 // ---------------------------------------------------------------------------- |
|
69 // |
|
70 CIpSecSadbHandler::CIpSecSadbHandler( MSipSecSadbObserver& aObserver ) : |
|
71 iObserver( aObserver ), |
|
72 iState( EAvailable ), |
|
73 iOngoingAdds( KOngoingAddsGranularity ) |
|
74 { |
|
75 } |
|
76 |
|
77 // ---------------------------------------------------------------------------- |
|
78 // CIpSecSadbHandler::~CIpSecSadbHandler |
|
79 // ---------------------------------------------------------------------------- |
|
80 // |
|
81 CIpSecSadbHandler::~CIpSecSadbHandler() |
|
82 { |
|
83 delete iSaDbMsgSender; |
|
84 iOngoingAdds.Reset(); |
|
85 iOngoingAdds.Close(); |
|
86 } |
|
87 |
|
88 |
|
89 // ---------------------------------------------------------------------------- |
|
90 // CIpSecSadbHandler::AddSasL |
|
91 // ---------------------------------------------------------------------------- |
|
92 // |
|
93 void CIpSecSadbHandler::AddSasL( |
|
94 MIpSecMechanismParams& aParams, |
|
95 TInetAddr aLocalAddress, |
|
96 TInetAddr aRemoteAddress, |
|
97 TSipSecSaParams& aSaParams ) |
|
98 { |
|
99 IssueRequestL( aParams, |
|
100 aLocalAddress, |
|
101 aRemoteAddress, |
|
102 aSaParams ); |
|
103 |
|
104 // Kick-start SA adding looping |
|
105 AddCompletedL( KErrNone ); |
|
106 } |
|
107 |
|
108 // ---------------------------------------------------------------------------- |
|
109 // CIpSecSadbHandler::DeleteSasL |
|
110 // ---------------------------------------------------------------------------- |
|
111 // |
|
112 void CIpSecSadbHandler::DeleteSasL( |
|
113 MIpSecMechanismParams& aParams, |
|
114 TInetAddr aLocalAddress, |
|
115 TInetAddr aRemoteAddress, |
|
116 TSipSecSaParams& aSaParams ) |
|
117 { |
|
118 CancelAddSaOps(); |
|
119 |
|
120 IssueRequestL( aParams, |
|
121 aLocalAddress, |
|
122 aRemoteAddress, |
|
123 aSaParams ); |
|
124 |
|
125 // Kick-start SA deleting looping |
|
126 DeleteCompletedL(); |
|
127 } |
|
128 |
|
129 // ---------------------------------------------------------------------------- |
|
130 // CIpSecSadbHandler::SetSaParamsL |
|
131 // ---------------------------------------------------------------------------- |
|
132 // |
|
133 void CIpSecSadbHandler::SetSaParamsL( |
|
134 TSipSecSaParams& aParams, |
|
135 CSIPSecurityHeaderBase& aCliHeader, |
|
136 CSIPSecurityHeaderBase& aSrvHeader, |
|
137 const TDesC8& aAuthKey ) |
|
138 { |
|
139 TInt len = aAuthKey.Length(); |
|
140 __ASSERT_ALWAYS( len == KAuthKeyFromSIMSize && len <= KAuthKeyMaxSize, |
|
141 User::Leave( KErrArgument ) ); |
|
142 |
|
143 aParams.iSpi_uc = SipSecUtils::ValueL( aCliHeader, KSpic ); |
|
144 aParams.iSpi_us = SipSecUtils::ValueL( aCliHeader, KSpis ); |
|
145 aParams.iPort_uc = SipSecUtils::ValueL( aCliHeader, KPortc ); |
|
146 aParams.iPort_us = SipSecUtils::ValueL( aCliHeader, KPorts ); |
|
147 aParams.iSpi_pc = SipSecUtils::ValueL( aSrvHeader, KSpic ); |
|
148 aParams.iSpi_ps = SipSecUtils::ValueL( aSrvHeader, KSpis ); |
|
149 aParams.iPort_pc = SipSecUtils::ValueL( aSrvHeader, KPortc ); |
|
150 aParams.iPort_ps = SipSecUtils::ValueL( aSrvHeader, KPorts ); |
|
151 |
|
152 RStringF v = SipSecUtils::ValueFL( aCliHeader, KAlgorithm ); |
|
153 const TDesC8& alg = v.DesC(); |
|
154 __ASSERT_ALWAYS( alg.Length(),User::Leave( KErrNotReady ) ); |
|
155 if ( alg == KHmacMd596 ) |
|
156 { |
|
157 aParams.iAuthAlg = SADB_AALG_MD5HMAC; |
|
158 aParams.iAuthKey.Copy( aAuthKey ); |
|
159 } |
|
160 else |
|
161 { |
|
162 aParams.iAuthAlg = SADB_AALG_SHA1HMAC; |
|
163 |
|
164 // In hmac-sha-1-96 160 bit key has to be used, aAuthKey retrieved |
|
165 // from SIM should be only 128 bits, pad with zeros from right |
|
166 const TUint KPadLength = 4; |
|
167 |
|
168 __ASSERT_ALWAYS( KAuthKeyFromSIMSize + KPadLength <= KAuthKeyMaxSize, |
|
169 User::Leave( KErrOverflow ) ); |
|
170 |
|
171 TBuf8<KAuthKeyMaxSize> authkey; |
|
172 authkey.Append( aAuthKey ); |
|
173 const TUint KPosKeyEnd = authkey.Length(); |
|
174 authkey.SetMax(); |
|
175 LittleEndian::Put32( &authkey[ KPosKeyEnd ], 0 ); |
|
176 aParams.iAuthKey.Copy( authkey ); |
|
177 } |
|
178 |
|
179 } |
|
180 |
|
181 // ---------------------------------------------------------------------------- |
|
182 // CIpSecSadbHandler::CancelAddSAOps |
|
183 // ---------------------------------------------------------------------------- |
|
184 // |
|
185 void CIpSecSadbHandler::CancelAddSaOps() |
|
186 { |
|
187 if ( iSaDbMsgSender->Type() == SADB_ADD ) |
|
188 { |
|
189 iSaDbMsgSender->Cancel(); |
|
190 Reset(); |
|
191 } |
|
192 } |
|
193 |
|
194 // ---------------------------------------------------------------------------- |
|
195 // CIpSecSadbHandler::SADBAddMsgReceived |
|
196 // ---------------------------------------------------------------------------- |
|
197 // |
|
198 void CIpSecSadbHandler::SADBAddMsgReceived( TUint aMsgSeq, TInt aError ) |
|
199 { |
|
200 TInt index = iOngoingAdds.FindInOrder( aMsgSeq ); |
|
201 if ( index != KErrNotFound ) |
|
202 { |
|
203 iOngoingAdds.Remove( index ); |
|
204 iOngoingAdds.Compress(); |
|
205 |
|
206 TBool aSuccess( !aError ); |
|
207 |
|
208 TRAP_IGNORE( SAsAddedL( aSuccess ) ) |
|
209 } |
|
210 } |
|
211 |
|
212 // ---------------------------------------------------------------------------- |
|
213 // CIpSecSadbHandler::MessageSentL |
|
214 // ---------------------------------------------------------------------------- |
|
215 // |
|
216 void CIpSecSadbHandler::MessageSentL( TInt aStatus, TInt aMsgType ) |
|
217 { |
|
218 if ( aMsgType == SADB_ADD ) |
|
219 { |
|
220 AddCompletedL( aStatus ); |
|
221 } |
|
222 else |
|
223 { |
|
224 // Error is ignored since anyway we should try to delete existing SAs |
|
225 DeleteCompletedL(); |
|
226 } |
|
227 } |
|
228 |
|
229 // ---------------------------------------------------------------------------- |
|
230 // CIpSecSadbHandler::MessageReceived |
|
231 // ---------------------------------------------------------------------------- |
|
232 // |
|
233 void CIpSecSadbHandler::MessageReceived( TInt /* aStatus */ ) |
|
234 { |
|
235 // Not used in this context |
|
236 } |
|
237 |
|
238 // ---------------------------------------------------------------------------- |
|
239 // CIpSecSadbHandler::IssueRequestL |
|
240 // ---------------------------------------------------------------------------- |
|
241 // |
|
242 void CIpSecSadbHandler::IssueRequestL( |
|
243 MIpSecMechanismParams& aParams, |
|
244 TInetAddr& aLocalAddress, |
|
245 TInetAddr& aRemoteAddress, |
|
246 TSipSecSaParams& aSaParams ) |
|
247 { |
|
248 if ( !IsAvailable() ) |
|
249 { |
|
250 User::Leave( KErrInUse ); |
|
251 } |
|
252 |
|
253 // Remember parameters regarding current request |
|
254 iParams = &aParams; |
|
255 iSaParams = &aSaParams; |
|
256 |
|
257 iLocalAddress = aLocalAddress; |
|
258 iRemoteAddress = aRemoteAddress; |
|
259 } |
|
260 |
|
261 // ---------------------------------------------------------------------------- |
|
262 // CIpSecSadbHandler::IsAvailable |
|
263 // ---------------------------------------------------------------------------- |
|
264 // |
|
265 TBool CIpSecSadbHandler::IsAvailable() |
|
266 { |
|
267 return ( iState == EAvailable ); |
|
268 } |
|
269 |
|
270 // ---------------------------------------------------------------------------- |
|
271 // CIpSecSadbHandler::Reset |
|
272 // ---------------------------------------------------------------------------- |
|
273 // |
|
274 void CIpSecSadbHandler::Reset() |
|
275 { |
|
276 iState = EAvailable; |
|
277 iOngoingAdds.Reset(); |
|
278 iOngoingAdds.Compress(); |
|
279 } |
|
280 |
|
281 // ---------------------------------------------------------------------------- |
|
282 // CIpSecSadbHandler::AddCompletedL |
|
283 // ---------------------------------------------------------------------------- |
|
284 // |
|
285 void CIpSecSadbHandler::AddCompletedL( TInt aError ) |
|
286 { |
|
287 // No use to continue if failure occured |
|
288 if ( aError != KErrNone ) |
|
289 { |
|
290 SAsAddedL( EFalse ); |
|
291 } |
|
292 |
|
293 switch ( iState ) |
|
294 { |
|
295 case EAvailable: |
|
296 { |
|
297 // 1. Inbound spi_us: port_us <- port_pc |
|
298 |
|
299 // Note: Family is KAfInet |
|
300 iLocalAddress.SetPort( iSaParams->iPort_us ); |
|
301 iRemoteAddress.SetPort( iSaParams->iPort_pc ); |
|
302 AddSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_us ); |
|
303 iState = EAddingInbound1; |
|
304 break; |
|
305 } |
|
306 case EAddingInbound1: |
|
307 { |
|
308 // 2. Inbound spi_uc: port_uc <- port_ps |
|
309 |
|
310 iLocalAddress.SetPort( iSaParams->iPort_uc ); |
|
311 iRemoteAddress.SetPort( iSaParams->iPort_ps ); |
|
312 AddSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_uc ); |
|
313 iState = EAddingInbound2; |
|
314 break; |
|
315 } |
|
316 case EAddingInbound2: |
|
317 { |
|
318 // 3. Outbound spi_ps: port_uc -> port_ps |
|
319 |
|
320 iLocalAddress.SetPort( iSaParams->iPort_uc ); |
|
321 iRemoteAddress.SetPort( iSaParams->iPort_ps ); |
|
322 AddSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_ps ); |
|
323 iState = EAddingOutbound1; |
|
324 break; |
|
325 } |
|
326 case EAddingOutbound1: |
|
327 { |
|
328 // 4. Outbound spi_pc: port_us -> port_pc |
|
329 |
|
330 iLocalAddress.SetPort( iSaParams->iPort_us ); |
|
331 iRemoteAddress.SetPort( iSaParams->iPort_pc ); |
|
332 AddSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_pc ); |
|
333 iState = EAddingOutbound2; |
|
334 break; |
|
335 } |
|
336 case EAddingOutbound2: |
|
337 { |
|
338 iState = EAvailable; |
|
339 SAsAddedL( ETrue ); |
|
340 break; |
|
341 } |
|
342 default: |
|
343 { |
|
344 break; |
|
345 } |
|
346 } |
|
347 } |
|
348 |
|
349 // ---------------------------------------------------------------------------- |
|
350 // CIpSecSadbHandler::DeleteCompletedL |
|
351 // ---------------------------------------------------------------------------- |
|
352 // |
|
353 void CIpSecSadbHandler::DeleteCompletedL() |
|
354 { |
|
355 switch ( iState ) |
|
356 { |
|
357 case EAvailable: |
|
358 { |
|
359 // 1. Inbound spi_us: port_us <- port_pc |
|
360 |
|
361 // Note: Family is KAfInet |
|
362 iLocalAddress.SetPort( iSaParams->iPort_us ); |
|
363 iRemoteAddress.SetPort( iSaParams->iPort_pc ); |
|
364 DeleteSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_us ); |
|
365 iState = EDeletingInbound1; |
|
366 break; |
|
367 } |
|
368 case EDeletingInbound1: |
|
369 { |
|
370 // 2. Inbound spi_uc: port_uc <- port_ps |
|
371 |
|
372 iLocalAddress.SetPort( iSaParams->iPort_uc ); |
|
373 iRemoteAddress.SetPort( iSaParams->iPort_ps ); |
|
374 DeleteSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_uc ); |
|
375 iState = EDeletingInbound2; |
|
376 break; |
|
377 } |
|
378 case EDeletingInbound2: |
|
379 { |
|
380 // 3. Outbound spi_ps: port_uc -> port_ps |
|
381 |
|
382 iLocalAddress.SetPort( iSaParams->iPort_uc ); |
|
383 iRemoteAddress.SetPort( iSaParams->iPort_ps ); |
|
384 DeleteSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_ps ); |
|
385 iState = EDeletingOutbound1; |
|
386 break; |
|
387 } |
|
388 case EDeletingOutbound1: |
|
389 { |
|
390 // 4. Outbound spi_pc: port_us -> port_pc |
|
391 |
|
392 iLocalAddress.SetPort( iSaParams->iPort_us ); |
|
393 iRemoteAddress.SetPort( iSaParams->iPort_pc ); |
|
394 DeleteSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_pc ); |
|
395 iState = EDeletingOutbound2; |
|
396 break; |
|
397 } |
|
398 case EDeletingOutbound2: |
|
399 { |
|
400 // All done, inform observer. |
|
401 // Might lead to destruction of this handler. |
|
402 Reset(); |
|
403 iObserver.SAsDeletedL(); |
|
404 break; |
|
405 } |
|
406 default: |
|
407 { |
|
408 break; |
|
409 } |
|
410 } |
|
411 } |
|
412 |
|
413 // ---------------------------------------------------------------------------- |
|
414 // CIpSecSadbHandler::AddSaL |
|
415 // ---------------------------------------------------------------------------- |
|
416 // |
|
417 void CIpSecSadbHandler::AddSaL( |
|
418 TInetAddr& aSourceAddress, |
|
419 TInetAddr& aDestinationAddress, |
|
420 TUint aSpi ) |
|
421 { |
|
422 TUint seqNum( iParams->SeqNumber() ); |
|
423 |
|
424 // Store sequence numbers of add operations |
|
425 User::LeaveIfError( iOngoingAdds.Append( seqNum ) ); |
|
426 |
|
427 TPfkeySendMsg* |
|
428 msg = new ( ELeave ) TPfkeySendMsg( SADB_ADD, SADB_SATYPE_ESP, |
|
429 seqNum, PID ); |
|
430 CleanupStack::PushL( msg ); |
|
431 |
|
432 // SPI has to be converted to network byte order |
|
433 TUint32 spi = ConvertToBigEndian( aSpi ); |
|
434 |
|
435 msg->Add( Int2Type<SADB_EXT_SA>(), spi, iSaParams->iAuthAlg, SADB_EALG_NULL, |
|
436 SADB_SASTATE_MATURE, 0,0 ); |
|
437 msg->Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSourceAddress, 0, 0 ); |
|
438 msg->Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDestinationAddress, 0, 0 ); |
|
439 msg->Add( Int2Type<SADB_EXT_KEY_AUTH>(), iSaParams->iAuthKey, 0 ); |
|
440 |
|
441 sadb_msg &m = msg->MsgHdr(); |
|
442 m.sadb_msg_len = static_cast<TUint16>( msg->Length() / KWordLen ); |
|
443 |
|
444 iSaDbMsgSender->SendL( msg, SADB_ADD ); |
|
445 |
|
446 CleanupStack::Pop( msg ); // msg ownership was transferred |
|
447 } |
|
448 |
|
449 |
|
450 // ---------------------------------------------------------------------------- |
|
451 // CIpSecSadbHandler::DeleteSaL |
|
452 // ---------------------------------------------------------------------------- |
|
453 // |
|
454 void CIpSecSadbHandler::DeleteSaL( |
|
455 TInetAddr& aSourceAddress, |
|
456 TInetAddr& aDestinationAddress, |
|
457 TUint aSpi ) |
|
458 { |
|
459 TPfkeySendMsg* |
|
460 msg = new ( ELeave ) TPfkeySendMsg( SADB_DELETE, SADB_SATYPE_ESP, |
|
461 iParams->SeqNumber(), PID ); |
|
462 CleanupStack::PushL( msg ); |
|
463 |
|
464 |
|
465 // SPI has to be converted to network byte order |
|
466 TUint32 spi = ConvertToBigEndian( aSpi ); |
|
467 |
|
468 msg->Add( Int2Type<SADB_EXT_SA>(), spi, 0, 0, |
|
469 SADB_SASTATE_MATURE, 0,0 ); |
|
470 msg->Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSourceAddress, 0, 0 ); |
|
471 msg->Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDestinationAddress, 0, 0 ); |
|
472 |
|
473 sadb_msg &m = msg->MsgHdr(); |
|
474 m.sadb_msg_len = static_cast<TUint16>( msg->Length() / KWordLen ); |
|
475 |
|
476 iSaDbMsgSender->SendL( msg, SADB_DELETE ); |
|
477 |
|
478 CleanupStack::Pop( msg ); // msg ownership was transferred |
|
479 } |
|
480 |
|
481 // ---------------------------------------------------------------------------- |
|
482 // CIpSecSadbHandler::SAsAddedL |
|
483 // ---------------------------------------------------------------------------- |
|
484 // |
|
485 void CIpSecSadbHandler::SAsAddedL( TBool aSuccess ) |
|
486 { |
|
487 // Haven't necassarily yet received all the sadb messages related |
|
488 // to add operations. In that case we have to wait for them since they |
|
489 // contain also information about success. |
|
490 if ( !aSuccess || ( iOngoingAdds.Count() == 0 && iState == EAvailable ) ) |
|
491 { |
|
492 iObserver.SAsAddedL( aSuccess ); |
|
493 Reset(); |
|
494 } |
|
495 } |
|
496 |
|
497 // ---------------------------------------------------------------------------- |
|
498 // CIpSecSadbHandler::ConvertToBigEndian |
|
499 // ---------------------------------------------------------------------------- |
|
500 // |
|
501 TUint32 CIpSecSadbHandler::ConvertToBigEndian( TUint32 aNum ) |
|
502 { |
|
503 const TInt KMaxTUint32CStringLen = 11; |
|
504 TUint8 temp[ KMaxTUint32CStringLen ]; |
|
505 LittleEndian::Put32( temp, aNum ); |
|
506 return BigEndian::Get32( temp ); |
|
507 } |
|
508 |
|
509 // End of File |