diff options
Diffstat (limited to 'src/lib/libcrypto/x509v3/pcy_tree.c')
-rw-r--r-- | src/lib/libcrypto/x509v3/pcy_tree.c | 235 |
1 files changed, 28 insertions, 207 deletions
diff --git a/src/lib/libcrypto/x509v3/pcy_tree.c b/src/lib/libcrypto/x509v3/pcy_tree.c index 92f6b24556..6c87a7f506 100644 --- a/src/lib/libcrypto/x509v3/pcy_tree.c +++ b/src/lib/libcrypto/x509v3/pcy_tree.c | |||
@@ -62,75 +62,6 @@ | |||
62 | 62 | ||
63 | #include "pcy_int.h" | 63 | #include "pcy_int.h" |
64 | 64 | ||
65 | /* Enable this to print out the complete policy tree at various point during | ||
66 | * evaluation. | ||
67 | */ | ||
68 | |||
69 | /*#define OPENSSL_POLICY_DEBUG*/ | ||
70 | |||
71 | #ifdef OPENSSL_POLICY_DEBUG | ||
72 | |||
73 | static void expected_print(BIO *err, X509_POLICY_LEVEL *lev, | ||
74 | X509_POLICY_NODE *node, int indent) | ||
75 | { | ||
76 | if ( (lev->flags & X509_V_FLAG_INHIBIT_MAP) | ||
77 | || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) | ||
78 | BIO_puts(err, " Not Mapped\n"); | ||
79 | else | ||
80 | { | ||
81 | int i; | ||
82 | STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; | ||
83 | ASN1_OBJECT *oid; | ||
84 | BIO_puts(err, " Expected: "); | ||
85 | for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) | ||
86 | { | ||
87 | oid = sk_ASN1_OBJECT_value(pset, i); | ||
88 | if (i) | ||
89 | BIO_puts(err, ", "); | ||
90 | i2a_ASN1_OBJECT(err, oid); | ||
91 | } | ||
92 | BIO_puts(err, "\n"); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static void tree_print(char *str, X509_POLICY_TREE *tree, | ||
97 | X509_POLICY_LEVEL *curr) | ||
98 | { | ||
99 | X509_POLICY_LEVEL *plev; | ||
100 | X509_POLICY_NODE *node; | ||
101 | int i; | ||
102 | BIO *err; | ||
103 | err = BIO_new_fp(stderr, BIO_NOCLOSE); | ||
104 | if (!curr) | ||
105 | curr = tree->levels + tree->nlevel; | ||
106 | else | ||
107 | curr++; | ||
108 | BIO_printf(err, "Level print after %s\n", str); | ||
109 | BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); | ||
110 | for (plev = tree->levels; plev != curr; plev++) | ||
111 | { | ||
112 | BIO_printf(err, "Level %ld, flags = %x\n", | ||
113 | plev - tree->levels, plev->flags); | ||
114 | for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) | ||
115 | { | ||
116 | node = sk_X509_POLICY_NODE_value(plev->nodes, i); | ||
117 | X509_POLICY_NODE_print(err, node, 2); | ||
118 | expected_print(err, plev, node, 2); | ||
119 | BIO_printf(err, " Flags: %x\n", node->data->flags); | ||
120 | } | ||
121 | if (plev->anyPolicy) | ||
122 | X509_POLICY_NODE_print(err, plev->anyPolicy, 2); | ||
123 | } | ||
124 | |||
125 | BIO_free(err); | ||
126 | |||
127 | } | ||
128 | #else | ||
129 | |||
130 | #define tree_print(a,b,c) /* */ | ||
131 | |||
132 | #endif | ||
133 | |||
134 | /* Initialize policy tree. Return values: | 65 | /* Initialize policy tree. Return values: |
135 | * 0 Some internal error occured. | 66 | * 0 Some internal error occured. |
136 | * -1 Inconsistent or invalid extensions in certificates. | 67 | * -1 Inconsistent or invalid extensions in certificates. |
@@ -156,10 +87,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
156 | *ptree = NULL; | 87 | *ptree = NULL; |
157 | n = sk_X509_num(certs); | 88 | n = sk_X509_num(certs); |
158 | 89 | ||
159 | #if 0 | ||
160 | /* Disable policy mapping for now... */ | 90 | /* Disable policy mapping for now... */ |
161 | flags |= X509_V_FLAG_INHIBIT_MAP; | 91 | flags |= X509_V_FLAG_INHIBIT_MAP; |
162 | #endif | ||
163 | 92 | ||
164 | if (flags & X509_V_FLAG_EXPLICIT_POLICY) | 93 | if (flags & X509_V_FLAG_EXPLICIT_POLICY) |
165 | explicit_policy = 0; | 94 | explicit_policy = 0; |
@@ -231,7 +160,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
231 | tree->auth_policies = NULL; | 160 | tree->auth_policies = NULL; |
232 | tree->user_policies = NULL; | 161 | tree->user_policies = NULL; |
233 | 162 | ||
234 | if (!tree->levels) | 163 | if (!tree) |
235 | { | 164 | { |
236 | OPENSSL_free(tree); | 165 | OPENSSL_free(tree); |
237 | return 0; | 166 | return 0; |
@@ -255,6 +184,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
255 | level++; | 184 | level++; |
256 | x = sk_X509_value(certs, i); | 185 | x = sk_X509_value(certs, i); |
257 | cache = policy_cache_set(x); | 186 | cache = policy_cache_set(x); |
187 | |||
258 | CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | 188 | CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); |
259 | level->cert = x; | 189 | level->cert = x; |
260 | 190 | ||
@@ -283,13 +213,13 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
283 | level->flags |= X509_V_FLAG_INHIBIT_MAP; | 213 | level->flags |= X509_V_FLAG_INHIBIT_MAP; |
284 | else | 214 | else |
285 | { | 215 | { |
286 | if (!(x->ex_flags & EXFLAG_SI)) | 216 | map_skip--; |
287 | map_skip--; | ||
288 | if ((cache->map_skip >= 0) | 217 | if ((cache->map_skip >= 0) |
289 | && (cache->map_skip < map_skip)) | 218 | && (cache->map_skip < map_skip)) |
290 | map_skip = cache->map_skip; | 219 | map_skip = cache->map_skip; |
291 | } | 220 | } |
292 | 221 | ||
222 | |||
293 | } | 223 | } |
294 | 224 | ||
295 | *ptree = tree; | 225 | *ptree = tree; |
@@ -307,32 +237,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
307 | 237 | ||
308 | } | 238 | } |
309 | 239 | ||
310 | static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, | 240 | /* This corresponds to RFC3280 XXXX XXXXX: |
311 | const X509_POLICY_DATA *data) | ||
312 | { | ||
313 | X509_POLICY_LEVEL *last = curr - 1; | ||
314 | X509_POLICY_NODE *node; | ||
315 | int i, matched = 0; | ||
316 | /* Iterate through all in nodes linking matches */ | ||
317 | for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) | ||
318 | { | ||
319 | node = sk_X509_POLICY_NODE_value(last->nodes, i); | ||
320 | if (policy_node_match(last, node, data->valid_policy)) | ||
321 | { | ||
322 | if (!level_add_node(curr, data, node, NULL)) | ||
323 | return 0; | ||
324 | matched = 1; | ||
325 | } | ||
326 | } | ||
327 | if (!matched && last->anyPolicy) | ||
328 | { | ||
329 | if (!level_add_node(curr, data, last->anyPolicy, NULL)) | ||
330 | return 0; | ||
331 | } | ||
332 | return 1; | ||
333 | } | ||
334 | |||
335 | /* This corresponds to RFC3280 6.1.3(d)(1): | ||
336 | * link any data from CertificatePolicies onto matching parent | 241 | * link any data from CertificatePolicies onto matching parent |
337 | * or anyPolicy if no match. | 242 | * or anyPolicy if no match. |
338 | */ | 243 | */ |
@@ -343,6 +248,7 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, | |||
343 | int i; | 248 | int i; |
344 | X509_POLICY_LEVEL *last; | 249 | X509_POLICY_LEVEL *last; |
345 | X509_POLICY_DATA *data; | 250 | X509_POLICY_DATA *data; |
251 | X509_POLICY_NODE *parent; | ||
346 | last = curr - 1; | 252 | last = curr - 1; |
347 | for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) | 253 | for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) |
348 | { | 254 | { |
@@ -355,109 +261,40 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, | |||
355 | * link because then it will have the mapping flags | 261 | * link because then it will have the mapping flags |
356 | * right and we can prune it later. | 262 | * right and we can prune it later. |
357 | */ | 263 | */ |
358 | #if 0 | ||
359 | if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) | 264 | if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) |
360 | && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) | 265 | && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) |
361 | continue; | 266 | continue; |
362 | #endif | 267 | /* Look for matching node in parent */ |
363 | /* Look for matching nodes in previous level */ | 268 | parent = level_find_node(last, data->valid_policy); |
364 | if (!tree_link_matching_nodes(curr, data)) | 269 | /* If no match link to anyPolicy */ |
270 | if (!parent) | ||
271 | parent = last->anyPolicy; | ||
272 | if (parent && !level_add_node(curr, data, parent, NULL)) | ||
365 | return 0; | 273 | return 0; |
366 | } | 274 | } |
367 | return 1; | 275 | return 1; |
368 | } | 276 | } |
369 | 277 | ||
370 | /* This corresponds to RFC3280 6.1.3(d)(2): | 278 | /* This corresponds to RFC3280 XXXX XXXXX: |
371 | * Create new data for any unmatched policies in the parent and link | 279 | * Create new data for any unmatched policies in the parent and link |
372 | * to anyPolicy. | 280 | * to anyPolicy. |
373 | */ | 281 | */ |
374 | 282 | ||
375 | static int tree_add_unmatched(X509_POLICY_LEVEL *curr, | ||
376 | const X509_POLICY_CACHE *cache, | ||
377 | const ASN1_OBJECT *id, | ||
378 | X509_POLICY_NODE *node, | ||
379 | X509_POLICY_TREE *tree) | ||
380 | { | ||
381 | X509_POLICY_DATA *data; | ||
382 | if (id == NULL) | ||
383 | id = node->data->valid_policy; | ||
384 | /* Create a new node with qualifiers from anyPolicy and | ||
385 | * id from unmatched node. | ||
386 | */ | ||
387 | data = policy_data_new(NULL, id, node_critical(node)); | ||
388 | |||
389 | if (data == NULL) | ||
390 | return 0; | ||
391 | /* Curr may not have anyPolicy */ | ||
392 | data->qualifier_set = cache->anyPolicy->qualifier_set; | ||
393 | data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; | ||
394 | if (!level_add_node(curr, data, node, tree)) | ||
395 | { | ||
396 | policy_data_free(data); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | return 1; | ||
401 | } | ||
402 | |||
403 | static int tree_link_unmatched(X509_POLICY_LEVEL *curr, | ||
404 | const X509_POLICY_CACHE *cache, | ||
405 | X509_POLICY_NODE *node, | ||
406 | X509_POLICY_TREE *tree) | ||
407 | { | ||
408 | const X509_POLICY_LEVEL *last = curr - 1; | ||
409 | int i; | ||
410 | |||
411 | if ( (last->flags & X509_V_FLAG_INHIBIT_MAP) | ||
412 | || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) | ||
413 | { | ||
414 | /* If no policy mapping: matched if one child present */ | ||
415 | if (node->nchild) | ||
416 | return 1; | ||
417 | if (!tree_add_unmatched(curr, cache, NULL, node, tree)) | ||
418 | return 0; | ||
419 | /* Add it */ | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | /* If mapping: matched if one child per expected policy set */ | ||
424 | STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; | ||
425 | if (node->nchild == sk_ASN1_OBJECT_num(expset)) | ||
426 | return 1; | ||
427 | /* Locate unmatched nodes */ | ||
428 | for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) | ||
429 | { | ||
430 | ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); | ||
431 | if (level_find_node(curr, node, oid)) | ||
432 | continue; | ||
433 | if (!tree_add_unmatched(curr, cache, oid, node, tree)) | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | } | ||
438 | |||
439 | return 1; | ||
440 | |||
441 | } | ||
442 | |||
443 | static int tree_link_any(X509_POLICY_LEVEL *curr, | 283 | static int tree_link_any(X509_POLICY_LEVEL *curr, |
444 | const X509_POLICY_CACHE *cache, | 284 | const X509_POLICY_CACHE *cache, |
445 | X509_POLICY_TREE *tree) | 285 | X509_POLICY_TREE *tree) |
446 | { | 286 | { |
447 | int i; | 287 | int i; |
448 | /*X509_POLICY_DATA *data;*/ | 288 | X509_POLICY_DATA *data; |
449 | X509_POLICY_NODE *node; | 289 | X509_POLICY_NODE *node; |
450 | X509_POLICY_LEVEL *last = curr - 1; | 290 | X509_POLICY_LEVEL *last; |
291 | |||
292 | last = curr - 1; | ||
451 | 293 | ||
452 | for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) | 294 | for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) |
453 | { | 295 | { |
454 | node = sk_X509_POLICY_NODE_value(last->nodes, i); | 296 | node = sk_X509_POLICY_NODE_value(last->nodes, i); |
455 | 297 | ||
456 | if (!tree_link_unmatched(curr, cache, node, tree)) | ||
457 | return 0; | ||
458 | |||
459 | #if 0 | ||
460 | |||
461 | /* Skip any node with any children: we only want unmathced | 298 | /* Skip any node with any children: we only want unmathced |
462 | * nodes. | 299 | * nodes. |
463 | * | 300 | * |
@@ -466,7 +303,6 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, | |||
466 | */ | 303 | */ |
467 | if (node->nchild) | 304 | if (node->nchild) |
468 | continue; | 305 | continue; |
469 | |||
470 | /* Create a new node with qualifiers from anyPolicy and | 306 | /* Create a new node with qualifiers from anyPolicy and |
471 | * id from unmatched node. | 307 | * id from unmatched node. |
472 | */ | 308 | */ |
@@ -483,9 +319,6 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, | |||
483 | policy_data_free(data); | 319 | policy_data_free(data); |
484 | return 0; | 320 | return 0; |
485 | } | 321 | } |
486 | |||
487 | #endif | ||
488 | |||
489 | } | 322 | } |
490 | /* Finally add link to anyPolicy */ | 323 | /* Finally add link to anyPolicy */ |
491 | if (last->anyPolicy) | 324 | if (last->anyPolicy) |
@@ -504,36 +337,30 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, | |||
504 | 337 | ||
505 | static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) | 338 | static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) |
506 | { | 339 | { |
507 | STACK_OF(X509_POLICY_NODE) *nodes; | ||
508 | X509_POLICY_NODE *node; | 340 | X509_POLICY_NODE *node; |
509 | int i; | 341 | int i; |
510 | nodes = curr->nodes; | 342 | for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--) |
511 | if (curr->flags & X509_V_FLAG_INHIBIT_MAP) | ||
512 | { | 343 | { |
513 | for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) | 344 | node = sk_X509_POLICY_NODE_value(curr->nodes, i); |
345 | /* Delete any mapped data: see RFC3280 XXXX */ | ||
346 | if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) | ||
514 | { | 347 | { |
515 | node = sk_X509_POLICY_NODE_value(nodes, i); | 348 | node->parent->nchild--; |
516 | /* Delete any mapped data: see RFC3280 XXXX */ | 349 | OPENSSL_free(node); |
517 | if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) | 350 | (void)sk_X509_POLICY_NODE_delete(curr->nodes, i); |
518 | { | ||
519 | node->parent->nchild--; | ||
520 | OPENSSL_free(node); | ||
521 | (void)sk_X509_POLICY_NODE_delete(nodes,i); | ||
522 | } | ||
523 | } | 351 | } |
524 | } | 352 | } |
525 | 353 | ||
526 | for(;;) { | 354 | for(;;) { |
527 | --curr; | 355 | --curr; |
528 | nodes = curr->nodes; | 356 | for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--) |
529 | for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) | ||
530 | { | 357 | { |
531 | node = sk_X509_POLICY_NODE_value(nodes, i); | 358 | node = sk_X509_POLICY_NODE_value(curr->nodes, i); |
532 | if (node->nchild == 0) | 359 | if (node->nchild == 0) |
533 | { | 360 | { |
534 | node->parent->nchild--; | 361 | node->parent->nchild--; |
535 | OPENSSL_free(node); | 362 | OPENSSL_free(node); |
536 | (void)sk_X509_POLICY_NODE_delete(nodes, i); | 363 | (void)sk_X509_POLICY_NODE_delete(curr->nodes, i); |
537 | } | 364 | } |
538 | } | 365 | } |
539 | if (curr->anyPolicy && !curr->anyPolicy->nchild) | 366 | if (curr->anyPolicy && !curr->anyPolicy->nchild) |
@@ -709,7 +536,6 @@ static int tree_evaluate(X509_POLICY_TREE *tree) | |||
709 | if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) | 536 | if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) |
710 | && !tree_link_any(curr, cache, tree)) | 537 | && !tree_link_any(curr, cache, tree)) |
711 | return 0; | 538 | return 0; |
712 | tree_print("before tree_prune()", tree, curr); | ||
713 | ret = tree_prune(tree, curr); | 539 | ret = tree_prune(tree, curr); |
714 | if (ret != 1) | 540 | if (ret != 1) |
715 | return ret; | 541 | return ret; |
@@ -778,6 +604,7 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, | |||
778 | *pexplicit_policy = 0; | 604 | *pexplicit_policy = 0; |
779 | ret = tree_init(&tree, certs, flags); | 605 | ret = tree_init(&tree, certs, flags); |
780 | 606 | ||
607 | |||
781 | switch (ret) | 608 | switch (ret) |
782 | { | 609 | { |
783 | 610 | ||
@@ -786,10 +613,6 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, | |||
786 | return 1; | 613 | return 1; |
787 | 614 | ||
788 | /* Some internal error */ | 615 | /* Some internal error */ |
789 | case -1: | ||
790 | return -1; | ||
791 | |||
792 | /* Some internal error */ | ||
793 | case 0: | 616 | case 0: |
794 | return 0; | 617 | return 0; |
795 | 618 | ||
@@ -823,8 +646,6 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, | |||
823 | if (!tree) goto error; | 646 | if (!tree) goto error; |
824 | ret = tree_evaluate(tree); | 647 | ret = tree_evaluate(tree); |
825 | 648 | ||
826 | tree_print("tree_evaluate()", tree, NULL); | ||
827 | |||
828 | if (ret <= 0) | 649 | if (ret <= 0) |
829 | goto error; | 650 | goto error; |
830 | 651 | ||