Source for gnu.java.security.provider.PKIXCertPathValidatorImpl

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