os/security/cryptomgmtlibs/cryptotokenfw/tsecdlg/Tsecdlg.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/cryptomgmtlibs/cryptotokenfw/tsecdlg/Tsecdlg.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,449 @@
     1.4 +/*
     1.5 +* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +* secdlgImpl.cpp
    1.19 +*
    1.20 +*/
    1.21 +
    1.22 +
    1.23 +#include "Tsecdlg.h"
    1.24 +#include <secdlgimpldefs.h>
    1.25 +#include <certificateapps.h>
    1.26 +#include <x509cert.h>
    1.27 +
    1.28 +
    1.29 +// These are not really allocated to us, but this is only for finding errors
    1.30 +// while debugging, so it doesn't really matter
    1.31 +const TInt KErrTooManyDialogs			= -12000;
    1.32 +const TInt KErrLabelMismatch 			= -12001;
    1.33 +const TInt KErrOperationMismatch		= -12002;
    1.34 +const TInt KErrOperationNotSupported	= -12003;
    1.35 +
    1.36 +_LIT(KpinValue,"pinkcloud");
    1.37 +_LIT(KYes,"Yes");
    1.38 +	
    1.39 +// ----------------------------------------------------------------------------
    1.40 +// Lib main entry point.
    1.41 +// This can leave and should leave (if failure occurs) despite the lack of trailing L.
    1.42 +//
    1.43 +
    1.44 +#ifdef _T_SECDLG_TEXTSHELL
    1.45 +EXPORT_C CArrayPtr<MNotifierBase2>* NotifierArray()
    1.46 +#else
    1.47 +CArrayPtr<MNotifierBase2>* NotifierArray()
    1.48 +#endif
    1.49 +	{
    1.50 +	//The notifierArray function CAN leave, despite no trailing L
    1.51 +	CArrayPtrFlat<MNotifierBase2>* subjects = new (ELeave) CArrayPtrFlat<MNotifierBase2>( 1 );
    1.52 +	CleanupStack::PushL(subjects);
    1.53 +	CTestSecDlgNotifier* notifier = CTestSecDlgNotifier::NewL();
    1.54 +	CleanupStack::PushL( notifier );
    1.55 +	subjects->AppendL( notifier );
    1.56 +	CleanupStack::Pop( 2,subjects);	//notifier, subjects
    1.57 +	return subjects;
    1.58 +	}
    1.59 +
    1.60 +// ----------------------------------------------------------------------------
    1.61 +// Ecom plugin implementation for UI notifier
    1.62 +//
    1.63 +
    1.64 +#ifndef _T_SECDLG_TEXTSHELL
    1.65 +
    1.66 +const TImplementationProxy ImplementationTable[] =
    1.67 +	{
    1.68 +		IMPLEMENTATION_PROXY_ENTRY(KTSecDlgNotiferUid, NotifierArray)
    1.69 +	};
    1.70 +
    1.71 +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
    1.72 +	{
    1.73 +	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
    1.74 +	return (ImplementationTable);
    1.75 +	}
    1.76 +
    1.77 +#endif
    1.78 +
    1.79 +// ----------------------------------------------------------------------------
    1.80 +// CInputSpec
    1.81 +//
    1.82 +
    1.83 +CInputSpec::CInputSpec(TSecurityDialogOperation aOp, HBufC* aLabelSpec, HBufC* aResponse1, HBufC* aResponse2) :
    1.84 +	iOp(aOp), iLabelSpec(aLabelSpec), iResponse1(aResponse1), iResponse2(aResponse2)
    1.85 +	{
    1.86 +	}
    1.87 +
    1.88 +CInputSpec::~CInputSpec()
    1.89 +	{
    1.90 +	delete iLabelSpec;
    1.91 +	delete iResponse1;
    1.92 +	delete iResponse2;
    1.93 +	}
    1.94 +
    1.95 +
    1.96 +// ----------------------------------------------------------------------------
    1.97 +// CTestSecDlgNotifier
    1.98 +//
    1.99 +
   1.100 +_LIT(KInputFile, "\\t_secdlg_in.dat");
   1.101 +_LIT(KOutputFile, "\\t_secdlg_out.dat");
   1.102 +
   1.103 +CTestSecDlgNotifier* CTestSecDlgNotifier::NewL()
   1.104 +	{
   1.105 +	CTestSecDlgNotifier* self=new (ELeave) CTestSecDlgNotifier();
   1.106 +	CleanupStack::PushL(self);
   1.107 +	self->ConstructL();
   1.108 +	CleanupStack::Pop(self);
   1.109 +	return self;
   1.110 +	}
   1.111 +
   1.112 +CTestSecDlgNotifier::CTestSecDlgNotifier()
   1.113 +	{
   1.114 +	iInfo.iUid = KUidSecurityDialogNotifier;
   1.115 +	iInfo.iChannel = TUid::Uid(0x00001234); // dummy
   1.116 +	iInfo.iPriority = ENotifierPriorityHigh;
   1.117 +	}
   1.118 +
   1.119 +void CTestSecDlgNotifier::ConstructL()
   1.120 +	{
   1.121 +	User::LeaveIfError(iFs.Connect());
   1.122 +	}
   1.123 +
   1.124 +
   1.125 +TInt CTestSecDlgNotifier::GetInputIndexL()
   1.126 +	{
   1.127 +	RFileReadStream stream;
   1.128 +	TDriveUnit sysDrive (RFs::GetSystemDrive());
   1.129 +	TDriveName driveName(sysDrive.Name());
   1.130 +	TBuf<128> outputFile (driveName);
   1.131 +	outputFile.Append(KOutputFile);
   1.132 +	
   1.133 +	TInt err = stream.Open(iFs, outputFile, EFileRead | EFileShareExclusive);
   1.134 +	// If the file doesn't exist yet just return zero
   1.135 +	if (err == KErrNotFound)
   1.136 +		{
   1.137 +		return 0;
   1.138 +		}
   1.139 +	User::LeaveIfError(err);
   1.140 +	stream.PushL();
   1.141 +	TInt index = stream.ReadInt32L();
   1.142 +	CleanupStack::PopAndDestroy(); // stream
   1.143 +	return index;
   1.144 +	}
   1.145 +
   1.146 +void CTestSecDlgNotifier::WriteDialogCountL(TInt aCount)
   1.147 +	{
   1.148 +	RFileWriteStream stream;
   1.149 +	TDriveUnit sysDrive (RFs::GetSystemDrive());
   1.150 +	TDriveName driveName(sysDrive.Name());
   1.151 +	TBuf<128> outputFile (driveName);
   1.152 +	outputFile.Append(KOutputFile);
   1.153 +	
   1.154 +	TInt err = stream.Replace(iFs, outputFile, EFileWrite | EFileShareExclusive);
   1.155 +	if (err == KErrNotFound)
   1.156 +		{
   1.157 +		err = stream.Create(iFs, outputFile, EFileWrite | EFileShareExclusive);
   1.158 +		}
   1.159 +	User::LeaveIfError(err);
   1.160 +	stream.PushL();
   1.161 +	stream.WriteInt32L(aCount);
   1.162 +	stream.CommitL();
   1.163 +	CleanupStack::PopAndDestroy(); // stream	
   1.164 +	}
   1.165 +
   1.166 +CInputSpec* CTestSecDlgNotifier::ReadInputSpecL(TInt aIndex)
   1.167 +	{
   1.168 +	RFileReadStream stream;
   1.169 +	TDriveUnit sysDrive (RFs::GetSystemDrive());
   1.170 +	TDriveName driveName(sysDrive.Name());
   1.171 +	TBuf<128> inputFile (driveName);
   1.172 +	inputFile.Append(KInputFile);
   1.173 +	User::LeaveIfError(stream.Open(iFs, inputFile, EFileRead | EFileShareExclusive));
   1.174 +	stream.PushL();
   1.175 +
   1.176 +	// Update dialog count here so test code can see how many dialogs were
   1.177 +	// requested if there were more than expected
   1.178 +	WriteDialogCountL(aIndex + 1);
   1.179 +	
   1.180 +	MStreamBuf* streamBuf = stream.Source();
   1.181 +	TInt labelSize, response1Size, response2Size;
   1.182 +
   1.183 +	// Skip records until we reach the one we want
   1.184 +	for (TInt i = 0 ; i < aIndex ; ++i)
   1.185 +		{
   1.186 +		stream.ReadInt32L();
   1.187 +		labelSize = stream.ReadInt32L();
   1.188 +		streamBuf->SeekL(MStreamBuf::ERead, EStreamMark, labelSize * 2);
   1.189 +		response1Size = stream.ReadInt32L();
   1.190 +		streamBuf->SeekL(MStreamBuf::ERead, EStreamMark, response1Size * 2);
   1.191 +		response2Size = stream.ReadInt32L();
   1.192 +		streamBuf->SeekL(MStreamBuf::ERead, EStreamMark, response2Size * 2);
   1.193 +		}
   1.194 +
   1.195 +	TSecurityDialogOperation op = static_cast<TSecurityDialogOperation>(stream.ReadInt32L());
   1.196 +
   1.197 +	labelSize = stream.ReadInt32L();
   1.198 +	HBufC* labelSpec = HBufC::NewMaxLC(labelSize);
   1.199 +	TPtr labelPtr(labelSpec->Des());
   1.200 +	stream.ReadL(labelPtr, labelSize);
   1.201 +	
   1.202 +	response1Size = stream.ReadInt32L();
   1.203 +	HBufC* response1 = HBufC::NewMaxLC(response1Size);
   1.204 +	TPtr response1Ptr(response1->Des());
   1.205 +	stream.ReadL(response1Ptr, response1Size);
   1.206 +	
   1.207 +	response2Size = stream.ReadInt32L();
   1.208 +	HBufC* response2 = HBufC::NewMaxLC(response2Size);
   1.209 +	TPtr response2Ptr(response2->Des());
   1.210 +	stream.ReadL(response2Ptr, response2Size);
   1.211 +
   1.212 +	CInputSpec* inputSpec = new (ELeave) CInputSpec(op, labelSpec, response1, response2);	
   1.213 +	CleanupStack::Pop(3, labelSpec);	
   1.214 +	CleanupStack::PopAndDestroy(); // stream
   1.215 +
   1.216 +	return inputSpec;
   1.217 +	}
   1.218 +
   1.219 +
   1.220 +void CTestSecDlgNotifier::DoEnterPINL(const CInputSpec& aSpec, const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
   1.221 +	{
   1.222 +	const TPINInput& pinInput = reinterpret_cast<const TPINInput&>(*aBuffer.Ptr());
   1.223 +
   1.224 +	if (pinInput.iPIN.iPINLabel.Find(aSpec.LabelSpec()) == KErrNotFound)
   1.225 +		{
   1.226 +		User::Leave(KErrLabelMismatch);
   1.227 +		}
   1.228 +	
   1.229 +	TPINValue pinValue = aSpec.Response1();
   1.230 +	TPckg<TPINValue> pinValueBufPtr(pinValue);
   1.231 +	aMessage.WriteL(aReplySlot, pinValueBufPtr);
   1.232 +	}
   1.233 +
   1.234 +void CTestSecDlgNotifier::DoChangePINL(const CInputSpec& aSpec, const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
   1.235 +	{
   1.236 +	const TPINInput& input = reinterpret_cast<const TPINInput&>(*aBuffer.Ptr());
   1.237 +
   1.238 +	if (input.iPIN.iPINLabel.Find(aSpec.LabelSpec()) == KErrNotFound)
   1.239 +		{
   1.240 +		User::Leave(KErrLabelMismatch);
   1.241 +		}
   1.242 +
   1.243 +	TTwoPINOutput output;
   1.244 +	output.iPINValueToCheck = aSpec.Response1();
   1.245 +	output.iNewPINValue = aSpec.Response2();
   1.246 +	TPckg<TTwoPINOutput> outputPckg(output);
   1.247 +	aMessage.WriteL(aReplySlot, outputPckg);
   1.248 +	}
   1.249 +
   1.250 +
   1.251 +void CTestSecDlgNotifier::Release()
   1.252 +	{
   1.253 +	delete this;
   1.254 +	}
   1.255 +
   1.256 +
   1.257 +
   1.258 +CTestSecDlgNotifier::TNotifierInfo CTestSecDlgNotifier::RegisterL()
   1.259 +	{
   1.260 +	return iInfo;
   1.261 +	}
   1.262 +
   1.263 +
   1.264 +
   1.265 +CTestSecDlgNotifier::TNotifierInfo CTestSecDlgNotifier::Info() const
   1.266 +	{
   1.267 +	return iInfo;
   1.268 +	}
   1.269 +
   1.270 +
   1.271 +
   1.272 +void CTestSecDlgNotifier::StartL(const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
   1.273 +	{
   1.274 +	TRAPD(err, DoStartL(aBuffer, aReplySlot, aMessage));
   1.275 +	aMessage.Complete(err);
   1.276 +	}
   1.277 +	
   1.278 +	
   1.279 +void CTestSecDlgNotifier::DoStartL(const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
   1.280 +	{
   1.281 +	// Minimum length is 4
   1.282 +	__ASSERT_DEBUG( aBuffer.Length() >= 4, User::Panic(_L("CTestSecDlgNotifier"), 0));
   1.283 +
   1.284 +	TUint operation = *reinterpret_cast<const TInt *>(aBuffer.Ptr()) & KSecurityDialogOperationMask;
   1.285 +	
   1.286 +	TInt index = GetInputIndexL();
   1.287 +	CInputSpec* spec = NULL;
   1.288 +
   1.289 +	TRAPD(err, spec = ReadInputSpecL(index));
   1.290 +	
   1.291 +	// If the input file doesn't exist then we will answer PIN requests with the
   1.292 +	// "pinkcloud" passphrase - this is so the certstore tests work independantly
   1.293 +	// from keystore
   1.294 +	if (err == KErrNotFound)
   1.295 +		{
   1.296 +		switch(operation)
   1.297 +			{
   1.298 +			case EEnterPIN:
   1.299 +				{
   1.300 +				TPINValue pinValue(KpinValue);
   1.301 +				TPckg<TPINValue> pinValueBufPtr(pinValue);
   1.302 +				aMessage.WriteL(aReplySlot, pinValueBufPtr);
   1.303 +				break;
   1.304 +				}
   1.305 +			case EServerAuthenticationFailure:
   1.306 +				{
   1.307 +				TServerAuthenticationFailureDialogResult output;
   1.308 +				output = EStop;				
   1.309 +	    		TServerAuthenticationFailureOutputBuf outputPckg(output);	
   1.310 +				aMessage.WriteL(aReplySlot, outputPckg);
   1.311 +				break;
   1.312 +				}
   1.313 +			default:
   1.314 +				{
   1.315 +				User::Leave(KErrOperationMismatch);
   1.316 +				break;
   1.317 +				}			
   1.318 +			}
   1.319 +		return;	
   1.320 +		}
   1.321 +	
   1.322 +	if (err == KErrEof)
   1.323 +		{
   1.324 +		User::Leave(KErrTooManyDialogs);
   1.325 +		}
   1.326 +
   1.327 +	User::LeaveIfError(err);
   1.328 +
   1.329 +	CleanupStack::PushL(spec);
   1.330 +	
   1.331 +	if (operation != spec->Operation())
   1.332 +		{
   1.333 +		User::Leave(KErrOperationMismatch);
   1.334 +		}
   1.335 +		
   1.336 +	switch (operation)
   1.337 +		{
   1.338 +		case EEnterPIN:
   1.339 +			DoEnterPINL(*spec, aBuffer, aReplySlot, aMessage);
   1.340 +			break;
   1.341 +
   1.342 +		case EChangePIN:
   1.343 +			DoChangePINL(*spec, aBuffer, aReplySlot, aMessage);
   1.344 +			break;
   1.345 +
   1.346 +		case ESecureConnection:
   1.347 + 			DoSecureConnectionL(*spec, aBuffer, aReplySlot, aMessage);
   1.348 + 			break;
   1.349 +
   1.350 +		case ESignText:
   1.351 +		case EEnablePIN:
   1.352 +		case EDisablePIN:
   1.353 +		case EUnblockPIN:		
   1.354 +		case EUnblockPINInClear:
   1.355 +		case EPINBlocked:
   1.356 +			// these operations are not yet implemented in this test harness
   1.357 +			User::Leave(KErrOperationNotSupported);
   1.358 +			break;
   1.359 +
   1.360 +		case EServerAuthenticationFailure:
   1.361 +			DoServerAuthenticationFailureL(*spec, aBuffer, aReplySlot, aMessage);
   1.362 +			break;
   1.363 +
   1.364 +		default:
   1.365 +			User::Panic(_L("CTestSecDlgNotifier"), 0);
   1.366 +		}
   1.367 +	CleanupStack::PopAndDestroy(spec);
   1.368 +	}
   1.369 +
   1.370 +void CTestSecDlgNotifier::DoServerAuthenticationFailureL(const CInputSpec& aSpec, const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage )
   1.371 +	{
   1.372 +	// Test for valid packing of dialog data by extracting the encoded certificate
   1.373 +	// and attempting to construct an X509 certificate from it.
   1.374 +	CServerAuthenticationFailureInput* srvAuthFail = CServerAuthenticationFailureInput::NewLC(aBuffer);
   1.375 +	TPtrC8 encodedCert;
   1.376 +	srvAuthFail->GetEncodedCert(encodedCert);
   1.377 +	
   1.378 +	// If CX509Certificate::NewL leaves the encoded cert buffer must not be valid.
   1.379 +	const CX509Certificate* cert = CX509Certificate::NewL(encodedCert);
   1.380 +
   1.381 +	// There is no further need for the cert, so it can be deleted immediately.
   1.382 +	delete cert;
   1.383 +	
   1.384 +	CleanupStack::PopAndDestroy(srvAuthFail);
   1.385 +	
   1.386 +	TServerAuthenticationFailureDialogResult output;
   1.387 +	output = EStop;
   1.388 +	if( (aSpec.Response1()).CompareF(KYes) == KErrNone )
   1.389 +		{
   1.390 +		output = EContinue;			
   1.391 +		}
   1.392 +	TServerAuthenticationFailureOutputBuf outputPckg(output);	
   1.393 +	aMessage.WriteL(aReplySlot, outputPckg);
   1.394 +	}
   1.395 +
   1.396 +void CTestSecDlgNotifier::DoSecureConnectionL(const CInputSpec& aSpec, const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage )
   1.397 +	{
   1.398 +	// If the client does not want to continue
   1.399 +	if( (aSpec.Response1()).CompareF(KYes) != KErrNone )
   1.400 +		{
   1.401 +		User::Leave(KErrCancel);	
   1.402 +		}
   1.403 +	else
   1.404 +		{
   1.405 +		const TSignInput* secureConnectionInput =
   1.406 +								reinterpret_cast<const TSignInput*>( aBuffer.Ptr() );
   1.407 +		// if the client certificate is requested
   1.408 +		if (secureConnectionInput->iDoClientAuthentication)
   1.409 +			{			
   1.410 +			TLex lexi(aSpec.Response2());
   1.411 +			TInt32 selectionId=0;
   1.412 +			TInt err=lexi.Val(selectionId);
   1.413 +
   1.414 +			TInt certHandleTotal = secureConnectionInput->iCertHandleArrayTotal;
   1.415 +			if (selectionId>certHandleTotal)
   1.416 +				{
   1.417 +				User::Leave(KErrNotFound);	
   1.418 +				}
   1.419 +												
   1.420 +			// Get index at start of list of TCTTokenObjectHandle objects
   1.421 +			TInt bufferIndex = sizeof( TSignInput );
   1.422 +			TInt certHandleSize = sizeof( TCTTokenObjectHandle );
   1.423 +			TPckgBuf<TCTTokenObjectHandle> certHandleBuf;
   1.424 +			TPtrC8 certHandleData( aBuffer.Mid( bufferIndex+(selectionId-1)*certHandleSize, certHandleSize ) );
   1.425 +			certHandleBuf.Copy( certHandleData );
   1.426 +			aMessage.WriteL( aReplySlot, certHandleBuf );			
   1.427 +			}			
   1.428 +		}	
   1.429 +	}	
   1.430 +
   1.431 +	
   1.432 +TPtrC8 CTestSecDlgNotifier::StartL( const TDesC8& /*aBuffer*/ )
   1.433 +	{
   1.434 +	User::Panic(_L("CTestSecDlgNotifier"), 0);
   1.435 +	return TPtrC8(KNullDesC8);
   1.436 +	}
   1.437 +
   1.438 +
   1.439 +void CTestSecDlgNotifier::Cancel()
   1.440 +	{
   1.441 +	// Don't think there is much we can do here. If a client deletes the
   1.442 +	// client-side security dialog instance, after calling a method that 
   1.443 +	// displays a dialog, this will not get called until the user dismisses
   1.444 +	// the dialog. We can't do anything then.
   1.445 +	}
   1.446 +
   1.447 +
   1.448 +TPtrC8 CTestSecDlgNotifier::UpdateL( const TDesC8& /*aBuffer*/ )
   1.449 +	{
   1.450 +	User::Panic(_L("CTestSecDlgNotifier"), 0);
   1.451 +	return NULL;
   1.452 +	}