/*
* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:
*
*/
#include "CRefSecurityDialog.h"
// ----------------------------------------------------------------------------
// SecurityDialogFactory
//
EXPORT_C MSecurityDialog* SecurityDialogFactory::CreateL()
{
return CRefSecurityDialog::NewL();
}
// ----------------------------------------------------------------------------
// CRefSecurityDialog
//
CRefSecurityDialog::~CRefSecurityDialog()
{
delete iRequester;
}
void CRefSecurityDialog::Release()
{
delete this;
}
CRefSecurityDialog* CRefSecurityDialog::NewL()
{
CRefSecurityDialog* self = new (ELeave) CRefSecurityDialog();
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
void CRefSecurityDialog::ConstructL()
{
iRequester = CDialogRequester::NewL( *this );
}
void CRefSecurityDialog::EnterPIN( const TPINParams& aPINParams, TBool aRetry,
TPINValue& aPINValue, TRequestStatus& aStatus )
{
iClientPINValuePtr = &aPINValue;
DoBasicPINOperation( EEnterPIN, aPINParams, aRetry, iPINValueBuf, aStatus );
}
void CRefSecurityDialog::EnablePIN( const TPINParams& aPINParams, TBool aRetry,
TPINValue& aPINValue, TRequestStatus& aStatus )
{
iClientPINValuePtr = &aPINValue;
DoBasicPINOperation( EEnablePIN, aPINParams, aRetry, iPINValueBuf, aStatus );
}
void CRefSecurityDialog::DisablePIN( const TPINParams& aPINParams, TBool aRetry,
TPINValue& aPINValue, TRequestStatus& aStatus )
{
iClientPINValuePtr = &aPINValue;
DoBasicPINOperation( EDisablePIN, aPINParams, aRetry, iPINValueBuf, aStatus );
}
void CRefSecurityDialog::ChangePIN( const TPINParams& aPINParams, TBool aRetry,
TPINValue& aOldPINValue, TPINValue& aNewPINValue,
TRequestStatus& aStatus )
{
iClientPINValuePtr = &aOldPINValue;
iClientSecondPINValuePtr = &aNewPINValue;
DoBasicPINOperation( EChangePIN, aPINParams, aRetry, iTwoPINOutputBuf, aStatus );
}
void CRefSecurityDialog::UnblockPIN( const TPINParams& aBlockedPINParams,
const TPINParams& aUnblockingPINParams, TBool aRetry,
TPINValue& aUnblockingPINValue, TPINValue& aNewPINValue,
TRequestStatus& aStatus )
{
iCurrentOperation = EUnblockPIN;
InitClientStatus( aStatus );
TUnblockPINInput unblockPINInput;
unblockPINInput.iOperation = EUnblockPIN;
if ( aRetry )
{
unblockPINInput.iOperation |= EPINValueIncorrect;
}
unblockPINInput.iPIN = aBlockedPINParams;
unblockPINInput.iUnblockPIN = aUnblockingPINParams;
TUnblockPINInputBuf unblockPINInputBuf( unblockPINInput );
iUnblockPINInputBuf.Copy( unblockPINInputBuf );
iClientPINValuePtr = &aUnblockingPINValue;
iClientSecondPINValuePtr = &aNewPINValue;
iRequester->RequestDialog( iUnblockPINInputBuf, iTwoPINOutputBuf );
}
void CRefSecurityDialog::UnblockPINInClear( const TPINParams& aBlockedPINParams,
const TPINParams& aUnblockingPINParams, TBool aRetry,
TUnblockPINValue& aUnblockingPINValue, TPINValue& aNewPINValue,
TRequestStatus& aStatus )
{
iCurrentOperation = EUnblockPINInClear;
InitClientStatus( aStatus );
TUnblockPINInput unblockPINInput;
unblockPINInput.iOperation = EUnblockPINInClear;
if ( aRetry )
{
unblockPINInput.iOperation |= EPINValueIncorrect;
}
unblockPINInput.iPIN = aBlockedPINParams;
unblockPINInput.iUnblockPIN = aUnblockingPINParams;
TUnblockPINInputBuf unblockPINInputBuf( unblockPINInput );
iClientUnblockPINValuePtr = &aUnblockingPINValue;
iClientSecondPINValuePtr = &aNewPINValue;
iUnblockPINInputBuf.Copy( unblockPINInputBuf );
iRequester->RequestDialog( iUnblockPINInputBuf, iUnblockPINInClearOutputBuf );
}
void CRefSecurityDialog::Cancel()
{
iRequester->Cancel();
if (iClientStatus)
{
User::RequestComplete(iClientStatus, KErrCancel);
}
}
void CRefSecurityDialog::PINBlocked( const TPINParams& aPINParams,
TRequestStatus& aStatus )
{
iCurrentOperation = EPINBlocked;
TPckg<TPINValue> pinValueBuf( KNullDesC() );
DoBasicPINOperation( EPINBlocked, aPINParams, EFalse, pinValueBuf, aStatus );
}
void CRefSecurityDialog::TotalBlocked( const TPINParams& aPINParams,
TRequestStatus& aStatus )
{
iCurrentOperation = ETotalBlocked;
TPckg<TPINValue> pinValueBuf( KNullDesC() );
DoBasicPINOperation( ETotalBlocked, aPINParams, EFalse, pinValueBuf, aStatus );
}
void CRefSecurityDialog::EstablishSecureConnection( const TDesC8& aCertData,
const RArray<TCTTokenObjectHandle>& aCertHandleList,
MSecurityDialog::TConnectionType aConnectionType,
TBool& aDoClientAuthentication, TCTTokenObjectHandle& aCertHandle,
TRequestStatus& aStatus )
{
iCurrentOperation = ESecureConnection;
InitClientStatus( aStatus );
TInt certDataSize = aCertData.Size();
TSignInput signInput;
signInput.iOperation = ESecureConnection;
signInput.iVariableDataSize = certDataSize;
signInput.iCertHandleArrayTotal = aCertHandleList.Count();
signInput.iDoClientAuthentication = aDoClientAuthentication;
signInput.iConnectionType = aConnectionType;
TPckgC<TSignInput> signInputBufPtr( signInput );
// iSignInputBuf is persistent because further input processing occurs in the AO before
// calling the notifier.
iSignInputBuf.Copy( signInputBufPtr );
iVariableDataPtr.Set( aCertData );
iClientDoClientAuthenticationPtr = &aDoClientAuthentication;
iClientCertInfoHandlePtr = &aCertHandle;
iRequester->RequestVariableBufferDialog( iSignInputBuf, iVariableDataPtr,
aCertHandleList, iCertInfoHandleBuf );
}
void CRefSecurityDialog::SignText( const TDesC& aTextToSign,
const RArray<TCTTokenObjectHandle>& aCertHandleList,
TCTTokenObjectHandle& aCertHandle,
TRequestStatus& aStatus )
{
iCurrentOperation = ESignText;
InitClientStatus( aStatus );
TInt textSize = aTextToSign.Size();
TSignInput signInput;
signInput.iOperation = ESignText;
signInput.iVariableDataSize = textSize;
signInput.iCertHandleArrayTotal = aCertHandleList.Count();
TPckgC<TSignInput> signInputBufPtr( signInput );
// iSignInputBuf is persistent because further input processing occurs in the AO before
// calling the notifier.
iSignInputBuf.Copy( signInputBufPtr );
const TUint8* textToSignPtr = reinterpret_cast<const TUint8*>( aTextToSign.Ptr() );
iVariableDataPtr.Set( textToSignPtr, textSize );
iClientCertInfoHandlePtr = &aCertHandle;
iRequester->RequestVariableBufferDialog( iSignInputBuf, iVariableDataPtr,
aCertHandleList, iCertInfoHandleBuf );
}
void CRefSecurityDialog::ServerAuthenticationFailure(const TDesC8& aServerName,const TValidationError& aFailureReason, const TDesC8& aEncodedCert,TRequestStatus& aStatus )
{
iCurrentOperation = EServerAuthenticationFailure;
InitClientStatus( aStatus );
CServerAuthenticationFailureInput* serverAuthenticationFailureInput = NULL;
TRAPD(err, serverAuthenticationFailureInput = CServerAuthenticationFailureInput::NewL(aServerName, aFailureReason, aEncodedCert));
// Ownership of the inputBuffer will pass to the requester.
HBufC8* inputBuffer = NULL;
if (err == KErrNone)
TRAP(err, inputBuffer = serverAuthenticationFailureInput->PackBufferL());
delete serverAuthenticationFailureInput;
if (err == KErrNone)
iRequester->RequestDialog(inputBuffer, iServerAuthenticationOutputBuf);
else
HandleResponse(err);
}
void CRefSecurityDialog::DoBasicPINOperation( TSecurityDialogOperation aOperation,
const TPINParams& aPINParams, TBool aRetry, TDes8& aPINValue,
TRequestStatus& aStatus )
{
iCurrentOperation = aOperation;
InitClientStatus( aStatus );
TPINInput pinInput;
pinInput.iOperation = aOperation;
if ( aRetry )
{
pinInput.iOperation |= EPINValueIncorrect;
}
pinInput.iPIN = aPINParams;
TPINInputBuf pinInputBuf( pinInput );
iPINInputBuf.Copy( pinInputBuf );
iRequester->RequestDialog( iPINInputBuf, aPINValue );
}
void CRefSecurityDialog::InitClientStatus( TRequestStatus& aStatus )
{
iClientStatus = &aStatus;
*iClientStatus = KRequestPending;
}
void CRefSecurityDialog::HandleResponse( TInt aResult )
{
if ( aResult >= KErrNone )
{
switch ( iCurrentOperation )
{
case EServerAuthenticationFailure:
{
TServerAuthenticationFailureDialogResult serverAuthenticationOutput = iServerAuthenticationOutputBuf();
if(serverAuthenticationOutput == EContinue)
{
aResult = KErrNone;
}
else if(serverAuthenticationOutput == EStop)
{
aResult = KErrAbort;
}
}
break;
case ESecureConnection:
{
if ( aResult == KClientAuthenticationRequested )
{
*iClientDoClientAuthenticationPtr = ETrue;
aResult = KErrNone;
}
else
{
*iClientDoClientAuthenticationPtr = EFalse;
}
*iClientCertInfoHandlePtr = iCertInfoHandleBuf();
break;
}
case ESignText:
{
*iClientCertInfoHandlePtr = iCertInfoHandleBuf();
break;
}
case EEnterPIN:
case EEnablePIN:
case EDisablePIN:
*iClientPINValuePtr = iPINValueBuf();
break;
case EChangePIN:
case EUnblockPIN:
{
TTwoPINOutput& twoPINOutput = iTwoPINOutputBuf();
*iClientPINValuePtr = twoPINOutput.iPINValueToCheck;
*iClientSecondPINValuePtr = twoPINOutput.iNewPINValue;
break;
}
case EUnblockPINInClear:
{
TUnblockPINInClearOutput& unblockPINOutput = iUnblockPINInClearOutputBuf();
*iClientUnblockPINValuePtr = unblockPINOutput.iPINValueToCheck;
*iClientSecondPINValuePtr = unblockPINOutput.iNewPINValue;
break;
}
case EPINBlocked:
case ETotalBlocked:
// No data to return
break;
default:
__ASSERT_DEBUG( EFalse, _L( "Invalid operation" ) );
}
}
User::RequestComplete( iClientStatus, aResult );
}
// ----------------------------------------------------------------------------
// CDialogRequester
//
CDialogRequester::CDialogRequester( CRefSecurityDialog& aSecDialog )
: CActive( EPriorityStandard ), iSecDialog( aSecDialog )
{
CActiveScheduler::Add( this );
}
CDialogRequester::~CDialogRequester()
{
Cancel();
iNotifier.Close();
}
CDialogRequester* CDialogRequester::NewL( CRefSecurityDialog& aSecDialog )
{
CDialogRequester* self = new (ELeave) CDialogRequester( aSecDialog );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
void CDialogRequester::ConstructL()
{
User::LeaveIfError( iNotifier.Connect() );
}
void CDialogRequester::RequestDialog( const TDesC8& aData, TDes8& aResponse )
{
iNotifier.StartNotifierAndGetResponse( iStatus, KUidSecurityDialogNotifier,
aData, aResponse );
iState = KMakingRequest;
SetActive();
}
void CDialogRequester::DoCancel()
{
delete iInputBuffer;
iInputBuffer = NULL;
iNotifier.CancelNotifier( KUidSecurityDialogNotifier );
}
void CDialogRequester::RequestVariableBufferDialog( const TDesC8& aOperationData,
const TDesC8& aVariableData,
const RArray<TCTTokenObjectHandle>& aCertHandleList,
TDes8& aResponse )
{
iOperationDataPtr = &aOperationData;
iVariableDataPtr = &aVariableData;
iCertHandleListPtr = &aCertHandleList;
iResponsePtr = &aResponse;
iState = KFillingVariableInputBuffer;
SetActive();
// Complete the AO immediately so that buffer processing can occur in RunL().
TRequestStatus* statusPtr = &iStatus;
User::RequestComplete( statusPtr, KErrNone );
}
void CDialogRequester::RequestDialog(HBufC8* aInputBuffer, TDes8& aResponse)
{
iInputBuffer = aInputBuffer;
RequestDialog(*iInputBuffer, aResponse);
}
void CDialogRequester::RunL()
{
switch ( iState )
{
case KFillingVariableInputBuffer:
{
TInt operationDataSize = iOperationDataPtr->Size();
TInt variableDataSize = iVariableDataPtr->Size();
TInt arraySize = sizeof( TCTTokenObjectHandle ) * iCertHandleListPtr->Count();
TInt bufferSize = operationDataSize + variableDataSize + arraySize;
iInputBuffer = HBufC8::NewL( bufferSize );
TPtr8 inputBufferPtr( iInputBuffer->Des() );
inputBufferPtr.Append( *iOperationDataPtr );
for ( TInt h = 0, total = iCertHandleListPtr->Count(); h < total; ++h )
{
const TCTTokenObjectHandle& certHandle = (*iCertHandleListPtr)[h];
TPckgC<TCTTokenObjectHandle> certHandleBuf( certHandle );
inputBufferPtr.Append( certHandleBuf );
}
inputBufferPtr.Append( *iVariableDataPtr );
RequestDialog( *iInputBuffer, *iResponsePtr );
break;
}
case KMakingRequest:
{
delete iInputBuffer;
iInputBuffer = NULL;
iSecDialog.HandleResponse( iStatus.Int() );
break;
}
default:
__ASSERT_DEBUG( EFalse, _L( "Invalid state" ) );
}
}
/**
* RunError should only be called if the buffer allocation fails, in which case
* let client handle it.
*/
TInt CDialogRequester::RunError( TInt aError )
{
iSecDialog.HandleResponse( aError );
return KErrNone;
}
// ----------------------------------------------------------------------------
// CServerAuthenticationFailureInput
//
CServerAuthenticationFailureInput::CServerAuthenticationFailureInput()
{
}
CServerAuthenticationFailureInput::~CServerAuthenticationFailureInput()
{
if(iServerName)
delete iServerName;
if(iEncodedCert)
delete iEncodedCert;
}
CServerAuthenticationFailureInput* CServerAuthenticationFailureInput::NewL(const TDesC8& aServerName,const TValidationError& aFailureReason, const TDesC8& aEncodedCert, const TBool aCreateOwnBuffers)
{
CServerAuthenticationFailureInput* self = CServerAuthenticationFailureInput::NewLC(aServerName, aFailureReason, aEncodedCert, aCreateOwnBuffers);
CleanupStack::Pop(self);
return self;
}
CServerAuthenticationFailureInput* CServerAuthenticationFailureInput::NewLC(const TDesC8& aServerName,const TValidationError& aFailureReason, const TDesC8& aEncodedCert, const TBool aCreateOwnBuffers)
{
CServerAuthenticationFailureInput* self = new(ELeave) CServerAuthenticationFailureInput();
CleanupStack::PushL(self);
self->ConstructL(aServerName, aFailureReason, aEncodedCert, aCreateOwnBuffers);
return self;
}
EXPORT_C CServerAuthenticationFailureInput* CServerAuthenticationFailureInput::NewL(const TDesC8& aBuffer, const TBool aCreateOwnBuffers)
{
CServerAuthenticationFailureInput* self = CServerAuthenticationFailureInput::NewLC(aBuffer, aCreateOwnBuffers);
CleanupStack::Pop(self);
return self;
}
EXPORT_C CServerAuthenticationFailureInput* CServerAuthenticationFailureInput::NewLC(const TDesC8& aBuffer, const TBool aCreateOwnBuffers)
{
CServerAuthenticationFailureInput* self = new(ELeave) CServerAuthenticationFailureInput();
CleanupStack::PushL(self);
self->ConstructL(aBuffer, aCreateOwnBuffers);
return self;
}
void CServerAuthenticationFailureInput::ConstructL(const TDesC8& aServerName,const TValidationError& aFailureReason, const TDesC8& aEncodedCert, const TBool aCreateOwnBuffers)
{
iFailureReason = aFailureReason;
if (aCreateOwnBuffers)
{
iServerName = aServerName.AllocL();
iServerNamePtr.Set(iServerName->Des());
iEncodedCert = aEncodedCert.AllocL();
iEncodedCertPtr.Set(iEncodedCert->Des());
}
else
{
iServerNamePtr.Set(aServerName);
iEncodedCertPtr.Set(aEncodedCert);
}
}
void CServerAuthenticationFailureInput::ConstructL(const TDesC8& aBuffer, const TBool aCreateOwnBuffers)
{
const TServerAuthenticationFailureInput* srvAuthFail =
reinterpret_cast<const TServerAuthenticationFailureInput*>
( aBuffer.Ptr() );
const TUint8* binaryDataPtr = aBuffer.Ptr() + sizeof(TServerAuthenticationFailureInput);
iFailureReason = srvAuthFail->iFailureReason;
if(aCreateOwnBuffers)
{
TPtrC8 dataPtr(binaryDataPtr, srvAuthFail->iServerNameLength);
iServerName = dataPtr.AllocL();
iServerNamePtr.Set(iServerName->Des());
dataPtr.Set(binaryDataPtr + srvAuthFail->iServerNameLength, srvAuthFail->iEncodedCertLength);
iEncodedCert = dataPtr.AllocL();
iEncodedCertPtr.Set(iEncodedCert->Des());
}
else
{
iServerNamePtr.Set(binaryDataPtr, srvAuthFail->iServerNameLength);
iEncodedCertPtr.Set(binaryDataPtr + srvAuthFail->iServerNameLength, srvAuthFail->iEncodedCertLength);
}
}
EXPORT_C TValidationError CServerAuthenticationFailureInput::FailureReason()
{
return iFailureReason;
}
EXPORT_C void CServerAuthenticationFailureInput::GetServerName(TPtrC8& aServerNamePtr)
{
aServerNamePtr.Set(iServerNamePtr);
}
EXPORT_C void CServerAuthenticationFailureInput::GetEncodedCert(TPtrC8& aEncodedCertPtr)
{
aEncodedCertPtr.Set(iEncodedCertPtr);
}
EXPORT_C HBufC8* CServerAuthenticationFailureInput::PackBufferL() const
{
TServerAuthenticationFailureInput serverAuthenticationInput;
serverAuthenticationInput.iOperation = EServerAuthenticationFailure;
serverAuthenticationInput.iFailureReason = iFailureReason;
serverAuthenticationInput.iServerNameLength = iServerNamePtr.Length();
serverAuthenticationInput.iEncodedCertLength = iEncodedCertPtr.Length();
TServerAuthenticationFailureInputBuf serverAuthenticationInputBuf(serverAuthenticationInput);
TInt bufferSize = sizeof(serverAuthenticationInputBuf) + iServerNamePtr.Length() + iEncodedCertPtr.Length();
HBufC8* packedBuffer = HBufC8::NewL(bufferSize);
TPtr8 packedBufferPtr(packedBuffer->Des());
packedBufferPtr.Append(serverAuthenticationInputBuf);
packedBufferPtr.Append(iServerNamePtr);
packedBufferPtr.Append(iEncodedCertPtr);
return packedBuffer;
}