summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509v3/pcy_tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509v3/pcy_tree.c')
-rw-r--r--src/lib/libcrypto/x509v3/pcy_tree.c235
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
73static 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
96static 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: 310static 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
375static 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
403static 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
283static int tree_link_any(X509_POLICY_LEVEL *curr, 443static 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
338static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) 505static 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