You need to sign in or sign up before continuing.
pcy_tree.c 22.5 KB
Newer Older
1
/*
M
Matt Caswell 已提交
2
 * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9
 */

10
#include "internal/cryptlib.h"
11 12 13
#include <openssl/x509.h>
#include <openssl/x509v3.h>

14
#include "pcy_local.h"
15

16 17 18 19 20 21 22 23 24 25 26 27
/*
 * If the maximum number of nodes in the policy tree isn't defined, set it to
 * a generous default of 1000 nodes.
 *
 * Defining this to be zero means unlimited policy tree growth which opens the
 * door on CVE-2023-0464.
 */

#ifndef OPENSSL_POLICY_TREE_NODES_MAX
# define OPENSSL_POLICY_TREE_NODES_MAX 1000
#endif

28 29
/*
 * Enable this to print out the complete policy tree at various point during
30 31 32
 * evaluation.
 */

33 34 35
/*
 * #define OPENSSL_POLICY_DEBUG
 */
36 37 38 39

#ifdef OPENSSL_POLICY_DEBUG

static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
                           X509_POLICY_NODE *node, int indent)
{
    if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
        || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
        BIO_puts(err, "  Not Mapped\n");
    else {
        int i;
        STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
        ASN1_OBJECT *oid;
        BIO_puts(err, "  Expected: ");
        for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
            oid = sk_ASN1_OBJECT_value(pset, i);
            if (i)
                BIO_puts(err, ", ");
            i2a_ASN1_OBJECT(err, oid);
        }
        BIO_puts(err, "\n");
    }
}
59 60

static void tree_print(char *str, X509_POLICY_TREE *tree,
61 62
                       X509_POLICY_LEVEL *curr)
{
63
    BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE);
64
    X509_POLICY_LEVEL *plev;
65

66 67 68 69 70 71
    if (err == NULL)
        return;
    if (!curr)
        curr = tree->levels + tree->nlevel;
    else
        curr++;
72

73 74 75
    BIO_printf(err, "Level print after %s\n", str);
    BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
    for (plev = tree->levels; plev != curr; plev++) {
76 77
        int i;

78
        BIO_printf(err, "Level %ld, flags = %x\n",
79
                   (long)(plev - tree->levels), plev->flags);
80
        for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
81 82
            X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(plev->nodes, i);

83 84 85 86 87 88 89 90 91
            X509_POLICY_NODE_print(err, node, 2);
            expected_print(err, plev, node, 2);
            BIO_printf(err, "  Flags: %x\n", node->data->flags);
        }
        if (plev->anyPolicy)
            X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
    }
    BIO_free(err);
}
92 93
#endif

94
/*-
95 96 97 98 99
 * Return value: <= 0 on error, or positive bit mask:
 *
 * X509_PCY_TREE_VALID: valid tree
 * X509_PCY_TREE_EMPTY: empty tree (including bare TA case)
 * X509_PCY_TREE_EXPLICIT: explicit policy required
100 101
 */
static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
102 103 104 105 106 107
                     unsigned int flags)
{
    X509_POLICY_TREE *tree;
    X509_POLICY_LEVEL *level;
    const X509_POLICY_CACHE *cache;
    X509_POLICY_DATA *data = NULL;
108 109 110 111 112 113
    int ret = X509_PCY_TREE_VALID;
    int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */
    int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1;
    int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1;
    int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1;
    int i;
114

115
    *ptree = NULL;
116

117 118 119
    /* Can't do anything with just a trust anchor */
    if (n == 0)
        return X509_PCY_TREE_EMPTY;
120

121 122 123 124 125 126 127
    /*
     * First setup the policy cache in all n non-TA certificates, this will be
     * used in X509_verify_cert() which will invoke the verify callback for all
     * certificates with invalid policy extensions.
     */
    for (i = n - 1; i >= 0; i--) {
        X509 *x = sk_X509_value(certs, i);
128

129 130 131 132
        /* Call for side-effect of computing hash and caching extensions */
        X509_check_purpose(x, -1, 0);

        /* If cache is NULL, likely ENOMEM: return immediately */
133
        if (policy_cache_set(x) == NULL)
134 135
            return X509_PCY_TREE_INTERNAL;
    }
136 137

    /*
138 139 140 141 142 143
     * At this point check for invalid policies and required explicit policy.
     * Note that the explicit_policy counter is a count-down to zero, with the
     * requirement kicking in if and once it does that.  The counter is
     * decremented for every non-self-issued certificate in the path, but may
     * be further reduced by policy constraints in a non-leaf certificate.
     *
144
     * The ultimate policy set is the intersection of all the policies along
145 146
     * the path, if we hit a certificate with an empty policy set, and explicit
     * policy is required we're done.
147
     */
148 149 150 151 152
    for (i = n - 1;
         i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0);
         i--) {
        X509 *x = sk_X509_value(certs, i);
        uint32_t ex_flags = X509_get_extension_flags(x);
V
Viktor Dukhovni 已提交
153

154
        /* All the policies are already cached, we can return early */
155
        if (ex_flags & EXFLAG_INVALID_POLICY)
156 157 158 159 160 161 162
            return X509_PCY_TREE_INVALID;

        /* Access the cache which we now know exists */
        cache = policy_cache_set(x);

        if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
            ret = X509_PCY_TREE_EMPTY;
163
        if (explicit_policy > 0) {
164
            if (!(ex_flags & EXFLAG_SI))
165
                explicit_policy--;
166
            if ((cache->explicit_skip >= 0)
167 168 169 170 171
                && (cache->explicit_skip < explicit_policy))
                explicit_policy = cache->explicit_skip;
        }
    }

172 173 174
    if (explicit_policy == 0)
        ret |= X509_PCY_TREE_EXPLICIT;
    if ((ret & X509_PCY_TREE_VALID) == 0)
175 176 177
        return ret;

    /* If we get this far initialize the tree */
178 179
    if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
        X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
180
        return X509_PCY_TREE_INTERNAL;
181
    }
182

183 184 185
    /* Limit the growth of the tree to mitigate CVE-2023-0464 */
    tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;

186 187 188 189 190 191 192 193
    /*
     * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
     *
     * The top level is implicitly for the trust anchor with valid expected
     * policies of anyPolicy.  (RFC 5280 has the TA at depth 0 and the leaf at
     * depth n, we have the leaf at depth 0 and the TA at depth n).
     */
    if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
194
        OPENSSL_free(tree);
195
        X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
196
        return X509_PCY_TREE_INTERNAL;
197
    }
198
    tree->nlevel = n+1;
199
    level = tree->levels;
200
    if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL)
201
        goto bad_tree;
202
    if (level_add_node(level, data, NULL, tree, 1) == NULL) {
203 204 205
        policy_data_free(data);
        goto bad_tree;
    }
206

207 208 209 210 211 212 213 214 215
    /*
     * In this pass initialize all the tree levels and whether anyPolicy and
     * policy mapping are inhibited at each level.
     */
    for (i = n - 1; i >= 0; i--) {
        X509 *x = sk_X509_value(certs, i);
        uint32_t ex_flags = X509_get_extension_flags(x);

        /* Access the cache which we now know exists */
216
        cache = policy_cache_set(x);
217

D
Dr. Stephen Henson 已提交
218
        X509_up_ref(x);
219
        (++level)->cert = x;
220 221 222 223 224 225 226

        if (!cache->anyPolicy)
            level->flags |= X509_V_FLAG_INHIBIT_ANY;

        /* Determine inhibit any and inhibit map flags */
        if (any_skip == 0) {
            /*
227 228
             * Any matching allowed only if certificate is self issued and not
             * the last in the chain.
229
             */
230
            if (!(ex_flags & EXFLAG_SI) || (i == 0))
231 232
                level->flags |= X509_V_FLAG_INHIBIT_ANY;
        } else {
233
            if (!(ex_flags & EXFLAG_SI))
234
                any_skip--;
235
            if ((cache->any_skip >= 0) && (cache->any_skip < any_skip))
236 237 238 239 240 241
                any_skip = cache->any_skip;
        }

        if (map_skip == 0)
            level->flags |= X509_V_FLAG_INHIBIT_MAP;
        else {
242
            if (!(ex_flags & EXFLAG_SI))
243
                map_skip--;
244
            if ((cache->map_skip >= 0) && (cache->map_skip < map_skip))
245 246 247 248 249
                map_skip = cache->map_skip;
        }
    }

    *ptree = tree;
250
    return ret;
251 252 253

 bad_tree:
    X509_policy_tree_free(tree);
254
    return X509_PCY_TREE_INTERNAL;
255
}
256

257 258 259
/*
 * Return value: 1 on success, 0 otherwise
 */
260
static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
261 262
                                    X509_POLICY_DATA *data,
                                    X509_POLICY_TREE *tree)
263 264 265
{
    X509_POLICY_LEVEL *last = curr - 1;
    int i, matched = 0;
266

267 268
    /* Iterate through all in nodes linking matches */
    for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
269 270
        X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);

271
        if (policy_node_match(last, node, data->valid_policy)) {
272
            if (level_add_node(curr, data, node, tree, 0) == NULL)
273 274 275 276 277
                return 0;
            matched = 1;
        }
    }
    if (!matched && last->anyPolicy) {
278
        if (level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL)
279 280 281 282 283 284 285 286
            return 0;
    }
    return 1;
}

/*
 * This corresponds to RFC3280 6.1.3(d)(1): link any data from
 * CertificatePolicies onto matching parent or anyPolicy if no match.
287 288
 *
 * Return value: 1 on success, 0 otherwise.
289 290
 */
static int tree_link_nodes(X509_POLICY_LEVEL *curr,
291 292
                           const X509_POLICY_CACHE *cache,
                           X509_POLICY_TREE *tree)
293 294 295 296
{
    int i;

    for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
297 298
        X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);

299
        /* Look for matching nodes in previous level */
300
        if (!tree_link_matching_nodes(curr, data, tree))
301 302 303 304 305 306 307 308
            return 0;
    }
    return 1;
}

/*
 * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
 * policies in the parent and link to anyPolicy.
309 310
 *
 * Return value: 1 on success, 0 otherwise.
311
 */
312
static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
313 314 315 316 317
                              const X509_POLICY_CACHE *cache,
                              const ASN1_OBJECT *id,
                              X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
{
    X509_POLICY_DATA *data;
318

319 320 321 322 323 324
    if (id == NULL)
        id = node->data->valid_policy;
    /*
     * Create a new node with qualifiers from anyPolicy and id from unmatched
     * node.
     */
325
    if ((data = policy_data_new(NULL, id, node_critical(node))) == NULL)
326
        return 0;
327

328 329 330
    /* Curr may not have anyPolicy */
    data->qualifier_set = cache->anyPolicy->qualifier_set;
    data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
331
    if (level_add_node(curr, data, node, tree, 1) == NULL) {
332 333 334 335 336
        policy_data_free(data);
        return 0;
    }
    return 1;
}
337

338 339 340
/*
 * Return value: 1 on success, 0 otherwise.
 */
341
static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
                               const X509_POLICY_CACHE *cache,
                               X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
{
    const X509_POLICY_LEVEL *last = curr - 1;
    int i;

    if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
        || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
        /* If no policy mapping: matched if one child present */
        if (node->nchild)
            return 1;
        if (!tree_add_unmatched(curr, cache, NULL, node, tree))
            return 0;
        /* Add it */
    } else {
        /* If mapping: matched if one child per expected policy set */
        STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
        if (node->nchild == sk_ASN1_OBJECT_num(expset))
            return 1;
        /* Locate unmatched nodes */
        for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
            ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
            if (level_find_node(curr, node, oid))
                continue;
            if (!tree_add_unmatched(curr, cache, oid, node, tree))
                return 0;
        }

    }
    return 1;
}
373

374 375 376
/*
 * Return value: 1 on success, 0 otherwise
 */
377
static int tree_link_any(X509_POLICY_LEVEL *curr,
378 379 380 381 382 383 384 385 386 387 388 389 390 391
                         const X509_POLICY_CACHE *cache,
                         X509_POLICY_TREE *tree)
{
    int i;
    X509_POLICY_NODE *node;
    X509_POLICY_LEVEL *last = curr - 1;

    for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
        node = sk_X509_POLICY_NODE_value(last->nodes, i);

        if (!tree_link_unmatched(curr, cache, node, tree))
            return 0;
    }
    /* Finally add link to anyPolicy */
392
    if (last->anyPolicy &&
393
        level_add_node(curr, cache->anyPolicy, last->anyPolicy, tree, 0) == NULL)
394
        return 0;
395 396 397
    return 1;
}

398 399 400 401 402 403 404 405 406
/*-
 * Prune the tree: delete any child mapped child data on the current level then
 * proceed up the tree deleting any data with no children. If we ever have no
 * data on a level we can halt because the tree will be empty.
 *
 * Return value: <= 0 error, otherwise one of:
 *
 * X509_PCY_TREE_VALID: valid tree
 * X509_PCY_TREE_EMPTY: empty tree
407 408
 */
static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
{
    STACK_OF(X509_POLICY_NODE) *nodes;
    X509_POLICY_NODE *node;
    int i;
    nodes = curr->nodes;
    if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
        for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
            node = sk_X509_POLICY_NODE_value(nodes, i);
            /* Delete any mapped data: see RFC3280 XXXX */
            if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
                node->parent->nchild--;
                OPENSSL_free(node);
                (void)sk_X509_POLICY_NODE_delete(nodes, i);
            }
        }
    }

    for (;;) {
        --curr;
        nodes = curr->nodes;
        for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
            node = sk_X509_POLICY_NODE_value(nodes, i);
            if (node->nchild == 0) {
                node->parent->nchild--;
                OPENSSL_free(node);
                (void)sk_X509_POLICY_NODE_delete(nodes, i);
            }
        }
        if (curr->anyPolicy && !curr->anyPolicy->nchild) {
            if (curr->anyPolicy->parent)
                curr->anyPolicy->parent->nchild--;
            OPENSSL_free(curr->anyPolicy);
            curr->anyPolicy = NULL;
        }
        if (curr == tree->levels) {
            /* If we zapped anyPolicy at top then tree is empty */
            if (!curr->anyPolicy)
446 447
                return X509_PCY_TREE_EMPTY;
            break;
448 449
        }
    }
450
    return X509_PCY_TREE_VALID;
451
}
452

453 454 455
/*
 * Return value: 1 on success, 0 otherwise.
 */
456
static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
457 458
                              X509_POLICY_NODE *pcy)
{
459 460
    if (*pnodes == NULL &&
        (*pnodes = policy_node_cmp_new()) == NULL)
461
        return 0;
462
    if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
463 464
        return 1;
    return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0;
465 466
}

467 468 469
#define TREE_CALC_FAILURE 0
#define TREE_CALC_OK_NOFREE 1
#define TREE_CALC_OK_DOFREE 2
470

471 472 473 474 475 476 477 478 479 480 481 482
/*-
 * Calculate the authority set based on policy tree. The 'pnodes' parameter is
 * used as a store for the set of policy nodes used to calculate the user set.
 * If the authority set is not anyPolicy then pnodes will just point to the
 * authority set. If however the authority set is anyPolicy then the set of
 * valid policies (other than anyPolicy) is store in pnodes.
 *
 * Return value:
 *  TREE_CALC_FAILURE on failure,
 *  TREE_CALC_OK_NOFREE on success and pnodes need not be freed,
 *  TREE_CALC_OK_DOFREE on success and pnodes needs to be freed
 */
483
static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
484 485 486 487 488 489 490 491 492 493 494
                                        STACK_OF(X509_POLICY_NODE) **pnodes)
{
    X509_POLICY_LEVEL *curr;
    X509_POLICY_NODE *node, *anyptr;
    STACK_OF(X509_POLICY_NODE) **addnodes;
    int i, j;
    curr = tree->levels + tree->nlevel - 1;

    /* If last level contains anyPolicy set is anyPolicy */
    if (curr->anyPolicy) {
        if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
495
            return TREE_CALC_FAILURE;
496 497 498 499 500 501 502 503 504 505 506
        addnodes = pnodes;
    } else
        /* Add policies to authority set */
        addnodes = &tree->auth_policies;

    curr = tree->levels;
    for (i = 1; i < tree->nlevel; i++) {
        /*
         * If no anyPolicy node on this this level it can't appear on lower
         * levels so end search.
         */
507
        if ((anyptr = curr->anyPolicy) == NULL)
508 509 510 511 512
            break;
        curr++;
        for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
            node = sk_X509_POLICY_NODE_value(curr->nodes, j);
            if ((node->parent == anyptr)
513 514 515 516 517 518 519
                && !tree_add_auth_node(addnodes, node)) {
                if (addnodes == pnodes) {
                    sk_X509_POLICY_NODE_free(*pnodes);
                    *pnodes = NULL;
                }
                return TREE_CALC_FAILURE;
            }
520 521 522
        }
    }
    if (addnodes == pnodes)
523
        return TREE_CALC_OK_DOFREE;
524 525

    *pnodes = tree->auth_policies;
526
    return TREE_CALC_OK_NOFREE;
527
}
528

529 530 531
/*
 * Return value: 1 on success, 0 otherwise.
 */
532
static int tree_calculate_user_set(X509_POLICY_TREE *tree,
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
                                   STACK_OF(ASN1_OBJECT) *policy_oids,
                                   STACK_OF(X509_POLICY_NODE) *auth_nodes)
{
    int i;
    X509_POLICY_NODE *node;
    ASN1_OBJECT *oid;
    X509_POLICY_NODE *anyPolicy;
    X509_POLICY_DATA *extra;

    /*
     * Check if anyPolicy present in authority constrained policy set: this
     * will happen if it is a leaf node.
     */
    if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
        return 1;

    anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;

    for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
        oid = sk_ASN1_OBJECT_value(policy_oids, i);
        if (OBJ_obj2nid(oid) == NID_any_policy) {
            tree->flags |= POLICY_FLAG_ANY_POLICY;
            return 1;
        }
    }

    for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
        oid = sk_ASN1_OBJECT_value(policy_oids, i);
        node = tree_find_sk(auth_nodes, oid);
        if (!node) {
            if (!anyPolicy)
                continue;
            /*
             * Create a new node with policy ID from user set and qualifiers
             * from anyPolicy.
             */
            extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
570
            if (extra == NULL)
571 572 573 574
                return 0;
            extra->qualifier_set = anyPolicy->data->qualifier_set;
            extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
                | POLICY_DATA_FLAG_EXTRA_NODE;
575
            node = level_add_node(NULL, extra, anyPolicy->parent, tree, 1);
576 577 578 579 580 581 582 583 584 585 586
        }
        if (!tree->user_policies) {
            tree->user_policies = sk_X509_POLICY_NODE_new_null();
            if (!tree->user_policies)
                return 1;
        }
        if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
            return 0;
    }
    return 1;
}
587

588 589 590 591 592 593
/*-
 * Return value: <= 0 error, otherwise one of:
 *  X509_PCY_TREE_VALID: valid tree
 *  X509_PCY_TREE_EMPTY: empty tree
 * (see tree_prune()).
 */
594
static int tree_evaluate(X509_POLICY_TREE *tree)
595 596 597 598
{
    int ret, i;
    X509_POLICY_LEVEL *curr = tree->levels + 1;
    const X509_POLICY_CACHE *cache;
599

600 601
    for (i = 1; i < tree->nlevel; i++, curr++) {
        cache = policy_cache_set(curr->cert);
602
        if (!tree_link_nodes(curr, cache, tree))
603
            return X509_PCY_TREE_INTERNAL;
604 605 606

        if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
            && !tree_link_any(curr, cache, tree))
607 608
            return X509_PCY_TREE_INTERNAL;
#ifdef OPENSSL_POLICY_DEBUG
609
        tree_print("before tree_prune()", tree, curr);
610
#endif
611
        ret = tree_prune(tree, curr);
612
        if (ret != X509_PCY_TREE_VALID)
613 614
            return ret;
    }
615
    return X509_PCY_TREE_VALID;
616 617 618 619 620 621 622
}

static void exnode_free(X509_POLICY_NODE *node)
{
    if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
        OPENSSL_free(node);
}
623 624

void X509_policy_tree_free(X509_POLICY_TREE *tree)
625 626 627
{
    X509_POLICY_LEVEL *curr;
    int i;
628

629 630
    if (!tree)
        return;
631

632 633
    sk_X509_POLICY_NODE_free(tree->auth_policies);
    sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
634

635
    for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
R
Rich Salz 已提交
636 637
        X509_free(curr->cert);
        sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
R
Rich Salz 已提交
638
        policy_node_free(curr->anyPolicy);
639
    }
640

R
Rich Salz 已提交
641
    sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
642 643
    OPENSSL_free(tree->levels);
    OPENSSL_free(tree);
644

645
}
646

647 648
/*-
 * Application policy checking function.
649
 * Return codes:
650 651 652 653
 *  X509_PCY_TREE_FAILURE:  Failure to satisfy explicit policy
 *  X509_PCY_TREE_INVALID:  Inconsistent or invalid extensions
 *  X509_PCY_TREE_INTERNAL: Internal error, most likely malloc
 *  X509_PCY_TREE_VALID:    Success (null tree if empty or bare TA)
654
 */
655
int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
656 657 658
                      STACK_OF(X509) *certs,
                      STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
{
659
    int init_ret;
660
    int ret;
661
    int calc_ret;
662 663
    X509_POLICY_TREE *tree = NULL;
    STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
664

665
    *ptree = NULL;
666
    *pexplicit_policy = 0;
667
    init_ret = tree_init(&tree, certs, flags);
668

669 670
    if (init_ret <= 0)
        return init_ret;
671

672 673 674 675 676 677
    if ((init_ret & X509_PCY_TREE_EXPLICIT) == 0) {
        if (init_ret & X509_PCY_TREE_EMPTY) {
            X509_policy_tree_free(tree);
            return X509_PCY_TREE_VALID;
        }
    } else {
678
        *pexplicit_policy = 1;
679 680 681
        /* Tree empty and requireExplicit True: Error */
        if (init_ret & X509_PCY_TREE_EMPTY)
            return X509_PCY_TREE_FAILURE;
682
    }
683

684
    ret = tree_evaluate(tree);
685
#ifdef OPENSSL_POLICY_DEBUG
686
    tree_print("tree_evaluate()", tree, NULL);
687
#endif
688 689
    if (ret <= 0)
        goto error;
690

691
    if (ret == X509_PCY_TREE_EMPTY) {
692
        X509_policy_tree_free(tree);
693 694 695
        if (init_ret & X509_PCY_TREE_EXPLICIT)
            return X509_PCY_TREE_FAILURE;
        return X509_PCY_TREE_VALID;
696
    }
697

698
    /* Tree is not empty: continue */
699 700

    if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0)
701
        goto error;
702 703
    ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
    if (calc_ret == TREE_CALC_OK_DOFREE)
704
        sk_X509_POLICY_NODE_free(auth_nodes);
705 706
    if (!ret)
        goto error;
707

708
    *ptree = tree;
709

710
    if (init_ret & X509_PCY_TREE_EXPLICIT) {
711 712
        nodes = X509_policy_tree_get0_user_policies(tree);
        if (sk_X509_POLICY_NODE_num(nodes) <= 0)
713
            return X509_PCY_TREE_FAILURE;
714
    }
715
    return X509_PCY_TREE_VALID;
716

717 718
 error:
    X509_policy_tree_free(tree);
719
    return X509_PCY_TREE_INTERNAL;
720
}