Source for gnu.java.security.provider.PKIXCertPathValidatorImpl

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