realtimenetprots/sipfw/SIP/SIPSec/IpSecPlugin/src/CIpSecSadbHandler.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/SIPSec/IpSecPlugin/src/CIpSecSadbHandler.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,509 @@
+// Copyright (c) 2004-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          : CIpSecSadbHandler.cpp
+// Part of       : SIPSec
+// Version       : SIP/4.0 
+//
+
+
+
+#include <pfkey_send.h>
+#include <lib_pfkey.h>
+
+#include "siprequest.h"
+#include "sipresponse.h"
+#include "sipsecurityclientheader.h"
+#include "sipsecurityserverheader.h"
+#include "sipsecurityverifyheader.h"
+
+#include "CIpSecSadbHandler.h"
+#include "MSipSecSaDbSendReceiveObserver.h"
+#include "SipSecIpsecParams.h"
+#include "SipSecUtils.h"
+#include "CSipSecSaDbMsgSender.h"
+#include "CSipSecSaDbMsgReceiver.h"
+#include "MIpSecMechanismParams.h"
+#include "MSipSecSadbObserver.h"
+
+const TInt KOngoingAddsGranularity = 4;
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::NewL
+// ----------------------------------------------------------------------------
+//
+CIpSecSadbHandler* CIpSecSadbHandler::NewL( 
+    MSipSecSadbObserver& aObserver, 
+    RSADB& aSADB )
+	{
+   	CIpSecSadbHandler* self = new ( ELeave ) CIpSecSadbHandler( aObserver );
+	CleanupStack::PushL( self );
+	self->ConstructL( aSADB );
+	CleanupStack::Pop( self );
+	return self;
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::ConstructL
+// ----------------------------------------------------------------------------
+//	
+void CIpSecSadbHandler::ConstructL( RSADB& aSADB )
+    {
+   	iSaDbMsgSender = CSipSecSaDbMsgSender::NewL( *this, aSADB );
+    }
+   
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::CIpSecSadbHandler
+// ----------------------------------------------------------------------------
+//	
+CIpSecSadbHandler::CIpSecSadbHandler( MSipSecSadbObserver& aObserver ) : 
+    iObserver( aObserver ),
+    iState( EAvailable ),
+    iOngoingAdds( KOngoingAddsGranularity )
+	{
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::~CIpSecSadbHandler
+// ----------------------------------------------------------------------------
+//	
+CIpSecSadbHandler::~CIpSecSadbHandler()
+	{
+	delete iSaDbMsgSender;
+	iOngoingAdds.Reset();
+	iOngoingAdds.Close();
+	}
+
+	
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::AddSasL
+// ----------------------------------------------------------------------------
+//	
+void CIpSecSadbHandler::AddSasL(
+	MIpSecMechanismParams& aParams,
+	TInetAddr aLocalAddress,
+	TInetAddr aRemoteAddress,
+	TSipSecSaParams& aSaParams )
+	{
+	IssueRequestL( aParams, 
+	               aLocalAddress, 
+	               aRemoteAddress, 
+	               aSaParams );
+
+    // Kick-start SA adding looping
+    AddCompletedL( KErrNone );
+	}
+	
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::DeleteSasL
+// ----------------------------------------------------------------------------
+//	
+void CIpSecSadbHandler::DeleteSasL( 
+	MIpSecMechanismParams& aParams,
+	TInetAddr aLocalAddress,
+	TInetAddr aRemoteAddress,
+	TSipSecSaParams& aSaParams )
+	{
+	CancelAddSaOps();
+	
+	IssueRequestL( aParams, 
+	               aLocalAddress, 
+	               aRemoteAddress, 
+	               aSaParams );
+	
+	// Kick-start SA deleting looping
+    DeleteCompletedL();	
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::SetSaParamsL
+// ----------------------------------------------------------------------------
+//				
+void CIpSecSadbHandler::SetSaParamsL( 
+	TSipSecSaParams& aParams, 				     
+	CSIPSecurityHeaderBase& aCliHeader, 
+	CSIPSecurityHeaderBase& aSrvHeader,
+	const TDesC8& aAuthKey )
+	{
+	TInt len = aAuthKey.Length();
+	__ASSERT_ALWAYS( len == KAuthKeyFromSIMSize && len <= KAuthKeyMaxSize, 
+	                 User::Leave( KErrArgument ) );
+	                 
+	aParams.iSpi_uc  = SipSecUtils::ValueL( aCliHeader, KSpic );
+	aParams.iSpi_us  = SipSecUtils::ValueL( aCliHeader, KSpis );
+	aParams.iPort_uc = SipSecUtils::ValueL( aCliHeader, KPortc );
+	aParams.iPort_us = SipSecUtils::ValueL( aCliHeader, KPorts );
+	aParams.iSpi_pc  = SipSecUtils::ValueL( aSrvHeader, KSpic );
+	aParams.iSpi_ps  = SipSecUtils::ValueL( aSrvHeader, KSpis );
+	aParams.iPort_pc = SipSecUtils::ValueL( aSrvHeader, KPortc );
+	aParams.iPort_ps = SipSecUtils::ValueL( aSrvHeader, KPorts );
+	
+	RStringF v = SipSecUtils::ValueFL( aCliHeader, KAlgorithm );
+	const TDesC8& alg = v.DesC();
+	__ASSERT_ALWAYS( alg.Length(),User::Leave( KErrNotReady ) );	  
+	if ( alg == KHmacMd596 )
+	    {
+	    aParams.iAuthAlg = SADB_AALG_MD5HMAC;
+	    aParams.iAuthKey.Copy( aAuthKey );
+	    }
+	else
+	    {
+	    aParams.iAuthAlg = SADB_AALG_SHA1HMAC;
+	    
+	    // In hmac-sha-1-96 160 bit key has to be used, aAuthKey retrieved
+	    // from SIM should be only 128 bits, pad with zeros from right
+        const TUint KPadLength = 4;
+        
+        __ASSERT_ALWAYS( KAuthKeyFromSIMSize + KPadLength <= KAuthKeyMaxSize,
+                         User::Leave( KErrOverflow ) );
+
+	    TBuf8<KAuthKeyMaxSize> authkey;
+	    authkey.Append( aAuthKey );
+	    const TUint KPosKeyEnd = authkey.Length();
+	    authkey.SetMax();
+	    LittleEndian::Put32( &authkey[ KPosKeyEnd ], 0 );
+	    aParams.iAuthKey.Copy( authkey );
+	    }
+	
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::CancelAddSAOps
+// ----------------------------------------------------------------------------
+//	
+void CIpSecSadbHandler::CancelAddSaOps()
+    {
+    if ( iSaDbMsgSender->Type() == SADB_ADD )
+        {
+        iSaDbMsgSender->Cancel();
+        Reset();
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::SADBAddMsgReceived
+// ----------------------------------------------------------------------------
+//       
+void CIpSecSadbHandler::SADBAddMsgReceived( TUint aMsgSeq, TInt aError )
+    {
+    TInt index = iOngoingAdds.FindInOrder( aMsgSeq );
+    if ( index != KErrNotFound )
+        {
+        iOngoingAdds.Remove( index );
+        iOngoingAdds.Compress();
+        
+        TBool aSuccess( !aError );
+        
+        TRAP_IGNORE( SAsAddedL( aSuccess ) )
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::MessageSentL
+// ----------------------------------------------------------------------------
+//
+void CIpSecSadbHandler::MessageSentL( TInt aStatus, TInt aMsgType )
+	{
+	if ( aMsgType == SADB_ADD )
+	    {
+	    AddCompletedL( aStatus );
+	    }
+	else
+	    {
+	    // Error is ignored since anyway we should try to delete existing SAs
+	    DeleteCompletedL();
+	    }
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::MessageReceived
+// ----------------------------------------------------------------------------
+//
+void CIpSecSadbHandler::MessageReceived( TInt /* aStatus */ )
+	{
+	// Not used in this context
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::IssueRequestL
+// ----------------------------------------------------------------------------
+//
+void CIpSecSadbHandler::IssueRequestL(
+    MIpSecMechanismParams& aParams,
+	TInetAddr& aLocalAddress,
+	TInetAddr& aRemoteAddress,
+	TSipSecSaParams& aSaParams )
+    {
+   	if ( !IsAvailable() )
+	    {
+	    User::Leave( KErrInUse );
+	    }
+	    
+	// Remember parameters regarding current request
+	iParams = &aParams;
+	iSaParams = &aSaParams;
+	
+	iLocalAddress = aLocalAddress;
+	iRemoteAddress = aRemoteAddress;
+    }
+ 
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::IsAvailable
+// ----------------------------------------------------------------------------
+//   
+TBool CIpSecSadbHandler::IsAvailable()
+    {
+    return ( iState == EAvailable );
+    }
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::Reset
+// ----------------------------------------------------------------------------
+//    
+void CIpSecSadbHandler::Reset()
+    {
+    iState = EAvailable;
+    iOngoingAdds.Reset();
+    iOngoingAdds.Compress();
+    }
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::AddCompletedL
+// ----------------------------------------------------------------------------
+//   
+void CIpSecSadbHandler::AddCompletedL( TInt aError )
+    {
+    // No use to continue if failure occured
+    if ( aError != KErrNone )
+	    {
+	    SAsAddedL( EFalse );
+	    }
+	
+	switch ( iState )
+	    {
+	    case EAvailable:
+	        {
+	        // 1. Inbound  spi_us: port_us <- port_pc
+
+             // Note: Family is KAfInet
+        	iLocalAddress.SetPort( iSaParams->iPort_us );
+        	iRemoteAddress.SetPort( iSaParams->iPort_pc );
+	        AddSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_us );
+	        iState = EAddingInbound1;
+	        break;
+	        }
+	    case EAddingInbound1:
+	        {
+	        // 2. Inbound  spi_uc: port_uc <- port_ps
+	
+	        iLocalAddress.SetPort( iSaParams->iPort_uc );
+	        iRemoteAddress.SetPort( iSaParams->iPort_ps );
+	        AddSaL(  iRemoteAddress, iLocalAddress, iSaParams->iSpi_uc );
+	        iState = EAddingInbound2;
+	        break;
+	        }
+	    case EAddingInbound2:
+	        {
+	        // 3. Outbound spi_ps: port_uc -> port_ps
+
+	        iLocalAddress.SetPort( iSaParams->iPort_uc );
+	        iRemoteAddress.SetPort( iSaParams->iPort_ps );
+	        AddSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_ps );
+	        iState = EAddingOutbound1;
+	        break;
+	        }
+	    case EAddingOutbound1:
+	        {
+	       	// 4. Outbound spi_pc: port_us -> port_pc
+	
+        	iLocalAddress.SetPort( iSaParams->iPort_us );
+        	iRemoteAddress.SetPort( iSaParams->iPort_pc );
+	        AddSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_pc );
+	        iState = EAddingOutbound2;
+	        break;
+	        }
+	    case EAddingOutbound2:
+	        {
+	        iState = EAvailable;
+	        SAsAddedL( ETrue );
+	        break;
+	        }
+	    default:
+	        {
+	        break;
+	        }
+	    }
+    }
+ 
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::DeleteCompletedL
+// ----------------------------------------------------------------------------
+//      
+void CIpSecSadbHandler::DeleteCompletedL()
+    {
+   	switch ( iState )
+	    {
+	    case EAvailable:
+	        {
+	        // 1. Inbound  spi_us: port_us <- port_pc
+
+            // Note: Family is KAfInet
+        	iLocalAddress.SetPort( iSaParams->iPort_us ); 
+        	iRemoteAddress.SetPort( iSaParams->iPort_pc );
+	        DeleteSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_us );
+	        iState = EDeletingInbound1;
+	        break;
+	        }
+	    case EDeletingInbound1:
+	        {
+	        // 2. Inbound  spi_uc: port_uc <- port_ps
+	
+	        iLocalAddress.SetPort( iSaParams->iPort_uc );
+	        iRemoteAddress.SetPort( iSaParams->iPort_ps );
+	        DeleteSaL( iRemoteAddress, iLocalAddress, iSaParams->iSpi_uc );
+	        iState = EDeletingInbound2;
+	        break;
+	        }
+	    case EDeletingInbound2:
+	        {
+	        // 3. Outbound spi_ps: port_uc -> port_ps
+
+	        iLocalAddress.SetPort( iSaParams->iPort_uc );
+	        iRemoteAddress.SetPort( iSaParams->iPort_ps );
+	        DeleteSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_ps );
+	        iState = EDeletingOutbound1;
+	        break;
+	        }
+	    case EDeletingOutbound1:
+	        {
+	       	// 4. Outbound spi_pc: port_us -> port_pc
+	
+        	iLocalAddress.SetPort( iSaParams->iPort_us );
+        	iRemoteAddress.SetPort( iSaParams->iPort_pc );
+	        DeleteSaL( iLocalAddress, iRemoteAddress, iSaParams->iSpi_pc );
+	        iState = EDeletingOutbound2;
+	        break;
+	        }
+	    case EDeletingOutbound2:
+	        {
+	        // All done, inform observer.
+	        // Might lead to destruction of this handler.
+	        Reset();
+	        iObserver.SAsDeletedL();
+	        break;
+	        }
+	    default:
+	        {
+	        break;
+	        }
+	    }
+    }
+    
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::AddSaL
+// ----------------------------------------------------------------------------
+//	
+void CIpSecSadbHandler::AddSaL( 
+    TInetAddr& aSourceAddress,
+    TInetAddr& aDestinationAddress,
+    TUint aSpi )
+	{
+	TUint seqNum( iParams->SeqNumber() );
+	
+	// Store sequence numbers of add operations
+	User::LeaveIfError( iOngoingAdds.Append( seqNum ) );
+	
+	TPfkeySendMsg*
+		msg = new ( ELeave ) TPfkeySendMsg( SADB_ADD, SADB_SATYPE_ESP, 
+		   							  	    seqNum, PID );
+	CleanupStack::PushL( msg );
+	
+	// SPI has to be converted to network byte order
+	TUint32 spi = ConvertToBigEndian( aSpi );
+	
+	msg->Add( Int2Type<SADB_EXT_SA>(), spi, iSaParams->iAuthAlg, SADB_EALG_NULL, 
+			  SADB_SASTATE_MATURE, 0,0 ); 
+	msg->Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSourceAddress, 0, 0 );
+	msg->Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDestinationAddress, 0, 0 );	
+	msg->Add( Int2Type<SADB_EXT_KEY_AUTH>(), iSaParams->iAuthKey, 0 );
+
+	sadb_msg &m = msg->MsgHdr();
+	m.sadb_msg_len = static_cast<TUint16>( msg->Length() / KWordLen );
+	
+	iSaDbMsgSender->SendL( msg, SADB_ADD );
+	
+	CleanupStack::Pop( msg ); // msg ownership was transferred
+	}
+
+	
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::DeleteSaL
+// ----------------------------------------------------------------------------
+//				     
+void CIpSecSadbHandler::DeleteSaL( 
+    TInetAddr& aSourceAddress,
+    TInetAddr& aDestinationAddress,
+    TUint aSpi )
+	{
+	TPfkeySendMsg*
+		msg = new ( ELeave ) TPfkeySendMsg( SADB_DELETE, SADB_SATYPE_ESP, 
+		   							  	    iParams->SeqNumber(), PID );
+	CleanupStack::PushL( msg );
+	
+    
+    // SPI has to be converted to network byte order
+	TUint32 spi = ConvertToBigEndian( aSpi );
+	
+	msg->Add( Int2Type<SADB_EXT_SA>(), spi, 0, 0, 
+			  SADB_SASTATE_MATURE, 0,0 ); 
+	msg->Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSourceAddress, 0, 0 );
+	msg->Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDestinationAddress, 0, 0 );
+	
+	sadb_msg &m = msg->MsgHdr();
+	m.sadb_msg_len = static_cast<TUint16>( msg->Length() / KWordLen );
+	
+	iSaDbMsgSender->SendL( msg, SADB_DELETE );
+	
+	CleanupStack::Pop( msg ); // msg ownership was transferred	
+	}
+
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::SAsAddedL
+// ----------------------------------------------------------------------------
+//	
+void CIpSecSadbHandler::SAsAddedL( TBool aSuccess )
+    {
+    // Haven't necassarily yet received all the sadb messages related
+    // to add operations. In that case we have to wait for them since they
+    // contain also information about success.
+    if ( !aSuccess || ( iOngoingAdds.Count() == 0 && iState == EAvailable ) )
+        {
+        iObserver.SAsAddedL( aSuccess );
+        Reset();
+        }
+    }
+	
+// ----------------------------------------------------------------------------
+// CIpSecSadbHandler::ConvertToBigEndian
+// ----------------------------------------------------------------------------
+//		
+TUint32 CIpSecSadbHandler::ConvertToBigEndian( TUint32 aNum )
+    {
+    const TInt KMaxTUint32CStringLen = 11;
+    TUint8 temp[ KMaxTUint32CStringLen ];	
+	LittleEndian::Put32( temp, aNum );
+	return BigEndian::Get32( temp );
+    }
+	
+// End of File