|
1 // Copyright (c) 2008-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 : sipsecdigestcache.cpp |
|
15 // Part of : SIPSec |
|
16 // Version : SIP/6.0 |
|
17 // |
|
18 |
|
19 |
|
20 |
|
21 #include "SipLogs.h" |
|
22 #include "siperr.h" |
|
23 #include "SipAssert.h" |
|
24 #include "sipsecdigestcache.h" |
|
25 #include "CSIPSecDigestCacheEntry.h" |
|
26 #include "CSIPSecDigestObserver.h" |
|
27 #include "CSIPSecUserRecord.h" |
|
28 #include "CSIPSecSIMRecord.h" |
|
29 #include "CSIPSecCredentials.h" |
|
30 #include "CSIPSecChallengeAKA.h" |
|
31 #include "RSIPSecChallengeResolver.h" |
|
32 #include "MSIPSecUser.h" |
|
33 #include "sipstrings.h" |
|
34 #include "sipstrconsts.h" |
|
35 #include "siprequest.h" |
|
36 #include "sipresponse.h" |
|
37 #include "sipsecdigestcontext.h" |
|
38 #include "sipauthenticateheaderbase.h" |
|
39 |
|
40 |
|
41 const TInt TSIPSecDigestCacheEntryIterator::iSIPSecOffset = |
|
42 _FOFF( TSIPSecDigestCacheEntryIterator, iLink ); |
|
43 |
|
44 // ============================ MEMBER FUNCTIONS =============================== |
|
45 |
|
46 |
|
47 // ---------------------------------------------------------------------------- |
|
48 // CSIPSecDigestCache::NewL |
|
49 // ---------------------------------------------------------------------------- |
|
50 // |
|
51 CSIPSecDigestCache* CSIPSecDigestCache::NewL( MTimerManager& aTimerManager ) |
|
52 { |
|
53 CSIPSecDigestCache* self = NewLC( aTimerManager ); |
|
54 CleanupStack::Pop( self ); |
|
55 return self; |
|
56 } |
|
57 |
|
58 // ---------------------------------------------------------------------------- |
|
59 // CSIPSecDigestCache::NewLC |
|
60 // ---------------------------------------------------------------------------- |
|
61 // |
|
62 CSIPSecDigestCache* CSIPSecDigestCache::NewLC( MTimerManager& aTimerManager ) |
|
63 { |
|
64 CSIPSecDigestCache* self = |
|
65 new ( ELeave ) CSIPSecDigestCache( aTimerManager ); |
|
66 CleanupStack::PushL( self ); |
|
67 return self; |
|
68 } |
|
69 |
|
70 // ---------------------------------------------------------------------------- |
|
71 // CSIPSecDigestCache |
|
72 // ---------------------------------------------------------------------------- |
|
73 // |
|
74 CSIPSecDigestCache::CSIPSecDigestCache( MTimerManager& aTimerManager ) : |
|
75 iProxyList( CSIPSecDigestCacheEntry::iSIPSecOffset ), |
|
76 iProxyListIter( iProxyList ), |
|
77 iEndpointList( CSIPSecDigestCacheEntry::iSIPSecOffset ), |
|
78 iEndpointListIter( iEndpointList ), |
|
79 iCredentialsList( CSIPSecUserRecord::iSIPSecOffset ), |
|
80 iCredentialsListIter( iCredentialsList ), |
|
81 #ifdef CPPUNIT_TEST |
|
82 // Use granularity 1 to make each append operation to allocate memory. |
|
83 iDigestObservers( 1 ), |
|
84 #endif |
|
85 iTimerManager( aTimerManager ) |
|
86 { |
|
87 } |
|
88 |
|
89 // ---------------------------------------------------------------------------- |
|
90 // ~CSIPSecDigestCache |
|
91 // ---------------------------------------------------------------------------- |
|
92 // |
|
93 CSIPSecDigestCache::~CSIPSecDigestCache() |
|
94 { |
|
95 RemoveAllEntries(); |
|
96 RemoveAllCredentials(); |
|
97 iDigestObservers.ResetAndDestroy(); |
|
98 } |
|
99 |
|
100 // ---------------------------------------------------------------------------- |
|
101 // CSIPSecDigestCache::InitializeIterator |
|
102 // ---------------------------------------------------------------------------- |
|
103 // |
|
104 void |
|
105 CSIPSecDigestCache::InitializeIterator( TSIPSecDigestCacheIterator& aIterator ) |
|
106 { |
|
107 iProxyListIter.SetToFirst(); |
|
108 iEndpointListIter.SetToFirst(); |
|
109 |
|
110 aIterator.iList.Reset(); |
|
111 aIterator.iList.AddLast( iProxyListIter ); |
|
112 aIterator.iList.AddLast( iEndpointListIter ); |
|
113 aIterator.iListIterator.SetToFirst(); |
|
114 } |
|
115 |
|
116 // ---------------------------------------------------------------------------- |
|
117 // CSIPSecDigestCache::AddEntry |
|
118 // ---------------------------------------------------------------------------- |
|
119 // |
|
120 void CSIPSecDigestCache::AddEntry( CSIPSecDigestCacheEntry* aCacheEntry ) |
|
121 { |
|
122 __SIP_ASSERT_RETURN( aCacheEntry, KErrArgument ); |
|
123 __SIP_ASSERT_RETURN( !IsEntryInCache( *aCacheEntry ), KErrAlreadyExists ); |
|
124 |
|
125 SelectCache( *aCacheEntry ).AddLast( *aCacheEntry ); |
|
126 } |
|
127 |
|
128 // ---------------------------------------------------------------------------- |
|
129 // CSIPSecDigestCache::RemoveEntry |
|
130 // ---------------------------------------------------------------------------- |
|
131 // |
|
132 void CSIPSecDigestCache::RemoveEntry( CSIPSecDigestCacheEntry& aCacheEntry ) |
|
133 { |
|
134 __SIP_ASSERT_RETURN( IsEntryInCache( aCacheEntry ), KErrNotFound ); |
|
135 |
|
136 aCacheEntry.UserData().CredentialsDetach(); |
|
137 SelectCache( aCacheEntry ).Remove( aCacheEntry ); |
|
138 delete &aCacheEntry; |
|
139 } |
|
140 |
|
141 // ---------------------------------------------------------------------------- |
|
142 // CSIPSecDigestCache::RemoveCacheEntry |
|
143 // ---------------------------------------------------------------------------- |
|
144 // |
|
145 TBool CSIPSecDigestCache::RemoveCacheEntry( CSIPSecDigestCacheEntry& aEntry, |
|
146 const MSIPSecUser& aUser ) |
|
147 { |
|
148 CSIPSecUserRecord& record = aEntry.UserData(); |
|
149 RemoveEntry( aEntry ); |
|
150 if ( record.CredentialsAttached() ) |
|
151 { |
|
152 ChangeRecordUserIfNeeded( record, aUser ); |
|
153 return EFalse; |
|
154 } |
|
155 |
|
156 __SIP_LOG( "SIPSecDigestCache:RemoveCacheEntry record not used" ) |
|
157 __SIP_ASSERT_RETURN_VALUE( IsCredentialsInList( record ), KErrNotFound ); |
|
158 iCredentialsList.Remove( record ); |
|
159 delete &record; |
|
160 return ETrue; |
|
161 } |
|
162 |
|
163 // ---------------------------------------------------------------------------- |
|
164 // CSIPSecDigestCache::IsEntryInCache |
|
165 // ---------------------------------------------------------------------------- |
|
166 // |
|
167 TBool CSIPSecDigestCache::IsEntryInCache( CSIPSecDigestCacheEntry& aCacheEntry ) |
|
168 { |
|
169 TSIPSecDigestCacheEntryIterator entryIterator = |
|
170 TSIPSecDigestCacheEntryIterator( SelectCache( aCacheEntry ) ); |
|
171 |
|
172 CSIPSecDigestCacheEntry* entry( NULL ); |
|
173 TBool found( EFalse ); |
|
174 while ( !found && ( entry = entryIterator.Next() ) != NULL ) |
|
175 { |
|
176 found = ( entry == &aCacheEntry ); |
|
177 } |
|
178 return found; |
|
179 } |
|
180 |
|
181 // ---------------------------------------------------------------------------- |
|
182 // CSIPSecDigestCache::SelectCache |
|
183 // ---------------------------------------------------------------------------- |
|
184 // |
|
185 TSglQue< CSIPSecDigestCacheEntry >& |
|
186 CSIPSecDigestCache::SelectCache( const CSIPSecDigestCacheEntry& aCacheEntry ) |
|
187 { |
|
188 if ( aCacheEntry.Type() == CSIPSecDigest::EEndPoint ) |
|
189 { |
|
190 return iEndpointList; |
|
191 } |
|
192 return iProxyList; |
|
193 } |
|
194 |
|
195 // ---------------------------------------------------------------------------- |
|
196 // CSIPSecDigestCache::AddUserCredentials |
|
197 // ---------------------------------------------------------------------------- |
|
198 // |
|
199 void CSIPSecDigestCache::AddUserCredentials( CSIPSecUserRecord* aCredentials ) |
|
200 { |
|
201 __SIP_ASSERT_RETURN( aCredentials, KErrArgument ); |
|
202 __SIP_ASSERT_RETURN( !IsCredentialsInList( *aCredentials ), |
|
203 KErrAlreadyExists ); |
|
204 iCredentialsList.AddLast( *aCredentials ); |
|
205 } |
|
206 |
|
207 // ---------------------------------------------------------------------------- |
|
208 // CSIPSecDigestCache::SearchRecordForResponse |
|
209 // Cache can have only one entry with matching MSIPSecUser and realm. |
|
210 // ---------------------------------------------------------------------------- |
|
211 // |
|
212 CSIPSecUserRecord* |
|
213 CSIPSecDigestCache::SearchRecordForResponse( const TDesC8& aRealm, |
|
214 const MSIPSecUser& aUser, |
|
215 TRegistrationId aRegistrationId ) |
|
216 { |
|
217 __ASSERT_ALWAYS( aRealm.Length() > 0, |
|
218 User::Panic( _L( "DigestCache:SearchRecForResp" ), KErrArgument ) ); |
|
219 |
|
220 CSIPSecUserRecord* record( NULL ); |
|
221 iCredentialsListIter.SetToFirst(); |
|
222 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
223 { |
|
224 if ( record->IsSameRealm( aRealm ) && |
|
225 record->CompareUser( aUser, aRegistrationId ) ) |
|
226 { |
|
227 return record; |
|
228 } |
|
229 } |
|
230 |
|
231 return NULL; |
|
232 } |
|
233 |
|
234 // ---------------------------------------------------------------------------- |
|
235 // CSIPSecDigestCache::SearchRecord |
|
236 // ---------------------------------------------------------------------------- |
|
237 // |
|
238 CSIPSecUserRecord* |
|
239 CSIPSecDigestCache::SearchRecord( const TDesC8& aRealm, |
|
240 TTransactionId aTransactionId ) |
|
241 { |
|
242 __ASSERT_ALWAYS( aRealm.Length() > 0, |
|
243 User::Panic( _L( "DigestCache:SearchRec(id)" ), KErrArgument ) ); |
|
244 |
|
245 CSIPSecUserRecord* record( NULL ); |
|
246 iCredentialsListIter.SetToFirst(); |
|
247 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
248 { |
|
249 if ( record->IsSameRealm( aRealm ) && |
|
250 record->TransactionIdPassedToClient() == aTransactionId ) |
|
251 { |
|
252 return record; |
|
253 } |
|
254 } |
|
255 |
|
256 return NULL; |
|
257 } |
|
258 |
|
259 // ---------------------------------------------------------------------------- |
|
260 // CSIPSecDigestCache::SearchRecord |
|
261 // ---------------------------------------------------------------------------- |
|
262 // |
|
263 CSIPSecUserRecord* CSIPSecDigestCache::SearchRecord( const TDesC8& aRealm, |
|
264 const MSIPSecUser& aUser ) |
|
265 { |
|
266 __ASSERT_ALWAYS( aRealm.Length() > 0, |
|
267 User::Panic( _L( "DigestCache:SearchRec(user)" ), KErrArgument ) ); |
|
268 |
|
269 CSIPSecUserRecord* record( NULL ); |
|
270 iCredentialsListIter.SetToFirst(); |
|
271 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
272 { |
|
273 if ( record->IsSameRealm( aRealm ) && &aUser == &record->SIPSecUser() ) |
|
274 { |
|
275 return record; |
|
276 } |
|
277 } |
|
278 |
|
279 return NULL; |
|
280 } |
|
281 |
|
282 // ---------------------------------------------------------------------------- |
|
283 // CSIPSecDigestCache::RemoveAllEntries |
|
284 // ---------------------------------------------------------------------------- |
|
285 // |
|
286 void CSIPSecDigestCache::RemoveAllEntries() |
|
287 { |
|
288 RemoveAllEntriesFromList( iProxyList ); |
|
289 RemoveAllEntriesFromList( iEndpointList ); |
|
290 } |
|
291 |
|
292 // ---------------------------------------------------------------------------- |
|
293 // CSIPSecDigestCache::RemoveAllEntriesFromList |
|
294 // ---------------------------------------------------------------------------- |
|
295 // |
|
296 void CSIPSecDigestCache::RemoveAllEntriesFromList( |
|
297 TSglQue<CSIPSecDigestCacheEntry>& aList ) |
|
298 { |
|
299 if ( !aList.IsEmpty() ) |
|
300 { |
|
301 CSIPSecDigestCacheEntry* entry( NULL ); |
|
302 TSIPSecDigestCacheEntryIterator entryIterator = |
|
303 TSIPSecDigestCacheEntryIterator( aList ); |
|
304 |
|
305 while ( ( entry = entryIterator.Next() ) != NULL ) |
|
306 { |
|
307 aList.Remove( *entry ); |
|
308 delete entry; |
|
309 } |
|
310 } |
|
311 } |
|
312 |
|
313 // ---------------------------------------------------------------------------- |
|
314 // CSIPSecDigestCache::RemoveAllCredentials |
|
315 // ---------------------------------------------------------------------------- |
|
316 // |
|
317 void CSIPSecDigestCache::RemoveAllCredentials() |
|
318 { |
|
319 if ( !iCredentialsList.IsEmpty() ) |
|
320 { |
|
321 CSIPSecUserRecord* record( NULL ); |
|
322 iCredentialsListIter.SetToFirst(); |
|
323 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
324 { |
|
325 iCredentialsList.Remove( *record ); |
|
326 delete record; |
|
327 } |
|
328 } |
|
329 } |
|
330 |
|
331 // ---------------------------------------------------------------------------- |
|
332 // CSIPSecDigestCache::IsCredentialsInList |
|
333 // ---------------------------------------------------------------------------- |
|
334 // |
|
335 TBool CSIPSecDigestCache::IsCredentialsInList( |
|
336 const CSIPSecUserRecord& aCredentials ) |
|
337 { |
|
338 if ( !iCredentialsList.IsEmpty() ) |
|
339 { |
|
340 CSIPSecUserRecord* record( NULL ); |
|
341 iCredentialsListIter.SetToFirst(); |
|
342 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
343 { |
|
344 if ( record == &aCredentials ) |
|
345 { |
|
346 return ETrue; |
|
347 } |
|
348 } |
|
349 } |
|
350 return EFalse; |
|
351 } |
|
352 |
|
353 // ---------------------------------------------------------------------------- |
|
354 // CSIPSecDigestCache::ClearCache |
|
355 // ---------------------------------------------------------------------------- |
|
356 // |
|
357 void CSIPSecDigestCache::ClearCache( const MSIPSecUser& aUser ) |
|
358 { |
|
359 RemoveUsedEntry( iProxyList, aUser ); |
|
360 RemoveUsedEntry( iEndpointList, aUser ); |
|
361 } |
|
362 |
|
363 // ---------------------------------------------------------------------------- |
|
364 // CSIPSecDigestCache::RemoveUsedEntry |
|
365 // ---------------------------------------------------------------------------- |
|
366 // |
|
367 void |
|
368 CSIPSecDigestCache::RemoveUsedEntry( TSglQue< CSIPSecDigestCacheEntry >& aList, |
|
369 const MSIPSecUser& aUser ) |
|
370 { |
|
371 if ( !aList.IsEmpty() ) |
|
372 { |
|
373 CSIPSecDigestCacheEntry* entry( NULL ); |
|
374 TSIPSecDigestCacheEntryIterator entryIter = |
|
375 TSIPSecDigestCacheEntryIterator( aList ); |
|
376 |
|
377 while ( ( entry = entryIter.Next() ) != NULL ) |
|
378 { |
|
379 // When removing cache items, do NOT compare trusted user |
|
380 if ( &entry->SIPSecUser() == &aUser ) |
|
381 { |
|
382 RemoveCacheEntry( *entry, aUser ); |
|
383 } |
|
384 } |
|
385 } |
|
386 } |
|
387 |
|
388 // ---------------------------------------------------------------------------- |
|
389 // CSIPSecDigestCache::ClearCache |
|
390 // ---------------------------------------------------------------------------- |
|
391 // |
|
392 void CSIPSecDigestCache::ClearCache( CSIPSecUserRecord& aCredentials, |
|
393 TBool aAKAOnly ) |
|
394 { |
|
395 RemoveMatchingEntry( iProxyList, aCredentials, aAKAOnly ); |
|
396 RemoveMatchingEntry( iEndpointList, aCredentials, aAKAOnly ); |
|
397 } |
|
398 |
|
399 // ---------------------------------------------------------------------------- |
|
400 // CSIPSecDigestCache::RemoveMatchingEntry |
|
401 // ---------------------------------------------------------------------------- |
|
402 // |
|
403 void CSIPSecDigestCache::RemoveMatchingEntry( |
|
404 TSglQue< CSIPSecDigestCacheEntry >& aList, |
|
405 CSIPSecUserRecord& aCredentials, |
|
406 TBool aAKAOnly ) |
|
407 { |
|
408 if ( !aList.IsEmpty() ) |
|
409 { |
|
410 CSIPSecDigestCacheEntry* entry( NULL ); |
|
411 TSIPSecDigestCacheEntryIterator entryIter = |
|
412 TSIPSecDigestCacheEntryIterator( aList ); |
|
413 |
|
414 while ( ( entry = entryIter.Next() ) != NULL ) |
|
415 { |
|
416 if ( entry->HoldsUserData( aCredentials ) && |
|
417 ( !aAKAOnly || |
|
418 ( static_cast< CSIPSecCredentials* >( entry )->Challenge(). |
|
419 Algorithm().AlgorithmName() == |
|
420 CSIPSecChallengeAKA::SupportedAlgorithm() ) ) ) |
|
421 { |
|
422 if ( RemoveCacheEntry( *entry, entry->SIPSecUser() ) ) |
|
423 { |
|
424 // Removed aCredentials, nothing refers to it, so exit loop |
|
425 return; |
|
426 } |
|
427 } |
|
428 } |
|
429 } |
|
430 } |
|
431 |
|
432 // ---------------------------------------------------------------------------- |
|
433 // CSIPSecDigestCache::ClearAKAEntriesWithOldRealm |
|
434 // ---------------------------------------------------------------------------- |
|
435 // |
|
436 void CSIPSecDigestCache::ClearAKAEntriesWithOldRealm( const TDesC8& aRealm ) |
|
437 { |
|
438 CSIPSecUserRecord* record( NULL ); |
|
439 iCredentialsListIter.SetToFirst(); |
|
440 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
441 { |
|
442 if ( !record->IsSameRealm( aRealm ) ) |
|
443 { |
|
444 ClearCache( *record, ETrue ); |
|
445 } |
|
446 } |
|
447 } |
|
448 |
|
449 // ---------------------------------------------------------------------------- |
|
450 // CSIPSecDigestCache::RegisterObserverL |
|
451 // Check if aObserver has a matching CSIPSecDigestObserver. If not, create |
|
452 // CSIPSecDigestObserver for it. Each SIP response has its own aObserver. |
|
453 // ---------------------------------------------------------------------------- |
|
454 // |
|
455 CSIPSecDigestObserver* CSIPSecDigestCache::RegisterObserverL( |
|
456 MSIPSecSecurityMechanismObserver& aObserver, |
|
457 CSIPSecUserRecord& aUserData ) |
|
458 { |
|
459 CSIPSecDigestObserver* observer( NULL ); |
|
460 TInt i( 0 ); |
|
461 while ( !observer && i < iDigestObservers.Count() ) |
|
462 { |
|
463 observer = iDigestObservers[ i++ ]; |
|
464 observer = observer->HasObserver( aObserver ) ? observer : NULL; |
|
465 } |
|
466 |
|
467 if ( !observer ) |
|
468 { |
|
469 observer = aUserData.CreateObserverL( aObserver ); |
|
470 CleanupStack::PushL( observer ); |
|
471 iDigestObservers.AppendL( observer ); |
|
472 CleanupStack::Pop( observer ); |
|
473 } |
|
474 |
|
475 return observer; |
|
476 } |
|
477 |
|
478 // ---------------------------------------------------------------------------- |
|
479 // CSIPSecDigestCache::CancelPendingOperations |
|
480 // ---------------------------------------------------------------------------- |
|
481 // |
|
482 void CSIPSecDigestCache::CancelPendingOperations( |
|
483 MSIPSecSecurityMechanismObserver* aObserver ) |
|
484 { |
|
485 CSIPSecUserRecord* record( NULL ); |
|
486 iCredentialsListIter.SetToFirst(); |
|
487 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
488 { |
|
489 record->CancelPendingOperations( aObserver ); |
|
490 } |
|
491 |
|
492 CleanObservers(); |
|
493 } |
|
494 |
|
495 // ---------------------------------------------------------------------------- |
|
496 // CSIPSecDigestCache::Cancel |
|
497 // ---------------------------------------------------------------------------- |
|
498 // |
|
499 TInt CSIPSecDigestCache::Cancel( TTransactionId aTransactionId, |
|
500 const TDesC8& aRealm, |
|
501 const MSIPSecUser* aTrustedUser ) |
|
502 { |
|
503 if ( aRealm.Length() == 0 ) |
|
504 { |
|
505 return KErrArgument; |
|
506 } |
|
507 |
|
508 TInt status( KErrNotFound ); |
|
509 CSIPSecUserRecord* record( NULL ); |
|
510 iCredentialsListIter.SetToFirst(); |
|
511 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
512 { |
|
513 if ( record->IsSameRealm( aRealm ) && |
|
514 ( record->TransactionIdPassedToClient() == aTransactionId || |
|
515 &record->SIPSecUser() == aTrustedUser ) ) |
|
516 { |
|
517 status = KErrNone; // At least one found |
|
518 record->CancelPendingOperations( NULL /* cancel all */ ); |
|
519 } |
|
520 } |
|
521 |
|
522 CleanObservers(); |
|
523 return status; |
|
524 } |
|
525 |
|
526 // ---------------------------------------------------------------------------- |
|
527 // CSIPSecDigestCache::Remove |
|
528 // ---------------------------------------------------------------------------- |
|
529 // |
|
530 TInt CSIPSecDigestCache::Remove( const TDesC8& aRealm ) |
|
531 { |
|
532 if ( aRealm.Length() == 0 ) |
|
533 { |
|
534 return KErrArgument; |
|
535 } |
|
536 |
|
537 TInt status( KErrNotFound ); |
|
538 CSIPSecUserRecord* record( NULL ); |
|
539 iCredentialsListIter.SetToFirst(); |
|
540 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
541 { |
|
542 if ( record->IsSameRealm( aRealm ) ) |
|
543 { |
|
544 status = KErrNone; // At least one found |
|
545 // Remove entries pointing to record, then remove record. |
|
546 ClearCache( *record, EFalse ); |
|
547 } |
|
548 } |
|
549 |
|
550 CleanObservers(); |
|
551 return status; |
|
552 } |
|
553 |
|
554 // ---------------------------------------------------------------------------- |
|
555 // CSIPSecDigestCache::CountResponses |
|
556 // There can be just one record per realm/transaction id pair, as many SIPSec |
|
557 // users can't have the same transaction id. Cache has just one IMS record. |
|
558 // Compare the real transaction ids, regardless of the value returned by |
|
559 // MSIPSecUser::PassOnlyRealmsToUser(). |
|
560 // ---------------------------------------------------------------------------- |
|
561 // |
|
562 TInt CSIPSecDigestCache::CountResponses( CSIPResponse& aResponse, |
|
563 CSIPRequest& aRequest, |
|
564 TTransactionId aTransactionId, |
|
565 RStringF aDefaultAlgorithm ) |
|
566 { |
|
567 TInt status( KErrNone ); |
|
568 |
|
569 RStringF alg; |
|
570 RStringF dummyQop; |
|
571 RSIPSecChallengeResolver::GetDigestParamsFromSecurityServer( aResponse, |
|
572 alg, |
|
573 dummyQop ); |
|
574 CSIPSecUserRecord* record( NULL ); |
|
575 iCredentialsListIter.SetToFirst(); |
|
576 while ( ( record = iCredentialsListIter++ ) != NULL ) |
|
577 { |
|
578 if ( record->Type() == CSIPSecUserRecord::EIMS && |
|
579 record->TransactionId() == aTransactionId ) |
|
580 { |
|
581 TBool match( EFalse ); |
|
582 if ( !HandleChallenges( aResponse, |
|
583 alg, |
|
584 aDefaultAlgorithm, |
|
585 record->Realm(), |
|
586 match ) ) |
|
587 { |
|
588 __SIP_ASSERT_RETURN_VALUE( !match, KErrAlreadyExists ); |
|
589 match = HandleAuthorizations( aRequest, |
|
590 alg, |
|
591 aDefaultAlgorithm, |
|
592 record->Realm() ); |
|
593 } |
|
594 if ( match && |
|
595 static_cast< CSIPSecSIMRecord* >( record )-> |
|
596 UpdateMessageCounter( aResponse.ResponseCode() ) ) |
|
597 { |
|
598 status = KErrSIPForbidden; |
|
599 } |
|
600 } |
|
601 } |
|
602 return status; |
|
603 } |
|
604 |
|
605 // ---------------------------------------------------------------------------- |
|
606 // CSIPSecDigestCache::CleanObservers |
|
607 // ---------------------------------------------------------------------------- |
|
608 // |
|
609 void CSIPSecDigestCache::CleanObservers() |
|
610 { |
|
611 TInt i( 0 ); |
|
612 while ( i < iDigestObservers.Count() ) |
|
613 { |
|
614 CSIPSecDigestObserver* observer = iDigestObservers[ i ]; |
|
615 if ( observer->IsCompleted() ) |
|
616 { |
|
617 iDigestObservers.Remove( i ); |
|
618 delete observer; |
|
619 } |
|
620 else |
|
621 { |
|
622 ++i; |
|
623 } |
|
624 } |
|
625 } |
|
626 |
|
627 // ----------------------------------------------------------------------------- |
|
628 // CSIPSecDigestCache::HandleChallenges |
|
629 // ----------------------------------------------------------------------------- |
|
630 // |
|
631 TBool CSIPSecDigestCache::HandleChallenges( CSIPResponse& aResponse, |
|
632 RStringF aAlgorithm, |
|
633 RStringF aDefaultAlgorithm, |
|
634 const TDesC8& aRealm, |
|
635 TBool& aMatch ) const |
|
636 { |
|
637 TBool proxyChallenges( EFalse ); |
|
638 TBool endpointChallenges( EFalse ); |
|
639 |
|
640 aMatch = HandleAuthHeaders( aResponse, |
|
641 aAlgorithm, |
|
642 aDefaultAlgorithm, |
|
643 SIPStrings::StringF( SipStrConsts::EProxyAuthenticateHeader ), |
|
644 aRealm, |
|
645 ETrue, |
|
646 proxyChallenges ) || |
|
647 HandleAuthHeaders( aResponse, |
|
648 aAlgorithm, |
|
649 aDefaultAlgorithm, |
|
650 SIPStrings::StringF( SipStrConsts::EWWWAuthenticateHeader ), |
|
651 aRealm, |
|
652 ETrue, |
|
653 endpointChallenges ); |
|
654 return proxyChallenges || endpointChallenges; |
|
655 } |
|
656 |
|
657 // ----------------------------------------------------------------------------- |
|
658 // CSIPSecDigestCache::HandleAuthorizations |
|
659 // ----------------------------------------------------------------------------- |
|
660 // |
|
661 TBool CSIPSecDigestCache::HandleAuthorizations( CSIPRequest& aRequest, |
|
662 RStringF aAlgorithm, |
|
663 RStringF aDefaultAlgorithm, |
|
664 const TDesC8& aRealm ) const |
|
665 { |
|
666 TBool dummy( EFalse ); |
|
667 return HandleAuthHeaders( aRequest, |
|
668 aAlgorithm, |
|
669 aDefaultAlgorithm, |
|
670 SIPStrings::StringF( SipStrConsts::EAuthorizationHeader ), |
|
671 aRealm, |
|
672 EFalse, |
|
673 dummy ) || |
|
674 HandleAuthHeaders( aRequest, |
|
675 aAlgorithm, |
|
676 aDefaultAlgorithm, |
|
677 SIPStrings::StringF( SipStrConsts::EProxyAuthorizationHeader ), |
|
678 aRealm, |
|
679 EFalse, |
|
680 dummy ); |
|
681 } |
|
682 |
|
683 // ----------------------------------------------------------------------------- |
|
684 // CSIPSecDigestCache::HandleAuthHeaders |
|
685 // ----------------------------------------------------------------------------- |
|
686 // |
|
687 TBool CSIPSecDigestCache::HandleAuthHeaders( CSIPMessage& aMessage, |
|
688 RStringF aAlgorithm, |
|
689 RStringF aDefaultAlgorithm, |
|
690 RStringF aHeaderName, |
|
691 const TDesC8& aRealm, |
|
692 TBool aCheckChallenges, |
|
693 TBool& aChallengeFound ) const |
|
694 { |
|
695 aChallengeFound = EFalse; |
|
696 TBool match( EFalse ); |
|
697 |
|
698 if ( aMessage.HeaderCount( aHeaderName ) > 0 ) |
|
699 { |
|
700 TSglQueIter< CSIPHeaderBase > headers = aMessage.Headers( aHeaderName ); |
|
701 while ( headers && !match ) |
|
702 { |
|
703 CSIPAuthHeaderBase* authHeader = |
|
704 static_cast< CSIPAuthHeaderBase* >( headers++ ); |
|
705 if ( !aCheckChallenges || |
|
706 RSIPSecChallengeResolver::IsValidDigestChallenge( |
|
707 *authHeader ) ) |
|
708 { |
|
709 aChallengeFound = ETrue; |
|
710 match = CompareAKARealm( *authHeader, |
|
711 aRealm, |
|
712 aAlgorithm, |
|
713 aDefaultAlgorithm ); |
|
714 } |
|
715 } |
|
716 } |
|
717 return match; |
|
718 } |
|
719 |
|
720 // ----------------------------------------------------------------------------- |
|
721 // CSIPSecDigestCache::CompareAKARealm |
|
722 // aAlgorithm may change in this function, but caller's algorithm must not. |
|
723 // ----------------------------------------------------------------------------- |
|
724 // |
|
725 TBool CSIPSecDigestCache::CompareAKARealm( CSIPAuthHeaderBase& aHeader, |
|
726 const TDesC8& aCachedRealm, |
|
727 RStringF aAlgorithm, |
|
728 RStringF aDefaultAlgorithm ) const |
|
729 { |
|
730 RSIPSecChallengeResolver::SelectAlgorithm( aHeader, |
|
731 aDefaultAlgorithm, |
|
732 aAlgorithm ); |
|
733 return ( TSIPSecDigestContext::GetDesParam( aHeader, |
|
734 SipStrConsts::ERealm ).Compare( aCachedRealm ) == 0 ) && |
|
735 ( aAlgorithm == SIPStrings::StringF( SipStrConsts::EAKAv1MD5 ) ); |
|
736 } |
|
737 |
|
738 // ----------------------------------------------------------------------------- |
|
739 // CSIPSecDigestCache::ChangeRecordUserIfNeeded |
|
740 // If none of the entries in iProxyList or iEndpointList that point to aRecord, |
|
741 // have the same SIPSec user as the aRecord, change aRecord's SIPSec user to be |
|
742 // any of the referring entries' SIPSec user. |
|
743 // ----------------------------------------------------------------------------- |
|
744 // |
|
745 void CSIPSecDigestCache::ChangeRecordUserIfNeeded( CSIPSecUserRecord& aRecord, |
|
746 const MSIPSecUser& aUser ) |
|
747 { |
|
748 // Do not compare trusted user |
|
749 if ( &aRecord.User() == &aUser ) |
|
750 { |
|
751 // Loop both proxy and endpoint caches. |
|
752 // iProxyListIter and iEndpointListIter are already used by the code |
|
753 // that calls ChangeRecordUserIfNeeded(), so use new iterators. |
|
754 TSIPSecDigestCacheEntryIterator proxyListIter( iProxyList ); |
|
755 TSIPSecDigestCacheEntryIterator endpointListIter( iEndpointList ); |
|
756 TSIPSecDigestCacheIterator cacheIterator; |
|
757 // Initialize iterators |
|
758 proxyListIter.SetToFirst(); |
|
759 endpointListIter.SetToFirst(); |
|
760 cacheIterator.iList.Reset(); |
|
761 cacheIterator.iList.AddLast( proxyListIter ); |
|
762 cacheIterator.iList.AddLast( endpointListIter ); |
|
763 cacheIterator.iListIterator.SetToFirst(); |
|
764 |
|
765 const MSIPSecUser* sipSecUser( NULL ); |
|
766 CSIPSecDigestCacheEntry* entry( NULL ); |
|
767 while ( ( entry = cacheIterator.Next() ) != NULL ) |
|
768 { |
|
769 if ( entry->HoldsUserData( aRecord ) ) |
|
770 { |
|
771 if ( &entry->SIPSecUser() == &aUser ) |
|
772 { |
|
773 return; // Same SIPSec user, no action needed |
|
774 } |
|
775 else |
|
776 { |
|
777 sipSecUser = &entry->SIPSecUser(); |
|
778 } |
|
779 } |
|
780 } |
|
781 |
|
782 // Original SIPSec user no longer uses aRecord. |
|
783 // Change SIPSec user to one of those still using it. |
|
784 __ASSERT_DEBUG( sipSecUser != NULL, |
|
785 User::Panic( _L( "DigestCache:ChangeRecUser" ), |
|
786 KErrNotFound ) ); |
|
787 if ( sipSecUser ) |
|
788 { |
|
789 aRecord.SetUser( *sipSecUser ); |
|
790 } |
|
791 } |
|
792 } |
|
793 |
|
794 // ============================ MEMBER FUNCTIONS =============================== |
|
795 |
|
796 // ---------------------------------------------------------------------------- |
|
797 // TSIPSecDigestCacheEntryIterator::TSIPSecDigestCacheEntryIterator |
|
798 // ---------------------------------------------------------------------------- |
|
799 // |
|
800 TSIPSecDigestCacheEntryIterator::TSIPSecDigestCacheEntryIterator( |
|
801 TSglQue<CSIPSecDigestCacheEntry>& aList ) : |
|
802 TSglQueIter<CSIPSecDigestCacheEntry>( aList ), |
|
803 iLink() |
|
804 { |
|
805 SetToFirst(); |
|
806 } |
|
807 |
|
808 // ---------------------------------------------------------------------------- |
|
809 // TSIPSecDigestCacheEntryIterator::Next |
|
810 // Return the next matching entry in the cache. |
|
811 // ---------------------------------------------------------------------------- |
|
812 // |
|
813 CSIPSecDigestCacheEntry* |
|
814 TSIPSecDigestCacheEntryIterator::Next( TSIPSecPluginContext& aContext ) |
|
815 { |
|
816 CSIPSecDigestCacheEntry* entry( NULL ); |
|
817 |
|
818 while ( ( entry = Next() ) != NULL ) |
|
819 { |
|
820 if ( entry->Match( aContext ) ) |
|
821 { |
|
822 return entry; |
|
823 } |
|
824 } |
|
825 |
|
826 return NULL; |
|
827 } |
|
828 |
|
829 // ---------------------------------------------------------------------------- |
|
830 // TSIPSecDigestCacheEntryIterator::Next |
|
831 // ---------------------------------------------------------------------------- |
|
832 // |
|
833 CSIPSecDigestCacheEntry* TSIPSecDigestCacheEntryIterator::Next() |
|
834 { |
|
835 return ( *this )++; |
|
836 } |
|
837 |
|
838 |
|
839 |
|
840 // ============================ MEMBER FUNCTIONS =============================== |
|
841 |
|
842 // ---------------------------------------------------------------------------- |
|
843 // TSIPSecDigestCacheIterator::TSIPSecDigestCacheIterator |
|
844 // ---------------------------------------------------------------------------- |
|
845 // |
|
846 TSIPSecDigestCacheIterator::TSIPSecDigestCacheIterator() : |
|
847 iList( TSIPSecDigestCacheEntryIterator::iSIPSecOffset ), |
|
848 iListIterator( TSglQueIter<TSIPSecDigestCacheEntryIterator>( iList ) ), |
|
849 iContext( NULL ) |
|
850 { |
|
851 } |
|
852 |
|
853 // ---------------------------------------------------------------------------- |
|
854 // TSIPSecDigestCacheIterator::TSIPSecDigestCacheIterator |
|
855 // ---------------------------------------------------------------------------- |
|
856 // |
|
857 TSIPSecDigestCacheIterator::TSIPSecDigestCacheIterator( |
|
858 TSIPSecPluginContext& aContext ) : |
|
859 iList( TSIPSecDigestCacheEntryIterator::iSIPSecOffset ), |
|
860 iListIterator( TSglQueIter<TSIPSecDigestCacheEntryIterator>( iList ) ), |
|
861 iContext( &aContext ) |
|
862 { |
|
863 } |
|
864 |
|
865 // ---------------------------------------------------------------------------- |
|
866 // TSIPSecDigestCacheIterator::TSIPSecDigestCacheIterator |
|
867 // ---------------------------------------------------------------------------- |
|
868 // |
|
869 CSIPSecDigestCacheEntry* TSIPSecDigestCacheIterator::Next() |
|
870 { |
|
871 TSIPSecDigestCacheEntryIterator* iter( NULL ); |
|
872 CSIPSecDigestCacheEntry* entry( NULL ); |
|
873 |
|
874 // Loop until an entry is found or both lists have been traversed |
|
875 while ( !entry && ( iter = iListIterator ) != NULL ) |
|
876 { |
|
877 // Get next entry from current list |
|
878 entry = iContext ? iter->Next( *iContext ) : iter->Next(); |
|
879 |
|
880 // If the current list has been exhausted, move to next list |
|
881 if ( !entry ) |
|
882 { |
|
883 iter = ( iListIterator )++; |
|
884 } |
|
885 } |
|
886 |
|
887 return entry; |
|
888 } |