diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/SIPSec/IpSecPlugin/src/CIpSecSadbHandler.cpp --- /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 +#include + +#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 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(), spi, iSaParams->iAuthAlg, SADB_EALG_NULL, + SADB_SASTATE_MATURE, 0,0 ); + msg->Add( Int2Type(), aSourceAddress, 0, 0 ); + msg->Add( Int2Type(), aDestinationAddress, 0, 0 ); + msg->Add( Int2Type(), iSaParams->iAuthKey, 0 ); + + sadb_msg &m = msg->MsgHdr(); + m.sadb_msg_len = static_cast( 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(), spi, 0, 0, + SADB_SASTATE_MATURE, 0,0 ); + msg->Add( Int2Type(), aSourceAddress, 0, 0 ); + msg->Add( Int2Type(), aDestinationAddress, 0, 0 ); + + sadb_msg &m = msg->MsgHdr(); + m.sadb_msg_len = static_cast( 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