pcy_tree.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:16k
源码类别:

其他游戏

开发平台:

Visual C++

  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. 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. 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. break;
  539. }
  540. if (!tree) goto error;
  541. ret = tree_evaluate(tree);
  542. if (ret <= 0)
  543. goto error;
  544. /* Return value 2 means tree empty */
  545. if (ret == 2)
  546. {
  547. X509_policy_tree_free(tree);
  548. if (*pexplicit_policy)
  549. return -2;
  550. else
  551. return 1;
  552. }
  553. /* Tree is not empty: continue */
  554. ret = tree_calculate_authority_set(tree, &auth_nodes);
  555. if (!ret)
  556. goto error;
  557. if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
  558. goto error;
  559. if (ret == 2)
  560. sk_X509_POLICY_NODE_free(auth_nodes);
  561. if (tree)
  562. *ptree = tree;
  563. if (*pexplicit_policy)
  564. {
  565. nodes = X509_policy_tree_get0_user_policies(tree);
  566. if (sk_X509_POLICY_NODE_num(nodes) <= 0)
  567. return -2;
  568. }
  569. return 1;
  570. error:
  571. X509_policy_tree_free(tree);
  572. return 0;
  573. }