Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/x509/pcy_tree.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: pcy_tree.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 2004.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
#include <openssl/x509.h>
60
#include <openssl/x509v3.h>
61
62
#include "pcy_int.h"
63
#include "x509_lcl.h"
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
74
expected_print(BIO *err, X509_POLICY_LEVEL *lev, X509_POLICY_NODE *node,
75
    int indent)
76
{
77
  if ((lev->flags & X509_V_FLAG_INHIBIT_MAP) ||
78
      !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
79
    BIO_puts(err, "  Not Mapped\n");
80
  else {
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
      oid = sk_ASN1_OBJECT_value(pset, i);
87
      if (i)
88
        BIO_puts(err, ", ");
89
      i2a_ASN1_OBJECT(err, oid);
90
    }
91
    BIO_puts(err, "\n");
92
  }
93
}
94
95
static void
96
tree_print(char *str, X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
97
{
98
  X509_POLICY_LEVEL *plev;
99
  X509_POLICY_NODE *node;
100
  int i;
101
  BIO *err;
102
103
  if ((err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL)
104
    return;
105
106
  if (!curr)
107
    curr = tree->levels + tree->nlevel;
108
  else
109
    curr++;
110
  BIO_printf(err, "Level print after %s\n", str);
111
  BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
112
  for (plev = tree->levels; plev != curr; plev++) {
113
    BIO_printf(err, "Level %ld, flags = %x\n",
114
        plev - tree->levels, plev->flags);
115
    for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
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
#else
128
129
#define tree_print(a,b,c) /* */
130
131
#endif
132
133
/* Initialize policy tree. Return values:
134
 *  0 Some internal error occured.
135
 * -1 Inconsistent or invalid extensions in certificates.
136
 *  1 Tree initialized OK.
137
 *  2 Policy tree is empty.
138
 *  5 Tree OK and requireExplicitPolicy true.
139
 *  6 Tree empty and requireExplicitPolicy true.
140
 */
141
142
static int
143
tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, unsigned int flags)
144
0
{
145
0
  X509_POLICY_TREE *tree;
146
0
  X509_POLICY_LEVEL *level;
147
0
  const X509_POLICY_CACHE *cache;
148
0
  X509_POLICY_DATA *data = NULL;
149
0
  X509 *x;
150
0
  int ret = 1;
151
0
  int i, n;
152
0
  int explicit_policy;
153
0
  int any_skip;
154
0
  int map_skip;
155
156
0
  *ptree = NULL;
157
0
  n = sk_X509_num(certs);
158
159
0
  if (flags & X509_V_FLAG_EXPLICIT_POLICY)
160
0
    explicit_policy = 0;
161
0
  else
162
0
    explicit_policy = n + 1;
163
164
0
  if (flags & X509_V_FLAG_INHIBIT_ANY)
165
0
    any_skip = 0;
166
0
  else
167
0
    any_skip = n + 1;
168
169
0
  if (flags & X509_V_FLAG_INHIBIT_MAP)
170
0
    map_skip = 0;
171
0
  else
172
0
    map_skip = n + 1;
173
174
  /* Can't do anything with just a trust anchor */
175
0
  if (n == 1)
176
0
    return 1;
177
  /* First setup policy cache in all certificates apart from the
178
   * trust anchor. Note any bad cache results on the way. Also can
179
   * calculate explicit_policy value at this point.
180
   */
181
0
  for (i = n - 2; i >= 0; i--) {
182
0
    x = sk_X509_value(certs, i);
183
0
    X509_check_purpose(x, -1, -1);
184
0
    cache = policy_cache_set(x);
185
    /* If cache NULL something bad happened: return immediately */
186
0
    if (cache == NULL)
187
0
      return 0;
188
    /* If inconsistent extensions keep a note of it but continue */
189
0
    if (x->ex_flags & EXFLAG_INVALID_POLICY)
190
0
      ret = -1;
191
    /* Otherwise if we have no data (hence no CertificatePolicies)
192
     * and haven't already set an inconsistent code note it.
193
     */
194
0
    else if ((ret == 1) && !cache->data)
195
0
      ret = 2;
196
0
    if (explicit_policy > 0) {
197
0
      if (!(x->ex_flags & EXFLAG_SI))
198
0
        explicit_policy--;
199
0
      if ((cache->explicit_skip != -1) &&
200
0
          (cache->explicit_skip < explicit_policy))
201
0
        explicit_policy = cache->explicit_skip;
202
0
    }
203
0
  }
204
205
0
  if (ret != 1) {
206
0
    if (ret == 2 && !explicit_policy)
207
0
      return 6;
208
0
    return ret;
209
0
  }
210
211
212
  /* If we get this far initialize the tree */
213
214
0
  tree = malloc(sizeof(X509_POLICY_TREE));
215
216
0
  if (!tree)
217
0
    return 0;
218
219
0
  tree->flags = 0;
220
0
  tree->levels = calloc(n, sizeof(X509_POLICY_LEVEL));
221
0
  tree->nlevel = 0;
222
0
  tree->extra_data = NULL;
223
0
  tree->auth_policies = NULL;
224
0
  tree->user_policies = NULL;
225
226
0
  if (!tree->levels) {
227
0
    free(tree);
228
0
    return 0;
229
0
  }
230
231
0
  tree->nlevel = n;
232
233
0
  level = tree->levels;
234
235
  /* Root data: initialize to anyPolicy */
236
237
0
  data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
238
239
0
  if (!data || !level_add_node(level, data, NULL, tree, NULL))
240
0
    goto bad_tree;
241
242
0
  for (i = n - 2; i >= 0; i--) {
243
0
    level++;
244
0
    x = sk_X509_value(certs, i);
245
0
    cache = policy_cache_set(x);
246
0
    CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
247
0
    level->cert = x;
248
249
0
    if (!cache->anyPolicy)
250
0
      level->flags |= X509_V_FLAG_INHIBIT_ANY;
251
252
    /* Determine inhibit any and inhibit map flags */
253
0
    if (any_skip == 0) {
254
      /* Any matching allowed if certificate is self
255
       * issued and not the last in the chain.
256
       */
257
0
      if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
258
0
        level->flags |= X509_V_FLAG_INHIBIT_ANY;
259
0
    } else {
260
0
      if (!(x->ex_flags & EXFLAG_SI))
261
0
        any_skip--;
262
0
      if ((cache->any_skip >= 0) &&
263
0
          (cache->any_skip < any_skip))
264
0
        any_skip = cache->any_skip;
265
0
    }
266
267
0
    if (map_skip == 0)
268
0
      level->flags |= X509_V_FLAG_INHIBIT_MAP;
269
0
    else {
270
0
      if (!(x->ex_flags & EXFLAG_SI))
271
0
        map_skip--;
272
0
      if ((cache->map_skip >= 0) &&
273
0
          (cache->map_skip < map_skip))
274
0
        map_skip = cache->map_skip;
275
0
    }
276
277
0
  }
278
279
0
  *ptree = tree;
280
281
0
  if (explicit_policy)
282
0
    return 1;
283
0
  else
284
0
    return 5;
285
286
0
bad_tree:
287
0
  X509_policy_tree_free(tree);
288
289
0
  return 0;
290
0
}
291
292
static int
293
tree_link_matching_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_DATA *data)
294
0
{
295
0
  X509_POLICY_LEVEL *last = curr - 1;
296
0
  X509_POLICY_NODE *node;
297
0
  int i, matched = 0;
298
299
  /* Iterate through all in nodes linking matches */
300
0
  for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
301
0
    node = sk_X509_POLICY_NODE_value(last->nodes, i);
302
0
    if (policy_node_match(last, node, data->valid_policy)) {
303
0
      if (!level_add_node(curr, data, node, NULL, NULL))
304
0
        return 0;
305
0
      matched = 1;
306
0
    }
307
0
  }
308
0
  if (!matched && last->anyPolicy) {
309
0
    if (!level_add_node(curr, data, last->anyPolicy, NULL, NULL))
310
0
      return 0;
311
0
  }
312
0
  return 1;
313
0
}
314
315
/* This corresponds to RFC3280 6.1.3(d)(1):
316
 * link any data from CertificatePolicies onto matching parent
317
 * or anyPolicy if no match.
318
 */
319
320
static int
321
tree_link_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache)
322
0
{
323
0
  int i;
324
0
  X509_POLICY_DATA *data;
325
326
0
  for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
327
0
    data = sk_X509_POLICY_DATA_value(cache->data, i);
328
    /* Look for matching nodes in previous level */
329
0
    if (!tree_link_matching_nodes(curr, data))
330
0
      return 0;
331
0
  }
332
0
  return 1;
333
0
}
334
335
/* This corresponds to RFC3280 6.1.3(d)(2):
336
 * Create new data for any unmatched policies in the parent and link
337
 * to anyPolicy.
338
 */
339
340
static int
341
tree_add_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
342
    const ASN1_OBJECT *id, X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
343
0
{
344
0
  X509_POLICY_DATA *data;
345
346
0
  if (id == NULL)
347
0
    id = node->data->valid_policy;
348
  /* Create a new node with qualifiers from anyPolicy and
349
   * id from unmatched node.
350
   */
351
0
  data = policy_data_new(NULL, id, node_critical(node));
352
353
0
  if (data == NULL)
354
0
    return 0;
355
  /* Curr may not have anyPolicy */
356
0
  data->qualifier_set = cache->anyPolicy->qualifier_set;
357
0
  data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
358
0
  if (!level_add_node(curr, data, node, tree, NULL)) {
359
0
    policy_data_free(data);
360
0
    return 0;
361
0
  }
362
363
0
  return 1;
364
0
}
365
366
static int
367
tree_link_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
368
    X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
369
0
{
370
0
  const X509_POLICY_LEVEL *last = curr - 1;
371
0
  int i;
372
373
0
  if ((last->flags & X509_V_FLAG_INHIBIT_MAP) ||
374
0
      !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
375
    /* If no policy mapping: matched if one child present */
376
0
    if (node->nchild)
377
0
      return 1;
378
0
    if (!tree_add_unmatched(curr, cache, NULL, node, tree))
379
0
      return 0;
380
    /* Add it */
381
0
  } else {
382
    /* If mapping: matched if one child per expected policy set */
383
0
    STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
384
0
    if (node->nchild == sk_ASN1_OBJECT_num(expset))
385
0
      return 1;
386
    /* Locate unmatched nodes */
387
0
    for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
388
0
      ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
389
0
      if (level_find_node(curr, node, oid))
390
0
        continue;
391
0
      if (!tree_add_unmatched(curr, cache, oid, node, tree))
392
0
        return 0;
393
0
    }
394
0
  }
395
396
0
  return 1;
397
0
}
398
399
static int
400
tree_link_any(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
401
    X509_POLICY_TREE *tree)
402
0
{
403
0
  int i;
404
0
  X509_POLICY_NODE *node;
405
0
  X509_POLICY_LEVEL *last = curr - 1;
406
407
0
  for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
408
0
    node = sk_X509_POLICY_NODE_value(last->nodes, i);
409
410
0
    if (!tree_link_unmatched(curr, cache, node, tree))
411
0
      return 0;
412
0
  }
413
  /* Finally add link to anyPolicy */
414
0
  if (last->anyPolicy) {
415
0
    if (!level_add_node(curr, cache->anyPolicy,
416
0
        last->anyPolicy, NULL, NULL))
417
0
      return 0;
418
0
  }
419
0
  return 1;
420
0
}
421
422
/* Prune the tree: delete any child mapped child data on the current level
423
 * then proceed up the tree deleting any data with no children. If we ever
424
 * have no data on a level we can halt because the tree will be empty.
425
 */
426
427
static int
428
tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
429
0
{
430
0
  STACK_OF(X509_POLICY_NODE) *nodes;
431
0
  X509_POLICY_NODE *node;
432
0
  int i;
433
434
0
  nodes = curr->nodes;
435
0
  if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
436
0
    for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
437
0
      node = sk_X509_POLICY_NODE_value(nodes, i);
438
      /* Delete any mapped data: see RFC3280 XXXX */
439
0
      if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
440
0
        node->parent->nchild--;
441
0
        free(node);
442
0
        (void)sk_X509_POLICY_NODE_delete(nodes, i);
443
0
      }
444
0
    }
445
0
  }
446
447
0
  for (;;) {
448
0
    --curr;
449
0
    nodes = curr->nodes;
450
0
    for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
451
0
      node = sk_X509_POLICY_NODE_value(nodes, i);
452
0
      if (node->nchild == 0) {
453
0
        node->parent->nchild--;
454
0
        free(node);
455
0
        (void)sk_X509_POLICY_NODE_delete(nodes, i);
456
0
      }
457
0
    }
458
0
    if (curr->anyPolicy && !curr->anyPolicy->nchild) {
459
0
      if (curr->anyPolicy->parent)
460
0
        curr->anyPolicy->parent->nchild--;
461
0
      free(curr->anyPolicy);
462
0
      curr->anyPolicy = NULL;
463
0
    }
464
0
    if (curr == tree->levels) {
465
      /* If we zapped anyPolicy at top then tree is empty */
466
0
      if (!curr->anyPolicy)
467
0
        return 2;
468
0
      return 1;
469
0
    }
470
0
  }
471
472
0
  return 1;
473
0
}
474
475
static int
476
tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, X509_POLICY_NODE *pcy)
477
0
{
478
0
  if (!*pnodes) {
479
0
    *pnodes = policy_node_cmp_new();
480
0
    if (!*pnodes)
481
0
      return 0;
482
0
  } else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
483
0
    return 1;
484
485
0
  if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
486
0
    return 0;
487
488
0
  return 1;
489
0
}
490
491
/* Calculate the authority set based on policy tree.
492
 * The 'pnodes' parameter is used as a store for the set of policy nodes
493
 * used to calculate the user set. If the authority set is not anyPolicy
494
 * then pnodes will just point to the authority set. If however the authority
495
 * set is anyPolicy then the set of valid policies (other than anyPolicy)
496
 * is store in pnodes. The return value of '2' is used in this case to indicate
497
 * that pnodes should be freed.
498
 */
499
500
static int
501
tree_calculate_authority_set(X509_POLICY_TREE *tree,
502
    STACK_OF(X509_POLICY_NODE) **pnodes)
503
0
{
504
0
  X509_POLICY_LEVEL *curr;
505
0
  X509_POLICY_NODE *node, *anyptr;
506
0
  STACK_OF(X509_POLICY_NODE) **addnodes;
507
0
  int i, j;
508
509
0
  curr = tree->levels + tree->nlevel - 1;
510
511
  /* If last level contains anyPolicy set is anyPolicy */
512
0
  if (curr->anyPolicy) {
513
0
    if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
514
0
      return 0;
515
0
    addnodes = pnodes;
516
0
  } else
517
    /* Add policies to authority set */
518
0
    addnodes = &tree->auth_policies;
519
520
0
  curr = tree->levels;
521
0
  for (i = 1; i < tree->nlevel; i++) {
522
    /* If no anyPolicy node on this this level it can't
523
     * appear on lower levels so end search.
524
     */
525
0
    if (!(anyptr = curr->anyPolicy))
526
0
      break;
527
0
    curr++;
528
0
    for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
529
0
      node = sk_X509_POLICY_NODE_value(curr->nodes, j);
530
0
      if ((node->parent == anyptr) &&
531
0
          !tree_add_auth_node(addnodes, node))
532
0
        return 0;
533
0
    }
534
0
  }
535
536
0
  if (addnodes == pnodes)
537
0
    return 2;
538
539
0
  *pnodes = tree->auth_policies;
540
541
0
  return 1;
542
0
}
543
544
static int
545
tree_calculate_user_set(X509_POLICY_TREE *tree,
546
    STACK_OF(ASN1_OBJECT) *policy_oids, STACK_OF(X509_POLICY_NODE) *auth_nodes)
547
0
{
548
0
  int i;
549
0
  X509_POLICY_NODE *node;
550
0
  ASN1_OBJECT *oid;
551
0
  X509_POLICY_NODE *anyPolicy;
552
0
  X509_POLICY_DATA *extra;
553
554
  /* Check if anyPolicy present in authority constrained policy set:
555
   * this will happen if it is a leaf node.
556
   */
557
558
0
  if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
559
0
    return 1;
560
561
0
  anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
562
563
0
  for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
564
0
    oid = sk_ASN1_OBJECT_value(policy_oids, i);
565
0
    if (OBJ_obj2nid(oid) == NID_any_policy) {
566
0
      tree->flags |= POLICY_FLAG_ANY_POLICY;
567
0
      return 1;
568
0
    }
569
0
  }
570
571
0
  for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
572
0
    oid = sk_ASN1_OBJECT_value(policy_oids, i);
573
0
    node = tree_find_sk(auth_nodes, oid);
574
0
    if (!node) {
575
0
      if (!anyPolicy)
576
0
        continue;
577
      /* Create a new node with policy ID from user set
578
       * and qualifiers from anyPolicy.
579
       */
580
0
      extra = policy_data_new(NULL, oid,
581
0
          node_critical(anyPolicy));
582
0
      if (!extra)
583
0
        return 0;
584
0
      extra->qualifier_set = anyPolicy->data->qualifier_set;
585
0
      extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS |
586
0
          POLICY_DATA_FLAG_EXTRA_NODE;
587
0
      (void) level_add_node(NULL, extra, anyPolicy->parent,
588
0
          tree, &node);
589
0
    }
590
0
    if (!tree->user_policies) {
591
0
      tree->user_policies = sk_X509_POLICY_NODE_new_null();
592
0
      if (!tree->user_policies)
593
0
        return 1;
594
0
    }
595
0
    if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
596
0
      return 0;
597
0
  }
598
0
  return 1;
599
0
}
600
601
static int
602
tree_evaluate(X509_POLICY_TREE *tree)
603
0
{
604
0
  int ret, i;
605
0
  X509_POLICY_LEVEL *curr = tree->levels + 1;
606
0
  const X509_POLICY_CACHE *cache;
607
608
0
  for (i = 1; i < tree->nlevel; i++, curr++) {
609
0
    cache = policy_cache_set(curr->cert);
610
0
    if (!tree_link_nodes(curr, cache))
611
0
      return 0;
612
613
0
    if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) &&
614
0
        !tree_link_any(curr, cache, tree))
615
0
      return 0;
616
0
    tree_print("before tree_prune()", tree, curr);
617
0
    ret = tree_prune(tree, curr);
618
0
    if (ret != 1)
619
0
      return ret;
620
0
  }
621
622
0
  return 1;
623
0
}
624
625
static void
626
exnode_free(X509_POLICY_NODE *node)
627
0
{
628
0
  if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
629
0
    free(node);
630
0
}
631
632
void
633
X509_policy_tree_free(X509_POLICY_TREE *tree)
634
0
{
635
0
  X509_POLICY_LEVEL *curr;
636
0
  int i;
637
638
0
  if (!tree)
639
0
    return;
640
641
0
  sk_X509_POLICY_NODE_free(tree->auth_policies);
642
0
  sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
643
644
0
  for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
645
0
    X509_free(curr->cert);
646
0
    if (curr->nodes)
647
0
      sk_X509_POLICY_NODE_pop_free(curr->nodes,
648
0
        policy_node_free);
649
0
    if (curr->anyPolicy)
650
0
      policy_node_free(curr->anyPolicy);
651
0
  }
652
653
0
  if (tree->extra_data)
654
0
    sk_X509_POLICY_DATA_pop_free(tree->extra_data,
655
0
        policy_data_free);
656
657
0
  free(tree->levels);
658
0
  free(tree);
659
0
}
660
661
/* Application policy checking function.
662
 * Return codes:
663
 *  0   Internal Error.
664
 *  1   Successful.
665
 * -1   One or more certificates contain invalid or inconsistent extensions
666
 * -2 User constrained policy set empty and requireExplicit true.
667
 */
668
669
int
670
X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
671
    STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids,
672
    unsigned int flags)
673
0
{
674
0
  int ret, ret2;
675
0
  X509_POLICY_TREE *tree = NULL;
676
0
  STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
677
678
0
  *ptree = NULL;
679
0
  *pexplicit_policy = 0;
680
0
  ret = tree_init(&tree, certs, flags);
681
682
0
  switch (ret) {
683
684
    /* Tree empty requireExplicit False: OK */
685
0
  case 2:
686
0
    return 1;
687
688
    /* Some internal error */
689
0
  case -1:
690
0
    return -1;
691
692
    /* Some internal error */
693
0
  case 0:
694
0
    return 0;
695
696
    /* Tree empty requireExplicit True: Error */
697
698
0
  case 6:
699
0
    *pexplicit_policy = 1;
700
0
    return -2;
701
702
    /* Tree OK requireExplicit True: OK and continue */
703
0
  case 5:
704
0
    *pexplicit_policy = 1;
705
0
    break;
706
707
    /* Tree OK: continue */
708
709
0
  case 1:
710
0
    if (!tree)
711
      /*
712
       * tree_init() returns success and a null tree
713
       * if it's just looking at a trust anchor.
714
       * I'm not sure that returning success here is
715
       * correct, but I'm sure that reporting this
716
       * as an internal error which our caller
717
       * interprets as a malloc failure is wrong.
718
       */
719
0
      return 1;
720
0
    break;
721
0
  }
722
723
0
  if (!tree)
724
0
    goto error;
725
0
  ret = tree_evaluate(tree);
726
727
0
  tree_print("tree_evaluate()", tree, NULL);
728
729
0
  if (ret <= 0)
730
0
    goto error;
731
732
  /* Return value 2 means tree empty */
733
0
  if (ret == 2) {
734
0
    X509_policy_tree_free(tree);
735
0
    if (*pexplicit_policy)
736
0
      return -2;
737
0
    else
738
0
      return 1;
739
0
  }
740
741
  /* Tree is not empty: continue */
742
743
0
  ret = tree_calculate_authority_set(tree, &auth_nodes);
744
0
  if (ret == 0)
745
0
    goto error;
746
747
0
  ret2 = tree_calculate_user_set(tree, policy_oids, auth_nodes);
748
749
  /* Return value 2 means auth_nodes needs to be freed */
750
0
  if (ret == 2)
751
0
    sk_X509_POLICY_NODE_free(auth_nodes);
752
753
0
  if (ret2 == 0)
754
0
    goto error;
755
756
0
  if (tree)
757
0
    *ptree = tree;
758
759
0
  if (*pexplicit_policy) {
760
0
    nodes = X509_policy_tree_get0_user_policies(tree);
761
0
    if (sk_X509_POLICY_NODE_num(nodes) <= 0)
762
0
      return -2;
763
0
  }
764
765
0
  return 1;
766
767
0
error:
768
0
  X509_policy_tree_free(tree);
769
770
0
  return 0;
771
0
}