pcy_tree.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /* pcy_tree.c */
  2. /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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. #include "cryptlib.h"
  59. #include <openssl/x509.h>
  60. #include <openssl/x509v3.h>
  61. #include "pcy_int.h"
  62. /* Initialize policy tree. Return values:
  63. * 0 Some internal error occured.
  64. * -1 Inconsistent or invalid extensions in certificates.
  65. * 1 Tree initialized OK.
  66. * 2 Policy tree is empty.
  67. * 5 Tree OK and requireExplicitPolicy true.
  68. * 6 Tree empty and requireExplicitPolicy true.
  69. */
  70. static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
  71. unsigned int flags)
  72. {
  73. X509_POLICY_TREE *tree;
  74. X509_POLICY_LEVEL *level;
  75. const X509_POLICY_CACHE *cache;
  76. X509_POLICY_DATA *data = NULL;
  77. X509 *x;
  78. int ret = 1;
  79. int i, n;
  80. int explicit_policy;
  81. int any_skip;
  82. int map_skip;
  83. *ptree = NULL;
  84. n = sk_X509_num(certs);
  85. /* Disable policy mapping for now... */
  86. flags |= X509_V_FLAG_INHIBIT_MAP;
  87. if (flags & X509_V_FLAG_EXPLICIT_POLICY)
  88. explicit_policy = 0;
  89. else
  90. explicit_policy = n + 1;
  91. if (flags & X509_V_FLAG_INHIBIT_ANY)
  92. any_skip = 0;
  93. else
  94. any_skip = n + 1;
  95. if (flags & X509_V_FLAG_INHIBIT_MAP)
  96. map_skip = 0;
  97. else
  98. map_skip = n + 1;
  99. /* Can't do anything with just a trust anchor */
  100. if (n == 1)
  101. return 1;
  102. /* First setup policy cache in all certificates apart from the
  103. * trust anchor. Note any bad cache results on the way. Also can
  104. * calculate explicit_policy value at this point.
  105. */
  106. for (i = n - 2; i >= 0; i--)
  107. {
  108. x = sk_X509_value(certs, i);
  109. X509_check_purpose(x, -1, -1);
  110. cache = policy_cache_set(x);
  111. /* If cache NULL something bad happened: return immediately */
  112. if (cache == NULL)
  113. return 0;
  114. /* If inconsistent extensions keep a note of it but continue */
  115. if (x->ex_flags & EXFLAG_INVALID_POLICY)
  116. ret = -1;
  117. /* Otherwise if we have no data (hence no CertificatePolicies)
  118. * and haven't already set an inconsistent code note it.
  119. */
  120. else if ((ret == 1) && !cache->data)
  121. ret = 2;
  122. if (explicit_policy > 0)
  123. {
  124. explicit_policy--;
  125. if (!(x->ex_flags & EXFLAG_SS)
  126. && (cache->explicit_skip != -1)
  127. && (cache->explicit_skip < explicit_policy))
  128. explicit_policy = cache->explicit_skip;
  129. }
  130. }
  131. if (ret != 1)
  132. {
  133. if (ret == 2 && !explicit_policy)
  134. return 6;
  135. return ret;
  136. }
  137. /* If we get this far initialize the tree */
  138. tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
  139. if (!tree)
  140. return 0;
  141. tree->flags = 0;
  142. tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
  143. tree->nlevel = 0;
  144. tree->extra_data = NULL;
  145. tree->auth_policies = NULL;
  146. tree->user_policies = NULL;
  147. if (!tree)
  148. {
  149. OPENSSL_free(tree);
  150. return 0;
  151. }
  152. memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
  153. tree->nlevel = n;
  154. level = tree->levels;
  155. /* Root data: initialize to anyPolicy */
  156. data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
  157. if (!data || !level_add_node(level, data, NULL, tree))
  158. goto bad_tree;
  159. for (i = n - 2; i >= 0; i--)
  160. {
  161. level++;
  162. x = sk_X509_value(certs, i);
  163. cache = policy_cache_set(x);
  164. CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
  165. level->cert = x;
  166. if (!cache->anyPolicy)
  167. level->flags |= X509_V_FLAG_INHIBIT_ANY;
  168. /* Determine inhibit any and inhibit map flags */
  169. if (any_skip == 0)
  170. {
  171. /* Any matching allowed if certificate is self
  172. * issued and not the last in the chain.
  173. */
  174. if (!(x->ex_flags & EXFLAG_SS) || (i == 0))
  175. level->flags |= X509_V_FLAG_INHIBIT_ANY;
  176. }
  177. else
  178. {
  179. any_skip--;
  180. if ((cache->any_skip > 0)
  181. && (cache->any_skip < any_skip))
  182. any_skip = cache->any_skip;
  183. }
  184. if (map_skip == 0)
  185. level->flags |= X509_V_FLAG_INHIBIT_MAP;
  186. else
  187. {
  188. map_skip--;
  189. if ((cache->map_skip > 0)
  190. && (cache->map_skip < map_skip))
  191. map_skip = cache->map_skip;
  192. }
  193. }
  194. *ptree = tree;
  195. if (explicit_policy)
  196. return 1;
  197. else
  198. return 5;
  199. bad_tree:
  200. X509_policy_tree_free(tree);
  201. return 0;
  202. }
  203. /* This corresponds to RFC3280 XXXX XXXXX:
  204. * link any data from CertificatePolicies onto matching parent
  205. * or anyPolicy if no match.
  206. */
  207. static int tree_link_nodes(X509_POLICY_LEVEL *curr,
  208. const X509_POLICY_CACHE *cache)
  209. {
  210. int i;
  211. X509_POLICY_LEVEL *last;
  212. X509_POLICY_DATA *data;
  213. X509_POLICY_NODE *parent;
  214. last = curr - 1;
  215. for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
  216. {
  217. data = sk_X509_POLICY_DATA_value(cache->data, i);
  218. /* If a node is mapped any it doesn't have a corresponding
  219. * CertificatePolicies entry.
  220. * However such an identical node would be created
  221. * if anyPolicy matching is enabled because there would be
  222. * no match with the parent valid_policy_set. So we create
  223. * link because then it will have the mapping flags
  224. * right and we can prune it later.
  225. */
  226. if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
  227. && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
  228. continue;
  229. /* Look for matching node in parent */
  230. parent = level_find_node(last, data->valid_policy);
  231. /* If no match link to anyPolicy */
  232. if (!parent)
  233. parent = last->anyPolicy;
  234. if (parent && !level_add_node(curr, data, parent, NULL))
  235. return 0;
  236. }
  237. return 1;
  238. }
  239. /* This corresponds to RFC3280 XXXX XXXXX:
  240. * Create new data for any unmatched policies in the parent and link
  241. * to anyPolicy.
  242. */
  243. static int tree_link_any(X509_POLICY_LEVEL *curr,
  244. const X509_POLICY_CACHE *cache,
  245. X509_POLICY_TREE *tree)
  246. {
  247. int i;
  248. X509_POLICY_DATA *data;
  249. X509_POLICY_NODE *node;
  250. X509_POLICY_LEVEL *last;
  251. last = curr - 1;
  252. for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
  253. {
  254. node = sk_X509_POLICY_NODE_value(last->nodes, i);
  255. /* Skip any node with any children: we only want unmathced
  256. * nodes.
  257. *
  258. * Note: need something better for policy mapping
  259. * because each node may have multiple children
  260. */
  261. if (node->nchild)
  262. continue;
  263. /* Create a new node with qualifiers from anyPolicy and
  264. * id from unmatched node.
  265. */
  266. data = policy_data_new(NULL, node->data->valid_policy,
  267. node_critical(node));
  268. if (data == NULL)
  269. return 0;
  270. data->qualifier_set = curr->anyPolicy->data->qualifier_set;
  271. data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
  272. if (!level_add_node(curr, data, node, tree))
  273. {
  274. policy_data_free(data);
  275. return 0;
  276. }
  277. }
  278. /* Finally add link to anyPolicy */
  279. if (last->anyPolicy)
  280. {
  281. if (!level_add_node(curr, cache->anyPolicy,
  282. last->anyPolicy, NULL))
  283. return 0;
  284. }
  285. return 1;
  286. }
  287. /* Prune the tree: delete any child mapped child data on the current level
  288. * then proceed up the tree deleting any data with no children. If we ever
  289. * have no data on a level we can halt because the tree will be empty.
  290. */
  291. static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
  292. {
  293. X509_POLICY_NODE *node;
  294. int i;
  295. for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--)
  296. {
  297. node = sk_X509_POLICY_NODE_value(curr->nodes, i);
  298. /* Delete any mapped data: see RFC3280 XXXX */
  299. if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
  300. {
  301. node->parent->nchild--;
  302. OPENSSL_free(node);
  303. (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
  304. }
  305. }
  306. for(;;) {
  307. --curr;
  308. for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--)
  309. {
  310. node = sk_X509_POLICY_NODE_value(curr->nodes, i);
  311. if (node->nchild == 0)
  312. {
  313. node->parent->nchild--;
  314. OPENSSL_free(node);
  315. (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
  316. }
  317. }
  318. if (curr->anyPolicy && !curr->anyPolicy->nchild)
  319. {
  320. if (curr->anyPolicy->parent)
  321. curr->anyPolicy->parent->nchild--;
  322. OPENSSL_free(curr->anyPolicy);
  323. curr->anyPolicy = NULL;
  324. }
  325. if (curr == tree->levels)
  326. {
  327. /* If we zapped anyPolicy at top then tree is empty */
  328. if (!curr->anyPolicy)
  329. return 2;
  330. return 1;
  331. }
  332. }
  333. return 1;
  334. }
  335. static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
  336. X509_POLICY_NODE *pcy)
  337. {
  338. if (!*pnodes)
  339. {
  340. *pnodes = policy_node_cmp_new();
  341. if (!*pnodes)
  342. return 0;
  343. }
  344. else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
  345. return 1;
  346. if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
  347. return 0;
  348. return 1;
  349. }
  350. /* Calculate the authority set based on policy tree.
  351. * The 'pnodes' parameter is used as a store for the set of policy nodes
  352. * used to calculate the user set. If the authority set is not anyPolicy
  353. * then pnodes will just point to the authority set. If however the authority
  354. * set is anyPolicy then the set of valid policies (other than anyPolicy)
  355. * is store in pnodes. The return value of '2' is used in this case to indicate
  356. * that pnodes should be freed.
  357. */
  358. static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
  359. STACK_OF(X509_POLICY_NODE) **pnodes)
  360. {
  361. X509_POLICY_LEVEL *curr;
  362. X509_POLICY_NODE *node, *anyptr;
  363. STACK_OF(X509_POLICY_NODE) **addnodes;
  364. int i, j;
  365. curr = tree->levels + tree->nlevel - 1;
  366. /* If last level contains anyPolicy set is anyPolicy */
  367. if (curr->anyPolicy)
  368. {
  369. if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
  370. return 0;
  371. addnodes = pnodes;
  372. }
  373. else
  374. /* Add policies to authority set */
  375. addnodes = &tree->auth_policies;
  376. curr = tree->levels;
  377. for (i = 1; i < tree->nlevel; i++)
  378. {
  379. /* If no anyPolicy node on this this level it can't
  380. * appear on lower levels so end search.
  381. */
  382. if (!(anyptr = curr->anyPolicy))
  383. break;
  384. curr++;
  385. for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
  386. {
  387. node = sk_X509_POLICY_NODE_value(curr->nodes, j);
  388. if ((node->parent == anyptr)
  389. && !tree_add_auth_node(addnodes, node))
  390. return 0;
  391. }
  392. }
  393. if (addnodes == pnodes)
  394. return 2;
  395. *pnodes = tree->auth_policies;
  396. return 1;
  397. }
  398. static int tree_calculate_user_set(X509_POLICY_TREE *tree,
  399. STACK_OF(ASN1_OBJECT) *policy_oids,
  400. STACK_OF(X509_POLICY_NODE) *auth_nodes)
  401. {
  402. int i;
  403. X509_POLICY_NODE *node;
  404. ASN1_OBJECT *oid;
  405. X509_POLICY_NODE *anyPolicy;
  406. X509_POLICY_DATA *extra;
  407. /* Check if anyPolicy present in authority constrained policy set:
  408. * this will happen if it is a leaf node.
  409. */
  410. if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
  411. return 1;
  412. anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
  413. for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
  414. {
  415. oid = sk_ASN1_OBJECT_value(policy_oids, i);
  416. if (OBJ_obj2nid(oid) == NID_any_policy)
  417. {
  418. tree->flags |= POLICY_FLAG_ANY_POLICY;
  419. return 1;
  420. }
  421. }
  422. for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
  423. {
  424. oid = sk_ASN1_OBJECT_value(policy_oids, i);
  425. node = tree_find_sk(auth_nodes, oid);
  426. if (!node)
  427. {
  428. if (!anyPolicy)
  429. continue;
  430. /* Create a new node with policy ID from user set
  431. * and qualifiers from anyPolicy.
  432. */
  433. extra = policy_data_new(NULL, oid,
  434. node_critical(anyPolicy));
  435. if (!extra)
  436. return 0;
  437. extra->qualifier_set = anyPolicy->data->qualifier_set;
  438. extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
  439. | POLICY_DATA_FLAG_EXTRA_NODE;
  440. node = level_add_node(NULL, extra, anyPolicy->parent,
  441. tree);
  442. }
  443. if (!tree->user_policies)
  444. {
  445. tree->user_policies = sk_X509_POLICY_NODE_new_null();
  446. if (!tree->user_policies)
  447. return 1;
  448. }
  449. if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
  450. return 0;
  451. }
  452. return 1;
  453. }
  454. static int tree_evaluate(X509_POLICY_TREE *tree)
  455. {
  456. int ret, i;
  457. X509_POLICY_LEVEL *curr = tree->levels + 1;
  458. const X509_POLICY_CACHE *cache;
  459. for(i = 1; i < tree->nlevel; i++, curr++)
  460. {
  461. cache = policy_cache_set(curr->cert);
  462. if (!tree_link_nodes(curr, cache))
  463. return 0;
  464. if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
  465. && !tree_link_any(curr, cache, tree))
  466. return 0;
  467. ret = tree_prune(tree, curr);
  468. if (ret != 1)
  469. return ret;
  470. }
  471. return 1;
  472. }
  473. static void exnode_free(X509_POLICY_NODE *node)
  474. {
  475. if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
  476. OPENSSL_free(node);
  477. }
  478. void X509_policy_tree_free(X509_POLICY_TREE *tree)
  479. {
  480. X509_POLICY_LEVEL *curr;
  481. int i;
  482. if (!tree)
  483. return;
  484. sk_X509_POLICY_NODE_free(tree->auth_policies);
  485. sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
  486. for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
  487. {
  488. if (curr->cert)
  489. X509_free(curr->cert);
  490. if (curr->nodes)
  491. sk_X509_POLICY_NODE_pop_free(curr->nodes,
  492. policy_node_free);
  493. if (curr->anyPolicy)
  494. policy_node_free(curr->anyPolicy);
  495. }
  496. if (tree->extra_data)
  497. sk_X509_POLICY_DATA_pop_free(tree->extra_data,
  498. policy_data_free);
  499. OPENSSL_free(tree->levels);
  500. OPENSSL_free(tree);
  501. }
  502. /* Application policy checking function.
  503. * Return codes:
  504. * 0 Internal Error.
  505. * 1 Successful.
  506. * -1 One or more certificates contain invalid or inconsistent extensions
  507. * -2 User constrained policy set empty and requireExplicit true.
  508. */
  509. int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
  510. STACK_OF(X509) *certs,
  511. STACK_OF(ASN1_OBJECT) *policy_oids,
  512. unsigned int flags)
  513. {
  514. int ret;
  515. X509_POLICY_TREE *tree = NULL;
  516. STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
  517. *ptree = NULL;
  518. *pexplicit_policy = 0;
  519. ret = tree_init(&tree, certs, flags);
  520. switch (ret)
  521. {
  522. /* Tree empty requireExplicit False: OK */
  523. case 2:
  524. return 1;
  525. /* Some internal error */
  526. case 0:
  527. return 0;
  528. /* Tree empty requireExplicit True: Error */
  529. case 6:
  530. *pexplicit_policy = 1;
  531. return -2;
  532. /* Tree OK requireExplicit True: OK and continue */
  533. case 5:
  534. *pexplicit_policy = 1;
  535. break;
  536. /* Tree OK: continue */
  537. case 1:
  538. if (!tree)
  539. /*
  540. * tree_init() returns success and a null tree
  541. * if it's just looking at a trust anchor.
  542. * I'm not sure that returning success here is
  543. * correct, but I'm sure that reporting this
  544. * as an internal error which our caller
  545. * interprets as a malloc failure is wrong.
  546. */
  547. return 1;
  548. break;
  549. }
  550. if (!tree) goto error;
  551. ret = tree_evaluate(tree);
  552. if (ret <= 0)
  553. goto error;
  554. /* Return value 2 means tree empty */
  555. if (ret == 2)
  556. {
  557. X509_policy_tree_free(tree);
  558. if (*pexplicit_policy)
  559. return -2;
  560. else
  561. return 1;
  562. }
  563. /* Tree is not empty: continue */
  564. ret = tree_calculate_authority_set(tree, &auth_nodes);
  565. if (!ret)
  566. goto error;
  567. if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
  568. goto error;
  569. if (ret == 2)
  570. sk_X509_POLICY_NODE_free(auth_nodes);
  571. if (tree)
  572. *ptree = tree;
  573. if (*pexplicit_policy)
  574. {
  575. nodes = X509_policy_tree_get0_user_policies(tree);
  576. if (sk_X509_POLICY_NODE_num(nodes) <= 0)
  577. return -2;
  578. }
  579. return 1;
  580. error:
  581. X509_policy_tree_free(tree);
  582. return 0;
  583. }