test_policychecker.c (16932B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * test_policychecker.c 6 * 7 * Test Policy Checking 8 * 9 */ 10 11 #include "testutil.h" 12 #include "testutil_nss.h" 13 14 #define PKIX_TEST_MAX_CERTS 10 15 16 static void *plContext = NULL; 17 18 static void 19 printUsage(char *testname) 20 { 21 char *fmt = 22 "USAGE: %s testname" 23 " [ENE|EE] \"{OID[:OID]*}\" [A|E|P] cert [cert]*\n" 24 "(The quotes are needed around the OID argument for dbx.)\n" 25 "(The optional arg A indicates initialAnyPolicyInhibit.)\n" 26 "(The optional arg E indicates initialExplicitPolicy.)\n" 27 "(The optional arg P indicates initialPolicyMappingInhibit.)\n"; 28 printf(fmt, testname); 29 } 30 31 static void 32 printUsageMax(PKIX_UInt32 numCerts) 33 { 34 printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n", 35 numCerts, PKIX_TEST_MAX_CERTS); 36 } 37 38 static PKIX_List * 39 policySetParse(char *policyString) 40 { 41 char *p = NULL; 42 char *oid = NULL; 43 char c = '\0'; 44 PKIX_Boolean validString = PKIX_FALSE; 45 PKIX_PL_OID *plOID = NULL; 46 PKIX_List *policySet = NULL; 47 48 PKIX_TEST_STD_VARS(); 49 50 p = policyString; 51 52 /* 53 * There may or may not be quotes around the initial-policy-set 54 * string. If they are omitted, dbx will strip off the curly braces. 55 * If they are included, dbx will strip off the quotes, but if you 56 * are running directly from a script, without dbx, the quotes will 57 * not be stripped. We need to be able to handle both cases. 58 */ 59 if (*p == '"') { 60 p++; 61 } 62 63 if ('{' != *p++) { 64 return (NULL); 65 } 66 oid = p; 67 68 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&policySet, plContext)); 69 70 /* scan to the end of policyString */ 71 while (!validString) { 72 /* scan to the end of the current OID string */ 73 c = *oid; 74 while ((c != '\0') && (c != ':') && (c != '}')) { 75 c = *++oid; 76 } 77 78 if ((c != ':') || (c != '}')) { 79 *oid = '\0'; /* store a null terminator */ 80 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(p, &plOID, plContext)); 81 82 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(policySet, 83 (PKIX_PL_Object *)plOID, 84 plContext)); 85 86 PKIX_TEST_DECREF_BC(plOID); 87 plOID = NULL; 88 if (c == '}') { 89 /* 90 * Any exit but this one means 91 * we were given a badly-formed string. 92 */ 93 validString = PKIX_TRUE; 94 } 95 p = ++oid; 96 } 97 } 98 99 cleanup: 100 if (!validString) { 101 PKIX_TEST_DECREF_AC(plOID); 102 PKIX_TEST_DECREF_AC(policySet); 103 policySet = NULL; 104 } 105 106 PKIX_TEST_RETURN(); 107 108 return (policySet); 109 } 110 111 /* 112 * FUNCTION: treeToStringHelper 113 * This function obtains the string representation of a PolicyNode 114 * Tree and compares it to the expected value. 115 * PARAMETERS: 116 * "parent" - a PolicyNode, the root of a PolicyNodeTree; 117 * must be non-NULL. 118 * "expected" - the desired string. 119 * THREAD SAFETY: 120 * Thread Safe 121 * 122 * Multiple threads can safely call this function without worrying 123 * about conflicts, even if they're operating on the same object. 124 * RETURNS: 125 * Nothing. 126 */ 127 static void 128 treeToStringHelper(PKIX_PolicyNode *parent, char *expected) 129 { 130 PKIX_PL_String *stringRep = NULL; 131 char *actual = NULL; 132 PKIX_TEST_STD_VARS(); 133 134 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)parent, &stringRep, plContext)); 135 136 actual = PKIX_String2ASCII(stringRep, plContext); 137 if (actual == NULL) { 138 pkixTestErrorMsg = "PKIX_String2ASCII Failed"; 139 goto cleanup; 140 } 141 142 if (PL_strcmp(actual, expected) != 0) { 143 testError("unexpected mismatch"); 144 (void)printf("Actual value:\t%s\n", actual); 145 (void)printf("Expected value:\t%s\n", expected); 146 } 147 148 cleanup: 149 150 PKIX_PL_Free(actual, plContext); 151 152 PKIX_TEST_DECREF_AC(stringRep); 153 154 PKIX_TEST_RETURN(); 155 } 156 157 static void 158 testPass(char *dirName, char *goodInput, char *diffInput, char *dateAscii) 159 { 160 161 PKIX_List *chain = NULL; 162 PKIX_ValidateParams *valParams = NULL; 163 PKIX_ValidateResult *valResult = NULL; 164 165 PKIX_TEST_STD_VARS(); 166 167 subTest("Basic-Common-Fields <pass>"); 168 /* 169 * Tests the Expiration, NameChaining, and Signature Checkers 170 */ 171 172 chain = createCertChain(dirName, goodInput, diffInput, plContext); 173 174 valParams = createValidateParams(dirName, 175 goodInput, 176 diffInput, 177 dateAscii, 178 NULL, 179 PKIX_FALSE, 180 PKIX_FALSE, 181 PKIX_FALSE, 182 PKIX_FALSE, 183 chain, 184 plContext); 185 186 PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext)); 187 188 cleanup: 189 190 PKIX_TEST_DECREF_AC(chain); 191 PKIX_TEST_DECREF_AC(valParams); 192 PKIX_TEST_DECREF_AC(valResult); 193 194 PKIX_TEST_RETURN(); 195 } 196 197 static void 198 testNistTest1(char *dirName) 199 { 200 #define PKIX_TEST_NUM_CERTS 2 201 char *trustAnchor = 202 "TrustAnchorRootCertificate.crt"; 203 char *intermediateCert = 204 "GoodCACert.crt"; 205 char *endEntityCert = 206 "ValidCertificatePathTest1EE.crt"; 207 char *certNames[PKIX_TEST_NUM_CERTS]; 208 char *asciiAnyPolicy = "2.5.29.32.0"; 209 PKIX_PL_Cert *certs[PKIX_TEST_NUM_CERTS] = { NULL, NULL }; 210 211 PKIX_ValidateParams *valParams = NULL; 212 PKIX_ValidateResult *valResult = NULL; 213 PKIX_List *chain = NULL; 214 PKIX_PL_OID *anyPolicyOID = NULL; 215 PKIX_List *initialPolicies = NULL; 216 char *anchorName = NULL; 217 218 PKIX_TEST_STD_VARS(); 219 220 subTest("testNistTest1: Creating the cert chain"); 221 /* 222 * Create a chain, but don't include the first certName. 223 * That's the anchor, and is supplied separately from 224 * the chain. 225 */ 226 certNames[0] = intermediateCert; 227 certNames[1] = endEntityCert; 228 chain = createCertChainPlus(dirName, certNames, certs, PKIX_TEST_NUM_CERTS, plContext); 229 230 subTest("testNistTest1: Creating the Validate Parameters"); 231 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(asciiAnyPolicy, &anyPolicyOID, plContext)); 232 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&initialPolicies, plContext)); 233 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(initialPolicies, (PKIX_PL_Object *)anyPolicyOID, plContext)); 234 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(initialPolicies, plContext)); 235 236 valParams = createValidateParams(dirName, 237 trustAnchor, 238 NULL, 239 NULL, 240 initialPolicies, 241 PKIX_FALSE, 242 PKIX_FALSE, 243 PKIX_FALSE, 244 PKIX_FALSE, 245 chain, 246 plContext); 247 248 subTest("testNistTest1: Validating the chain"); 249 PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext)); 250 251 cleanup: 252 253 PKIX_PL_Free(anchorName, plContext); 254 255 PKIX_TEST_DECREF_AC(anyPolicyOID); 256 PKIX_TEST_DECREF_AC(initialPolicies); 257 PKIX_TEST_DECREF_AC(valParams); 258 PKIX_TEST_DECREF_AC(valResult); 259 PKIX_TEST_DECREF_AC(chain); 260 261 PKIX_TEST_RETURN(); 262 } 263 264 static void 265 testNistTest2(char *dirName) 266 { 267 #define PKIX_TEST_NUM_CERTS 2 268 char *trustAnchor = 269 "TrustAnchorRootCertificate.crt"; 270 char *intermediateCert = 271 "GoodCACert.crt"; 272 char *endEntityCert = 273 "ValidCertificatePathTest1EE.crt"; 274 char *certNames[PKIX_TEST_NUM_CERTS]; 275 char *asciiNist1Policy = "2.16.840.1.101.3.2.1.48.1"; 276 PKIX_PL_Cert *certs[PKIX_TEST_NUM_CERTS] = { NULL, NULL }; 277 278 PKIX_ValidateParams *valParams = NULL; 279 PKIX_ValidateResult *valResult = NULL; 280 PKIX_List *chain = NULL; 281 PKIX_PL_OID *Nist1PolicyOID = NULL; 282 PKIX_List *initialPolicies = NULL; 283 char *anchorName = NULL; 284 285 PKIX_TEST_STD_VARS(); 286 287 subTest("testNistTest2: Creating the cert chain"); 288 /* 289 * Create a chain, but don't include the first certName. 290 * That's the anchor, and is supplied separately from 291 * the chain. 292 */ 293 certNames[0] = intermediateCert; 294 certNames[1] = endEntityCert; 295 chain = createCertChainPlus(dirName, certNames, certs, PKIX_TEST_NUM_CERTS, plContext); 296 297 subTest("testNistTest2: Creating the Validate Parameters"); 298 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(asciiNist1Policy, &Nist1PolicyOID, plContext)); 299 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&initialPolicies, plContext)); 300 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(initialPolicies, (PKIX_PL_Object *)Nist1PolicyOID, plContext)); 301 PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(initialPolicies, plContext)); 302 303 valParams = createValidateParams(dirName, 304 trustAnchor, 305 NULL, 306 NULL, 307 initialPolicies, 308 PKIX_FALSE, 309 PKIX_FALSE, 310 PKIX_FALSE, 311 PKIX_FALSE, 312 chain, 313 plContext); 314 315 subTest("testNistTest2: Validating the chain"); 316 PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext)); 317 318 cleanup: 319 320 PKIX_PL_Free(anchorName, plContext); 321 322 PKIX_TEST_DECREF_AC(Nist1PolicyOID); 323 PKIX_TEST_DECREF_AC(initialPolicies); 324 PKIX_TEST_DECREF_AC(valParams); 325 PKIX_TEST_DECREF_AC(valResult); 326 PKIX_TEST_DECREF_AC(chain); 327 328 PKIX_TEST_RETURN(); 329 } 330 331 static void 332 printValidPolicyTree(PKIX_ValidateResult *valResult) 333 { 334 PKIX_PolicyNode *validPolicyTree = NULL; 335 PKIX_PL_String *treeString = NULL; 336 337 PKIX_TEST_STD_VARS(); 338 PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree(valResult, &validPolicyTree, plContext)); 339 if (validPolicyTree) { 340 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)validPolicyTree, 341 &treeString, 342 plContext)); 343 (void)printf("validPolicyTree is\n\t%s\n", 344 treeString->escAsciiString); 345 } else { 346 (void)printf("validPolicyTree is NULL\n"); 347 } 348 349 cleanup: 350 351 PKIX_TEST_DECREF_AC(validPolicyTree); 352 PKIX_TEST_DECREF_AC(treeString); 353 354 PKIX_TEST_RETURN(); 355 } 356 357 int 358 test_policychecker(int argc, char *argv[]) 359 { 360 361 PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; 362 PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; 363 PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; 364 PKIX_Boolean expectedResult = PKIX_FALSE; 365 PKIX_UInt32 chainLength = 0; 366 PKIX_UInt32 initArgs = 0; 367 PKIX_UInt32 firstCert = 0; 368 PKIX_UInt32 i = 0; 369 PKIX_Int32 j = 0; 370 PKIX_UInt32 actualMinorVersion; 371 PKIX_ProcessingParams *procParams = NULL; 372 char *firstTrustAnchor = "yassir2yassir"; 373 char *secondTrustAnchor = "yassir2bcn"; 374 char *dateAscii = "991201000000Z"; 375 PKIX_ValidateParams *valParams = NULL; 376 PKIX_ValidateResult *valResult = NULL; 377 PKIX_List *userInitialPolicySet = NULL; /* List of PKIX_PL_OID */ 378 char *certNames[PKIX_TEST_MAX_CERTS]; 379 PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS]; 380 PKIX_List *chain = NULL; 381 PKIX_Error *validationError = NULL; 382 PKIX_VerifyNode *verifyTree = NULL; 383 PKIX_PL_String *verifyString = NULL; 384 char *dirName = NULL; 385 char *dataCentralDir = NULL; 386 char *anchorName = NULL; 387 388 PKIX_TEST_STD_VARS(); 389 390 PKIX_TEST_EXPECT_NO_ERROR( 391 PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); 392 393 /* 394 * Perform hard-coded tests if no command line args. 395 * If command line args are provided, they must be: 396 * arg[1]: test name 397 * arg[2]: "ENE" or "EE", for "expect no error" or "expect error" 398 * arg[3]: directory for certificates 399 * arg[4]: user-initial-policy-set, consisting of braces 400 * containing zero or more OID sequences, separated by commas 401 * arg[5]: (optional) "E", indicating initialExplicitPolicy 402 * arg[firstCert]: the path and filename of the trust anchor certificate 403 * arg[firstCert+1..(n-1)]: successive certificates in the chain 404 * arg[n]: the end entity certificate 405 * 406 * Example: test_policychecker test1EE ENE 407 * {2.5.29.32.0,2.5.29.32.3.6} Anchor CA EndEntity 408 */ 409 410 dirName = argv[3 + j]; 411 dataCentralDir = argv[4 + j]; 412 413 if (argc <= 5 || ((6 == argc) && (j))) { 414 415 testPass(dataCentralDir, 416 firstTrustAnchor, 417 secondTrustAnchor, 418 dateAscii); 419 420 testNistTest1(dirName); 421 422 testNistTest2(dirName); 423 424 goto cleanup; 425 } 426 427 if (argc < (7 + j)) { 428 printUsage(argv[0]); 429 pkixTestErrorMsg = "Invalid command line arguments."; 430 goto cleanup; 431 } 432 433 if (PORT_Strcmp(argv[2 + j], "ENE") == 0) { 434 expectedResult = PKIX_TRUE; 435 } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) { 436 expectedResult = PKIX_FALSE; 437 } else { 438 printUsage(argv[0]); 439 pkixTestErrorMsg = "Invalid command line arguments."; 440 goto cleanup; 441 } 442 443 userInitialPolicySet = policySetParse(argv[5 + j]); 444 if (!userInitialPolicySet) { 445 printUsage(argv[0]); 446 pkixTestErrorMsg = "Invalid command line arguments."; 447 goto cleanup; 448 } 449 450 for (initArgs = 0; initArgs < 3; initArgs++) { 451 if (PORT_Strcmp(argv[6 + j + initArgs], "A") == 0) { 452 initialAnyPolicyInhibit = PKIX_TRUE; 453 } else if (PORT_Strcmp(argv[6 + j + initArgs], "E") == 0) { 454 initialExplicitPolicy = PKIX_TRUE; 455 } else if (PORT_Strcmp(argv[6 + j + initArgs], "P") == 0) { 456 initialPolicyMappingInhibit = PKIX_TRUE; 457 } else { 458 break; 459 } 460 } 461 462 firstCert = initArgs + j + 6; 463 chainLength = argc - (firstCert + 1); 464 if (chainLength > PKIX_TEST_MAX_CERTS) { 465 printUsageMax(chainLength); 466 pkixTestErrorMsg = "Invalid command line arguments."; 467 goto cleanup; 468 } 469 470 /* 471 * Create a chain, but don't include the first certName. 472 * That's the anchor, and is supplied separately from 473 * the chain. 474 */ 475 for (i = 0; i < chainLength; i++) { 476 477 certNames[i] = argv[i + (firstCert + 1)]; 478 certs[i] = NULL; 479 } 480 chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext); 481 482 subTest(argv[1 + j]); 483 484 valParams = createValidateParams(dirName, 485 argv[firstCert], 486 NULL, 487 NULL, 488 userInitialPolicySet, 489 initialPolicyMappingInhibit, 490 initialAnyPolicyInhibit, 491 initialExplicitPolicy, 492 PKIX_FALSE, 493 chain, 494 plContext); 495 496 if (expectedResult == PKIX_TRUE) { 497 subTest(" (expecting successful validation)"); 498 499 PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext)); 500 501 printValidPolicyTree(valResult); 502 503 } else { 504 subTest(" (expecting validation to fail)"); 505 validationError = PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext); 506 if (!validationError) { 507 printValidPolicyTree(valResult); 508 pkixTestErrorMsg = "Should have thrown an error here."; 509 } 510 PKIX_TEST_DECREF_BC(validationError); 511 } 512 513 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext)); 514 (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString); 515 516 cleanup: 517 518 PKIX_PL_Free(anchorName, plContext); 519 520 PKIX_TEST_DECREF_AC(verifyString); 521 PKIX_TEST_DECREF_AC(verifyTree); 522 PKIX_TEST_DECREF_AC(userInitialPolicySet); 523 PKIX_TEST_DECREF_AC(chain); 524 PKIX_TEST_DECREF_AC(valParams); 525 PKIX_TEST_DECREF_AC(valResult); 526 PKIX_TEST_DECREF_AC(validationError); 527 528 PKIX_Shutdown(plContext); 529 530 PKIX_TEST_RETURN(); 531 532 endTests("PolicyChecker"); 533 534 return (0); 535 }