realtimenetprots/sipfw/SIP/SIPSec/DigestPlugin/src/CSIPSecCredentials.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Name          : CSIPSecCredentials.cpp
       
    15 // Part of       : SIPDigestPlugin
       
    16 // Version       : SIP/6.0
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include "CSIPSecCredentials.h"
       
    22 #include "CSIPSecChallenge.h"
       
    23 #include "MSIPSecAlgorithm.h"
       
    24 #include "sipsecdigestcontext.h"
       
    25 #include "CSIPSecUserRecord.h"
       
    26 #include "MSIPSecUser.h"
       
    27 #include "SipLogs.h"
       
    28 #include "siprequest.h"
       
    29 #include "uricontainer.h"
       
    30 #include "sipauthorizationheader.h"
       
    31 #include "sipproxyauthorizationheader.h"
       
    32 #include "sipauthenticateheaderbase.h"
       
    33 #include "sipauthenticationinfoheader.h"
       
    34 #include "sipstrings.h"
       
    35 #include "sipstrconsts.h"
       
    36 
       
    37 
       
    38 // ============================ MEMBER FUNCTIONS ===============================
       
    39 
       
    40 
       
    41 // -----------------------------------------------------------------------------
       
    42 // CSIPSecCredentials::NewL
       
    43 // -----------------------------------------------------------------------------
       
    44 //
       
    45 CSIPSecCredentials*
       
    46 CSIPSecCredentials::NewL( CSIPSecChallenge* aChallenge, 
       
    47                           CSIPSecDigest& aMechanism,
       
    48 			              TSIPSecPluginCtxResponse& aContext )
       
    49     {
       
    50 	__ASSERT_ALWAYS( aChallenge, User::Leave( KErrArgument ) );
       
    51 
       
    52 	const MSIPSecUser* sipSecUser = aChallenge->Owner();
       
    53 	if ( !sipSecUser )
       
    54         {
       
    55         sipSecUser = &aContext.SIPSecUser();
       
    56         }
       
    57 
       
    58     CSIPSecCredentials* self = new ( ELeave ) CSIPSecCredentials( aMechanism,											 					  
       
    59 																  *sipSecUser );
       
    60 	CleanupStack::PushL( self );
       
    61 	self->ConstructL( aChallenge, aContext );
       
    62 	CleanupStack::Pop( self );
       
    63 	return self;
       
    64 	}
       
    65 
       
    66 // -----------------------------------------------------------------------------
       
    67 // CSIPSecCredentials::CSIPSecCredentials
       
    68 // -----------------------------------------------------------------------------
       
    69 //
       
    70 CSIPSecCredentials::CSIPSecCredentials( CSIPSecDigest& aMechanism,
       
    71 										const MSIPSecUser& aUser ) :
       
    72     CSIPSecDigestCacheEntry( aUser ),
       
    73     iMechanism( aMechanism )
       
    74     {
       
    75     }
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 // CSIPSecChallenge::~CSIPSecCredentials
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 CSIPSecCredentials::~CSIPSecCredentials()
       
    82     {
       
    83     delete iChallenge;
       
    84     delete iAuthorizationHeader;
       
    85     }
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 // CSIPSecCredentials::ConstructL
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 void CSIPSecCredentials::ConstructL( CSIPSecChallenge* aChallenge,
       
    92 									 TSIPSecPluginCtxResponse& aContext )
       
    93     {
       
    94     __ASSERT_ALWAYS( aChallenge, User::Leave( KErrArgument ) );
       
    95 
       
    96     CSIPSecDigestCacheEntry::ConstructL( ChallengeType( *aChallenge,
       
    97     													&aContext ),
       
    98 										 aContext.RemoteTarget() );
       
    99     CreateContentL( *aChallenge );
       
   100 	TSIPSecDigestCtxSetup ctx( *this, aContext.TransactionId(), &aContext );
       
   101     aChallenge->PopulateCredentialsL( ctx );
       
   102 
       
   103 	// Take ownership of aChallenge when leave can't occur any more
       
   104 	iChallenge = aChallenge;
       
   105     }
       
   106 
       
   107 // -----------------------------------------------------------------------------
       
   108 // CSIPSecCredentials::UpdateL
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 void CSIPSecCredentials::UpdateL( CSIPSecUserRecord& aUserCredentials )
       
   112     {
       
   113     // If user credentials update is for this entry
       
   114     if ( HoldsUserData( aUserCredentials ) && !UserData().IsUpdating() )
       
   115         {
       
   116         TSIPSecDigestCtxSetup ctx( *this, aUserCredentials.TransactionId() );
       
   117 		TBool askCredentials( EFalse );
       
   118 
       
   119         // As credentials were obtained, DigestUpdateL must not indicate "wait".        
       
   120         __ASSERT_ALWAYS( !DigestUpdateL( ctx, askCredentials ),
       
   121         				 User::Leave( KErrGeneral ) );
       
   122 		__ASSERT_ALWAYS( !askCredentials, User::Leave( KErrGeneral ) );
       
   123         }
       
   124     }
       
   125 
       
   126 // -----------------------------------------------------------------------------
       
   127 // CSIPSecCredentials::UpdateL
       
   128 // -----------------------------------------------------------------------------
       
   129 //
       
   130 void CSIPSecCredentials::UpdateL( TSIPSecPluginCtxRequest& aContext )
       
   131     {
       
   132 	__SIP_LOG( "SIPSecCred:UpdateL(ctx)" )
       
   133 
       
   134 	if ( UserData().IsValid() )
       
   135 		{
       
   136 		__SIP_LOG( "user data is valid" )
       
   137 
       
   138 		TSIPSecDigestCtxProcess ctx( *this, &aContext );
       
   139 	    UpdateContentL( ctx );
       
   140 
       
   141 	    iChallenge->Algorithm().ProcessRequestL( ctx );
       
   142 
       
   143 	    // Add a (Proxy-)Authorization header
       
   144 		aContext.SIPRequest().AddHeaderL( Content() );
       
   145 		}
       
   146 
       
   147 	__SIP_LOG( "SIPSecCred:UpdateL(ctx) end" )
       
   148     }
       
   149 
       
   150 // -----------------------------------------------------------------------------
       
   151 // CSIPSecCredentials::HandleL
       
   152 // Called for each matching cache entry. They store the new nonce.
       
   153 // -----------------------------------------------------------------------------
       
   154 //
       
   155 void CSIPSecCredentials::HandleL( TSIPSecPluginCtxInfo& aAuthenticationInfo )
       
   156     {
       
   157     RStringF cnonce = SIPStrings::StringF( SipStrConsts::ECNonce );
       
   158     RStringF nc 	= SIPStrings::StringF( SipStrConsts::ENonceCount );
       
   159     RStringF qop 	= SIPStrings::StringF( SipStrConsts::EQop );
       
   160     CSIPAuthenticationInfoHeader& authInfo =
       
   161     	aAuthenticationInfo.AuthenticationInfoHeader();
       
   162 
       
   163     if ( Content().ParamValue( qop ) 	   == authInfo.Value( qop ) &&
       
   164     	 Content().DesParamValue( cnonce ) == authInfo.DesValue( cnonce ) &&
       
   165     	 Content().ParamValue( nc )        == authInfo.Value( nc ) )
       
   166         {
       
   167 		const TDesC8& responseAuth = authInfo.DesValue( SIPStrings::StringF(
       
   168 			SipStrConsts::EResponseAuth ) );
       
   169         if ( responseAuth.Length() > 0 )
       
   170             {
       
   171             TBuf8< KSIPSecDigestHashHexSize > response;
       
   172             TSIPSecDigestAuthInfoContext ctx( *this,
       
   173             								  response,
       
   174             								  &aAuthenticationInfo );
       
   175             // Process the response auth
       
   176             iChallenge->Algorithm().ProcessRequestL( ctx );
       
   177 
       
   178             if ( responseAuth.Compare( response ) != 0 )
       
   179                 {
       
   180                 User::Leave( KErrPermissionDenied );
       
   181                 }
       
   182             }
       
   183 
       
   184         const TDesC8& nextNonce = authInfo.DesValue(
       
   185         	SIPStrings::StringF( SipStrConsts::ENextNonce ) );
       
   186         if ( nextNonce.Length() > 0 )
       
   187             {
       
   188 		    RStringF nonce = SIPStrings::StringF( SipStrConsts::ENonce );			              	    
       
   189             Content().SetDesParamL( nonce, nextNonce );
       
   190             iChallenge->Content().SetDesParamL( nonce, nextNonce );
       
   191             SetNonceCountL( 0 );
       
   192             }
       
   193         }
       
   194     }
       
   195 
       
   196 // -----------------------------------------------------------------------------
       
   197 // CSIPSecCredentials::HandleL
       
   198 // Process Security-Verify header
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 void CSIPSecCredentials::HandleL( TSIPSecPluginCtxVerify& aSecurityVerifyCtx )
       
   202     {
       
   203     HBufC8* requestURI =
       
   204     	aSecurityVerifyCtx.SIPRequest().RequestURI()->ToTextL();
       
   205     CleanupStack::PushL( requestURI );
       
   206 
       
   207 	TSIPSecDigestVerifyContext ctx( *this, *requestURI, &aSecurityVerifyCtx );
       
   208     iChallenge->Algorithm().ProcessRequestL( ctx );
       
   209 
       
   210     CleanupStack::PopAndDestroy( requestURI );
       
   211     }
       
   212 
       
   213 // -----------------------------------------------------------------------------
       
   214 // CSIPSecCredentials::DigestUpdateL
       
   215 // Generate CNonce if it doesn't exist.
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 TBool CSIPSecCredentials::DigestUpdateL( TSIPSecDigestCtxSetup& aContext,
       
   219 										 TBool& aAskCredentials )
       
   220     {
       
   221     UpdateContentL( aContext );
       
   222 
       
   223 	if ( iChallenge->HasQop() &&
       
   224     	 !Content().HasParam( SIPStrings::StringF( SipStrConsts::ECNonce ) ) )
       
   225         {
       
   226         iChallenge->Algorithm().GenerateCNonceL( aContext );
       
   227         }
       
   228     return iChallenge->Algorithm().ProcessResponseL( aContext,
       
   229     												 aAskCredentials );
       
   230     }
       
   231 
       
   232 // -----------------------------------------------------------------------------
       
   233 // CSIPSecCredentials::ChallengeType
       
   234 // -----------------------------------------------------------------------------
       
   235 //
       
   236 CSIPSecDigest::TChallengeType
       
   237 CSIPSecCredentials::ChallengeType( const CSIPSecChallenge& aChallenge,
       
   238     							   const TSIPSecPluginContext* aContext ) const
       
   239     {
       
   240     CSIPSecDigest::TChallengeType type = aChallenge.Type();
       
   241     TBool ignoreOutboundProxy( aContext &&
       
   242                                aContext->OutboundProxy().Length() == 0 );
       
   243 
       
   244     if ( type == CSIPSecDigest::EProxy &&
       
   245          !ignoreOutboundProxy &&
       
   246     	 iUserCredentials &&
       
   247     	 iUserCredentials->OutboundProxy().Length() > 0 )
       
   248         {
       
   249         type = CSIPSecDigest::EOutboundProxy;
       
   250         }
       
   251 
       
   252     return type;
       
   253     }
       
   254 
       
   255 // -----------------------------------------------------------------------------
       
   256 // CSIPSecCredentials::Type
       
   257 // -----------------------------------------------------------------------------
       
   258 //
       
   259 CSIPSecDigest::TChallengeType CSIPSecCredentials::Type() const
       
   260     {    
       
   261     return ChallengeType( *iChallenge );
       
   262     }
       
   263     
       
   264 // -----------------------------------------------------------------------------
       
   265 // CSIPSecCredentials::Type
       
   266 // -----------------------------------------------------------------------------
       
   267 //
       
   268 CSIPSecDigest::TChallengeType CSIPSecCredentials::Type(
       
   269     const TSIPSecPluginContext& aContext ) const
       
   270     {    
       
   271     return ChallengeType( *iChallenge, &aContext );
       
   272     }
       
   273 
       
   274 // -----------------------------------------------------------------------------
       
   275 // CSIPSecCredentials::DoesMatch
       
   276 // aChallenge::Owner() is always NULL at this phase.
       
   277 // -----------------------------------------------------------------------------
       
   278 //
       
   279 TBool CSIPSecCredentials::DoesMatch( const CSIPSecChallenge& aChallenge,
       
   280 									 const MSIPSecUser& aUser,
       
   281 									 TRegistrationId aRegistrationId ) const
       
   282 	{
       
   283 	return aChallenge.Type() == iChallenge->Type() &&
       
   284 		   ( aChallenge.Realm().Compare( iChallenge->Realm() ) == 0 ) &&
       
   285 		   iUserCredentials &&
       
   286 		   iUserCredentials->CompareUser( aUser, aRegistrationId );
       
   287 	}
       
   288 
       
   289 // -----------------------------------------------------------------------------
       
   290 // CSIPSecCredentials::ChallengeReceived
       
   291 // If "stale=true", retry with new nonce. Username and password are valid.
       
   292 // Otherwise ask username and password. PopulateCredentialsL later copies nonce
       
   293 // to CSIPSecCredentials::iAuthorizationHeader.
       
   294 // -----------------------------------------------------------------------------
       
   295 //
       
   296 TBool CSIPSecCredentials::ChallengeReceived( CSIPSecChallenge& aNewChallenge )
       
   297     {
       
   298 	RStringF stale = SIPStrings::StringF( SipStrConsts::EStale );	
       
   299 
       
   300     TBool hasStale = aNewChallenge.Content().HasParam( stale );    
       
   301 	_LIT8( KSIPSecStaleTrue, "true" );
       
   302     TBool isStale = hasStale &&
       
   303 		aNewChallenge.Content().ParamValue( stale ).DesC().CompareF(
       
   304 			KSIPSecStaleTrue ) == 0;
       
   305     TBool hasAuts =
       
   306     	Content().HasParam( SIPStrings::StringF( SipStrConsts::EAuts ) );
       
   307 	TBool isAKA = aNewChallenge.Algorithm().AlgorithmName() ==
       
   308 		 				SIPStrings::StringF( SipStrConsts::EAKAv1MD5 );
       
   309 
       
   310     if ( !isStale || hasAuts || isAKA )
       
   311         {
       
   312         // Credentials are wrong
       
   313         UserData().Invalidate( CSIPSecUserRecord::ENoState );
       
   314 
       
   315 		RStringF nonce = SIPStrings::StringF( SipStrConsts::ENonce );
       
   316         if ( aNewChallenge.Content().DesParamValue( nonce ) !=
       
   317         	 Content().DesParamValue( nonce ) )
       
   318         	{
       
   319         	// Server gave a new nonce, clear old username and password so even
       
   320         	// if application gives same username and password, the request is
       
   321         	// sent. As nonce is different, the result will be different.
       
   322         	UserData().ClearUsernameAndPassword();
       
   323         	}
       
   324         }
       
   325 
       
   326     aNewChallenge.SetOwner( &iUser );
       
   327 
       
   328 	// Remove unless SIPSec user asked the response and waits credentials
       
   329 	TBool remove = iUser.PassOnlyRealmsToUser() || !UserData().IsUpdating();
       
   330 
       
   331 	__SIP_INT_LOG1( "SIPSecCred:ChallRecv remove", remove )
       
   332 	return remove;
       
   333     }
       
   334 
       
   335 // -----------------------------------------------------------------------------
       
   336 // CSIPSecCredentials::Mechanism
       
   337 // -----------------------------------------------------------------------------
       
   338 //
       
   339 CSIPSecDigest& CSIPSecCredentials::Mechanism() const
       
   340     {
       
   341     return iMechanism;
       
   342     }
       
   343 
       
   344 // -----------------------------------------------------------------------------
       
   345 // CSIPSecCredentials::Content
       
   346 // -----------------------------------------------------------------------------
       
   347 //
       
   348 CSIPAuthorizationHeaderBase& CSIPSecCredentials::Content()
       
   349     {
       
   350     return *iAuthorizationHeader;
       
   351     }
       
   352 
       
   353 // -----------------------------------------------------------------------------
       
   354 // CSIPSecCredentials::Challenge
       
   355 // -----------------------------------------------------------------------------
       
   356 //
       
   357 CSIPSecChallenge& CSIPSecCredentials::Challenge()
       
   358     {
       
   359     return *iChallenge;
       
   360     }
       
   361     
       
   362 // -----------------------------------------------------------------------------
       
   363 // CSIPSecCredentials::CreateContentL
       
   364 // Delete old AuthorizationHeader when can't leave, so it retains its old value
       
   365 // in case of leave. Otherwise crashes e.g. in CSIPSecCredentials::Content that
       
   366 // expects iAuthorizationHeader to exist.
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 void CSIPSecCredentials::CreateContentL( CSIPSecChallenge& aChallenge )
       
   370     {
       
   371 	TBool hasType = aChallenge.Type() == CSIPSecDigest::EEndPoint || 
       
   372                     aChallenge.Type() == CSIPSecDigest::EProxy;
       
   373     __ASSERT_ALWAYS( hasType, User::Leave( KErrArgument ) );
       
   374 
       
   375     // Create a new authorization header
       
   376     CSIPAuthorizationHeaderBase* authorization( NULL );
       
   377 	RStringF digest = SIPStrings::Pool().OpenFStringL( KSIPSecDigestScheme );
       
   378 	CleanupClosePushL( digest );
       
   379 
       
   380     if ( aChallenge.Type() == CSIPSecDigest::EEndPoint )
       
   381         {
       
   382         authorization = CSIPAuthorizationHeader::NewL( digest );
       
   383         }
       
   384     else
       
   385         {
       
   386         authorization = CSIPProxyAuthorizationHeader::NewL( digest );
       
   387         }
       
   388 
       
   389     CleanupStack::PopAndDestroy(); // digest
       
   390     CleanupStack::PushL( authorization );
       
   391 
       
   392 	if ( aChallenge.HasQop() )
       
   393 		{
       
   394 		RStringF qop =
       
   395 			SIPStrings::Pool().OpenFStringL( aChallenge.QopDescriptor() );
       
   396 		CleanupClosePushL( qop );
       
   397 		authorization->SetParamL( SIPStrings::StringF( SipStrConsts::EQop ),
       
   398 													   qop );
       
   399         CleanupStack::PopAndDestroy(); // qop
       
   400 		}
       
   401 
       
   402 	CleanupStack::Pop( authorization );
       
   403 	delete iAuthorizationHeader;
       
   404     iAuthorizationHeader = authorization;
       
   405     }
       
   406 
       
   407 // -----------------------------------------------------------------------------
       
   408 // CSIPSecCredentials::UpdateContentL
       
   409 // -----------------------------------------------------------------------------
       
   410 //
       
   411 void CSIPSecCredentials::UpdateContentL( TSIPSecDigestCtxSetup& aContext )
       
   412     {
       
   413     aContext.SetDesParamValueL( SipStrConsts::EUserName,
       
   414     						 	aContext.UserData().UserName() );
       
   415     }
       
   416 
       
   417 // -----------------------------------------------------------------------------
       
   418 // CSIPSecCredentials::SetNonceCountL
       
   419 // -----------------------------------------------------------------------------
       
   420 //
       
   421 void CSIPSecCredentials::SetNonceCountL( TUint aNonceCount )
       
   422     {
       
   423     iNonceCount = aNonceCount;
       
   424 
       
   425     const TInt KNonceCountLength = 8;
       
   426 	TBuf8< KNonceCountLength > ncDescr;
       
   427 	ncDescr.NumFixedWidth( iNonceCount, EHex, KNonceCountLength );
       
   428 
       
   429     TSIPSecDigestContext::SetParamValueL( Content(),
       
   430     									  SipStrConsts::ENonceCount,
       
   431     									  ncDescr );
       
   432     }
       
   433 
       
   434 // -----------------------------------------------------------------------------
       
   435 // CSIPSecCredentials::UpdateContentL
       
   436 // Increment nonce count and set Request-URI.
       
   437 // -----------------------------------------------------------------------------
       
   438 //
       
   439 void CSIPSecCredentials::UpdateContentL( TSIPSecDigestCtxProcess& aContext )
       
   440     {
       
   441     if ( iChallenge->HasQop() )
       
   442         {
       
   443         SetNonceCountL( iNonceCount + 1 );
       
   444         }
       
   445 
       
   446     TSIPSecPluginCtxRequest& parent =
       
   447     	static_cast<TSIPSecPluginCtxRequest&>( aContext.Parent() );
       
   448     HBufC8* requestURI = parent.SIPRequest().RequestURI()->ToTextL();
       
   449     CleanupStack::PushL( requestURI );
       
   450 
       
   451     aContext.SetParamValueL( SipStrConsts::EUri, *requestURI );
       
   452     CleanupStack::PopAndDestroy( requestURI );
       
   453     }