realtimenetprots/sipfw/SIP/SIPSec/DigestPlugin/inc/sipsecdigestcache.h
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/SIPSec/DigestPlugin/inc/sipsecdigestcache.h	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,500 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* Name          : sipsecdigestcache.h
+* Part of       : SIPSec
+* Version       : SIP/6.0 
+*
+*/
+
+
+
+
+/**
+ @internalComponent
+*/
+
+#ifndef __SIPSEC_DIGESTCACHE_H__
+#define __SIPSEC_DIGESTCACHE_H__
+
+// INCLUDES
+#include "CSIPSecDigestCacheEntry.h"
+#include <e32base.h>
+
+// FORWARD DECLARATIONS
+class CSIPMessage;
+class CSIPResponse;
+class CSIPRequest;
+class CSIPAuthHeaderBase;
+class MSIPSecSecurityMechanismObserver;
+class CSIPSecDigestObserver;
+class MTimerManager;
+class TSIPSecPluginContext;
+class CSIPSecUserRecord;
+
+
+// CLASS DECLARATION
+/**
+ * @brief Class is cache entry iterator
+ * 
+ * @class TSIPSecDigestCacheEntryIterator sipsecdigestcache.h
+ *		  "sipsecdigestcache.h" 
+ */
+class TSIPSecDigestCacheEntryIterator :
+	public TSglQueIter<CSIPSecDigestCacheEntry>
+    {
+public:
+
+    /**
+    * Constructor
+    * @param aList The list to iterate
+    */
+    TSIPSecDigestCacheEntryIterator(
+    	TSglQue< CSIPSecDigestCacheEntry >& aList );
+
+    /**
+    * Returns next matching entry for the matching context
+    * @param aContext a context
+    * @return next matching entry or NULL
+    */	
+    CSIPSecDigestCacheEntry* Next( TSIPSecPluginContext& aContext );
+
+    /**
+    * Returns next matching entry regardless of context    
+    * @return next matching entry or NULL
+    */	
+    CSIPSecDigestCacheEntry* Next();
+
+public: // Data
+
+    static const TInt iSIPSecOffset;
+
+    TSglQueLink iLink; 
+    };
+
+
+
+
+/**
+ * @brief Class is cache iterator
+ * 
+ * @class TSIPSecDigestCacheIterator sipsecdigestcache.h "sipsecdigestcache.h"
+ *
+ */
+class TSIPSecDigestCacheIterator 
+    {
+public:
+
+    /**
+    * Constructor
+    */
+    TSIPSecDigestCacheIterator();
+
+    /**
+    * Constructor
+    * @param aContext the context
+    */	
+    TSIPSecDigestCacheIterator( TSIPSecPluginContext& aContext );
+
+    /**
+    * Returns next matching entry
+    * @return Next matching entry or NULL
+    */	
+    CSIPSecDigestCacheEntry* Next();
+
+public: // Data
+
+    // Queue
+    TSglQue<TSIPSecDigestCacheEntryIterator> iList;
+
+    TSglQueIter<TSIPSecDigestCacheEntryIterator> iListIterator;
+
+	// Not owned
+    TSIPSecPluginContext* iContext;
+    };
+
+
+
+/**
+ * @brief Class represents cache for credentials
+ * 
+ * @class CSIPSecDigestCache sipsecdigestcache.h "sipsecdigestcache.h"
+ *
+ * Class provides caching (adding, removing and seraching) of
+ * - credentials, searced based on request context
+ * - user credentials, searched based on realm
+ * Class also holds array of SIPSec observers
+ *
+ *
+ * Cache can have many CSIPSecUserRecords with a same realm, if MSIPSecUser
+ * differs.
+ *
+ * For one MSIPSecUser, cache can have one CSIPSecUserRecord per realm.
+ * Further challenges with the same MSIPSecUser and realm use the same record.
+ *
+ * For one transaction id, cache can have many CSIPSecUserRecords if the realms
+ * differ (SIP response had challenges with different realms).
+ * This does not apply to a case when the transaction id is empty.
+ */
+class CSIPSecDigestCache : public CBase
+	{
+public:	// Constructors and destructor
+
+    /**
+    * Constructs an object; leaves on failure.
+    * @param aTimerManager Timer Manager
+    * @return new instance
+    */
+    static CSIPSecDigestCache* NewL( MTimerManager& aTimerManager );
+
+    /**
+    * Constructs an object and adds the pointer to the cleanup stack;
+    * leaves on failure.
+    * @param aTimerManager Timer Manager
+    * @return new instance
+    */
+    static CSIPSecDigestCache* NewLC( MTimerManager& aTimerManager );
+
+    /**
+    * Destructor
+    */
+    ~CSIPSecDigestCache();
+
+public: // New functions
+
+    /**
+    * Creates cache iterator
+    *
+    * @param aContext the context
+    * @return iterator
+    */
+    void InitializeIterator( TSIPSecDigestCacheIterator& aIterator );
+
+    /**
+    * Adds an CSIPSecDigestCacheEntry object into the cache.    
+    * @pre aCacheEntry != NULL
+    * @pre aCacheEntry is not yet stored in the cache
+    * @param aCacheEntry an cache entry. Ownership is transferred.
+    */
+    void AddEntry( CSIPSecDigestCacheEntry* aCacheEntry );
+
+    /**
+    * Removes the entry from the cache and deletes the entry.    
+    * @pre aCacheEntry is in the cache
+    * @param aCacheEntry Cache entry
+    */
+    void RemoveEntry( CSIPSecDigestCacheEntry& aCacheEntry );
+
+    /**
+    * Checks if the specified entry is in the cache.
+    * @param aCacheEntry Cache entry
+    * @return ETrue if entry is in the cache, EFalse if not.
+    */
+    TBool IsEntryInCache( CSIPSecDigestCacheEntry& aCacheEntry );
+
+    /**
+    * Adds an CSIPSecUserRecord object into the cache.
+    * @pre aCredentials != NULL
+    * @param aCredentials user credentials
+    * The ownership is transferred.
+    */		
+    void AddUserCredentials( CSIPSecUserRecord* aCredentials );
+
+    /**
+    * Search for an user record with a matching realm and is related to the
+    * specified SIPSec user (or its trusted user).
+    * @pre aRealm.Length() > 0
+    * @param aRealm realm
+    * @param aUser SIPSec user
+    * @param aRegistrationId Registration id
+    * @return CSIPSecUserRecord Found record or NULL if there is no match.
+    *		  The ownership is not transferred.
+    */
+    CSIPSecUserRecord*
+    	SearchRecordForResponse( const TDesC8& aRealm,
+					 			 const MSIPSecUser& aUser,
+								 TRegistrationId aRegistrationId );
+
+	/**
+    * Search for an user record with a matching realm and transaction id.
+    * @pre aRealm.Length() > 0
+    * @param aRealm realm
+    * @param aTransactionId Transaction id, can be empty.
+    * @return CSIPSecUserRecord Found record or NULL if there is no match.
+    *	The ownership is not transferred.
+    */
+	CSIPSecUserRecord* SearchRecord( const TDesC8& aRealm,
+								     TTransactionId aTransactionId );
+
+	/**
+    * Search for an user record with a matching realm and SIPSec user.
+    * @pre aRealm.Length() > 0
+    * @param aRealm realm
+    * @param aUser SIPSec user that is setting the credentials
+    * @return CSIPSecUserRecord Found record or NULL if there is no match.
+    *	The ownership is not transferred.
+    */
+	CSIPSecUserRecord* SearchRecord( const TDesC8& aRealm,
+			  						 const MSIPSecUser& aUser );
+
+    /**
+    * Clears all cache entries belonging to a user
+    * @param aUser SIPSec user
+    */	
+    void ClearCache( const MSIPSecUser& aUser );
+
+    /**
+    * Clears all cache entries belonging to realm (credentials).
+    * @param aCredentials User credentials
+    * @param aAKAOnly If ETrue, only AKA cache entries are cleared
+    *				  If EFalse, all cache entries are cleared
+    */
+    void ClearCache( CSIPSecUserRecord& aCredentials, TBool aAKAOnly );
+
+	/**
+    * Clears all AKA cache entries that have a different realm than aRealm.
+    * @param aRealm Realm
+    */
+	void ClearAKAEntriesWithOldRealm( const TDesC8& aRealm );
+
+    /**
+    * Registers mechanism observer and returns matching digest observer
+    * @param aObserver Mechanism observer
+    * @param aUserData User record for which the observer is for
+    * @return Digest observer, ownership is not transferred.
+    */	
+    CSIPSecDigestObserver*
+    	RegisterObserverL( MSIPSecSecurityMechanismObserver& aObserver,
+    					   CSIPSecUserRecord& aUserData );
+    
+    /**
+    * Removes observers, which do not have pending operations.
+    */	
+    void CleanObservers();
+
+    /**
+    * Cancels pending operations requested by SIP
+    * @param aObserver observer
+    */
+    void CancelPendingOperations( MSIPSecSecurityMechanismObserver* aObserver );
+
+	/**
+    * Removes an entry from the cache, or cancels pending operations.
+    * @param aTransactionId Transaction id of the targeted cache entry, can be
+    *						empty.
+    * @param aRealm Realm of the targeted cache entry
+    * @param aRemove ETrue if the entry is to be removed
+    *				 EFalse if the pending operations related to the cache
+    *						entry will be canceled
+    * @return KErrNone if successful, otherwise a system-wide error code
+    */
+	TInt Cancel( TTransactionId aTransactionId,
+				 const TDesC8& aRealm,
+                 const MSIPSecUser* aTrustedUser );
+
+	/**
+    * Removes all cache entries for the realm
+    * @param aRealm Realm of the targeted cache entry
+    * @return KErrNone if successful, otherwise a system-wide error code
+    */
+	TInt Remove( const TDesC8& aRealm );
+
+	/*
+     * Checks if too many successive 401 responses are received with the same
+     * realm. This affects only IMS.
+	 * @param aResponse SIP response
+	 * @param aRequest SIP request
+	 * @param aTransactionId Transaction id	
+	 * @param aDefaultAlgorithm Default algorithm
+	 * @return KErrSIPForbidden Too many successive 401 responses received
+	 *		   KErrNone otherwise
+     */
+	TInt CountResponses( CSIPResponse& aResponse,
+					     CSIPRequest& aRequest,
+					     TTransactionId aTransactionId,
+					     RStringF aDefaultAlgorithm );
+
+    /**
+    * Return timer services interface    
+    */
+    inline MTimerManager& Timer() 
+        {
+        return iTimerManager;
+        }
+
+private: // New functions, for internal use
+
+    /**
+    * Constructor
+    * @param aTimerManager Timer Manager
+    */
+    CSIPSecDigestCache( MTimerManager& aTimerManager );
+
+    /**
+    * Returns the cache that is associated with aCacheEntry.
+    * @param aCacheEntry Cache enty
+    * @return Cache to use with aCacheEntry
+    */
+	TSglQue< CSIPSecDigestCacheEntry >&
+		SelectCache( const CSIPSecDigestCacheEntry& aCacheEntry );
+
+    /**
+    * Removes all entries
+    */
+    void RemoveAllEntries();
+
+	/**
+    * Removes all entries from aList.
+    */
+    void RemoveAllEntriesFromList( TSglQue<CSIPSecDigestCacheEntry>& aList );
+
+    /**
+    * Removes all credentials
+    */
+    void RemoveAllCredentials();
+
+    /**
+    * Checks if the specified credentials are in the list.
+    * @param aCredentials Credentials
+    * @return ETrue  if credentials are in the list,
+    *		  EFalse otherwise
+    */
+    TBool IsCredentialsInList( const CSIPSecUserRecord& aCredentials );
+
+	/**
+	* Clears all entries from the specified cache belonging to the given user.
+    * @param aList Cache list
+    * @param aUser SIPSec user
+    */
+	void RemoveUsedEntry( TSglQue<CSIPSecDigestCacheEntry>& aList,
+						  const MSIPSecUser& aUser );
+
+	/**
+    * If aList contains aCredentials, the aCredentials and the cache entries
+    * referring to it are removed from aList and deleted.
+    * @param aList Queue of cache entries
+    * @param aCredentials Credentials
+    * @param aAKAOnly If ETrue, only AKA cache entries are cleared
+    *				  If EFalse, all cache entries are cleared
+    */
+	void RemoveMatchingEntry( TSglQue<CSIPSecDigestCacheEntry>& aList,
+							  CSIPSecUserRecord& aCredentials,
+							  TBool aAKAOnly );
+
+	/**
+    * Removes entry from cache and deletes it. If the associated
+    * CSIPSecUserRecord is no longer referred, it is also deleted.
+    * @param aEntry Cache entry
+    * @return ETrue if the associated CSIPSecUserRecord was also deleted,
+    *		  EFalse otherwise.
+    */
+	TBool RemoveCacheEntry( CSIPSecDigestCacheEntry& aEntry,
+							const MSIPSecUser& aUser );
+
+	/*
+     * Search the challenges present in aResponse, and check if they match the
+     * cache entry.
+	 * @param aResponse SIP response
+	 * @param aAlgorithm Algorithm from Security-Server header or empty.
+	 * @param aDefaultAlgorithm Default algorithm
+	 * @param aRealm Realm in the cache
+	 * @param aMatch OUT: Set to ETrue if a challenge matches the cache entry.
+	 * @return ETrue if the SIP response had at least one challenge
+     */
+	TBool HandleChallenges( CSIPResponse& aResponse,
+						    RStringF aAlgorithm,
+						    RStringF aDefaultAlgorithm,
+						    const TDesC8& aRealm,
+						    TBool& aMatch ) const;
+
+	/*
+     * Check if an authorization-header in aRequest matches a cache entry.
+	 * @param aRequest SIP request
+	 * @param aAlgorithm Algorithm from Security-Server header or empty
+	 * @param aDefaultAlgorithm Default algorithm
+	 * @param aRealm Realm in the cache entry
+	 * @return ETrue If a header matched the cache entry.
+     */
+	TBool HandleAuthorizations( CSIPRequest& aRequest,
+							    RStringF aAlgorithm,
+							    RStringF aDefaultAlgorithm,
+							    const TDesC8& aRealm ) const;
+
+	/*
+     * Check if the authenticate- or authorization-headers present in aMessage,
+     * match the cache entry.
+	 * @param aMessage SIP message
+	 * @param aAlgorithm Algorithm from Security-Server header or empty
+	 * @param aDefaultAlgorithm Default algorithm
+	 * @param aHeaderName Name of the headers to process.
+	 * @param aRealm Realm in the cache entry
+	 * @param aCheckChallenges ETrue if the challenges in authenticate must be
+	 *		  checked that they are valid digest challenges.
+	 * @param aChallengeFound ETrue if response had at least one challenge.
+	 * @return ETrue If a header matched the cache entry.
+     */
+	TBool HandleAuthHeaders( CSIPMessage& aMessage,
+							 RStringF aAlgorithm,
+							 RStringF aDefaultAlgorithm,
+							 RStringF aHeaderName,
+							 const TDesC8& aRealm,
+							 TBool aCheckChallenges,
+							 TBool& aChallengeFound ) const;
+
+	TBool CompareAKARealm( CSIPAuthHeaderBase& aHeader,
+						   const TDesC8& aCachedRealm,
+						   RStringF aAlgorithm,
+						   RStringF aDefaultAlgorithm ) const;
+
+	/*
+	 * When proxy- or endpoint cache entry is removed from the cache, checks
+	 * if the MSIPSecUser of the CSIPSecUserRecord that was pointed by the
+	 * removed cache entry, needs to be changed.
+     * @param 
+     */
+	void ChangeRecordUserIfNeeded( CSIPSecUserRecord& record,
+								   const MSIPSecUser& aUser );
+
+private: // Data
+        
+    // Proxy cache entries, owned.
+	TSglQue< CSIPSecDigestCacheEntry > iProxyList;
+    // Proxy cache iterator
+    TSIPSecDigestCacheEntryIterator iProxyListIter;
+
+    // Endpoint cache entries, owned.
+	TSglQue< CSIPSecDigestCacheEntry > iEndpointList;
+    // Endpoint cache iterator
+    TSIPSecDigestCacheEntryIterator iEndpointListIter;
+
+    // Credentials list, owned.
+	TSglQue< CSIPSecUserRecord > iCredentialsList;    
+    // Credentials list iterator
+	TSglQueIter< CSIPSecUserRecord > iCredentialsListIter;
+
+    // Requests, owned.
+	RPointerArray< CSIPSecDigestObserver > iDigestObservers;
+	
+	// Timer services
+    MTimerManager& iTimerManager;
+
+#ifdef CPPUNIT_TEST
+    friend class CSIPSecDigestTest;
+	friend class CSIPSecDigestCacheTest;
+#endif
+	};
+	
+#endif // __SIPSEC_DIGESTCACHE_H__
+
+// End of File