|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "x509constraintext.h" |
|
20 #include "extensiontest.h" |
|
21 #include "t_input.h" |
|
22 |
|
23 _LIT(KFileNameStart, "<filename>"); |
|
24 _LIT(KExpectedDeviceIdList, "<device_id_list>"); |
|
25 _LIT(KExpectedDevice, "<device_id>"); |
|
26 _LIT(KExpectedSidList, "<sid_list>"); |
|
27 _LIT(KExpectedSid, "<sid>"); |
|
28 _LIT(KExpectedVidList, "<vid_list>"); |
|
29 _LIT(KExpectedVid, "<vid>"); |
|
30 _LIT(KExpectedCapabilities, "<capabilities>"); |
|
31 _LIT(KCorrupt, "<corrupt>"); |
|
32 _LIT(KMatch, "<match>"); |
|
33 |
|
34 CTestAction* CExtensionTest::NewL(RFs& aFs, CConsoleBase& aConsole, |
|
35 Output& aOut, const TTestActionSpec& aTestActionSpec) |
|
36 { |
|
37 CTestAction* self = CExtensionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec); |
|
38 CleanupStack::Pop(self); |
|
39 return self; |
|
40 } |
|
41 |
|
42 CTestAction* CExtensionTest::NewLC(RFs& aFs, CConsoleBase& aConsole, |
|
43 Output& aOut, const TTestActionSpec& aTestActionSpec) |
|
44 { |
|
45 CExtensionTest* self = new(ELeave) CExtensionTest(aFs, aConsole, aOut); |
|
46 CleanupStack::PushL(self); |
|
47 self->ConstructL(aTestActionSpec); |
|
48 return self; |
|
49 } |
|
50 |
|
51 CExtensionTest::CExtensionTest(RFs& aFs, CConsoleBase& aConsole, Output& aOut) |
|
52 : CTestAction(aConsole, aOut), |
|
53 iFs(aFs) |
|
54 { |
|
55 } |
|
56 |
|
57 CExtensionTest::~CExtensionTest() |
|
58 { |
|
59 iExpectedDeviceIdList.ResetAndDestroy(); |
|
60 iExpectedDeviceIdList.Close(); |
|
61 iExpectedSidList.Close(); |
|
62 iExpectedVidList.Close(); |
|
63 } |
|
64 |
|
65 void CExtensionTest::ConstructL(const TTestActionSpec& aTestActionSpec) |
|
66 { |
|
67 CTestAction::ConstructL(aTestActionSpec); |
|
68 TInt startPos = 0; |
|
69 TInt err = 0; |
|
70 |
|
71 HBufC* aBody = HBufC::NewLC(aTestActionSpec.iActionBody.Length()); |
|
72 aBody->Des().Copy(aTestActionSpec.iActionBody); |
|
73 |
|
74 // Filename of the certificate file |
|
75 TPtrC fileNameStart = Input::ParseElement(*aBody, KFileNameStart); |
|
76 iCertFileName.Copy(fileNameStart); |
|
77 |
|
78 // Whether we expect at least on of the extensions to be corrupt |
|
79 TPtrC corruptStart = Input::ParseElement(*aBody, KCorrupt); |
|
80 if (corruptStart.CompareF(_L("True")) == 0) |
|
81 { |
|
82 iExpectedCorrupt = ETrue; |
|
83 } |
|
84 |
|
85 // We expect the certificate to match the constraints |
|
86 TPtrC matchStart = Input::ParseElement(*aBody, KMatch); |
|
87 if (matchStart.CompareF(_L("True")) == 0) |
|
88 { |
|
89 iExpectedMatch = ETrue; |
|
90 } |
|
91 |
|
92 // Extract the lists of constraints that are expected to be present |
|
93 startPos = 0; |
|
94 TPtrC deviceListStart = Input::ParseElement(*aBody, KExpectedDeviceIdList, startPos, err); |
|
95 if (err >= 0) |
|
96 { |
|
97 BuildStringListL(iExpectedDeviceIdList, deviceListStart, KExpectedDevice); |
|
98 iDeviceIdsPresent = ETrue; |
|
99 } |
|
100 |
|
101 startPos = 0; |
|
102 TPtrC sidListStart = Input::ParseElement(*aBody, KExpectedSidList, startPos, err); |
|
103 if (err >= 0) |
|
104 { |
|
105 BuildIntList(iExpectedSidList, sidListStart, KExpectedSid); |
|
106 iSidsPresent = ETrue; |
|
107 } |
|
108 |
|
109 startPos = 0; |
|
110 TPtrC vidListStart = Input::ParseElement(*aBody, KExpectedVidList, startPos, err); |
|
111 if (err >= 0) |
|
112 { |
|
113 BuildIntList(iExpectedVidList, vidListStart, KExpectedVid); |
|
114 iVidsPresent = ETrue; |
|
115 } |
|
116 |
|
117 startPos = 0; |
|
118 TPtrC capabilities = Input::ParseElement(*aBody, KExpectedCapabilities, startPos, err); |
|
119 if (err >= 0) |
|
120 { |
|
121 BuildCapabilitySet(iExpectedCapabilities, capabilities); |
|
122 iCapabilitiesPresent = ETrue; |
|
123 } |
|
124 |
|
125 CleanupStack::PopAndDestroy(aBody); |
|
126 } |
|
127 |
|
128 void CExtensionTest::BuildStringListL(RPointerArray<HBufC>& aStrings, const TDesC& aBuf, const TDesC& aTag) |
|
129 { |
|
130 TInt pos = 0; |
|
131 TInt err = 0; |
|
132 do |
|
133 { |
|
134 // Find next value for the specified tag and add it to the string array |
|
135 // if it exists. |
|
136 TPtrC str = Input::ParseElement(aBuf, aTag, pos, err); |
|
137 if (err >= 0) |
|
138 { |
|
139 aStrings.Append(str.AllocL()); |
|
140 } |
|
141 } |
|
142 while (err >= 0); |
|
143 } |
|
144 |
|
145 void CExtensionTest::BuildIntList(RArray<TInt>& aInts, const TDesC& aBuf, const TDesC& aTag) |
|
146 { |
|
147 TInt pos = 0; |
|
148 TInt err = 0; |
|
149 do |
|
150 { |
|
151 // Attempt to convert the contents of val to an int and store in |
|
152 // the aInts array if it is a valid integer. |
|
153 TInt n = Input::ParseIntElement(aBuf, aTag, pos, err); |
|
154 if (err >= 0) |
|
155 { |
|
156 aInts.Append(n); |
|
157 } |
|
158 } |
|
159 while (err >= 0); |
|
160 } |
|
161 |
|
162 void CExtensionTest::BuildCapabilitySet(TCapabilitySet& aCapabilitySet, const TDesC& aBuf) |
|
163 { |
|
164 aCapabilitySet.SetEmpty(); |
|
165 TUint length = aBuf.Length(); |
|
166 for (TUint i = 0; i < length && i < ECapability_Limit; i++) |
|
167 { |
|
168 if (aBuf[i] == '1') |
|
169 { |
|
170 aCapabilitySet.AddCapability(static_cast<TCapability>(i)); |
|
171 } |
|
172 } |
|
173 } |
|
174 |
|
175 void CExtensionTest::PerformAction(TRequestStatus& aStatus) |
|
176 { |
|
177 HBufC8* buf = NULL; |
|
178 TInt err = KErrNone; |
|
179 |
|
180 TRAP(err, buf = Input::ReadFileL(iCertFileName, iFs)); |
|
181 if (err == KErrNotFound) |
|
182 { |
|
183 iResult = EFalse; |
|
184 iFinished = ETrue; |
|
185 SetScriptError(EFileNotFound, iCertFileName); |
|
186 TRequestStatus* status = &aStatus; |
|
187 iActionState = EPostrequisite; |
|
188 User::RequestComplete(status, KErrNone); |
|
189 return; |
|
190 } |
|
191 else if (err != KErrNone) |
|
192 { |
|
193 User::Leave(err); |
|
194 } |
|
195 |
|
196 CleanupStack::PushL(buf); |
|
197 CX509Certificate* cert = CX509Certificate::NewLC(buf->Des()); |
|
198 |
|
199 Print(_L("Checking certificate extensions in file ")); |
|
200 PrintLine(iCertFileName); |
|
201 |
|
202 TBool match = EFalse; |
|
203 TBool corrupt = EFalse; |
|
204 CheckExtensionsL(*cert, match, corrupt); |
|
205 if (corrupt) |
|
206 { |
|
207 iResult = iExpectedCorrupt; |
|
208 if (!iResult) |
|
209 { |
|
210 Print(_L("Found unexpected corrupt extension.")); |
|
211 } |
|
212 } |
|
213 else |
|
214 { |
|
215 // no error. test whether the certificate matched the |
|
216 // test script. |
|
217 iResult = (match == iExpectedMatch); |
|
218 } |
|
219 CleanupStack::PopAndDestroy(2, buf); // cert, buf |
|
220 |
|
221 TRequestStatus* status = &aStatus; |
|
222 iActionState = EPostrequisite; |
|
223 User::RequestComplete(status, KErrNone); |
|
224 } |
|
225 |
|
226 void CExtensionTest::CheckExtensionsL(const CX509Certificate& cert, |
|
227 TBool& match, TBool& corrupt) |
|
228 { |
|
229 TInt err = KErrNone; |
|
230 |
|
231 match = ETrue; |
|
232 corrupt = EFalse; |
|
233 |
|
234 TRAP(err, match &= CheckDeviceIdListL(cert)); |
|
235 if (err == KErrArgument) |
|
236 { |
|
237 PrintLine(_L("The device id constraint is corrupt.")); |
|
238 corrupt = ETrue; |
|
239 } |
|
240 else if (err != KErrNone) |
|
241 { |
|
242 User::Leave(err); |
|
243 } |
|
244 |
|
245 TRAP(err, match &= CheckSidListL(cert)); |
|
246 if (err == KErrArgument) |
|
247 { |
|
248 PrintLine(_L("The secure id constraint is corrupt.")); |
|
249 corrupt = ETrue; |
|
250 } |
|
251 else if (err != KErrNone) |
|
252 { |
|
253 User::Leave(err); |
|
254 } |
|
255 |
|
256 TRAP(err, match &= CheckVidListL(cert)); |
|
257 if (err == KErrArgument) |
|
258 { |
|
259 PrintLine(_L("The vendor id constraint is corrupt.")); |
|
260 corrupt = ETrue; |
|
261 } |
|
262 else if (err != KErrNone) |
|
263 { |
|
264 User::Leave(err); |
|
265 } |
|
266 |
|
267 TRAP(err, match &= CheckCapabilitiesL(cert)); |
|
268 if (err == KErrArgument) |
|
269 { |
|
270 PrintLine(_L("The capabilities constraint is corrupt.")); |
|
271 corrupt = ETrue; |
|
272 } |
|
273 else if (err != KErrNone) |
|
274 { |
|
275 User::Leave(err); |
|
276 } |
|
277 } |
|
278 |
|
279 TBool CExtensionTest::CheckDeviceIdListL(const CX509Certificate& cert) |
|
280 { |
|
281 TBool match = ETrue; |
|
282 const CX509CertExtension* ext = cert.Extension(KDeviceIdListConstraint); |
|
283 if (ext) |
|
284 { |
|
285 // use NewL because this covers NewLC as well |
|
286 CX509Utf8StringListExt* stringListExt = CX509Utf8StringListExt::NewL(ext->Data()); |
|
287 CleanupStack::PushL(stringListExt); |
|
288 if (! IsEqual(stringListExt->StringArray(), iExpectedDeviceIdList)) |
|
289 { |
|
290 PrintLine(_L("Device Id list is different.")); |
|
291 match = EFalse; |
|
292 } |
|
293 CleanupStack::PopAndDestroy(stringListExt); |
|
294 } |
|
295 else if (iDeviceIdsPresent) |
|
296 { |
|
297 PrintLine(_L("Device Id constraint is missing.")); |
|
298 match = EFalse; |
|
299 } |
|
300 return match; |
|
301 } |
|
302 |
|
303 TBool CExtensionTest::CheckSidListL(const CX509Certificate& cert) |
|
304 { |
|
305 const CX509CertExtension* ext = cert.Extension(KSidListConstraint); |
|
306 TBool match = ETrue; |
|
307 if (ext) |
|
308 { |
|
309 // use NewL because this covers NewLC as well |
|
310 CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data()); |
|
311 CleanupStack::PushL(intListExt); |
|
312 if (! IsEqual(intListExt->IntArray(), iExpectedSidList)) |
|
313 { |
|
314 PrintLine(_L("SID list is different")); |
|
315 match = EFalse; |
|
316 } |
|
317 CleanupStack::PopAndDestroy(intListExt); |
|
318 } |
|
319 else if (iSidsPresent) |
|
320 { |
|
321 PrintLine(_L("SID constraint is missing.")); |
|
322 match = EFalse; |
|
323 } |
|
324 return match; |
|
325 } |
|
326 |
|
327 TBool CExtensionTest::CheckVidListL(const CX509Certificate& cert) |
|
328 { |
|
329 const CX509CertExtension* ext = cert.Extension(KVidListConstraint); |
|
330 TBool match = ETrue; |
|
331 if (ext) |
|
332 { |
|
333 // use NewL because this covers NewLC as well |
|
334 CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data()); |
|
335 CleanupStack::PushL(intListExt); |
|
336 |
|
337 if (! IsEqual(intListExt->IntArray(), iExpectedVidList)) |
|
338 { |
|
339 PrintLine(_L("VID list is different")); |
|
340 match = EFalse; |
|
341 } |
|
342 CleanupStack::PopAndDestroy(intListExt); |
|
343 } |
|
344 else if (iVidsPresent) |
|
345 { |
|
346 PrintLine(_L("VID constraint is missing.")); |
|
347 match = EFalse; |
|
348 } |
|
349 return match; |
|
350 } |
|
351 |
|
352 TBool CExtensionTest::CheckCapabilitiesL(const CX509Certificate& cert) |
|
353 { |
|
354 const CX509CertExtension* ext = cert.Extension(KCapabilitiesConstraint); |
|
355 TBool match = ETrue; |
|
356 if (ext) |
|
357 { |
|
358 // use NewL because this covers NewLC as well |
|
359 CX509CapabilitySetExt* capabilitySetExt = CX509CapabilitySetExt::NewL(ext->Data()); |
|
360 CleanupStack::PushL(capabilitySetExt); |
|
361 |
|
362 const TCapabilitySet& capabilitySet = capabilitySetExt->CapabilitySet(); |
|
363 |
|
364 if (! (capabilitySet.HasCapabilities(iExpectedCapabilities) |
|
365 && iExpectedCapabilities.HasCapabilities(capabilitySet))) |
|
366 { |
|
367 PrintLine(_L("Capability constraints are different.")); |
|
368 match = EFalse; |
|
369 } |
|
370 CleanupStack::PopAndDestroy(capabilitySetExt); |
|
371 } |
|
372 else if (iCapabilitiesPresent) |
|
373 { |
|
374 PrintLine(_L("Capability constraint is missing.")); |
|
375 match = EFalse; |
|
376 } |
|
377 return match; |
|
378 } |
|
379 |
|
380 TBool CExtensionTest::IsEqual(const RArray<TInt>& aArray1, const RArray<TInt>& aArray2) |
|
381 { |
|
382 if (aArray1.Count() == aArray2.Count()) |
|
383 { |
|
384 TInt count = aArray1.Count(); |
|
385 for (TInt i = 0; i < count; i++) |
|
386 { |
|
387 if (aArray1[i] != aArray2[i]) |
|
388 { |
|
389 return EFalse; |
|
390 } |
|
391 } |
|
392 return ETrue; |
|
393 } |
|
394 return EFalse; |
|
395 } |
|
396 |
|
397 TBool CExtensionTest::IsEqual(const RPointerArray<HBufC>& aArray1, const RPointerArray<HBufC>& aArray2) |
|
398 { |
|
399 if (aArray1.Count() == aArray2.Count()) |
|
400 { |
|
401 TInt count = aArray1.Count(); |
|
402 for (TInt i = 0; i < count; i++) |
|
403 { |
|
404 if (aArray1[i]->Compare(*aArray2[i]) != 0) |
|
405 { |
|
406 return EFalse; |
|
407 } |
|
408 } |
|
409 return ETrue; |
|
410 } |
|
411 return EFalse; |
|
412 } |
|
413 |
|
414 void CExtensionTest::DoReportAction() |
|
415 { |
|
416 } |
|
417 |
|
418 void CExtensionTest::DoCheckResult(TInt /*aError*/) |
|
419 { |
|
420 } |
|
421 |
|
422 void CExtensionTest::Print(const TDesC& aText) |
|
423 { |
|
424 iConsole.Printf(aText); |
|
425 iOut.writeString(aText); |
|
426 } |
|
427 void CExtensionTest::PrintLine(const TDesC& aText) |
|
428 { |
|
429 iConsole.Printf(aText); |
|
430 iConsole.Printf(_L("\n")); |
|
431 |
|
432 iOut.writeString(aText); |
|
433 iOut.writeNewLine(); |
|
434 } |