realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransportTls.cpp
changeset 0 307788aac0a8
--- /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
+