--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gba/gbaserver/src/dataretriever.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,1358 @@
+/*
+* Copyright (c) 2007 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: Implementation of bootstrap and data retriever
+*
+*/
+
+
+#include <e32math.h>
+#include <hash.h>
+#include <commdb.h>
+#include <es_enum.h>
+#include <centralrepository.h>
+#include <cmconnectionmethodext.h>
+#include <cmconnectionmethoddef.h>
+#include <cmpluginpacketdatadef.h>
+#include <cmdestinationext.h>
+#include <http/thttpevent.h>
+#include "dataretriever.h"
+#include "GbaCommon.h"
+#include "GBALogger.h"
+#include "bootstrap.h"
+
+_LIT8(KUserAgent,"S60 GBA 1.0");
+_LIT8(KAccept,"*/*");
+_LIT8(KNCVal_2, ":00000001:");
+_LIT8(Kfopaque,"");
+_LIT8(Kfalgo,"AKAv1-MD5");
+_LIT8(Kalgorithm,"algorithm");
+_LIT8(formatStr, "%02x");
+_LIT8(KAuthInt,"auth-int");
+_LIT8(KAuts,"auts");
+_LIT8(KHTTPAuthInfo,"Authentication-Info");
+_LIT8(KMD5HashofEmpty,"d41d8cd98f00b204e9800998ecf8427e");
+_LIT8(KClose, "Close");
+_LIT(KColon, ":");
+
+
+//Constants
+const TInt KNumber3 = 3;
+const TInt KNumber5 = 5;
+const TInt KNumber8 = 8;
+const TInt KNumber32 = 32;
+const TInt KNumber33 = 33;
+const TInt KNumber34 = 34;
+// Length of a digest hash when represented in hex
+const TInt KHashLength = 32;
+// Length of a digest hash before converting to hex.
+const TInt KRawHashLength = 16;
+const TInt KMaxRequestBuffer = 255;
+const TInt KAlgLength = 40;
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::NewL()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever* CDataRetriever::NewL( MBootstrapCallBack* aBootstrapCallBack )
+ {
+ CDataRetriever* self = NewLC( aBootstrapCallBack );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::NewLC()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever* CDataRetriever::NewLC( MBootstrapCallBack* aBootstrapCallBack )
+ {
+ CDataRetriever* self = new (ELeave) CDataRetriever( aBootstrapCallBack ) ;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::CDataRetriever()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever::CDataRetriever( MBootstrapCallBack* aBootstrapCallBack )
+ : iBootstrapCallBack( aBootstrapCallBack )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::ConstructL()
+ {
+ iHttpHandler = C3GPPBootstrapHttpHandler::NewL( this, iBootstrapCallBack );
+ iInternalState = EReadyForRequest;
+ iCmManagerExt.OpenL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::~CDataRetriever()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever::~CDataRetriever()
+ {
+ GBA_TRACE_DEBUG(("CDataRetriever::~CDataRetriever"));
+
+ delete iHttpHandler;
+ iHTTPTransaction.Close();
+ iHTTPSession.Close();
+ iConnection.Close();
+ iSockServ.Close();
+ iCmManagerExt.Close();
+
+ if ( iInternalState == EMakeRequestCalled )
+ {
+ GBA_TRACE_DEBUG(("CDataRetriever::~CDataRetriever EMakeRequestCalled"));
+ User::RequestComplete(iCallerRequestStatus, KErrCancel);
+ }
+
+ GBA_TRACE_DEBUG(("CDataRetriever::~CDataRetriever End"));
+ }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::EventRequestCompletedL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::EventRequestCompletedL(TInt aErrorCode)
+ {
+ GBA_TRACE_DEBUG(("CDataRetriever::EventRequestCompletedL enter"));
+
+ if ( iInternalState == EMakeRequestCalled )
+ {
+ GBA_TRACE_DEBUG(("CDataRetriever::EventRequestCompletedL EMakeRequestCalled"));
+
+ TRAPD( err, iBootstrapCallBack->CompleteBootStrappingL( aErrorCode ) );
+ if( err == KErrNone )
+ User::RequestComplete(iCallerRequestStatus,aErrorCode);
+ else
+ User::RequestComplete(iCallerRequestStatus, err);
+ // Get Ready for new request
+ iHttpHandler->Reset();
+ iHTTPTransaction.Close();
+ iHTTPSession.Close();
+ iConnection.Close();
+ iSockServ.Close();
+ iInternalState = EReadyForRequest;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::CancelRequest()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::CancelRequest()
+ {
+ GBA_TRACE_DEBUG(("CDataRetriever::CancelRequest"));
+ if ( iInternalState == EMakeRequestCalled )
+ {
+ iInternalState = EReadyForRequest;
+ iHttpHandler->Reset();
+ iHTTPTransaction.Close();
+ iHTTPSession.Close();
+ iConnection.Close();
+ iSockServ.Close();
+ User::RequestComplete( iCallerRequestStatus, KErrCancel );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::MakeRequestL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::MakeRequestL(
+ TRequestStatus* aRequestStatus,
+ const TDesC8& aIdentity,
+ const TDesC8& aRealm,
+ const TDesC8& aBsfUri,
+ const TDesC8& aReferrerNAFUri,
+ const TInt& aIAPID )
+ {
+ GBA_TRACE_BEGIN();
+
+ if ( iInternalState != EReadyForRequest )
+ {
+ User::LeaveIfError( KErrInUse );
+ }
+
+ iCallerRequestStatus = aRequestStatus;
+
+ SetupSessionL( aIAPID );
+
+ // Add headers appropriate to all methods
+ TUriParser8 URIParse;
+
+ User::LeaveIfError( URIParse.Parse( aBsfUri ) );
+
+ iHTTPTransaction = iHTTPSession.OpenTransactionL( URIParse, *iHttpHandler );
+ RHTTPHeaders hdr = iHTTPTransaction.Request().GetHeaderCollection();
+
+ GBA_TRACE_DEBUG(URIParse.Extract(EUriHost) );
+
+ SetHeaderL(hdr,HTTP::EHost, URIParse.Extract(EUriHost) );
+ SetHeaderL(hdr,HTTP::EUserAgent, KUserAgent);
+ SetHeaderL(hdr,HTTP::EAccept, KAccept);
+ SetHeaderL(hdr,HTTP::EReferer, aReferrerNAFUri);
+
+ SetHeaderL(hdr, HTTP::EConnection, KClose);
+
+ TBuf8<KMaxRequestBuffer> bufAuth;
+ bufAuth.Copy(_L8("Digest username=\""));
+ bufAuth.Append(aIdentity);
+ bufAuth.Append(_L8("\", realm=\""));
+
+ bufAuth.Append(aRealm);
+ bufAuth.Append(_L8("\", nonce=\"\", uri=\"/\", response=\"\""));
+
+ GBA_TRACE_DEBUG(bufAuth);
+ SetHeaderL(hdr,HTTP::EAuthorization,bufAuth);
+
+ iHTTPTransaction.SubmitL();
+ iInternalState = EMakeRequestCalled;
+ GBA_TRACE_END();
+ }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::SetHeaderL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
+ {
+ RStringF valStr = iHTTPSession.StringPool().OpenFStringL(aHdrValue);
+ THTTPHdrVal val(valStr);
+ aHeaders.SetFieldL(iHTTPSession.StringPool().StringF(aHdrField,RHTTPSession::GetTable()), val);
+ valStr.Close();
+ }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::SetupSessionL()
+// Establish a connection for bootstrapping
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::SetupSessionL( const TInt& aIAPID )
+ {
+ GBA_TRACE_DEBUG(("CDataRetriever::SetupSession"));
+ // check that sockserver is available
+
+ User::LeaveIfError(iSockServ.Connect() );
+ GBA_TRACE_DEBUG(("Socket server connected"));
+
+ // check that connection is possible
+ User::LeaveIfError(iConnection.Open(iSockServ) );
+ GBA_TRACE_DEBUG(("Connection opened"));
+
+ if ( !ValidateGivenIAPIDL( aIAPID ) )
+ {
+ GBA_TRACE_DEBUG(("No valid iapid from user"));
+ TConnSnapPref snapPref;
+ TUint32 snapid = GetInternetDestIDL();
+ GBA_TRACE_DEBUG_NUM(("the chosen snap id is %d"), snapid );
+ snapPref.SetSnap( snapid );
+ TInt err = iConnection.Start( snapPref );
+
+ if ( err != KErrNone )
+ {
+ GBA_TRACE_DEBUG_NUM(("internet nap error is %d"), err );
+ TCommDbConnPref connPref;
+ connPref.SetDialogPreference( ECommDbDialogPrefPrompt );
+ User::LeaveIfError( iConnection.Start( connPref ) );
+ }
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("User gives valid iapid go with it"));
+ //given iapid is valid, go with it
+ TCommDbConnPref connPref;
+ connPref.SetDirection( ECommDbConnectionDirectionOutgoing );
+
+ //No dialog present
+ connPref.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
+ connPref.SetIapId( aIAPID );
+
+ User::LeaveIfError( iConnection.Start( connPref ) );
+ }
+
+ GBA_TRACE_DEBUG(("Access point selection done!"));
+
+ GBA_TRACE_DEBUG(("CDataRetriever::SetupSession, connect choosen is done "));
+
+ iHTTPSession.OpenL();
+
+ //GBA Http filter gets loaded into to http session when session is opened
+ //Remove GBA http filter from http session iHTTPSession
+ //Reason: Ub interface should not have the User-Agent string "3gpp-gba"
+ RStringF filterName = iHTTPSession.StringPool().OpenFStringL( KHTTPFilterGBAName );
+ CleanupClosePushL<RStringF>( filterName );
+ iHTTPSession.FilterCollection().RemoveFilter( filterName );
+ CleanupStack::PopAndDestroy( &filterName );
+
+ GBA_TRACE_DEBUG(("Session opened"));
+
+ //Set selected access point.
+ RStringPool strPool = iHTTPSession.StringPool();
+ RHTTPConnectionInfo httpconnInfo = iHTTPSession.ConnectionInfo();
+
+ httpconnInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketServ,
+ RHTTPSession::GetTable() ), THTTPHdrVal (iSockServ.Handle()) );
+
+ TInt connPtr = REINTERPRET_CAST(TInt, &iConnection);
+
+ httpconnInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketConnection,
+ RHTTPSession::GetTable() ), THTTPHdrVal (connPtr) );
+
+ //if 2G interface and cert is untrusted, surpress the warning dialog
+ if ( iBootstrapCallBack->InterfaceIs2G() )
+ {
+ //surpress the warning dialog
+ httpconnInfo.SetPropertyL ( strPool.StringF(HTTP::ESecureDialog,
+ RHTTPSession::GetTable() ),strPool.StringF(HTTP::EDialogNoPrompt,
+ RHTTPSession::GetTable() ) );
+ }
+
+ GBA_TRACE_DEBUG(("SetupSession done"));
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::ValidateGivenIAPIDL()
+// ---------------------------------------------------------------------------
+//
+TBool CDataRetriever::ValidateGivenIAPIDL( const TInt& aIAPID )
+ {
+ using namespace CMManager;
+ GBA_TRACE_DEBUG((" start valid iapid given by user"));
+ //aIAPID == -1 selected default accesspoint
+ if ( aIAPID == -1 )
+ {
+ return EFalse;
+ }
+ else
+ {
+ TInt CleanupCounter = 0;
+
+ RArray<TUint32> destIdArray;
+ CleanupClosePushL( destIdArray );
+ CleanupCounter++;
+ iCmManagerExt.AllDestinationsL( destIdArray );
+
+ for ( TInt i = 0; i< destIdArray.Count(); i++ )
+ {
+ RCmDestinationExt dest = iCmManagerExt.DestinationL( destIdArray[i] );
+ CleanupClosePushL( dest );
+ CleanupCounter++;
+
+ for ( TInt j=0; j < dest.ConnectionMethodCount(); j++ )
+ {
+
+ TUint32 iapId = dest. ConnectionMethodL(j).GetIntAttributeL( ECmIapId );
+
+ if ( iapId == aIAPID )
+ {
+ GBA_TRACE_DEBUG((" IAPID matches !!"));
+ CleanupStack::PopAndDestroy( CleanupCounter );
+ return ETrue;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &dest ); //dest
+ CleanupCounter--; // dest
+ }
+ GBA_TRACE_DEBUG((" search is over no matching IAPID!!"));
+ CleanupStack::PopAndDestroy( CleanupCounter );
+ return EFalse;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::QueryResponseValueL()
+// ---------------------------------------------------------------------------
+//
+HBufC8* CDataRetriever::QueryResponseValueL()
+ {
+ return iHttpHandler->GetResponse();
+ }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::GetInternetDestIDL()
+// ---------------------------------------------------------------------------
+//
+TUint32 CDataRetriever::GetInternetDestIDL()
+ {
+ using namespace CMManager;
+ GBA_TRACE_DEBUG((" Get the Dest ID of Internet"));
+
+ TInt CleanupCounter = 0;
+
+ RArray<TUint32> destIdArray;
+ CleanupClosePushL( destIdArray );
+ CleanupCounter++;
+ iCmManagerExt.AllDestinationsL( destIdArray );
+
+ for ( TInt i = 0; i< destIdArray.Count(); i++ )
+ {
+ RCmDestinationExt dest = iCmManagerExt.DestinationL( destIdArray[i] );
+ CleanupClosePushL( dest );
+ CleanupCounter++;
+
+ if ( dest.MetadataL( ESnapMetadataInternet ) )
+ {
+ GBA_TRACE_DEBUG_NUM((" found the internet dest id = %d"), destIdArray[i] );
+
+ TUint32 desID = destIdArray[i];
+ CleanupStack::PopAndDestroy( CleanupCounter );
+ return desID;
+ }
+
+ CleanupStack::PopAndDestroy( &dest );
+ CleanupCounter--; // dest
+ }
+ GBA_TRACE_DEBUG(("not found the internet dest id") );
+ CleanupStack::PopAndDestroy( CleanupCounter );
+ return NULL;
+ }
+
+
+// C3GPPBootstrapHttpHandler
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::ConstructL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::ConstructL()
+ {
+ iResponse=HBufC8::NewL(KMaxBootstrapRespLen);
+ iMD5Calculator = CMD5::NewL();
+ iSucceeded=EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::C3GPPBootstrapHttpHandler()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler::C3GPPBootstrapHttpHandler( MHttpRequestEvents* aEventSink, M3GPPAuthenticationCallback* aDataRetrieverCallBack )
+ : iEventSink ( aEventSink ), iDataRetrieverCallBack ( aDataRetrieverCallBack )
+ {
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler()
+ {
+ GBA_TRACE_DEBUG(("C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler()"));
+ Reset();
+ delete iResponse;
+ delete iMD5Calculator;
+ GBA_TRACE_DEBUG(("C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler() end"));
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::Reset()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::Reset()
+ {
+ // close strings in string pool if they were opened
+ iUsername.Close();
+ iPassword.Close();
+ iNonce.Close();
+ iCnonce.Close();
+ iUri.Close();
+ iRealm.Close();
+ iMethod.Close();
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::NewLC()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler* C3GPPBootstrapHttpHandler::NewLC( MHttpRequestEvents* aEventSink,
+ M3GPPAuthenticationCallback* aDataRetrieverCallBack )
+ {
+ C3GPPBootstrapHttpHandler* me = new(ELeave)C3GPPBootstrapHttpHandler( aEventSink, aDataRetrieverCallBack );
+ CleanupStack::PushL(me);
+ me->ConstructL();
+ return me;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::NewL()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler* C3GPPBootstrapHttpHandler::NewL( MHttpRequestEvents* aEventSink ,
+ M3GPPAuthenticationCallback* aDataRetrieverCallBack )
+ {
+ C3GPPBootstrapHttpHandler* me = NewLC(aEventSink, aDataRetrieverCallBack );
+ CleanupStack::Pop(me);
+ return me;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::MHFRunL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
+ {
+ GBA_TRACE_DEBUG_NUM(("MHFRunL received event %d"), aEvent.iStatus );
+
+ switch (aEvent.iStatus)
+ {
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ // HTTP response headers have been received.
+ // We can determine now if there is going to be a response body to save.
+ GBA_TRACE_DEBUG(("THTTPEvent::EGotResponseHeaders"));
+ RHTTPResponse resp = aTransaction.Response();
+ TInt status = resp.StatusCode();
+
+ RStringF statusStr = resp.StatusText();
+
+ // 401 = we received a authorization challenge
+ if ( status == HTTPStatus::EUnauthorized )
+ {
+ // resubmit the transaction and hope for the best
+ TInt result = HandleAuthorizationChallengeL(aTransaction, aEvent);
+ if( result == KErrNone )
+ {
+ aTransaction.Cancel();
+ aTransaction.SubmitL();
+ }
+ else
+ {
+ aTransaction.Cancel();
+ iEventSink->EventRequestCompletedL( result );
+ }
+ //a new request with password is sent.
+ return;
+ }
+ TInt responseBodySize = 0;
+
+ // 200 received, succeeded with body
+ if ( resp.HasBody() && ( status == HTTPStatus::EOk ) )
+ {
+ MHTTPDataSupplier *respbody = resp.Body();
+ if ( respbody )
+ {
+ responseBodySize = respbody->OverallDataSize();
+ GBA_TRACE_DEBUG_NUM(("Response body size is %d"), responseBodySize );
+ iSucceeded = ETrue;
+ }
+ }
+ //Reallocate iResponse buffer size if the response size is greater than KMaxBootstrapRespLen
+ if( responseBodySize > KMaxBootstrapRespLen )
+ iResponse = iResponse->ReAllocL( responseBodySize );
+ // we take this opportunity to reset our own buffers
+ TPtr8 ptrResp(iResponse->Des());
+
+ ptrResp.Zero();
+ }
+ break;
+
+ case THTTPEvent::EGotResponseBodyData:
+ {
+ GBA_TRACE_DEBUG(("THTTPEvent::EGotResponseBodyData"));
+ // Get the body data supplier
+ iRespBody = aTransaction.Response().Body();
+
+ // Some (more) body data has been received (in the HTTP response)
+ // Append to the output file if we're saving responses
+ TPtr8 ptrResp(iResponse->Des());
+
+ TPtrC8 bodyData;
+ TBool lastChunk = EFalse;
+
+ while ( !lastChunk )
+ {
+ GBA_TRACE_DEBUG(("THTTPEvent::EGotResponseBodyData in loop"));
+ lastChunk = iRespBody->GetNextDataPart( bodyData );
+
+ //Issue with formatting string with a special character
+ //GBA_TRACE_DEBUG( bodyData );
+ if ( bodyData.Length() <= ( ptrResp.MaxLength() - ptrResp.Length() ) )
+ {
+ ptrResp.Append( bodyData );
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ GBA_TRACE_DEBUG_NUM(("Response body received size is %d"), iResponse->Length() );
+ // Done with that bit of body data
+ iRespBody->ReleaseData();
+ }
+ break;
+
+ case THTTPEvent::EResponseComplete:
+ {
+ GBA_TRACE_DEBUG(("THTTPEvent::EResponseComplete"));
+ // The transaction's response is complete
+ }
+ break;
+
+ case THTTPEvent::ESucceeded:
+ {
+ GBA_TRACE_DEBUG(("THTTPEvent::ESucceeded || KErrDisconnected"));
+ if ( iSucceeded )
+ {
+ // verify authrsp
+ User::LeaveIfError(CheckRspAuthL(aTransaction));
+
+ //Set it back
+ iSucceeded=EFalse;
+
+ GBA_TRACE_DEBUG(("THTTPEvent::ESucceeded || KErrDisconnected 1"));
+ iEventSink->EventRequestCompletedL(KErrNone);
+ }
+ else
+ {
+ iEventSink->EventRequestCompletedL( KErrDisconnected );
+ GBA_TRACE_DEBUG(("Connection was closed"));
+ }
+ }
+ break;
+
+ case THTTPEvent::EFailed:
+ {
+ GBA_TRACE_DEBUG(("THTTPEvent::EFailed"));
+ RHTTPResponse resp = aTransaction.Response();
+ TInt status = resp.StatusCode();
+ GBA_TRACE_DEBUG_NUM( ("http StatusCode : %d "), status );
+ iEventSink->EventRequestCompletedL( KErrUnknown );
+ }
+ break;
+
+ //The transaction is being cancelled. An outgoing event.
+ case THTTPEvent::ECancel:
+ {
+ GBA_TRACE_DEBUG(("THTTPEvent::ECancel"));
+ aTransaction.Cancel();
+ }
+ break;
+
+ // this warning can come when going through proxies
+ case THTTPEvent::ERedirectedTemporarily:
+ break;
+
+ default:
+ {
+ GBA_TRACE_DEBUG_NUM(("Failed with HTTP event event: %d "),aEvent.iStatus );
+ if( aEvent.iStatus < 0 )
+ {
+ // close off the transaction if it's an error
+ aTransaction.Cancel();
+ iEventSink->EventRequestCompletedL( aEvent.iStatus );
+ }
+ }
+ break;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::MHFRunError()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrapHttpHandler::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& aEvent)
+ {
+ GBA_TRACE_DEBUG_NUM(("MHFRunError called with error code = %d"), aError);
+ GBA_TRACE_DEBUG_NUM(("MHFRunError called with http event = %d"),aEvent.iStatus );
+ // tell caller that there was an error
+ TRAPD(err, iEventSink->EventRequestCompletedL(aError));
+ return err;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::HandleAuthorizationChallengeL()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrapHttpHandler::HandleAuthorizationChallengeL( RHTTPTransaction aTransaction, const THTTPEvent& /*aEvent*/ )
+ {
+ GBA_TRACE_BEGIN();
+ TInt pushCount = 0;
+ RStringPool stringPool = aTransaction.Session().StringPool();
+ RStringF wwwAuthHeader = stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
+ RHTTPHeaders headers(aTransaction.Response().GetHeaderCollection());
+
+ //find header which has digest algorithm and qop is auth-int
+ TInt headerPart = FindHeaderPartToUseL( aTransaction );
+
+ if ( headerPart == KErrNotFound )
+ {
+ return KErrArgument;
+ }
+
+ THTTPHdrVal authTypeParam;
+ TInt error = headers.GetField( wwwAuthHeader, headerPart, authTypeParam );
+
+ // If anything goes wrong, just stop. This will have the effect of
+ // returning the error response from the server to the client.
+ if ( error != KErrNone )
+ {
+ return error;
+ }
+
+ TBool haveUserPW = EFalse;
+ RString realm;
+ RString username;
+ RString password;
+ RString nonce;
+ RString algorithm;
+ RString resync;
+
+ // Get realm value from response header
+ THTTPHdrVal realmVal;
+ error = headers.GetParam( wwwAuthHeader,
+ stringPool.StringF( HTTP::ERealm, RHTTPSession::GetTable() ), realmVal, headerPart ) ;
+ if ( error != KErrNone )
+ {
+ return error;
+ }
+
+ realm = realmVal.Str();
+ GBA_TRACE_DEBUG(("Realm:"));
+ GBA_TRACE_DEBUG(realm.DesC());
+
+ THTTPHdrVal nonceVal;
+ //Get nonce value from response header
+ // contain the RAND and AUTH
+ error = headers.GetParam( stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()),
+ nonceVal,
+ headerPart);
+ if ( error != KErrNone )
+ {
+ return error;
+ }
+
+ nonce=nonceVal.Str();
+ GBA_TRACE_DEBUG(("Nonce:"));
+ GBA_TRACE_DEBUG(nonce.DesC());
+
+ //Fetch algorithm type
+ THTTPHdrVal algVal;
+ error = headers.GetParam( stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::EAlgorithm,RHTTPSession::GetTable()),
+ algVal,
+ headerPart);
+ if ( error != KErrNone )
+ {
+ return error;
+ }
+
+ algorithm=algVal.Str();
+ GBA_TRACE_DEBUG(("Algorithm:"));
+ GBA_TRACE_DEBUG(algorithm.DesC());
+
+ // If the SQN is out of range, Resync is required
+ TBool resyncrequired = EFalse;
+
+ //Get password from smart card
+ //The smart card will first authenticate the nonce value
+ RStringF authType = authTypeParam.StrF();
+
+ TRAP( error, haveUserPW = iDataRetrieverCallBack->GetCredentialsL( aTransaction.Request().URI(),
+ realm, nonce, algorithm, username, password, resync, resyncrequired ) ) ;
+
+ if ( error != KErrNone )
+ {
+ GBA_TRACE_DEBUG_NUM(("Get Gredentails failed with error %d"), error );
+ return error;
+ }
+
+ if ( haveUserPW || resyncrequired )
+ {
+ CleanupClosePushL(username);
+ pushCount++;
+ CleanupClosePushL(password);
+ pushCount++;
+ //Resync required
+ if( resyncrequired )
+ {
+ CleanupClosePushL(resync);
+ pushCount++;
+ }
+
+ GBA_TRACE_DEBUG(("HandleAuthorizationChallengeL: received following credentials"));
+ GBA_TRACE_DEBUG(("Realm:"));
+ GBA_TRACE_DEBUG(realm.DesC());
+ GBA_TRACE_DEBUG(("Username:"));
+ GBA_TRACE_DEBUG(username.DesC());
+ GBA_TRACE_DEBUG(("Password:"));
+ GBA_TRACE_DEBUG_BINARY(password.DesC());
+ GBA_TRACE_DEBUG(("Resync:"));
+ GBA_TRACE_DEBUG_BINARY(resync.DesC());
+
+ }
+ else //No password and no resync required
+ {
+ CleanupStack::PopAndDestroy( pushCount );
+ return KErrNotFound;
+ }
+
+ // Encode the Username/Password
+ switch ( authType.Index( RHTTPSession::GetTable() ) )
+ {
+ case HTTP::EDigest:
+ {
+ THTTPHdrVal requestUri;
+ RHTTPTransactionPropertySet propSet = aTransaction.PropertySet();
+ propSet.Property( stringPool.StringF(HTTP::EUri,RHTTPSession::GetTable()), requestUri );
+ //save rsp auth calcuation
+ //Save the string handle for rsp auth checking
+ //Close the previous handle, then set new one
+ iUsername.Close();
+ iUsername = username.Copy();
+ iPassword.Close();
+ iPassword = password.Copy();
+ iRealm.Close();
+ iRealm = realm.Copy();
+ iNonce.Close();
+ iNonce = nonce.Copy();
+ iUri.Close();
+ iUri = requestUri.Str().Copy();
+
+ TRAP ( error, EncodeDigestAuthL( username, password, aTransaction, headerPart, requestUri ) );
+ GBA_TRACE_DEBUG(("After Encode Digest AuthL"));
+ if ( error != KErrNone )
+ {
+ GBA_TRACE_DEBUG_NUM(("After Encode Digest AuthL error %d"), error );
+ CleanupStack::PopAndDestroy( pushCount );
+ return error;
+ }
+ }
+ break;
+ default:
+ {
+ CleanupStack::PopAndDestroy( pushCount );
+ return KErrArgument;
+ }
+
+ }
+ GBA_TRACE_DEBUG(("After Encode Digest AuthL 1"));
+ // Resubmit the request to the server
+ // add resyncronization header to the request if it is available
+ if ( resyncrequired )
+ {
+ THTTPHdrVal hdrVal;
+ RStringF unStr = stringPool.OpenFStringL(KAuts);
+ CleanupClosePushL(unStr);
+ pushCount++;
+ hdrVal.SetStr(resync);
+ RHTTPHeaders requestHeaders(aTransaction.Request().GetHeaderCollection());
+ requestHeaders.SetFieldL( stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ unStr,
+ hdrVal );
+ }
+ GBA_TRACE_DEBUG(("After Encode Digest AuthL 2"));
+ CleanupStack::PopAndDestroy( pushCount );
+ GBA_TRACE_DEBUG(("After Encode Digest AuthL 3"));
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::FindHeaderPartToUseL()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrapHttpHandler::FindHeaderPartToUseL( RHTTPTransaction aTransaction ) const
+ {
+ //We only pick up the first digest authentication fields:
+
+ RStringPool stringPool = aTransaction.Session().StringPool();
+
+ RStringF wwwAuthenticate = stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
+ RStringF realm = stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable());
+ RStringF nonce = stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable());
+ RStringF qop = stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable());
+
+ RHTTPHeaders headers = aTransaction.Response().GetHeaderCollection();
+ const TInt parts = headers.FieldPartsL( wwwAuthenticate );
+
+ for ( TInt i = 0; i < parts; i++ )
+ {
+ THTTPHdrVal fieldVal;// The name of the current field.
+ THTTPHdrVal hdrVal;//A scratch hdrVal
+ headers.GetField(wwwAuthenticate, i, fieldVal);
+ switch ( fieldVal.StrF().Index(RHTTPSession::GetTable() ) )
+ {
+ case HTTP::EDigest:
+ {
+ // It is Digest, let us check realm, nonce, qop then
+ if ( headers.GetParam(wwwAuthenticate, realm, hdrVal, i ) == KErrNone
+ &&
+ headers.GetParam(wwwAuthenticate, nonce, hdrVal, i ) == KErrNone)
+ {
+ // We've got a realm and a nonce. If there's a qop, we
+ // need to check it's acceptable.
+ if ( headers.GetParam(wwwAuthenticate, qop, hdrVal, i ) == KErrNone
+ &&
+ FindAuth( hdrVal.Str().DesC() ) )
+ {
+ // the header has qop and it is auth-int.
+ // we found it
+ return i;
+ }
+
+ }
+ }
+ break;
+
+ default:
+ //Ingore if it is not Digest
+ break;
+ }
+ }
+ return KErrNotFound;
+}
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::EncodeDigestAuthL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::EncodeDigestAuthL( const RString& aUsername,
+ const RString& aPW,
+ RHTTPTransaction& aTransaction,
+ TInt aHeaderPart,
+ const THTTPHdrVal& aRequestUri )
+ {
+ GBA_TRACE_BEGIN();
+ TInt pushCount = 0;
+
+ RStringPool stringPool = aTransaction.Session().StringPool();
+
+ GBA_TRACE_DEBUG(("Username:"));
+ GBA_TRACE_DEBUG(aUsername.DesC());
+
+ GBA_TRACE_DEBUG(("Passwd:"));
+ GBA_TRACE_DEBUG_BINARY(aPW.DesC());
+
+ TBuf8<KHashLength> hash;
+ TBuf8<KHashLength> cnonce;
+ //Nonce
+ THTTPHdrVal nonce;
+ RHTTPHeaders headers = aTransaction.Response().GetHeaderCollection();
+ TInt error = headers.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()), nonce,
+ aHeaderPart);
+
+ if ( error != KErrNone )
+ {
+ User::LeaveIfError( error );
+ }
+
+ //realm
+ THTTPHdrVal realm;
+ error = headers.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()), realm,
+ aHeaderPart);
+
+ if ( error != KErrNone )
+ {
+ User::LeaveIfError( error );
+ }
+
+ //qop
+ THTTPHdrVal qop;
+ error = headers.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable()), qop,
+ aHeaderPart);
+
+ if ( error != KErrNone )
+ {
+ User::LeaveIfError( error );
+ }
+
+ GenerateCNonce( cnonce );
+
+ GBA_TRACE_DEBUG(("cnonce:"));
+ GBA_TRACE_DEBUG_BINARY( cnonce );
+
+ RString cnonceString = stringPool.OpenStringL(cnonce);
+ CleanupClosePushL(cnonceString);
+ pushCount++;
+
+ // stored for auth calculations
+ iCnonce.Close();
+ iCnonce = cnonceString.Copy();
+
+ // stored for auth calculations
+ iMethod.Close();
+ iMethod = aTransaction.Request().Method().Copy();
+
+ DigestCalcL( KMD5HashofEmpty, hash );
+
+ GBA_TRACE_DEBUG(("hash:"));
+ GBA_TRACE_DEBUG_BINARY( hash );
+
+ // OK. hash now contains the digest response. Set up the header.
+ RHTTPHeaders requestHeaders(aTransaction.Request().GetHeaderCollection());
+ RHTTPHeaders responseHeaders(aTransaction.Response().GetHeaderCollection());
+
+ requestHeaders.RemoveField(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()));
+
+ //Copy useranme
+ THTTPHdrVal hdrVal;
+ hdrVal.SetStr(aUsername);
+
+ //Set the username to request header
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::EUsername,RHTTPSession::GetTable()),
+ hdrVal);
+
+ // copy Realm from response headers
+ responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()),
+ hdrVal,
+ aHeaderPart);
+
+ // Set the Realm to request header
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()),
+ hdrVal);
+
+ // copy nonce from response headers
+ responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()),
+ hdrVal,
+ aHeaderPart);
+
+ // set nonce to request header
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()),
+ hdrVal);
+
+ // Set uri to request header.
+ // the uri has already been fetched from http property setting
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::EUri,RHTTPSession::GetTable()),
+ aRequestUri);
+
+ // Qop with quotation marks
+ // copy qop from response headers
+ responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable()),
+ hdrVal,
+ aHeaderPart);
+
+ // Set Qop to request header
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable()),
+ hdrVal);
+
+ //Set Nc
+ hdrVal.SetStrF(stringPool.StringF(HTTP::E00000001,RHTTPSession::GetTable()));
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::ENc,RHTTPSession::GetTable()),
+ hdrVal);
+
+ // Set Cnonce to request header.
+ hdrVal.SetStr(cnonceString);
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::ECnonce,RHTTPSession::GetTable()),
+ hdrVal);
+
+ // Set response to request header.
+ RString hashStr = stringPool.OpenStringL(hash);
+ CleanupClosePushL(hashStr);
+ hdrVal.SetStr(hashStr);
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::EResponse,RHTTPSession::GetTable()),
+ hdrVal);
+ CleanupStack::PopAndDestroy(&hashStr);
+
+ // Get Opaque from response header.
+ error = responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ stringPool.StringF(HTTP::EOpaque,RHTTPSession::GetTable()),
+ hdrVal, aHeaderPart);
+
+ // Set Opaque
+ if ( error != KErrNotFound )
+ {
+ GBA_TRACE_DEBUG((" found the opaque value and copy it"));
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::EOpaque,RHTTPSession::GetTable()),
+ hdrVal);
+ }
+ else
+ {
+ GBA_TRACE_DEBUG((" No opaque value send empty one"));
+ RString opaque = stringPool.OpenStringL(Kfopaque);
+ GBA_TRACE_DEBUG((" No opaque value send empty one 1"));
+ CleanupClosePushL(opaque);
+ pushCount++;
+ hdrVal.SetStr(opaque);
+ GBA_TRACE_DEBUG((" No opaque value send empty one 2"));
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+ stringPool.StringF(HTTP::EOpaque,RHTTPSession::GetTable()),
+ hdrVal);
+ }
+ GBA_TRACE_DEBUG((" No opaque value send empty one 3"));
+ // Set algorithm.
+ TBuf8<KAlgLength> algbuf;
+ algbuf.Copy(_L8(", "));
+ algbuf.Append(Kalgorithm);
+ algbuf.Append(_L8("="));
+ algbuf.Append(Kfalgo);
+
+ GBA_TRACE_DEBUG((" No opaque value send empty one 5"));
+
+ RStringF valStr = stringPool.OpenFStringL(algbuf);
+ THTTPHdrVal val(valStr);
+ requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), val);
+ valStr.Close();
+
+ GBA_TRACE_DEBUG((" No opaque value send empty one 4"));
+
+ CleanupStack::PopAndDestroy(pushCount);
+ GBA_TRACE_DEBUG((" No opaque value send empty one 6"));
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::FindAuth()
+// -----------------------------------------------------------------------------
+//
+TBool C3GPPBootstrapHttpHandler::FindAuth(const TDesC8& aQop) const
+ {
+ GBA_TRACE_BEGIN();
+ if ( aQop == KAuthInt )
+ {
+ GBA_TRACE_DEBUG((" qop is equal to auth-int"));
+ return ETrue;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG((" qop is NOT equal to auth-int"));
+ GBA_TRACE_DEBUG((""));
+ return EFalse;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::HA1L()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::HAOneL(const RString& aUsername,const RString& aPW,
+ const RString& aRealm, TDes8& aResult)
+ {
+ HBufC8* a1 = HBufC8::NewMaxLC(aUsername.DesC().Length()
+ + aPW.DesC().Length()
+ + 1
+ + aRealm.DesC().Length() + 1
+ );
+ TPtr8 a1Mod = a1->Des();
+ a1Mod.Zero();
+
+ a1Mod.Append(aUsername.DesC());
+ a1Mod.Append(':');
+ a1Mod.Append(aRealm.DesC());
+ a1Mod.Append(':');
+ a1Mod.Append(aPW.DesC().Ptr(),aPW.DesC().Length());
+
+ GBA_TRACE_DEBUG(a1Mod);
+ Hash(*a1, aResult);
+ GBA_TRACE_DEBUG(("after hash"));
+ CleanupStack::PopAndDestroy(a1);
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::HAtwoL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::HATwoL(const RStringF& aMethod,
+ const RString& aRequestUri,
+ const TDesC8& aHentity,
+ TDes8& aResult)
+ {
+ // In the auth qop, a2 is Method:digest-uri-value:empty body hash
+ // Allocate enough space for the method, the URI and the colon, empty content-hash and colon.
+ TPtrC8 requestUri = aRequestUri.DesC();
+ TPtrC8 method = aMethod.DesC();
+ HBufC8* a2 = HBufC8::NewMaxLC( requestUri.Length() + method.Length() + KNumber34 );
+ TPtr8 a2Mod = a2->Des();
+ a2Mod.Zero();
+ a2Mod.Append(method);
+ a2Mod.Append(':');
+
+ a2Mod.Append( requestUri );
+ GBA_TRACE_DEBUG( requestUri );
+ // since for this method is always auth-int we always add hentity
+ a2Mod.Append(':');
+ a2Mod.Append(aHentity);
+ GBA_TRACE_DEBUG(a2Mod);
+
+ Hash(*a2, aResult);
+
+ GBA_TRACE_DEBUG_BINARY(aResult);
+ CleanupStack::PopAndDestroy(a2);
+
+ GBA_TRACE_DEBUG(("Exit HATwoL"));
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::Hash()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::Hash(const TDesC8& aMessage, TDes8& aHash)
+ {
+ GBA_TRACE_DEBUG(("hash"));
+ // Calculate the 128 bit (16 byte) hash
+ iMD5Calculator->Reset();
+ TPtrC8 hash = iMD5Calculator->Hash(aMessage);
+ GBA_TRACE_DEBUG(("after hash"));
+ // Now print it as a 32 byte hex number
+ aHash.Zero();
+ for ( TInt ii = 0; ii < KRawHashLength; ii++ )
+ {
+ TBuf8<2> scratch;
+ scratch.Zero();
+ scratch.Format(formatStr, hash[ii]);
+ aHash.Append(scratch);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::GenerateCNonce()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::GenerateCNonce(TDes8& aNonce)
+ {
+ // The purpose of the client nonce is to protect aextst 'chosen
+ // plaintext' attacks where a hostile server tricks the client
+ // into supplying a password using a specific server nonce that
+ // allows an (as yet undiscovered) flaw in MD5 to recover the
+ // password. As such the only important thing about client nonces
+ // is that they change and aren't predictable. See section 4.9 of
+ // RFC2616
+
+ TTime time;
+ time.UniversalTime();
+ TInt64 randomNumber = Math::Rand(iSeed);
+ randomNumber <<= KNumber32;
+ randomNumber += Math::Rand(iSeed);
+ TBuf8<KNumber33> key;
+ key.Zero();
+ key.AppendNum(time.Int64(), EHex);
+ key.Append(KColon);
+ key.AppendNum(randomNumber, EHex);
+
+ Hash(key, aNonce);
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::CheckRspAuthL()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrapHttpHandler::CheckRspAuthL(RHTTPTransaction aTransaction)
+ {
+ RStringF wwwAuthInfoHeader = aTransaction.Session().StringPool().OpenFStringL(KHTTPAuthInfo);
+ RHTTPHeaders headers(aTransaction.Response().GetHeaderCollection());
+
+ THTTPHdrVal rspAuthVal;
+
+ TInt retVal = headers.FieldPartsL(wwwAuthInfoHeader);
+
+ TInt error = headers.GetField(wwwAuthInfoHeader, 0, rspAuthVal);
+
+ if(error != KErrNone)
+ {
+ wwwAuthInfoHeader.Close();
+ return error;
+ }
+ wwwAuthInfoHeader.Close();
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::DigestCalcL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::DigestCalcL(
+ const TDesC8& aHentity,
+ TDes8& aResult )
+ {
+ TInt stringToHashLength = iNonce.DesC().Length() +
+ KNumber8 + // auth-int length
+ KNumber3 * KHashLength + KNumber8 + iPassword.DesC().Length() + KNumber5;
+ HBufC8* stringToHash = HBufC8::NewMaxLC(stringToHashLength);
+ TPtr8 stringMod = stringToHash->Des();
+ stringMod.Zero();
+ HAOneL(iUsername, iPassword, iRealm, stringMod);
+ stringMod.Append(':');
+ stringMod.Append(iNonce.DesC());
+ stringMod.Append(KNCVal_2);
+ stringMod.Append(iCnonce.DesC());
+ stringMod.Append(':');
+ stringMod.Append(KAuthInt);
+ stringMod.Append(':');
+ TBuf8<KHashLength> hash;
+ HATwoL(iMethod, iUri, aHentity,hash);
+ GBA_TRACE_DEBUG_BINARY(stringMod);
+ stringMod.Append(hash);
+ GBA_TRACE_DEBUG(stringMod);
+ Hash(*stringToHash, aResult);
+ CleanupStack::PopAndDestroy(stringToHash);
+ };
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::GetResponse()
+// -----------------------------------------------------------------------------
+//
+ HBufC8* C3GPPBootstrapHttpHandler::GetResponse()
+ {
+ return iResponse->Alloc();
+ };
+
+//EOF