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, 207 insertions, 28 deletions
diff --git a/src/lib/libcrypto/x509v3/pcy_tree.c b/src/lib/libcrypto/x509v3/pcy_tree.c index 6c87a7f506..92f6b24556 100644 --- a/src/lib/libcrypto/x509v3/pcy_tree.c +++ b/src/lib/libcrypto/x509v3/pcy_tree.c | |||
@@ -62,6 +62,75 @@ | |||
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 | |||
65 | /* Initialize policy tree. Return values: | 134 | /* Initialize policy tree. Return values: |
66 | * 0 Some internal error occured. | 135 | * 0 Some internal error occured. |
67 | * -1 Inconsistent or invalid extensions in certificates. | 136 | * -1 Inconsistent or invalid extensions in certificates. |
@@ -87,8 +156,10 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
87 | *ptree = NULL; | 156 | *ptree = NULL; |
88 | n = sk_X509_num(certs); | 157 | n = sk_X509_num(certs); |
89 | 158 | ||
159 | #if 0 | ||
90 | /* Disable policy mapping for now... */ | 160 | /* Disable policy mapping for now... */ |
91 | flags |= X509_V_FLAG_INHIBIT_MAP; | 161 | flags |= X509_V_FLAG_INHIBIT_MAP; |
162 | #endif | ||
92 | 163 | ||
93 | if (flags & X509_V_FLAG_EXPLICIT_POLICY) | 164 | if (flags & X509_V_FLAG_EXPLICIT_POLICY) |
94 | explicit_policy = 0; | 165 | explicit_policy = 0; |
@@ -160,7 +231,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
160 | tree->auth_policies = NULL; | 231 | tree->auth_policies = NULL; |
161 | tree->user_policies = NULL; | 232 | tree->user_policies = NULL; |
162 | 233 | ||
163 | if (!tree) | 234 | if (!tree->levels) |
164 | { | 235 | { |
165 | OPENSSL_free(tree); | 236 | OPENSSL_free(tree); |
166 | return 0; | 237 | return 0; |
@@ -184,7 +255,6 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
184 | level++; | 255 | level++; |
185 | x = sk_X509_value(certs, i); | 256 | x = sk_X509_value(certs, i); |
186 | cache = policy_cache_set(x); | 257 | cache = policy_cache_set(x); |
187 | |||
188 | CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | 258 | CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); |
189 | level->cert = x; | 259 | level->cert = x; |
190 | 260 | ||
@@ -213,13 +283,13 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
213 | level->flags |= X509_V_FLAG_INHIBIT_MAP; | 283 | level->flags |= X509_V_FLAG_INHIBIT_MAP; |
214 | else | 284 | else |
215 | { | 285 | { |
216 | map_skip--; | 286 | if (!(x->ex_flags & EXFLAG_SI)) |
287 | map_skip--; | ||
217 | if ((cache->map_skip >= 0) | 288 | if ((cache->map_skip >= 0) |
218 | && (cache->map_skip < map_skip)) | 289 | && (cache->map_skip < map_skip)) |
219 | map_skip = cache->map_skip; | 290 | map_skip = cache->map_skip; |
220 | } | 291 | } |
221 | 292 | ||
222 | |||
223 | } | 293 | } |
224 | 294 | ||
225 | *ptree = tree; | 295 | *ptree = tree; |
@@ -237,7 +307,32 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, | |||
237 | 307 | ||
238 | } | 308 | } |
239 | 309 | ||
240 | /* This corresponds to RFC3280 XXXX XXXXX: | 310 | static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, |
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): | ||
241 | * link any data from CertificatePolicies onto matching parent | 336 | * link any data from CertificatePolicies onto matching parent |
242 | * or anyPolicy if no match. | 337 | * or anyPolicy if no match. |
243 | */ | 338 | */ |
@@ -248,7 +343,6 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, | |||
248 | int i; | 343 | int i; |
249 | X509_POLICY_LEVEL *last; | 344 | X509_POLICY_LEVEL *last; |
250 | X509_POLICY_DATA *data; | 345 | X509_POLICY_DATA *data; |
251 | X509_POLICY_NODE *parent; | ||
252 | last = curr - 1; | 346 | last = curr - 1; |
253 | for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) | 347 | for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) |
254 | { | 348 | { |
@@ -261,40 +355,109 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, | |||
261 | * link because then it will have the mapping flags | 355 | * link because then it will have the mapping flags |
262 | * right and we can prune it later. | 356 | * right and we can prune it later. |
263 | */ | 357 | */ |
358 | #if 0 | ||
264 | if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) | 359 | if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) |
265 | && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) | 360 | && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) |
266 | continue; | 361 | continue; |
267 | /* Look for matching node in parent */ | 362 | #endif |
268 | parent = level_find_node(last, data->valid_policy); | 363 | /* Look for matching nodes in previous level */ |
269 | /* If no match link to anyPolicy */ | 364 | if (!tree_link_matching_nodes(curr, data)) |
270 | if (!parent) | ||
271 | parent = last->anyPolicy; | ||
272 | if (parent && !level_add_node(curr, data, parent, NULL)) | ||
273 | return 0; | 365 | return 0; |
274 | } | 366 | } |
275 | return 1; | 367 | return 1; |
276 | } | 368 | } |
277 | 369 | ||
278 | /* This corresponds to RFC3280 XXXX XXXXX: | 370 | /* This corresponds to RFC3280 6.1.3(d)(2): |
279 | * Create new data for any unmatched policies in the parent and link | 371 | * Create new data for any unmatched policies in the parent and link |
280 | * to anyPolicy. | 372 | * to anyPolicy. |
281 | */ | 373 | */ |
282 | 374 | ||
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 | |||
283 | static int tree_link_any(X509_POLICY_LEVEL *curr, | 443 | static int tree_link_any(X509_POLICY_LEVEL *curr, |
284 | const X509_POLICY_CACHE *cache, | 444 | const X509_POLICY_CACHE *cache, |
285 | X509_POLICY_TREE *tree) | 445 | X509_POLICY_TREE *tree) |
286 | { | 446 | { |
287 | int i; | 447 | int i; |
288 | X509_POLICY_DATA *data; | 448 | /*X509_POLICY_DATA *data;*/ |
289 | X509_POLICY_NODE *node; | 449 | X509_POLICY_NODE *node; |
290 | X509_POLICY_LEVEL *last; | 450 | X509_POLICY_LEVEL *last = curr - 1; |
291 | |||
292 | last = curr - 1; | ||
293 | 451 | ||
294 | for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) | 452 | for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) |
295 | { | 453 | { |
296 | node = sk_X509_POLICY_NODE_value(last->nodes, i); | 454 | node = sk_X509_POLICY_NODE_value(last->nodes, i); |
297 | 455 | ||
456 | if (!tree_link_unmatched(curr, cache, node, tree)) | ||
457 | return 0; | ||
458 | |||
459 | #if 0 | ||
460 | |||
298 | /* Skip any node with any children: we only want unmathced | 461 | /* Skip any node with any children: we only want unmathced |
299 | * nodes. | 462 | * nodes. |
300 | * | 463 | * |
@@ -303,6 +466,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, | |||
303 | */ | 466 | */ |
304 | if (node->nchild) | 467 | if (node->nchild) |
305 | continue; | 468 | continue; |
469 | |||
306 | /* Create a new node with qualifiers from anyPolicy and | 470 | /* Create a new node with qualifiers from anyPolicy and |
307 | * id from unmatched node. | 471 | * id from unmatched node. |
308 | */ | 472 | */ |
@@ -319,6 +483,9 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, | |||
319 | policy_data_free(data); | 483 | policy_data_free(data); |
320 | return 0; | 484 | return 0; |
321 | } | 485 | } |
486 | |||
487 | #endif | ||
488 | |||
322 | } | 489 | } |
323 | /* Finally add link to anyPolicy */ | 490 | /* Finally add link to anyPolicy */ |
324 | if (last->anyPolicy) | 491 | if (last->anyPolicy) |
@@ -337,30 +504,36 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, | |||
337 | 504 | ||
338 | static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) | 505 | static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) |
339 | { | 506 | { |
507 | STACK_OF(X509_POLICY_NODE) *nodes; | ||
340 | X509_POLICY_NODE *node; | 508 | X509_POLICY_NODE *node; |
341 | int i; | 509 | int i; |
342 | for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--) | 510 | nodes = curr->nodes; |
511 | if (curr->flags & X509_V_FLAG_INHIBIT_MAP) | ||
343 | { | 512 | { |
344 | node = sk_X509_POLICY_NODE_value(curr->nodes, i); | 513 | for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) |
345 | /* Delete any mapped data: see RFC3280 XXXX */ | ||
346 | if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) | ||
347 | { | 514 | { |
348 | node->parent->nchild--; | 515 | node = sk_X509_POLICY_NODE_value(nodes, i); |
349 | OPENSSL_free(node); | 516 | /* Delete any mapped data: see RFC3280 XXXX */ |
350 | (void)sk_X509_POLICY_NODE_delete(curr->nodes, i); | 517 | if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) |
518 | { | ||
519 | node->parent->nchild--; | ||
520 | OPENSSL_free(node); | ||
521 | (void)sk_X509_POLICY_NODE_delete(nodes,i); | ||
522 | } | ||
351 | } | 523 | } |
352 | } | 524 | } |
353 | 525 | ||
354 | for(;;) { | 526 | for(;;) { |
355 | --curr; | 527 | --curr; |
356 | for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--) | 528 | nodes = curr->nodes; |
529 | for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) | ||
357 | { | 530 | { |
358 | node = sk_X509_POLICY_NODE_value(curr->nodes, i); | 531 | node = sk_X509_POLICY_NODE_value(nodes, i); |
359 | if (node->nchild == 0) | 532 | if (node->nchild == 0) |
360 | { | 533 | { |
361 | node->parent->nchild--; | 534 | node->parent->nchild--; |
362 | OPENSSL_free(node); | 535 | OPENSSL_free(node); |
363 | (void)sk_X509_POLICY_NODE_delete(curr->nodes, i); | 536 | (void)sk_X509_POLICY_NODE_delete(nodes, i); |
364 | } | 537 | } |
365 | } | 538 | } |
366 | if (curr->anyPolicy && !curr->anyPolicy->nchild) | 539 | if (curr->anyPolicy && !curr->anyPolicy->nchild) |
@@ -536,6 +709,7 @@ static int tree_evaluate(X509_POLICY_TREE *tree) | |||
536 | if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) | 709 | if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) |
537 | && !tree_link_any(curr, cache, tree)) | 710 | && !tree_link_any(curr, cache, tree)) |
538 | return 0; | 711 | return 0; |
712 | tree_print("before tree_prune()", tree, curr); | ||
539 | ret = tree_prune(tree, curr); | 713 | ret = tree_prune(tree, curr); |
540 | if (ret != 1) | 714 | if (ret != 1) |
541 | return ret; | 715 | return ret; |
@@ -604,7 +778,6 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, | |||
604 | *pexplicit_policy = 0; | 778 | *pexplicit_policy = 0; |
605 | ret = tree_init(&tree, certs, flags); | 779 | ret = tree_init(&tree, certs, flags); |
606 | 780 | ||
607 | |||
608 | switch (ret) | 781 | switch (ret) |
609 | { | 782 | { |
610 | 783 | ||
@@ -613,6 +786,10 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, | |||
613 | return 1; | 786 | return 1; |
614 | 787 | ||
615 | /* Some internal error */ | 788 | /* Some internal error */ |
789 | case -1: | ||
790 | return -1; | ||
791 | |||
792 | /* Some internal error */ | ||
616 | case 0: | 793 | case 0: |
617 | return 0; | 794 | return 0; |
618 | 795 | ||
@@ -646,6 +823,8 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, | |||
646 | if (!tree) goto error; | 823 | if (!tree) goto error; |
647 | ret = tree_evaluate(tree); | 824 | ret = tree_evaluate(tree); |
648 | 825 | ||
826 | tree_print("tree_evaluate()", tree, NULL); | ||
827 | |||
649 | if (ret <= 0) | 828 | if (ret <= 0) |
650 | goto error; | 829 | goto error; |
651 | 830 | ||