--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransportTls.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,946 @@
+// Copyright (c) 2005-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 : CTransportTls.cpp
+// Part of : ConnectionMgr
+// implementation
+// Version : SIP/5.0
+//
+
+
+
+#include <securesocket.h>
+
+#include "CTransportTls.h"
+#include "CSipConnection.h"
+#include "CErrorHandler.h"
+#include "MTransactionFinder.h"
+#include "MTransportOwner.h"
+#include "MServerTaFactory.h"
+#include "CSender.h"
+#include "CSenderTcp.h"
+#include "CReceiverTcp.h"
+#include "CommonConsts.h"
+#include "siperr.h"
+#include "NetworkInfo.h"
+#include "COwnerSettingsList.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "TTlsTransTcpConnecting.h"
+#include "TTlsTransTlsConnecting.h"
+#include "TTlsTransTlsConnected.h"
+#include "CSecureSocketContainer.h"
+#include <sipnattraversalcontroller.h>
+#include "SipLogs.h"
+#include "uricontainer.h"
+#include "sipuri.h"
+#include "siphostport.h"
+#include <asn1dec.h>
+#include <ssl_internal.h>
+#include <x509cert.h>
+#include <x500dn.h>
+#include <x520ava.h>
+#include <x509certext.h>
+#include <x509gn.h>
+#include <securitydefsconst.h>
+
+const TInt KMaxConnectAttempts = 2;
+_LIT(KSipDomainOID, "1.3.6.1.5.5.7.3.20");
+_LIT(KAnyExtendedKeyUsage, "2.5.29.37.0");
+
+// -----------------------------------------------------------------------------
+// CTransportTls::NewL
+// -----------------------------------------------------------------------------
+//
+CTransportTls* CTransportTls::NewL(
+ RSocketServ& aServer,
+ MTransactionFinder& aFinder,
+ MServerTaFactory& aTaFactory,
+ MTransportOwner& aTransportOwner,
+ MTimerManager& aTimer,
+ const TSIPTransportParams& aTransportParams,
+ const TInetAddr& aRemoteAddr,
+ TUint aTOne,
+ CSIPServerResolver& aServerResolver,
+ RConnection& aConnection,
+ MSigCompController& aSigCompHandler,
+ CNetworkInfo& aNetworkInfo,
+ COwnerSettingsList& aSettingsList,
+ CSIPNATTraversalController& aNATTraversal )
+ {
+ CTransportTls* self = NewLC( aServer,
+ aFinder,
+ aTaFactory,
+ aTransportOwner,
+ aTimer,
+ aTransportParams,
+ aRemoteAddr,
+ aTOne,
+ aServerResolver,
+ aConnection,
+ aSigCompHandler,
+ aNetworkInfo,
+ aSettingsList,
+ aNATTraversal );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::NewLC
+// -----------------------------------------------------------------------------
+//
+CTransportTls* CTransportTls::NewLC(
+ RSocketServ& aServer,
+ MTransactionFinder& aFinder,
+ MServerTaFactory& aTaFactory,
+ MTransportOwner& aTransportOwner,
+ MTimerManager& aTimer,
+ const TSIPTransportParams& aTransportParams,
+ const TInetAddr& aRemoteAddr,
+ TUint aTOne,
+ CSIPServerResolver& aServerResolver,
+ RConnection& aConnection,
+ MSigCompController& aSigCompHandler,
+ CNetworkInfo& aNetworkInfo,
+ COwnerSettingsList& aSettingsList,
+ CSIPNATTraversalController& aNATTraversal )
+ {
+ CTransportTls* self = new ( ELeave ) CTransportTls( aServer,
+ aFinder,
+ aTaFactory,
+ aTransportOwner,
+ aTimer,
+ aTransportParams,
+ aRemoteAddr,
+ aTOne,
+ aServerResolver,
+ aConnection,
+ aSigCompHandler,
+ aNetworkInfo,
+ aSettingsList,
+ aNATTraversal );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::CTransportTls
+// -----------------------------------------------------------------------------
+//
+CTransportTls::CTransportTls(
+ RSocketServ& aServer,
+ MTransactionFinder& aFinder,
+ MServerTaFactory& aTaFactory,
+ MTransportOwner& aTransportOwner,
+ MTimerManager& aTimer,
+ const TSIPTransportParams& aTransportParams,
+ const TInetAddr& aRemoteAddr,
+ TUint aTOne,
+ CSIPServerResolver& aServerResolver,
+ RConnection& aConnection,
+ MSigCompController& aSigCompHandler,
+ CNetworkInfo& aNetworkInfo,
+ COwnerSettingsList& aSettingsList,
+ CSIPNATTraversalController& aNATTraversal ) :
+ CTransport( aFinder,
+ aTaFactory,
+ aTransportOwner,
+ aServerResolver,
+ aSigCompHandler,
+ aTransportParams,
+ aNetworkInfo,
+ aSettingsList,
+ aNATTraversal ),
+ iSocketServ( aServer ),
+ iTimer( aTimer ),
+ iTimerValue( 64 * aTOne ),
+ iConnection( aConnection ),
+ iRemoteAddr( aRemoteAddr ),
+ iStates( TTlsTransStateBase::EMaxStates ),
+ iCurrentState( TTlsTransStateBase::ETcpConnecting ),
+ iIsSending( EFalse )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ConstructL()
+ {
+ iErrorHandler = CTransportErrorHandler::NewL( *this );
+
+ User::LeaveIfError( iSocket.Open( iSocketServ,
+ KAfInet,
+ KSockStream,
+ KProtocolInetTcp,
+ iConnection ) );
+
+ // Secure socket will be added later to the container
+ iSocketContainer = CSecureSocketContainer::NewL( iSocket );
+
+ iReceiver = CReceiverTcp::NewL( *this );
+
+ iSender = CSenderTcp::NewL( *this, iSettingsList );
+ iDomainName = NULL;
+
+ InitializeStatesL();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTransportTls::~CTransportTls
+// -----------------------------------------------------------------------------
+//
+CTransportTls::~CTransportTls()
+ {
+ iTimer.Stop( iMyTimerId );
+ delete iErrorHandler;
+ delete iReceiver;
+ delete iSender;
+ delete iSocketContainer;
+ delete iDomainName;
+ if ( iSecureSocket )
+ {
+ iNATTraversal.SocketIdle( EFalse, *iSecureSocket );
+ delete iSecureSocket;
+ }
+ iSocket.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::HandleMessage
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::HandleMessage(
+ const TSIPTransportParams& aParams,
+ RStringF aProtocol,
+ const TInetAddr& aRemoteAddr,
+ TUint /*aLocalPort*/,
+ TBool /*aIsStrict*/ )
+ {
+ return ( aProtocol == SIPStrings::StringF( SipStrConsts::ETLS ) &&
+ iRemoteAddr.CmpAddr( aRemoteAddr ) &&
+ Match( aParams ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::SourcePort
+// -----------------------------------------------------------------------------
+//
+TUint CTransportTls::SourcePort()
+ {
+ return iSocket.LocalPort();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::SendToNetL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::SendToNetL(
+ const TSIPTransportParams& aParams,
+ const TInetAddr& aAddress,
+ CSIPMessage& aMessage,
+ TBool /*aForceUDP*/,
+ TUint aOrigTransport,
+ TRequestStatus &aStatus )
+ {
+ HandleMixedAddressFamilysL( aMessage, aAddress );
+
+ CurrentState().SendToNetL( aParams,
+ aAddress,
+ aMessage,
+ aOrigTransport,
+ aStatus );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::CancelSend
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::CancelSend( TRequestStatus& aStatus )
+ {
+ return iSender->FindAndCancel( aStatus );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ErrorHandler
+// -----------------------------------------------------------------------------
+//
+CTransportErrorHandler& CTransportTls::ErrorHandler()
+ {
+ return *iErrorHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::WaitL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::WaitL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::IsWaiting
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::IsWaiting( TUint /*aProtocol*/, TUint /*aPort*/ )
+ {
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::CancelAllRequests
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::CancelAllRequests( CSIPConnection::TState aReason )
+ {
+ GetSender().CancelAllRequests( aReason );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Protocol
+// -----------------------------------------------------------------------------
+//
+TUint CTransportTls::Protocol()
+ {
+ return KProtocolTls;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::GetSocketContainerL
+// -----------------------------------------------------------------------------
+//
+CSocketContainer& CTransportTls::GetSocketContainerL(
+ const TInetAddr& /*aRemoteAddr*/ )
+ {
+ return *iSocketContainer;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::InformSendingStatus
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::InformSendingStatus( const TInetAddr& /*aRemoteAddr*/ )
+ {
+ Sending( iIsSending );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Sender
+// -----------------------------------------------------------------------------
+//
+CSender* CTransportTls::Sender(
+ const TSIPTransportParams& aParams,
+ TUint aProtocol,
+ const TInetAddr& aRemoteAddr )
+ {
+ if ( Protocol() == aProtocol &&
+ aRemoteAddr.CmpAddr( iRemoteAddr ) &&
+ Match( aParams ) )
+ {
+ return iSender;
+ }
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Disconnect
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::Disconnect( const TInetAddr& /*aRemoteHost*/ )
+ {
+ // If this is reserved or persistent transport,
+ // only all send operations are cleared
+ if ( IsReservedTransport() || IsPersistent() )
+ {
+ iSender->CancelAllRequests( KErrSIPTransportFailure );
+ }
+ else
+ {
+ Remove();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::PersistentRemoteAddr
+// -----------------------------------------------------------------------------
+//
+TInetAddr* CTransportTls::PersistentRemoteAddr(
+ MSIPNATBindingObserver* aBindingObserver )
+ {
+ TInt index = iBindingObservers.FindInAddressOrder( aBindingObserver );
+ if ( index >= 0 && index < iBindingObservers.Count() )
+ {
+ return &iRemoteAddr;
+ }
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::SocketContainer
+// -----------------------------------------------------------------------------
+//
+CSocketContainer& CTransportTls::SocketContainer()
+ {
+ return *iSocketContainer;
+ }
+// -----------------------------------------------------------------------------
+// CTransportTls::SocketContainer
+// -----------------------------------------------------------------------------
+//
+CSocketContainer* CTransportTls::SocketContainer(
+ TUint /*aIPAddrFamily*/ )
+ {
+ return iSocketContainer;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ReceivedDataL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ReceivedDataL(
+ HBufC8* /*aData*/,
+ const TInetAddr& /*aRemoteAddr*/,
+ TBool /*aCompressed*/ )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ReceivedDataL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ReceivedDataL(
+ CSIPMessage* aMessage,
+ const TInetAddr& aRemoteAddr,
+ TInt aError,
+ TBool aCompressed )
+ {
+ RecvL( aMessage, aRemoteAddr, aError, aCompressed );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::SigCompHandler
+// -----------------------------------------------------------------------------
+//
+MSigCompController* CTransportTls::SigCompHandler()
+ {
+ return SigCompressionHandler();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ResetSocketL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ResetSocketL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ContinueL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ContinueL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::StopL
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::StopL()
+ {
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Remove
+// -----------------------------------------------------------------------------
+//
+TInt CTransportTls::Remove()
+ {
+ return iTransportOwner->RemoveTransport( this );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ConnectionOpenL
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::ConnectionOpenL()
+ {
+ return CurrentState().ConnectionOpenL();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::DisconnectedL
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::DisconnectedL()
+ {
+ TBool retVal( ETrue );
+
+ // Flow failure notification may lead to immediate self deletion
+ if ( !NotifyFlowFailure() )
+ {
+ retVal = CurrentState().DisconnectedL();
+ }
+
+ return retVal;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ReRouteL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ReRouteL( TUint /*aProtocol*/, COutgoingData* aData )
+ {
+ // TLS transport doesn't allow rerouting
+ if ( aData )
+ {
+ TRequestStatus* status = aData->Status();
+ if ( status != 0 && *status == KRequestPending )
+ {
+ User::RequestComplete( status, KErrSIPTransportFailure );
+ }
+ delete aData;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::IapId
+// -----------------------------------------------------------------------------
+//
+TUint32 CTransportTls::IapId()
+ {
+ return iTransportOwner->IapId();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Sending
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::Sending( TBool aIsSending )
+ {
+ iIsSending = aIsSending;
+
+ if ( iSecureSocket )
+ {
+ iNATTraversal.SocketIdle( !iIsSending, *iSecureSocket );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ChangeStateL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ChangeStateL( TTlsTransStateBase::TState aState )
+ {
+ iCurrentState = aState;
+
+ CurrentState().EnterL();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ConnectTcpL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ConnectTcpL()
+ {
+ iReceiver->Connect( iRemoteAddr );
+ iConnectAttemptCount++;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ConnectTlsL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ConnectTlsL()
+ {
+ if ( !iSecureSocket )
+ {
+ _LIT( KTLS1,"TLS1.0" );
+ iSecureSocket = CSecureSocket::NewL( iSocket, KTLS1 );
+ }
+
+ CheckCipherSuiteAvailabilityL();
+
+ // Don't show any pop-up queries if matching certificate is not found
+ // while establishing the secure connection.
+ User::LeaveIfError(
+ iSecureSocket->SetDialogMode( EDialogModeUnattended ) );
+
+
+ iSocketContainer->SetSecureSocket( iSecureSocket );
+
+ iReceiver->Connect( iRemoteAddr );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Retry
+// -----------------------------------------------------------------------------
+//
+TBool CTransportTls::Retry() const
+ {
+ return ( iConnectAttemptCount < KMaxConnectAttempts );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::ResetL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::ResetL()
+ {
+ iSocketContainer->SetSecureSocket( 0 );
+ iSecureSocket->FlushSessionCache();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::Destroy
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::Destroy()
+ {
+ Remove();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::GetSender
+// -----------------------------------------------------------------------------
+//
+CSender& CTransportTls::GetSender()
+ {
+ return *iSender;
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::StartTimerL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::StartTimerL( TInt aTimeout )
+ {
+ iTimer.Stop( iMyTimerId );
+ iMyTimerId = iTimer.StartL( this, aTimeout );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::StopTimer
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::StopTimer()
+ {
+ iTimer.Stop( iMyTimerId );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::TimerExpiredL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::TimerExpiredL(
+ TTimerId /*aTimerId*/,
+ TAny* /*aTimerParam*/ )
+ {
+ if ( IsReservedTransport() || IsPersistent() )
+ {
+ iSender->CancelAllRequests( KErrSIPTransportFailure );
+ }
+ else
+ {
+ Remove();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::InitializeStatesL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::InitializeStatesL()
+ {
+ iStates.AppendL( TTlsTransTcpConnecting( *this ),
+ sizeof( TTlsTransTcpConnecting ) );
+
+ iStates.AppendL( TTlsTransTlsConnecting( *this ),
+ sizeof( TTlsTransTlsConnecting ) );
+
+ iStates.AppendL( TTlsTransTlsConnected( *this, iTimerValue ),
+ sizeof( TTlsTransTlsConnected ) );
+
+ ChangeStateL( TTlsTransStateBase::ETcpConnecting );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::CurrentState
+// -----------------------------------------------------------------------------
+//
+TTlsTransStateBase& CTransportTls::CurrentState()
+ {
+ return iStates.At( iCurrentState );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::CheckCipherSuiteAvailabilityL
+// -----------------------------------------------------------------------------
+//
+void CTransportTls::CheckCipherSuiteAvailabilityL()
+ {
+ __ASSERT_DEBUG( iSecureSocket,
+ User::Panic(
+ _L("CTransportTls::CheckCipherSuiteAvailabilityL iSecureSocket=0"),
+ KErrNotReady ) );
+
+ const TInt KCipherSuitesDesLen = 64;
+ TBuf8< KCipherSuitesDesLen > ciphers;
+ User::LeaveIfError( iSecureSocket->AvailableCipherSuites( ciphers ) );
+
+ // Each cipher should consist from two bytes
+ TInt len( ciphers.Length() );
+ const TInt KCipherSuiteInBytes = 2;
+ __ASSERT_ALWAYS( !( len % KCipherSuiteInBytes ),
+ User::Leave( KErrGeneral ) );
+
+ // At least this cipher suite should be supported
+ // (value defined in RFC 3268)
+ const TUint TLS_RSA_WITH_AES_128_CBC_SHA_Value = 0x2F;
+
+ TBool found( EFalse );
+ for ( TInt i = 0; i < len && !found; i += KCipherSuiteInBytes )
+ {
+ TUint cipherVal = BigEndian::Get16( ciphers.Mid( i ).Ptr() );
+ found = ( cipherVal == TLS_RSA_WITH_AES_128_CBC_SHA_Value );
+ }
+
+ __ASSERT_ALWAYS( found, User::Leave( KErrNotSupported ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::SetDomainName
+// -----------------------------------------------------------------------------
+void CTransportTls::SetDomainNameL(const TDesC8& aDomainName)
+ {
+ iDomainName = aDomainName.AllocL();
+ __SIP_DES16_LOG("Domain name for TLS Certificate matching in the SIP message is: ", *iDomainName);
+ }
+
+// -----------------------------------------------------------------------------
+// CTransportTls::HasSecureSocket
+// -----------------------------------------------------------------------------
+TBool CTransportTls::HasSecureSocket()
+ {
+ if(iSecureSocket)
+ return ETrue;
+ else
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------------
+// CTransportTls::MatchCertificate
+// Below function implements the logic as per draft draft-ietf-sip-domain-certs-04
+// Section 7.1 Finding SIP Identities in a Certificate, 7.2 Comparing SIP Identities
+// and 7.3 Client Behavior
+// -----------------------------------------------------------------------------------
+TBool CTransportTls::MatchCertificateL()
+ {
+ //If the domain name is NULL, return ETrue. Domain name matching in the certificate
+ //is carried out only when Domain name is of type 'Text'
+ if(NULL == iDomainName)
+ return ETrue;
+
+ //Get the server Certificate
+ const CX509Certificate* cert = iSecureSocket->ServerCert();
+
+ //Implementations MUST check for restrictions on certificate usage declared by any
+ //extendedKeyUsage extentions in the certificate. The SIP Extended Key
+ //Usage (EKU) document [draft-ietf-sip-eku-05:Section 4] defines an extendedKeyUsage
+ //for SIP.
+ TBool result = ETrue;
+ const CX509CertExtension* ext = cert->Extension(KExtendedKeyUsage);
+ if (ext)
+ {
+ result = EFalse;
+ CX509ExtendedKeyUsageExt* extendedKeyUsage = CX509ExtendedKeyUsageExt::NewLC(ext->Data());
+ const CArrayPtrFlat<HBufC>& usages = extendedKeyUsage->KeyUsages();
+
+ //Check for extended key usages
+ for (TInt k = 0; k < usages.Count(); k++)
+ {
+ if (usages[k]->Compare(KServerAuthOID) == 0 || usages[k]->Compare(KClientAuthOID) == 0 ||
+ usages[k]->Compare(KSipDomainOID)== 0 || usages[k]->Compare(KAnyExtendedKeyUsage) == 0)
+ {
+ result = ETrue;
+ break;
+ }
+ else
+ result = EFalse;
+ }
+ CleanupStack::PopAndDestroy();
+ }
+
+ //If the result is EFalse, it means certificate is not acceptable for use as a
+ //SIP certificate, otherwise Certificate can be used as SIP Certificate so proceed
+ //with next steps for domain matching
+ if (!result)
+ return EFalse;
+
+ //Examine each value in the SubjectAltName field. The SubjectAltName field
+ //can be absent or can contain one or more values. Each value in the SubjectAltName
+ //has a type, the only types acceptable for SIP domain are URI and DNS.
+ //The values MUST be compared as DNS names, which means that the
+ //comparison is case insensitive as specified by RFC 4343
+ const CX509CertExtension* iExt = cert->Extension(KSubjectAltName);
+ TInt domainlength = iDomainName->Length();
+ TBool isMatch = EFalse;
+ if( iExt )
+ {
+ CX509AltNameExt* iSubjectAltName = CX509AltNameExt::NewLC(iExt->Data());
+ const CArrayPtrFlat<CX509GeneralName>& gNs = iSubjectAltName->AltName();
+ const TInt count = gNs.Count();
+
+ //Go in the loop and get the general name to find the type.
+ //Only value allowed is URI type and DNS type. DNS type only allowed
+ //if any URI type does not have scheme sip.
+ TASN1DecIA5String encStr;
+ TInt pos = 0;
+ HBufC* suri = NULL;
+ HBufC8* buf = NULL;
+ CURIContainer *uricontainer = NULL;
+ for( TInt i = 0; i < count; i++ )
+ {
+ //Reset the position
+ pos = 0;
+ const CX509GeneralName* gN = gNs.At(i);
+ if(EX509URI == gN->Tag())
+ {
+ // If the scheme of the URI value is "sip", and the URI value
+ // that contains a userpart (there is an '@'), the value MUST NOT
+ // be accpeted as a SIP domain identity (a value with a userpart
+ // identifies an individual user, not a domain).
+ // If the scheme of the URI value is "sip", and there is no
+ // userinfo component in the URI (there is no '@'), then the
+ // hostpart MUST be accepted as a SIP domain identity.
+ suri = encStr.DecodeDERL(gN->Data(), pos);
+ CleanupStack::PushL(suri);
+ buf = HBufC8::NewL(suri->Length());
+ CleanupStack::PushL(buf);
+ buf->Des().Copy(*suri);
+ uricontainer = CURIContainer::DecodeL(*buf);
+ CleanupStack::PopAndDestroy(buf);
+ CleanupStack::PopAndDestroy(suri);
+
+ //Is the URI scheme sip ?
+ if(uricontainer->IsSIPURI() && !uricontainer->SIPURI()->IsSIPSURI())
+ {
+ const TDesC8& user = uricontainer->SIPURI()->User();
+ TInt length = user.Length();
+ if(0 == length)
+ {
+ __SIP_DES8_LOG("Data is: ", uricontainer->SIPURI()->HostPort().Host())
+ if((uricontainer->SIPURI()->HostPort().Host().CompareF(*iDomainName) == 0) ||
+ (uricontainer->SIPURI()->HostPort().Host().Right(domainlength).CompareF(*iDomainName) == 0))
+ {
+ isMatch = ETrue;
+ break;
+ }
+ }
+ }
+ delete uricontainer;
+ uricontainer = NULL;
+ }//end if
+ } //end for
+
+ //Clear the memory created in case isMatch has turned True
+ if(uricontainer)
+ {
+ delete uricontainer;
+ uricontainer = NULL;
+ CleanupStack::PopAndDestroy(iSubjectAltName);
+ iSubjectAltName = NULL;
+ return isMatch;
+ }
+
+ //There are no parameters with type value URI and scheme SIP
+ //Check for domain names in type DNS
+ for(TInt i = 0; i < count; i++)
+ {
+ // Match with domain name system identifier as a SIP domain identity
+ // if and only if no other identity is found that matches the "sip"
+ // URI type described
+ const CX509GeneralName* gN = gNs.At(i);
+ pos = 0;
+ if(EX509DNSName == gN->Tag())
+ {
+ suri = encStr.DecodeDERL(gN->Data(), pos);
+ CleanupStack::PushL(suri);
+ buf = HBufC8::NewL(suri->Length());
+ buf->Des().Copy(*suri);
+ CleanupStack::PopAndDestroy(suri);
+ __SIP_DES8_LOG("Domain Name in type DNS is: ", *buf)
+ if((buf->CompareF(*iDomainName) == 0) ||
+ (buf->Right(domainlength).CompareF(*iDomainName) == 0))
+ {
+ isMatch = ETrue;
+ break;
+ }
+ delete buf;
+ buf = NULL;
+ }
+ }//end for
+
+ //Clear the memory created in case isMatch has turned True
+ if(buf)
+ {
+ delete buf;
+ buf = NULL;
+ CleanupStack::PopAndDestroy(iSubjectAltName);
+ iSubjectAltName = NULL;
+ return isMatch;
+ }
+
+ //Destroy the local copy of SubjectAltName in case isMatch is still False
+ CleanupStack::PopAndDestroy(iSubjectAltName);
+ iSubjectAltName = NULL;
+ } //end if (iExt)
+
+ //If the SubjectAltName is not found then matching happens against
+ //CN name in the subject field
+ const CX500DistinguishedName& subjectName = cert->SubjectName();
+ const TInt count = subjectName.Count();
+ for( TInt i=0; i<count; ++i )
+ {
+ const CX520AttributeTypeAndValue& attribute = subjectName.Element(i);
+
+ HBufC* valuePtr = NULL;
+ const TDesC& type = attribute.Type();
+ if( type.Compare(KX520CommonName) == 0 )
+ {
+ valuePtr = attribute.ValueL();
+ HBufC8* buf = HBufC8::NewL(valuePtr->Length());
+ buf->Des().Copy(*valuePtr);
+ if((buf->CompareF(*iDomainName) == 0) ||
+ (buf->Right(domainlength).CompareF(*iDomainName) == 0))
+ {
+ isMatch = ETrue;
+ }
+ delete valuePtr;
+ delete buf;
+ break;
+ }
+ else
+ isMatch = EFalse;
+ }//end for
+ return isMatch;
+ }//end function
+
+// End of File
+