sl@0: /* sl@0: * Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "x509constraintext.h" sl@0: #include "extensiontest.h" sl@0: #include "t_input.h" sl@0: sl@0: _LIT(KFileNameStart, ""); sl@0: _LIT(KExpectedDeviceIdList, ""); sl@0: _LIT(KExpectedDevice, ""); sl@0: _LIT(KExpectedSidList, ""); sl@0: _LIT(KExpectedSid, ""); sl@0: _LIT(KExpectedVidList, ""); sl@0: _LIT(KExpectedVid, ""); sl@0: _LIT(KExpectedCapabilities, ""); sl@0: _LIT(KCorrupt, ""); sl@0: _LIT(KMatch, ""); sl@0: sl@0: CTestAction* CExtensionTest::NewL(RFs& aFs, CConsoleBase& aConsole, sl@0: Output& aOut, const TTestActionSpec& aTestActionSpec) sl@0: { sl@0: CTestAction* self = CExtensionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CTestAction* CExtensionTest::NewLC(RFs& aFs, CConsoleBase& aConsole, sl@0: Output& aOut, const TTestActionSpec& aTestActionSpec) sl@0: { sl@0: CExtensionTest* self = new(ELeave) CExtensionTest(aFs, aConsole, aOut); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aTestActionSpec); sl@0: return self; sl@0: } sl@0: sl@0: CExtensionTest::CExtensionTest(RFs& aFs, CConsoleBase& aConsole, Output& aOut) sl@0: : CTestAction(aConsole, aOut), sl@0: iFs(aFs) sl@0: { sl@0: } sl@0: sl@0: CExtensionTest::~CExtensionTest() sl@0: { sl@0: iExpectedDeviceIdList.ResetAndDestroy(); sl@0: iExpectedDeviceIdList.Close(); sl@0: iExpectedSidList.Close(); sl@0: iExpectedVidList.Close(); sl@0: } sl@0: sl@0: void CExtensionTest::ConstructL(const TTestActionSpec& aTestActionSpec) sl@0: { sl@0: CTestAction::ConstructL(aTestActionSpec); sl@0: TInt startPos = 0; sl@0: TInt err = 0; sl@0: sl@0: HBufC* aBody = HBufC::NewLC(aTestActionSpec.iActionBody.Length()); sl@0: aBody->Des().Copy(aTestActionSpec.iActionBody); sl@0: sl@0: // Filename of the certificate file sl@0: TPtrC fileNameStart = Input::ParseElement(*aBody, KFileNameStart); sl@0: iCertFileName.Copy(fileNameStart); sl@0: sl@0: // Whether we expect at least on of the extensions to be corrupt sl@0: TPtrC corruptStart = Input::ParseElement(*aBody, KCorrupt); sl@0: if (corruptStart.CompareF(_L("True")) == 0) sl@0: { sl@0: iExpectedCorrupt = ETrue; sl@0: } sl@0: sl@0: // We expect the certificate to match the constraints sl@0: TPtrC matchStart = Input::ParseElement(*aBody, KMatch); sl@0: if (matchStart.CompareF(_L("True")) == 0) sl@0: { sl@0: iExpectedMatch = ETrue; sl@0: } sl@0: sl@0: // Extract the lists of constraints that are expected to be present sl@0: startPos = 0; sl@0: TPtrC deviceListStart = Input::ParseElement(*aBody, KExpectedDeviceIdList, startPos, err); sl@0: if (err >= 0) sl@0: { sl@0: BuildStringListL(iExpectedDeviceIdList, deviceListStart, KExpectedDevice); sl@0: iDeviceIdsPresent = ETrue; sl@0: } sl@0: sl@0: startPos = 0; sl@0: TPtrC sidListStart = Input::ParseElement(*aBody, KExpectedSidList, startPos, err); sl@0: if (err >= 0) sl@0: { sl@0: BuildIntList(iExpectedSidList, sidListStart, KExpectedSid); sl@0: iSidsPresent = ETrue; sl@0: } sl@0: sl@0: startPos = 0; sl@0: TPtrC vidListStart = Input::ParseElement(*aBody, KExpectedVidList, startPos, err); sl@0: if (err >= 0) sl@0: { sl@0: BuildIntList(iExpectedVidList, vidListStart, KExpectedVid); sl@0: iVidsPresent = ETrue; sl@0: } sl@0: sl@0: startPos = 0; sl@0: TPtrC capabilities = Input::ParseElement(*aBody, KExpectedCapabilities, startPos, err); sl@0: if (err >= 0) sl@0: { sl@0: BuildCapabilitySet(iExpectedCapabilities, capabilities); sl@0: iCapabilitiesPresent = ETrue; sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(aBody); sl@0: } sl@0: sl@0: void CExtensionTest::BuildStringListL(RPointerArray& aStrings, const TDesC& aBuf, const TDesC& aTag) sl@0: { sl@0: TInt pos = 0; sl@0: TInt err = 0; sl@0: do sl@0: { sl@0: // Find next value for the specified tag and add it to the string array sl@0: // if it exists. sl@0: TPtrC str = Input::ParseElement(aBuf, aTag, pos, err); sl@0: if (err >= 0) sl@0: { sl@0: HBufC* string = str.AllocLC(); sl@0: aStrings.AppendL(string); sl@0: CleanupStack::Pop(string); sl@0: } sl@0: } sl@0: while (err >= 0); sl@0: } sl@0: sl@0: void CExtensionTest::BuildIntList(RArray& aInts, const TDesC& aBuf, const TDesC& aTag) sl@0: { sl@0: TInt pos = 0; sl@0: TInt err = 0; sl@0: do sl@0: { sl@0: // Attempt to convert the contents of val to an int and store in sl@0: // the aInts array if it is a valid integer. sl@0: TInt n = Input::ParseIntElement(aBuf, aTag, pos, err); sl@0: if (err >= 0) sl@0: { sl@0: // This append should not fail as the parsing went fine. sl@0: // So, ignoring the leave just to satisfy non leaving method convention. sl@0: TRAP_IGNORE(aInts.AppendL(n)); sl@0: } sl@0: } sl@0: while (err >= 0); sl@0: } sl@0: sl@0: void CExtensionTest::BuildCapabilitySet(TCapabilitySet& aCapabilitySet, const TDesC& aBuf) sl@0: { sl@0: aCapabilitySet.SetEmpty(); sl@0: TUint length = aBuf.Length(); sl@0: for (TUint i = 0; i < length && i < ECapability_Limit; i++) sl@0: { sl@0: if (aBuf[i] == '1') sl@0: { sl@0: aCapabilitySet.AddCapability(static_cast(i)); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CExtensionTest::PerformAction(TRequestStatus& aStatus) sl@0: { sl@0: HBufC8* buf = NULL; sl@0: TInt err = KErrNone; sl@0: sl@0: TRAP(err, buf = Input::ReadFileL(iCertFileName, iFs)); sl@0: if (err == KErrNotFound) sl@0: { sl@0: iResult = EFalse; sl@0: iFinished = ETrue; sl@0: SetScriptError(EFileNotFound, iCertFileName); sl@0: TRequestStatus* status = &aStatus; sl@0: iActionState = EPostrequisite; sl@0: User::RequestComplete(status, KErrNone); sl@0: return; sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: sl@0: CleanupStack::PushL(buf); sl@0: CX509Certificate* cert = CX509Certificate::NewLC(buf->Des()); sl@0: sl@0: Print(_L("Checking certificate extensions in file ")); sl@0: PrintLine(iCertFileName); sl@0: sl@0: TBool match = EFalse; sl@0: TBool corrupt = EFalse; sl@0: CheckExtensionsL(*cert, match, corrupt); sl@0: if (corrupt) sl@0: { sl@0: iResult = iExpectedCorrupt; sl@0: if (!iResult) sl@0: { sl@0: Print(_L("Found unexpected corrupt extension.")); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // no error. test whether the certificate matched the sl@0: // test script. sl@0: iResult = (match == iExpectedMatch); sl@0: } sl@0: CleanupStack::PopAndDestroy(2, buf); // cert, buf sl@0: sl@0: TRequestStatus* status = &aStatus; sl@0: iActionState = EPostrequisite; sl@0: User::RequestComplete(status, KErrNone); sl@0: } sl@0: sl@0: void CExtensionTest::CheckExtensionsL(const CX509Certificate& cert, sl@0: TBool& match, TBool& corrupt) sl@0: { sl@0: TInt err = KErrNone; sl@0: sl@0: match = ETrue; sl@0: corrupt = EFalse; sl@0: sl@0: TRAP(err, match &= CheckDeviceIdListL(cert)); sl@0: if (err == KErrArgument) sl@0: { sl@0: PrintLine(_L("The device id constraint is corrupt.")); sl@0: corrupt = ETrue; sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: sl@0: TRAP(err, match &= CheckSidListL(cert)); sl@0: if (err == KErrArgument) sl@0: { sl@0: PrintLine(_L("The secure id constraint is corrupt.")); sl@0: corrupt = ETrue; sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: sl@0: TRAP(err, match &= CheckVidListL(cert)); sl@0: if (err == KErrArgument) sl@0: { sl@0: PrintLine(_L("The vendor id constraint is corrupt.")); sl@0: corrupt = ETrue; sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: sl@0: TRAP(err, match &= CheckCapabilitiesL(cert)); sl@0: if (err == KErrArgument) sl@0: { sl@0: PrintLine(_L("The capabilities constraint is corrupt.")); sl@0: corrupt = ETrue; sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: sl@0: TBool CExtensionTest::CheckDeviceIdListL(const CX509Certificate& cert) sl@0: { sl@0: TBool match = ETrue; sl@0: const CX509CertExtension* ext = cert.Extension(KDeviceIdListConstraint); sl@0: if (ext) sl@0: { sl@0: // use NewL because this covers NewLC as well sl@0: CX509Utf8StringListExt* stringListExt = CX509Utf8StringListExt::NewL(ext->Data()); sl@0: CleanupStack::PushL(stringListExt); sl@0: if (! IsEqual(stringListExt->StringArray(), iExpectedDeviceIdList)) sl@0: { sl@0: PrintLine(_L("Device Id list is different.")); sl@0: match = EFalse; sl@0: } sl@0: CleanupStack::PopAndDestroy(stringListExt); sl@0: } sl@0: else if (iDeviceIdsPresent) sl@0: { sl@0: PrintLine(_L("Device Id constraint is missing.")); sl@0: match = EFalse; sl@0: } sl@0: return match; sl@0: } sl@0: sl@0: TBool CExtensionTest::CheckSidListL(const CX509Certificate& cert) sl@0: { sl@0: const CX509CertExtension* ext = cert.Extension(KSidListConstraint); sl@0: TBool match = ETrue; sl@0: if (ext) sl@0: { sl@0: // use NewL because this covers NewLC as well sl@0: CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data()); sl@0: CleanupStack::PushL(intListExt); sl@0: if (! IsEqual(intListExt->IntArray(), iExpectedSidList)) sl@0: { sl@0: PrintLine(_L("SID list is different")); sl@0: match = EFalse; sl@0: } sl@0: CleanupStack::PopAndDestroy(intListExt); sl@0: } sl@0: else if (iSidsPresent) sl@0: { sl@0: PrintLine(_L("SID constraint is missing.")); sl@0: match = EFalse; sl@0: } sl@0: return match; sl@0: } sl@0: sl@0: TBool CExtensionTest::CheckVidListL(const CX509Certificate& cert) sl@0: { sl@0: const CX509CertExtension* ext = cert.Extension(KVidListConstraint); sl@0: TBool match = ETrue; sl@0: if (ext) sl@0: { sl@0: // use NewL because this covers NewLC as well sl@0: CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data()); sl@0: CleanupStack::PushL(intListExt); sl@0: sl@0: if (! IsEqual(intListExt->IntArray(), iExpectedVidList)) sl@0: { sl@0: PrintLine(_L("VID list is different")); sl@0: match = EFalse; sl@0: } sl@0: CleanupStack::PopAndDestroy(intListExt); sl@0: } sl@0: else if (iVidsPresent) sl@0: { sl@0: PrintLine(_L("VID constraint is missing.")); sl@0: match = EFalse; sl@0: } sl@0: return match; sl@0: } sl@0: sl@0: TBool CExtensionTest::CheckCapabilitiesL(const CX509Certificate& cert) sl@0: { sl@0: const CX509CertExtension* ext = cert.Extension(KCapabilitiesConstraint); sl@0: TBool match = ETrue; sl@0: if (ext) sl@0: { sl@0: // use NewL because this covers NewLC as well sl@0: CX509CapabilitySetExt* capabilitySetExt = CX509CapabilitySetExt::NewL(ext->Data()); sl@0: CleanupStack::PushL(capabilitySetExt); sl@0: sl@0: const TCapabilitySet& capabilitySet = capabilitySetExt->CapabilitySet(); sl@0: sl@0: if (! (capabilitySet.HasCapabilities(iExpectedCapabilities) sl@0: && iExpectedCapabilities.HasCapabilities(capabilitySet))) sl@0: { sl@0: PrintLine(_L("Capability constraints are different.")); sl@0: match = EFalse; sl@0: } sl@0: CleanupStack::PopAndDestroy(capabilitySetExt); sl@0: } sl@0: else if (iCapabilitiesPresent) sl@0: { sl@0: PrintLine(_L("Capability constraint is missing.")); sl@0: match = EFalse; sl@0: } sl@0: return match; sl@0: } sl@0: sl@0: TBool CExtensionTest::IsEqual(const RArray& aArray1, const RArray& aArray2) sl@0: { sl@0: if (aArray1.Count() == aArray2.Count()) sl@0: { sl@0: TInt count = aArray1.Count(); sl@0: for (TInt i = 0; i < count; i++) sl@0: { sl@0: if (aArray1[i] != aArray2[i]) sl@0: { sl@0: return EFalse; sl@0: } sl@0: } sl@0: return ETrue; sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: TBool CExtensionTest::IsEqual(const RPointerArray& aArray1, const RPointerArray& aArray2) sl@0: { sl@0: if (aArray1.Count() == aArray2.Count()) sl@0: { sl@0: TInt count = aArray1.Count(); sl@0: for (TInt i = 0; i < count; i++) sl@0: { sl@0: if (aArray1[i]->Compare(*aArray2[i]) != 0) sl@0: { sl@0: return EFalse; sl@0: } sl@0: } sl@0: return ETrue; sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: void CExtensionTest::DoReportAction() sl@0: { sl@0: } sl@0: sl@0: void CExtensionTest::DoCheckResult(TInt /*aError*/) sl@0: { sl@0: } sl@0: sl@0: void CExtensionTest::Print(const TDesC& aText) sl@0: { sl@0: iConsole.Printf(aText); sl@0: iOut.writeString(aText); sl@0: } sl@0: void CExtensionTest::PrintLine(const TDesC& aText) sl@0: { sl@0: iConsole.Printf(aText); sl@0: iConsole.Printf(_L("\n")); sl@0: sl@0: iOut.writeString(aText); sl@0: iOut.writeNewLine(); sl@0: }