Source for gnu.java.security.provider.PKIXCertPathValidatorImpl

   1: /* PKIXCertPathValidatorImpl.java -- PKIX certificate path validator.
   2:    Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.java.security.provider;
  40: 
  41: import gnu.java.security.Configuration;
  42: import gnu.java.security.OID;
  43: import gnu.java.security.Registry;
  44: import gnu.java.security.key.dss.DSSPublicKey;
  45: import gnu.java.security.x509.GnuPKIExtension;
  46: import gnu.java.security.x509.PolicyNodeImpl;
  47: import gnu.java.security.x509.X509CRLSelectorImpl;
  48: import gnu.java.security.x509.X509CertSelectorImpl;
  49: import gnu.java.security.x509.ext.BasicConstraints;
  50: import gnu.java.security.x509.ext.CertificatePolicies;
  51: import gnu.java.security.x509.ext.Extension;
  52: import gnu.java.security.x509.ext.KeyUsage;
  53: import gnu.java.security.x509.ext.PolicyConstraint;
  54: 
  55: import java.io.IOException;
  56: import java.security.InvalidAlgorithmParameterException;
  57: import java.security.InvalidKeyException;
  58: import java.security.PublicKey;
  59: import java.security.cert.CRL;
  60: import java.security.cert.CertPath;
  61: import java.security.cert.CertPathParameters;
  62: import java.security.cert.CertPathValidatorException;
  63: import java.security.cert.CertPathValidatorResult;
  64: import java.security.cert.CertPathValidatorSpi;
  65: import java.security.cert.CertStore;
  66: import java.security.cert.CertStoreException;
  67: import java.security.cert.CertificateException;
  68: import java.security.cert.PKIXCertPathChecker;
  69: import java.security.cert.PKIXCertPathValidatorResult;
  70: import java.security.cert.PKIXParameters;
  71: import java.security.cert.TrustAnchor;
  72: import java.security.cert.X509CRL;
  73: import java.security.cert.X509Certificate;
  74: import java.security.interfaces.DSAParams;
  75: import java.security.interfaces.DSAPublicKey;
  76: import java.util.Arrays;
  77: import java.util.Collection;
  78: import java.util.Collections;
  79: import java.util.Date;
  80: import java.util.HashSet;
  81: import java.util.Iterator;
  82: import java.util.LinkedList;
  83: import java.util.List;
  84: import java.util.Set;
  85: import java.util.logging.Logger;
  86: 
  87: /**
  88:  * An implementation of the Public Key Infrastructure's X.509 certificate path
  89:  * validation algorithm.
  90:  * <p>
  91:  * See <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
  92:  * Public Key Infrastructure Certificate and Certificate Revocation List (CRL)
  93:  * Profile</a>.
  94:  *
  95:  * @author Casey Marshall (rsdio@metastatic.org)
  96:  */
  97: public class PKIXCertPathValidatorImpl
  98:     extends CertPathValidatorSpi
  99: {
 100:   private static final Logger log = Logger.getLogger(PKIXCertPathValidatorImpl.class.getName());
 101: 
 102:   public static final String ANY_POLICY = "2.5.29.32.0";
 103: 
 104:   public PKIXCertPathValidatorImpl()
 105:   {
 106:     super();
 107:   }
 108: 
 109:   public CertPathValidatorResult engineValidate(CertPath path,
 110:                                                 CertPathParameters params)
 111:       throws CertPathValidatorException, InvalidAlgorithmParameterException
 112:   {
 113:     if (! (params instanceof PKIXParameters))
 114:       throw new InvalidAlgorithmParameterException("not a PKIXParameters object");
 115:     // First check if the certificate path is valid.
 116:     //
 117:     // This means that:
 118:     //
 119:     // (a) for all x in {1, ..., n-1}, the subject of certificate x is
 120:     // the issuer of certificate x+1;
 121:     //
 122:     // (b) for all x in {1, ..., n}, the certificate was valid at the
 123:     // time in question.
 124:     //
 125:     // Because this is the X.509 algorithm, we also check if all
 126:     // cerificates are of type X509Certificate.
 127:     PolicyNodeImpl rootNode = new PolicyNodeImpl();
 128:     Set initPolicies = ((PKIXParameters) params).getInitialPolicies();
 129:     rootNode.setValidPolicy(ANY_POLICY);
 130:     rootNode.setCritical(false);
 131:     rootNode.setDepth(0);
 132:     if (initPolicies != null)
 133:       rootNode.addAllExpectedPolicies(initPolicies);
 134:     else
 135:       rootNode.addExpectedPolicy(ANY_POLICY);
 136:     List checks = ((PKIXParameters) params).getCertPathCheckers();
 137:     List l = path.getCertificates();
 138:     if (l == null || l.size() == 0)
 139:       throw new CertPathValidatorException();
 140:     X509Certificate[] p = null;
 141:     try
 142:       {
 143:         p = (X509Certificate[]) l.toArray(new X509Certificate[l.size()]);
 144:       }
 145:     catch (ClassCastException cce)
 146:       {
 147:         throw new CertPathValidatorException("invalid certificate path");
 148:       }
 149:     String sigProvider = ((PKIXParameters) params).getSigProvider();
 150:     PublicKey prevKey = null;
 151:     Date now = ((PKIXParameters) params).getDate();
 152:     if (now == null)
 153:       now = new Date();
 154:     LinkedList policyConstraints = new LinkedList();
 155:     for (int i = p.length - 1; i >= 0; i--)
 156:       {
 157:         try
 158:           {
 159:             p[i].checkValidity(now);
 160:           }
 161:         catch (CertificateException ce)
 162:           {
 163:             throw new CertPathValidatorException(ce.toString());
 164:           }
 165:         Set uce = getCritExts(p[i]);
 166:         for (Iterator check = checks.iterator(); check.hasNext();)
 167:           {
 168:             try
 169:               {
 170:                 ((PKIXCertPathChecker) check.next()).check(p[i], uce);
 171:               }
 172:             catch (Exception x)
 173:               {
 174:               }
 175:           }
 176:         PolicyConstraint constr = null;
 177:         if (p[i] instanceof GnuPKIExtension)
 178:           {
 179:             Extension pcx = ((GnuPKIExtension) p[i]).getExtension(PolicyConstraint.ID);
 180:             if (pcx != null)
 181:               constr = (PolicyConstraint) pcx.getValue();
 182:           }
 183:         else
 184:           {
 185:             byte[] pcx = p[i].getExtensionValue(PolicyConstraint.ID.toString());
 186:             if (pcx != null)
 187:               {
 188:                 try
 189:                   {
 190:                     constr = new PolicyConstraint(pcx);
 191:                   }
 192:                 catch (Exception x)
 193:                   {
 194:                   }
 195:               }
 196:           }
 197:         if (constr != null && constr.getRequireExplicitPolicy() >= 0)
 198:           policyConstraints.add(new int[] { p.length - i,
 199:                                             constr.getRequireExplicitPolicy() });
 200:         updatePolicyTree(p[i], rootNode, p.length - i, (PKIXParameters) params,
 201:                          checkExplicitPolicy(p.length - i, policyConstraints));
 202:         // The rest of the tests involve this cert's relationship with the
 203:         // next in the path. If this cert is the end entity, we can stop.
 204:         if (i == 0)
 205:           break;
 206: 
 207:         basicSanity(p, i);
 208:         PublicKey pubKey = null;
 209:         try
 210:           {
 211:             pubKey = p[i].getPublicKey();
 212:             if (pubKey instanceof DSAPublicKey)
 213:               {
 214:                 DSAParams dsa = ((DSAPublicKey) pubKey).getParams();
 215:                 // If the DSA public key is missing its parameters, use those
 216:                 // from the previous cert's key.
 217:                 if (dsa == null || dsa.getP() == null || dsa.getG() == null
 218:                     || dsa.getQ() == null)
 219:                   {
 220:                     if (prevKey == null)
 221:                       throw new InvalidKeyException("DSA keys not chainable");
 222:                     if (! (prevKey instanceof DSAPublicKey))
 223:                       throw new InvalidKeyException("DSA keys not chainable");
 224:                     dsa = ((DSAPublicKey) prevKey).getParams();
 225:                     pubKey = new DSSPublicKey(Registry.X509_ENCODING_ID,
 226:                                               dsa.getP(), dsa.getQ(),
 227:                                               dsa.getG(),
 228:                                               ((DSAPublicKey) pubKey).getY());
 229:                   }
 230:               }
 231:             if (sigProvider == null)
 232:               p[i - 1].verify(pubKey);
 233:             else
 234:               p[i - 1].verify(pubKey, sigProvider);
 235:             prevKey = pubKey;
 236:           }
 237:         catch (Exception e)
 238:           {
 239:             throw new CertPathValidatorException(e.toString());
 240:           }
 241:         if (! p[i].getSubjectDN().equals(p[i - 1].getIssuerDN()))
 242:           throw new CertPathValidatorException("issuer DN mismatch");
 243:         boolean[] issuerUid = p[i - 1].getIssuerUniqueID();
 244:         boolean[] subjectUid = p[i].getSubjectUniqueID();
 245:         if (issuerUid != null && subjectUid != null)
 246:           if (! Arrays.equals(issuerUid, subjectUid))
 247:             throw new CertPathValidatorException("UID mismatch");
 248: 
 249:         // Check the certificate against the revocation lists.
 250:         if (((PKIXParameters) params).isRevocationEnabled())
 251:           {
 252:             X509CRLSelectorImpl selector = new X509CRLSelectorImpl();
 253:             try
 254:               {
 255:                 selector.addIssuerName(p[i].getSubjectDN());
 256:               }
 257:             catch (IOException ioe)
 258:               {
 259:                 throw new CertPathValidatorException("error selecting CRLs");
 260:               }
 261:             List certStores = ((PKIXParameters) params).getCertStores();
 262:             List crls = new LinkedList();
 263:             for (Iterator it = certStores.iterator(); it.hasNext();)
 264:               {
 265:                 CertStore cs = (CertStore) it.next();
 266:                 try
 267:                   {
 268:                     Collection c = cs.getCRLs(selector);
 269:                     crls.addAll(c);
 270:                   }
 271:                 catch (CertStoreException cse)
 272:                   {
 273:                   }
 274:               }
 275:             if (crls.isEmpty())
 276:               throw new CertPathValidatorException("no CRLs for issuer");
 277:             boolean certOk = false;
 278:             for (Iterator it = crls.iterator(); it.hasNext();)
 279:               {
 280:                 CRL crl = (CRL) it.next();
 281:                 if (! (crl instanceof X509CRL))
 282:                   continue;
 283:                 X509CRL xcrl = (X509CRL) crl;
 284:                 if (! checkCRL(xcrl, p, now, p[i], pubKey, certStores))
 285:                   continue;
 286:                 if (xcrl.isRevoked(p[i - 1]))
 287:                   throw new CertPathValidatorException("certificate is revoked");
 288:                 else
 289:                   certOk = true;
 290:               }
 291:             if (! certOk)
 292:               throw new CertPathValidatorException(
 293:                   "certificate's validity could not be determined");
 294:           }
 295:       }
 296:     rootNode.setReadOnly();
 297:     // Now ensure that the first certificate in the chain was issued
 298:     // by a trust anchor.
 299:     Exception cause = null;
 300:     Set anchors = ((PKIXParameters) params).getTrustAnchors();
 301:     for (Iterator i = anchors.iterator(); i.hasNext();)
 302:       {
 303:         TrustAnchor anchor = (TrustAnchor) i.next();
 304:         X509Certificate anchorCert = null;
 305:         PublicKey anchorKey = null;
 306:         if (anchor.getTrustedCert() != null)
 307:           {
 308:             anchorCert = anchor.getTrustedCert();
 309:             anchorKey = anchorCert.getPublicKey();
 310:           }
 311:         else
 312:           anchorKey = anchor.getCAPublicKey();
 313:         if (anchorKey == null)
 314:           continue;
 315:         try
 316:           {
 317:             if (anchorCert != null)
 318:               anchorCert.checkValidity(now);
 319:             p[p.length - 1].verify(anchorKey);
 320:             if (anchorCert != null && anchorCert.getBasicConstraints() >= 0
 321:                 && anchorCert.getBasicConstraints() < p.length)
 322:               continue;
 323: 
 324:             if (((PKIXParameters) params).isRevocationEnabled())
 325:               {
 326:                 X509CRLSelectorImpl selector = new X509CRLSelectorImpl();
 327:                 if (anchorCert != null)
 328:                   try
 329:                     {
 330:                       selector.addIssuerName(anchorCert.getSubjectDN());
 331:                     }
 332:                   catch (IOException ioe)
 333:                     {
 334:                     }
 335:                 else
 336:                   selector.addIssuerName(anchor.getCAName());
 337:                 List certStores = ((PKIXParameters) params).getCertStores();
 338:                 List crls = new LinkedList();
 339:                 for (Iterator it = certStores.iterator(); it.hasNext();)
 340:                   {
 341:                     CertStore cs = (CertStore) it.next();
 342:                     try
 343:                       {
 344:                         Collection c = cs.getCRLs(selector);
 345:                         crls.addAll(c);
 346:                       }
 347:                     catch (CertStoreException cse)
 348:                       {
 349:                       }
 350:                   }
 351:                 if (crls.isEmpty())
 352:                   continue;
 353:                 for (Iterator it = crls.iterator(); it.hasNext();)
 354:                   {
 355:                     CRL crl = (CRL) it.next();
 356:                     if (! (crl instanceof X509CRL))
 357:                       continue;
 358:                     X509CRL xcrl = (X509CRL) crl;
 359:                     try
 360:                       {
 361:                         xcrl.verify(anchorKey);
 362:                       }
 363:                     catch (Exception x)
 364:                       {
 365:                         continue;
 366:                       }
 367:                     Date nextUpdate = xcrl.getNextUpdate();
 368:                     if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
 369:                       continue;
 370:                     if (xcrl.isRevoked(p[p.length - 1]))
 371:                       throw new CertPathValidatorException("certificate is revoked");
 372:                   }
 373:               }
 374:             // The chain is valid; return the result.
 375:             return new PKIXCertPathValidatorResult(anchor, rootNode,
 376:                                                    p[0].getPublicKey());
 377:           }
 378:         catch (Exception ignored)
 379:           {
 380:             cause = ignored;
 381:             continue;
 382:           }
 383:       }
 384:     // The path is not valid.
 385:     CertPathValidatorException cpve =
 386:         new CertPathValidatorException("path validation failed");
 387:     if (cause != null)
 388:       cpve.initCause(cause);
 389:     throw cpve;
 390:   }
 391: 
 392:   /**
 393:    * Check if a given CRL is acceptable for checking the revocation status of
 394:    * certificates in the path being checked.
 395:    * <p>
 396:    * The CRL is accepted iff:
 397:    * <ol>
 398:    * <li>The <i>nextUpdate</i> field (if present) is in the future.</li>
 399:    * <li>The CRL does not contain any unsupported critical extensions.</li>
 400:    * <li>The CRL is signed by one of the certificates in the path, or,</li>
 401:    * <li>The CRL is signed by the given public key and was issued by the public
 402:    * key's subject, or,</li>
 403:    * <li>The CRL is signed by a certificate in the given cert stores, and that
 404:    * cert is signed by one of the certificates in the path.</li>
 405:    * </ol>
 406:    *
 407:    * @param crl The CRL being checked.
 408:    * @param path The path this CRL is being checked against.
 409:    * @param now The value to use as 'now'.
 410:    * @param pubKeyCert The certificate authenticating the public key.
 411:    * @param pubKey The public key to check.
 412:    * @return True if the CRL is acceptable.
 413:    */
 414:   private static boolean checkCRL(X509CRL crl, X509Certificate[] path,
 415:                                   Date now, X509Certificate pubKeyCert,
 416:                                   PublicKey pubKey, List certStores)
 417:   {
 418:     Date nextUpdate = crl.getNextUpdate();
 419:     if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
 420:       return false;
 421:     if (crl.hasUnsupportedCriticalExtension())
 422:       return false;
 423:     for (int i = 0; i < path.length; i++)
 424:       {
 425:         if (! path[i].getSubjectDN().equals(crl.getIssuerDN()))
 426:           continue;
 427:         boolean[] keyUsage = path[i].getKeyUsage();
 428:         if (keyUsage != null)
 429:           {
 430:             if (! keyUsage[KeyUsage.CRL_SIGN])
 431:               continue;
 432:           }
 433:         try
 434:           {
 435:             crl.verify(path[i].getPublicKey());
 436:             return true;
 437:           }
 438:         catch (Exception x)
 439:           {
 440:           }
 441:       }
 442:     if (crl.getIssuerDN().equals(pubKeyCert.getSubjectDN()))
 443:       {
 444:         try
 445:           {
 446:             boolean[] keyUsage = pubKeyCert.getKeyUsage();
 447:             if (keyUsage != null)
 448:               {
 449:                 if (! keyUsage[KeyUsage.CRL_SIGN])
 450:                   throw new Exception();
 451:               }
 452:             crl.verify(pubKey);
 453:             return true;
 454:           }
 455:         catch (Exception x)
 456:           {
 457:           }
 458:       }
 459:     try
 460:       {
 461:         X509CertSelectorImpl select = new X509CertSelectorImpl();
 462:         select.addSubjectName(crl.getIssuerDN());
 463:         List certs = new LinkedList();
 464:         for (Iterator it = certStores.iterator(); it.hasNext();)
 465:           {
 466:             CertStore cs = (CertStore) it.next();
 467:             try
 468:               {
 469:                 certs.addAll(cs.getCertificates(select));
 470:               }
 471:             catch (CertStoreException cse)
 472:               {
 473:               }
 474:           }
 475:         for (Iterator it = certs.iterator(); it.hasNext();)
 476:           {
 477:             X509Certificate c = (X509Certificate) it.next();
 478:             for (int i = 0; i < path.length; i++)
 479:               {
 480:                 if (! c.getIssuerDN().equals(path[i].getSubjectDN()))
 481:                   continue;
 482:                 boolean[] keyUsage = c.getKeyUsage();
 483:                 if (keyUsage != null)
 484:                   {
 485:                     if (! keyUsage[KeyUsage.CRL_SIGN])
 486:                       continue;
 487:                   }
 488:                 try
 489:                   {
 490:                     c.verify(path[i].getPublicKey());
 491:                     crl.verify(c.getPublicKey());
 492:                     return true;
 493:                   }
 494:                 catch (Exception x)
 495:                   {
 496:                   }
 497:               }
 498:             if (c.getIssuerDN().equals(pubKeyCert.getSubjectDN()))
 499:               {
 500:                 c.verify(pubKey);
 501:                 crl.verify(c.getPublicKey());
 502:               }
 503:           }
 504:       }
 505:     catch (Exception x)
 506:       {
 507:       }
 508:     return false;
 509:   }
 510: 
 511:   private static Set getCritExts(X509Certificate cert)
 512:   {
 513:     HashSet s = new HashSet();
 514:     if (cert instanceof GnuPKIExtension)
 515:       {
 516:         Collection exts = ((GnuPKIExtension) cert).getExtensions();
 517:         for (Iterator it = exts.iterator(); it.hasNext();)
 518:           {
 519:             Extension ext = (Extension) it.next();
 520:             if (ext.isCritical() && ! ext.isSupported())
 521:               s.add(ext.getOid().toString());
 522:           }
 523:       }
 524:     else
 525:       s.addAll(cert.getCriticalExtensionOIDs());
 526:     return s;
 527:   }
 528: 
 529:   /**
 530:    * Perform a basic sanity check on the CA certificate at <code>index</code>.
 531:    */
 532:   private static void basicSanity(X509Certificate[] path, int index)
 533:       throws CertPathValidatorException
 534:   {
 535:     X509Certificate cert = path[index];
 536:     int pathLen = 0;
 537:     for (int i = index - 1; i > 0; i--)
 538:       {
 539:         if (! path[i].getIssuerDN().equals(path[i].getSubjectDN()))
 540:           pathLen++;
 541:       }
 542:     Extension e = null;
 543:     if (cert instanceof GnuPKIExtension)
 544:       {
 545:         e = ((GnuPKIExtension) cert).getExtension(BasicConstraints.ID);
 546:       }
 547:     else
 548:       {
 549:         try
 550:           {
 551:             e = new Extension(cert.getExtensionValue(BasicConstraints.ID.toString()));
 552:           }
 553:         catch (Exception x)
 554:           {
 555:           }
 556:       }
 557:     if (e == null)
 558:       throw new CertPathValidatorException("no basicConstraints");
 559:     BasicConstraints bc = (BasicConstraints) e.getValue();
 560:     if (! bc.isCA())
 561:       throw new CertPathValidatorException(
 562:           "certificate cannot be used to verify signatures");
 563:     if (bc.getPathLengthConstraint() >= 0
 564:         && bc.getPathLengthConstraint() < pathLen)
 565:       throw new CertPathValidatorException("path is too long");
 566: 
 567:     boolean[] keyUsage = cert.getKeyUsage();
 568:     if (keyUsage != null)
 569:       {
 570:         if (! keyUsage[KeyUsage.KEY_CERT_SIGN])
 571:           throw new CertPathValidatorException(
 572:               "certificate cannot be used to sign certificates");
 573:       }
 574:   }
 575: 
 576:   private static void updatePolicyTree(X509Certificate cert,
 577:                                        PolicyNodeImpl root, int depth,
 578:                                        PKIXParameters params,
 579:                                        boolean explicitPolicy)
 580:       throws CertPathValidatorException
 581:   {
 582:     if (Configuration.DEBUG)
 583:       log.fine("updatePolicyTree depth == " + depth);
 584:     Set nodes = new HashSet();
 585:     LinkedList stack = new LinkedList();
 586:     Iterator current = null;
 587:     stack.addLast(Collections.singleton(root).iterator());
 588:     do
 589:       {
 590:         current = (Iterator) stack.removeLast();
 591:         while (current.hasNext())
 592:           {
 593:             PolicyNodeImpl p = (PolicyNodeImpl) current.next();
 594:             if (Configuration.DEBUG)
 595:               log.fine("visiting node == " + p);
 596:             if (p.getDepth() == depth - 1)
 597:               {
 598:                 if (Configuration.DEBUG)
 599:                   log.fine("added node");
 600:                 nodes.add(p);
 601:               }
 602:             else
 603:               {
 604:                 if (Configuration.DEBUG)
 605:                   log.fine("skipped node");
 606:                 stack.addLast(current);
 607:                 current = p.getChildren();
 608:               }
 609:           }
 610:       }
 611:     while (! stack.isEmpty());
 612: 
 613:     Extension e = null;
 614:     CertificatePolicies policies = null;
 615:     List qualifierInfos = null;
 616:     if (cert instanceof GnuPKIExtension)
 617:       {
 618:         e = ((GnuPKIExtension) cert).getExtension(CertificatePolicies.ID);
 619:         if (e != null)
 620:           policies = (CertificatePolicies) e.getValue();
 621:       }
 622: 
 623:     List cp = null;
 624:     if (policies != null)
 625:       cp = policies.getPolicies();
 626:     else
 627:       cp = Collections.EMPTY_LIST;
 628:     boolean match = false;
 629:     if (Configuration.DEBUG)
 630:       {
 631:         log.fine("nodes are == " + nodes);
 632:         log.fine("cert policies are == " + cp);
 633:       }
 634:     for (Iterator it = nodes.iterator(); it.hasNext();)
 635:       {
 636:         PolicyNodeImpl parent = (PolicyNodeImpl) it.next();
 637:         if (Configuration.DEBUG)
 638:           log.fine("adding policies to " + parent);
 639:         for (Iterator it2 = cp.iterator(); it2.hasNext();)
 640:           {
 641:             OID policy = (OID) it2.next();
 642:             if (Configuration.DEBUG)
 643:               log.fine("trying to add policy == " + policy);
 644:             if (policy.toString().equals(ANY_POLICY)
 645:                 && params.isAnyPolicyInhibited())
 646:               continue;
 647:             PolicyNodeImpl child = new PolicyNodeImpl();
 648:             child.setValidPolicy(policy.toString());
 649:             child.addExpectedPolicy(policy.toString());
 650:             if (parent.getExpectedPolicies().contains(policy.toString()))
 651:               {
 652:                 parent.addChild(child);
 653:                 match = true;
 654:               }
 655:             else if (parent.getExpectedPolicies().contains(ANY_POLICY))
 656:               {
 657:                 parent.addChild(child);
 658:                 match = true;
 659:               }
 660:             else if (ANY_POLICY.equals(policy.toString()))
 661:               {
 662:                 parent.addChild(child);
 663:                 match = true;
 664:               }
 665:             if (match && policies != null)
 666:               {
 667:                 List qualifiers = policies.getPolicyQualifierInfos(policy);
 668:                 if (qualifiers != null)
 669:                   child.addAllPolicyQualifiers(qualifiers);
 670:               }
 671:           }
 672:       }
 673:     if (! match && (params.isExplicitPolicyRequired() || explicitPolicy))
 674:       throw new CertPathValidatorException("policy tree building failed");
 675:   }
 676: 
 677:   private boolean checkExplicitPolicy(int depth, List explicitPolicies)
 678:   {
 679:     if (Configuration.DEBUG)
 680:       log.fine("checkExplicitPolicy depth=" + depth);
 681:     for (Iterator it = explicitPolicies.iterator(); it.hasNext();)
 682:       {
 683:         int[] i = (int[]) it.next();
 684:         int caDepth = i[0];
 685:         int limit = i[1];
 686:         if (Configuration.DEBUG)
 687:           log.fine("  caDepth=" + caDepth + " limit=" + limit);
 688:         if (depth - caDepth >= limit)
 689:           return true;
 690:       }
 691:     return false;
 692:   }
 693: }