0001: package org.bouncycastle.x509;
0002:
0003: import org.bouncycastle.asn1.ASN1InputStream;
0004: import org.bouncycastle.asn1.ASN1Sequence;
0005: import org.bouncycastle.asn1.ASN1TaggedObject;
0006: import org.bouncycastle.asn1.DEREncodable;
0007: import org.bouncycastle.asn1.DEREnumerated;
0008: import org.bouncycastle.asn1.DERIA5String;
0009: import org.bouncycastle.asn1.DERInteger;
0010: import org.bouncycastle.asn1.DERObject;
0011: import org.bouncycastle.asn1.DERObjectIdentifier;
0012: import org.bouncycastle.asn1.x509.AccessDescription;
0013: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
0014: import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
0015: import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
0016: import org.bouncycastle.asn1.x509.BasicConstraints;
0017: import org.bouncycastle.asn1.x509.CRLDistPoint;
0018: import org.bouncycastle.asn1.x509.DistributionPoint;
0019: import org.bouncycastle.asn1.x509.DistributionPointName;
0020: import org.bouncycastle.asn1.x509.GeneralName;
0021: import org.bouncycastle.asn1.x509.GeneralNames;
0022: import org.bouncycastle.asn1.x509.GeneralSubtree;
0023: import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
0024: import org.bouncycastle.asn1.x509.NameConstraints;
0025: import org.bouncycastle.asn1.x509.PolicyInformation;
0026: import org.bouncycastle.asn1.x509.X509Extensions;
0027: import org.bouncycastle.asn1.x509.qualified.Iso4217CurrencyCode;
0028: import org.bouncycastle.asn1.x509.qualified.MonetaryValue;
0029: import org.bouncycastle.asn1.x509.qualified.QCStatement;
0030: import org.bouncycastle.i18n.ErrorBundle;
0031: import org.bouncycastle.i18n.LocaleString;
0032: import org.bouncycastle.i18n.filter.TrustedInput;
0033: import org.bouncycastle.i18n.filter.UntrustedInput;
0034: import org.bouncycastle.i18n.filter.UntrustedUrlInput;
0035: import org.bouncycastle.jce.provider.AnnotatedException;
0036: import org.bouncycastle.jce.provider.CertPathValidatorUtilities;
0037: import org.bouncycastle.jce.provider.PKIXNameConstraints;
0038: import org.bouncycastle.jce.provider.PKIXPolicyNode;
0039: import org.bouncycastle.x509.extension.X509ExtensionUtil;
0040:
0041: import javax.security.auth.x500.X500Principal;
0042: import java.io.ByteArrayInputStream;
0043: import java.io.IOException;
0044: import java.math.BigInteger;
0045: import java.net.HttpURLConnection;
0046: import java.net.InetAddress;
0047: import java.net.URL;
0048: import java.security.GeneralSecurityException;
0049: import java.security.PublicKey;
0050: import java.security.SignatureException;
0051: import java.security.cert.CertPath;
0052: import java.security.cert.CertPathValidatorException;
0053: import java.security.cert.CertificateExpiredException;
0054: import java.security.cert.CertificateFactory;
0055: import java.security.cert.CertificateNotYetValidException;
0056: import java.security.cert.PKIXCertPathChecker;
0057: import java.security.cert.PKIXParameters;
0058: import java.security.cert.PolicyNode;
0059: import java.security.cert.TrustAnchor;
0060: import java.security.cert.X509CRL;
0061: import java.security.cert.X509CRLEntry;
0062: import java.security.cert.X509CRLSelector;
0063: import java.security.cert.X509CertSelector;
0064: import java.security.cert.X509Certificate;
0065: import java.util.ArrayList;
0066: import java.util.Collection;
0067: import java.util.Date;
0068: import java.util.Enumeration;
0069: import java.util.HashMap;
0070: import java.util.HashSet;
0071: import java.util.Iterator;
0072: import java.util.List;
0073: import java.util.Map;
0074: import java.util.Set;
0075: import java.util.Vector;
0076:
0077: /**
0078: * PKIXCertPathReviewer<br>
0079: * Validation of X.509 Certificate Paths. Tries to find as much errors in the Path as possible.
0080: */
0081: public class PKIXCertPathReviewer extends CertPathValidatorUtilities {
0082:
0083: private static final String QC_STATEMENT = X509Extensions.QCStatements
0084: .getId();
0085: private static final String CRL_DIST_POINTS = X509Extensions.CRLDistributionPoints
0086: .getId();
0087: private static final String AUTH_INFO_ACCESS = X509Extensions.AuthorityInfoAccess
0088: .getId();
0089:
0090: private static final String RESOURCE_NAME = "org.bouncycastle.x509.CertPathReviewerMessages";
0091:
0092: // input parameters
0093:
0094: protected CertPath certPath;
0095:
0096: protected PKIXParameters pkixParams;
0097:
0098: protected Date validDate;
0099:
0100: // state variables
0101:
0102: protected List certs;
0103:
0104: protected int n;
0105:
0106: // output variables
0107:
0108: protected List[] notifications;
0109: protected List[] errors;
0110: protected TrustAnchor trustAnchor;
0111: protected PublicKey subjectPublicKey;
0112: protected PolicyNode policyTree;
0113:
0114: private boolean initialized;
0115:
0116: /**
0117: * Initializes the PKIXCertPathReviewer with the given {@link CertPath} and {@link PKIXParameters} params
0118: * @param certPath the {@link CertPath} to validate
0119: * @param params the {@link PKIXParameters} to use
0120: * @throws CertPathReviewerException if the certPath is empty
0121: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} is already initialized
0122: */
0123: public void init(CertPath certPath, PKIXParameters params)
0124: throws CertPathReviewerException {
0125: if (initialized) {
0126: throw new IllegalStateException(
0127: "object is already initialized!");
0128: }
0129: initialized = true;
0130:
0131: // check input parameters
0132: if (certPath == null) {
0133: throw new NullPointerException("certPath was null");
0134: }
0135: this .certPath = certPath;
0136:
0137: certs = certPath.getCertificates();
0138: n = certs.size();
0139: if (certs.isEmpty()) {
0140: throw new CertPathReviewerException(new ErrorBundle(
0141: RESOURCE_NAME, "CertPathReviewer.emptyCertPath"));
0142: }
0143:
0144: pkixParams = (PKIXParameters) params.clone();
0145:
0146: // 6.1.1 - Inputs
0147:
0148: // a) done
0149:
0150: // b)
0151:
0152: validDate = getValidDate(pkixParams);
0153:
0154: // c) part of pkixParams
0155:
0156: // d) done at the beginning of checkSignatures
0157:
0158: // e) f) g) part of pkixParams
0159:
0160: // initialize output parameters
0161:
0162: notifications = null;
0163: errors = null;
0164: trustAnchor = null;
0165: subjectPublicKey = null;
0166: policyTree = null;
0167: }
0168:
0169: /**
0170: * Creates a PKIXCertPathReviewer and initializes it with the given {@link CertPath} and {@link PKIXParameters} params
0171: * @param certPath the {@link CertPath} to validate
0172: * @param params the {@link PKIXParameters} to use
0173: * @throws CertPathReviewerException if the certPath is empty
0174: */
0175: public PKIXCertPathReviewer(CertPath certPath, PKIXParameters params)
0176: throws CertPathReviewerException {
0177: init(certPath, params);
0178: }
0179:
0180: /**
0181: * Creates an empty PKIXCertPathReviewer. Don't forget to call init() to initialize the object.
0182: */
0183: public PKIXCertPathReviewer() {
0184: // do nothing
0185: }
0186:
0187: /**
0188: *
0189: * @return the CertPath that was validated
0190: */
0191: public CertPath getCertPath() {
0192: return certPath;
0193: }
0194:
0195: /**
0196: *
0197: * @return the size of the CertPath
0198: */
0199: public int getCertPathSize() {
0200: return n;
0201: }
0202:
0203: /**
0204: * Returns an Array of Lists which contains a List of global error messages
0205: * and a List of error messages for each certificate in the path.
0206: * The global error List is at index 0. The error lists for each certificate at index 1 to n.
0207: * The error messages are of type.
0208: * @return the Array of Lists which contain the error messages
0209: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0210: */
0211: public List[] getErrors() {
0212: doChecks();
0213: return errors;
0214: }
0215:
0216: /**
0217: * Returns an List of error messages for the certificate at the given index in the CertPath.
0218: * If index == -1 then the list of global errors is returned with errors not specific to a certificate.
0219: * @param index the index of the certificate in the CertPath
0220: * @return List of error messages for the certificate
0221: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0222: */
0223: public List getErrors(int index) {
0224: doChecks();
0225: return errors[index + 1];
0226: }
0227:
0228: /**
0229: * Returns an Array of Lists which contains a List of global notification messages
0230: * and a List of botification messages for each certificate in the path.
0231: * The global notificatio List is at index 0. The notification lists for each certificate at index 1 to n.
0232: * The error messages are of type.
0233: * @return the Array of Lists which contain the notification messages
0234: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0235: */
0236: public List[] getNotifications() {
0237: doChecks();
0238: return notifications;
0239: }
0240:
0241: /**
0242: * Returns an List of notification messages for the certificate at the given index in the CertPath.
0243: * If index == -1 then the list of global notifications is returned with notifications not specific to a certificate.
0244: * @param index the index of the certificate in the CertPath
0245: * @return List of notification messages for the certificate
0246: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0247: */
0248: public List getNotifications(int index) {
0249: doChecks();
0250: return notifications[index + 1];
0251: }
0252:
0253: /**
0254: *
0255: * @return the valid policy tree, <b>null</b> if no valid policy exists.
0256: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0257: */
0258: public PolicyNode getPolicyTree() {
0259: doChecks();
0260: return policyTree;
0261: }
0262:
0263: /**
0264: *
0265: * @return the PublicKey if the last certificate in the CertPath
0266: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0267: */
0268: public PublicKey getSubjectPublicKey() {
0269: doChecks();
0270: return subjectPublicKey;
0271: }
0272:
0273: /**
0274: *
0275: * @return the TrustAnchor for the CertPath, <b>null</b> if no valid TrustAnchor was found.
0276: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0277: */
0278: public TrustAnchor getTrustAnchor() {
0279: doChecks();
0280: return trustAnchor;
0281: }
0282:
0283: /**
0284: *
0285: * @return if the CertPath is valid
0286: * @throws IllegalStateException if the {@link PKIXCertPathReviewer} was not initialized
0287: */
0288: public boolean isValidCertPath() {
0289: doChecks();
0290: boolean valid = true;
0291: for (int i = 0; i < errors.length; i++) {
0292: if (!errors[i].isEmpty()) {
0293: valid = false;
0294: break;
0295: }
0296: }
0297: return valid;
0298: }
0299:
0300: protected void addNotification(ErrorBundle msg) {
0301: notifications[0].add(msg);
0302: }
0303:
0304: protected void addNotification(ErrorBundle msg, int index) {
0305: if (index < -1 || index >= n) {
0306: throw new IndexOutOfBoundsException();
0307: }
0308: notifications[index + 1].add(msg);
0309: }
0310:
0311: protected void addError(ErrorBundle msg) {
0312: errors[0].add(msg);
0313: }
0314:
0315: protected void addError(ErrorBundle msg, int index) {
0316: if (index < -1 || index >= n) {
0317: throw new IndexOutOfBoundsException();
0318: }
0319: errors[index + 1].add(msg);
0320: }
0321:
0322: protected void doChecks() {
0323: if (!initialized) {
0324: throw new IllegalStateException(
0325: "Object not initialized. Call init() first.");
0326: }
0327: if (notifications == null) {
0328: // initialize lists
0329: notifications = new List[n + 1];
0330: errors = new List[n + 1];
0331:
0332: for (int i = 0; i < notifications.length; i++) {
0333: notifications[i] = new ArrayList();
0334: errors[i] = new ArrayList();
0335: }
0336:
0337: // check Signatures
0338: checkSignatures();
0339:
0340: // check Name Constraints
0341: checkNameConstraints();
0342:
0343: // check Path Length
0344: checkPathLength();
0345:
0346: // check Policy
0347: checkPolicy();
0348:
0349: // check other critical extensions
0350: checkCriticalExtensions();
0351:
0352: }
0353: }
0354:
0355: private void checkNameConstraints() {
0356: X509Certificate cert = null;
0357:
0358: //
0359: // Setup
0360: //
0361:
0362: // (b) and (c)
0363: PKIXNameConstraints nameConstraints = new PKIXNameConstraints();
0364:
0365: //
0366: // process each certificate except the last in the path
0367: //
0368: int index;
0369: int i;
0370:
0371: try {
0372: for (index = certs.size() - 1; index > 0; index--) {
0373: i = n - index;
0374:
0375: //
0376: // certificate processing
0377: //
0378:
0379: cert = (X509Certificate) certs.get(index);
0380:
0381: // b),c)
0382:
0383: if (!isSelfIssued(cert)) {
0384: X500Principal principal = getSubjectPrincipal(cert);
0385: ASN1InputStream aIn = new ASN1InputStream(
0386: new ByteArrayInputStream(principal
0387: .getEncoded()));
0388: ASN1Sequence dns;
0389:
0390: try {
0391: dns = (ASN1Sequence) aIn.readObject();
0392: } catch (IOException e) {
0393: ErrorBundle msg = new ErrorBundle(
0394: RESOURCE_NAME,
0395: "CertPathReviewer.ncSubjectNameError",
0396: new Object[] { new UntrustedInput(
0397: principal) });
0398: throw new CertPathReviewerException(msg, e,
0399: certPath, index);
0400: }
0401:
0402: try {
0403: nameConstraints.checkPermittedDN(dns);
0404: } catch (CertPathValidatorException cpve) {
0405: ErrorBundle msg = new ErrorBundle(
0406: RESOURCE_NAME,
0407: "CertPathReviewer.notPermittedDN",
0408: new Object[] { new UntrustedInput(
0409: principal.getName()) });
0410: throw new CertPathReviewerException(msg, cpve,
0411: certPath, index);
0412: }
0413:
0414: try {
0415: nameConstraints.checkExcludedDN(dns);
0416: } catch (CertPathValidatorException cpve) {
0417: ErrorBundle msg = new ErrorBundle(
0418: RESOURCE_NAME,
0419: "CertPathReviewer.excludedDN",
0420: new Object[] { new UntrustedInput(
0421: principal.getName()) });
0422: throw new CertPathReviewerException(msg, cpve,
0423: certPath, index);
0424: }
0425:
0426: ASN1Sequence altName;
0427: try {
0428: altName = (ASN1Sequence) getExtensionValue(
0429: cert, SUBJECT_ALTERNATIVE_NAME);
0430: } catch (AnnotatedException ae) {
0431: ErrorBundle msg = new ErrorBundle(
0432: RESOURCE_NAME,
0433: "CertPathReviewer.subjAltNameExtError");
0434: throw new CertPathReviewerException(msg, ae,
0435: certPath, index);
0436: }
0437:
0438: if (altName != null) {
0439: for (int j = 0; j < altName.size(); j++) {
0440: GeneralName name = GeneralName
0441: .getInstance(altName.getObjectAt(j));
0442:
0443: try {
0444: nameConstraints.checkPermitted(name);
0445: nameConstraints.checkExcluded(name);
0446: } catch (CertPathValidatorException cpve) {
0447: ErrorBundle msg = new ErrorBundle(
0448: RESOURCE_NAME,
0449: "CertPathReviewer.notPermittedEmail",
0450: new Object[] { new UntrustedInput(
0451: name) });
0452: throw new CertPathReviewerException(
0453: msg, cpve, certPath, index);
0454: }
0455: // switch(o.getTagNo()) TODO - move resources to PKIXNameConstraints
0456: // {
0457: // case 1:
0458: // String email = DERIA5String.getInstance(o, true).getString();
0459: //
0460: // try
0461: // {
0462: // checkPermittedEmail(permittedSubtreesEmail, email);
0463: // }
0464: // catch (CertPathValidatorException cpve)
0465: // {
0466: // ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.notPermittedEmail",
0467: // new Object[] {new UntrustedInput(email)});
0468: // throw new CertPathReviewerException(msg,cpve,certPath,index);
0469: // }
0470: //
0471: // try
0472: // {
0473: // checkExcludedEmail(excludedSubtreesEmail, email);
0474: // }
0475: // catch (CertPathValidatorException cpve)
0476: // {
0477: // ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.excludedEmail",
0478: // new Object[] {new UntrustedInput(email)});
0479: // throw new CertPathReviewerException(msg,cpve,certPath,index);
0480: // }
0481: //
0482: // break;
0483: // case 4:
0484: // ASN1Sequence altDN = ASN1Sequence.getInstance(o, true);
0485: //
0486: // try
0487: // {
0488: // checkPermittedDN(permittedSubtreesDN, altDN);
0489: // }
0490: // catch (CertPathValidatorException cpve)
0491: // {
0492: // X509Name altDNName = new X509Name(altDN);
0493: // ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.notPermittedDN",
0494: // new Object[] {new UntrustedInput(altDNName)});
0495: // throw new CertPathReviewerException(msg,cpve,certPath,index);
0496: // }
0497: //
0498: // try
0499: // {
0500: // checkExcludedDN(excludedSubtreesDN, altDN);
0501: // }
0502: // catch (CertPathValidatorException cpve)
0503: // {
0504: // X509Name altDNName = new X509Name(altDN);
0505: // ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.excludedDN",
0506: // new Object[] {new UntrustedInput(altDNName)});
0507: // throw new CertPathReviewerException(msg,cpve,certPath,index);
0508: // }
0509: //
0510: // break;
0511: // case 7:
0512: // byte[] ip = ASN1OctetString.getInstance(o, true).getOctets();
0513: //
0514: // try
0515: // {
0516: // checkPermittedIP(permittedSubtreesIP, ip);
0517: // }
0518: // catch (CertPathValidatorException cpve)
0519: // {
0520: // ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.notPermittedIP",
0521: // new Object[] {IPtoString(ip)});
0522: // throw new CertPathReviewerException(msg,cpve,certPath,index);
0523: // }
0524: //
0525: // try
0526: // {
0527: // checkExcludedIP(excludedSubtreesIP, ip);
0528: // }
0529: // catch (CertPathValidatorException cpve)
0530: // {
0531: // ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.excludedIP",
0532: // new Object[] {IPtoString(ip)});
0533: // throw new CertPathReviewerException(msg,cpve,certPath,index);
0534: // }
0535: // }
0536: }
0537: }
0538: }
0539:
0540: //
0541: // prepare for next certificate
0542: //
0543:
0544: //
0545: // (g) handle the name constraints extension
0546: //
0547: ASN1Sequence ncSeq;
0548: try {
0549: ncSeq = (ASN1Sequence) getExtensionValue(cert,
0550: NAME_CONSTRAINTS);
0551: } catch (AnnotatedException ae) {
0552: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0553: "CertPathReviewer.ncExtError");
0554: throw new CertPathReviewerException(msg, ae,
0555: certPath, index);
0556: }
0557:
0558: if (ncSeq != null) {
0559: NameConstraints nc = new NameConstraints(ncSeq);
0560:
0561: //
0562: // (g) (1) permitted subtrees
0563: //
0564: ASN1Sequence permitted = nc.getPermittedSubtrees();
0565: if (permitted != null) {
0566: Enumeration e = permitted.getObjects();
0567: while (e.hasMoreElements()) {
0568: GeneralSubtree subtree = GeneralSubtree
0569: .getInstance(e.nextElement());
0570:
0571: nameConstraints
0572: .intersectPermittedSubtree(subtree);
0573: }
0574: }
0575:
0576: //
0577: // (g) (2) excluded subtrees
0578: //
0579: ASN1Sequence excluded = nc.getExcludedSubtrees();
0580: if (excluded != null) {
0581: Enumeration e = excluded.getObjects();
0582: while (e.hasMoreElements()) {
0583: GeneralSubtree subtree = GeneralSubtree
0584: .getInstance(e.nextElement());
0585:
0586: nameConstraints.addExcludedSubtree(subtree);
0587: }
0588: }
0589: }
0590:
0591: } // for
0592: } catch (CertPathReviewerException cpre) {
0593: addError(cpre.getErrorMessage(), cpre.getIndex());
0594: }
0595:
0596: }
0597:
0598: /*
0599: * checks: - path length constraints and reports - total path length
0600: */
0601: private void checkPathLength() {
0602: // init
0603: int maxPathLength = n;
0604: int totalPathLength = 0;
0605:
0606: X509Certificate cert = null;
0607:
0608: int i;
0609: for (int index = certs.size() - 1; index > 0; index--) {
0610: i = n - index;
0611:
0612: cert = (X509Certificate) certs.get(index);
0613:
0614: // l)
0615:
0616: if (!isSelfIssued(cert)) {
0617: if (maxPathLength <= 0) {
0618: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0619: "CertPathReviewer.pathLenghtExtended");
0620: addError(msg);
0621: }
0622: maxPathLength--;
0623: totalPathLength++;
0624: }
0625:
0626: // m)
0627:
0628: BasicConstraints bc;
0629: try {
0630: bc = BasicConstraints.getInstance(getExtensionValue(
0631: cert, BASIC_CONSTRAINTS));
0632: } catch (AnnotatedException ae) {
0633: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0634: "CertPathReviewer.processLengthConstError");
0635: addError(msg, index);
0636: bc = null;
0637: }
0638:
0639: if (bc != null) {
0640: BigInteger _pathLengthConstraint = bc
0641: .getPathLenConstraint();
0642:
0643: if (_pathLengthConstraint != null) {
0644: int _plc = _pathLengthConstraint.intValue();
0645:
0646: if (_plc < maxPathLength) {
0647: maxPathLength = _plc;
0648: }
0649: }
0650: }
0651:
0652: }
0653:
0654: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0655: "CertPathReviewer.totalPathLength",
0656: new Object[] { new Integer(totalPathLength) });
0657:
0658: addNotification(msg);
0659: }
0660:
0661: /*
0662: * checks: - signatures - name chaining - validity of certificates - todo:
0663: * if certificate revoked (if specified in the parameters)
0664: */
0665: private void checkSignatures() {
0666: // 1.6.1 - Inputs
0667:
0668: // d)
0669:
0670: TrustAnchor trust = null;
0671: X500Principal trustPrincipal = null;
0672:
0673: // validation date
0674: {
0675: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0676: "CertPathReviewer.certPathValidDate", new Object[] {
0677: new TrustedInput(validDate),
0678: new TrustedInput(new Date()) });
0679: addNotification(msg);
0680: }
0681:
0682: // find trust anchors
0683: try {
0684: X509Certificate cert = (X509Certificate) certs.get(certs
0685: .size() - 1);
0686: Collection trustColl = getTrustAnchors(cert, pkixParams
0687: .getTrustAnchors());
0688: if (trustColl.size() > 1) {
0689: // conflicting trust anchors
0690: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0691: "CertPathReviewer.conflictingTrustAnchors",
0692: new Object[] {
0693: new Integer(trustColl.size()),
0694: new UntrustedInput(cert
0695: .getIssuerX500Principal()) });
0696: addError(msg);
0697: } else if (trustColl.isEmpty()) {
0698: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0699: "CertPathReviewer.noTrustAnchorFound",
0700: new Object[] {
0701: new UntrustedInput(cert
0702: .getIssuerX500Principal()),
0703: new Integer(pkixParams
0704: .getTrustAnchors().size()) });
0705: addError(msg);
0706: } else {
0707: PublicKey trustPublicKey;
0708: trust = (TrustAnchor) trustColl.iterator().next();
0709: if (trust.getTrustedCert() != null) {
0710: trustPublicKey = trust.getTrustedCert()
0711: .getPublicKey();
0712: } else {
0713: trustPublicKey = trust.getCAPublicKey();
0714: }
0715: try {
0716: cert.verify(trustPublicKey);
0717: } catch (SignatureException e) {
0718: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0719: "CertPathReviewer.trustButInvalidCert");
0720: addError(msg);
0721: } catch (Exception e) {
0722: // do nothing, error occurs again later
0723: }
0724: }
0725: } catch (CertPathReviewerException cpre) {
0726: addError(cpre.getErrorMessage());
0727: }
0728:
0729: if (trust != null) {
0730: // get the name of the trustAnchor
0731: X509Certificate sign = trust.getTrustedCert();
0732: try {
0733: if (sign != null) {
0734: trustPrincipal = getSubjectPrincipal(sign);
0735: } else {
0736: trustPrincipal = new X500Principal(trust
0737: .getCAName());
0738: }
0739: } catch (IllegalArgumentException ex) {
0740: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0741: "CertPathReviewer.trustDNInvalid",
0742: new Object[] { new UntrustedInput(trust
0743: .getCAName()) });
0744: addError(msg);
0745: }
0746:
0747: // test key usages of the trust anchor
0748: if (sign != null) {
0749: boolean[] ku = sign.getKeyUsage();
0750: if (ku != null && !ku[5]) {
0751: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0752: "CertPathReviewer.trustKeyUsage");
0753: addNotification(msg);
0754: }
0755: }
0756: }
0757:
0758: // 1.6.2 - Initialization
0759:
0760: PublicKey workingPublicKey = null;
0761: X500Principal workingIssuerName = trustPrincipal;
0762:
0763: X509Certificate sign = null;
0764:
0765: AlgorithmIdentifier workingAlgId = null;
0766: DERObjectIdentifier workingPublicKeyAlgorithm = null;
0767: DEREncodable workingPublicKeyParameters = null;
0768:
0769: if (trust != null) {
0770: sign = trust.getTrustedCert();
0771:
0772: if (sign != null) {
0773: workingPublicKey = sign.getPublicKey();
0774: } else {
0775: workingPublicKey = trust.getCAPublicKey();
0776: }
0777:
0778: try {
0779: workingAlgId = getAlgorithmIdentifier(workingPublicKey);
0780: workingPublicKeyAlgorithm = workingAlgId.getObjectId();
0781: workingPublicKeyParameters = workingAlgId
0782: .getParameters();
0783: } catch (CertPathValidatorException ex) {
0784: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0785: "CertPathReviewer.trustPubKeyError");
0786: addError(msg);
0787: workingAlgId = null;
0788: }
0789:
0790: }
0791:
0792: // Basic cert checks
0793:
0794: X509Certificate cert = null;
0795: int i;
0796:
0797: for (int index = certs.size() - 1; index >= 0; index--) {
0798: //
0799: // i as defined in the algorithm description
0800: //
0801: i = n - index;
0802:
0803: //
0804: // set certificate to be checked in this round
0805: // sign and workingPublicKey and workingIssuerName are set
0806: // at the end of the for loop and initialied the
0807: // first time from the TrustAnchor
0808: //
0809: cert = (X509Certificate) certs.get(index);
0810:
0811: // verify signature
0812: if (workingPublicKey != null) {
0813: try {
0814: cert.verify(workingPublicKey, "BC");
0815: } catch (GeneralSecurityException ex) {
0816: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0817: "CertPathReviewer.signatureNotVerified",
0818: new Object[] { ex.getMessage(), ex,
0819: ex.getClass().getName() });
0820: addError(msg, index);
0821: }
0822: } else if (isSelfIssued(cert)) {
0823: try {
0824: cert.verify(cert.getPublicKey(), "BC");
0825: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0826: "CertPathReviewer.rootKeyIsValidButNotATrustAnchor");
0827: addError(msg, index);
0828: } catch (GeneralSecurityException ex) {
0829: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0830: "CertPathReviewer.signatureNotVerified",
0831: new Object[] { ex.getMessage(), ex,
0832: ex.getClass().getName() });
0833: addError(msg, index);
0834: }
0835: } else {
0836: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0837: "CertPathReviewer.NoIssuerPublicKey");
0838: // if there is an authority key extension add the serial and issuer of the missing certificate
0839: byte[] akiBytes = cert
0840: .getExtensionValue(X509Extensions.AuthorityKeyIdentifier
0841: .getId());
0842: if (akiBytes != null) {
0843: try {
0844: AuthorityKeyIdentifier aki = (AuthorityKeyIdentifier) X509ExtensionUtil
0845: .fromExtensionValue(akiBytes);
0846: GeneralNames issuerNames = aki
0847: .getAuthorityCertIssuer();
0848: if (issuerNames != null) {
0849: GeneralName name = issuerNames.getNames()[0];
0850: BigInteger serial = aki
0851: .getAuthorityCertSerialNumber();
0852: if (serial != null) {
0853: Object[] extraArgs = {
0854: new LocaleString(RESOURCE_NAME,
0855: "missingIssuer"),
0856: " \"",
0857: name,
0858: "\" ",
0859: new LocaleString(RESOURCE_NAME,
0860: "missingSerial"), " ",
0861: serial };
0862: msg.setExtraArguments(extraArgs);
0863: }
0864: }
0865: } catch (IOException e) {
0866: // ignore
0867: }
0868: }
0869: addError(msg, index);
0870: }
0871:
0872: // certificate valid?
0873: try {
0874: cert.checkValidity(validDate);
0875: } catch (CertificateNotYetValidException cnve) {
0876: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0877: "CertPathReviewer.certificateNotYetValid",
0878: new Object[] { new TrustedInput(cert
0879: .getNotBefore()) });
0880: addError(msg, index);
0881: } catch (CertificateExpiredException cee) {
0882: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0883: "CertPathReviewer.certificateExpired",
0884: new Object[] { new TrustedInput(cert
0885: .getNotAfter()) });
0886: addError(msg, index);
0887: }
0888:
0889: // certificate revoked?
0890: if (pkixParams.isRevocationEnabled()) {
0891: // read crl distribution points extension
0892: CRLDistPoint crlDistPoints = null;
0893: try {
0894: DERObject crl_dp = getExtensionValue(cert,
0895: CRL_DIST_POINTS);
0896: if (crl_dp != null) {
0897: crlDistPoints = CRLDistPoint
0898: .getInstance(crl_dp);
0899: }
0900: } catch (AnnotatedException ae) {
0901: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0902: "CertPathReviewer.crlDistPtExtError");
0903: addError(msg, index);
0904: }
0905:
0906: // read authority information access extension
0907: AuthorityInformationAccess authInfoAcc = null;
0908: try {
0909: DERObject auth_info_acc = getExtensionValue(cert,
0910: AUTH_INFO_ACCESS);
0911: if (auth_info_acc != null) {
0912: authInfoAcc = AuthorityInformationAccess
0913: .getInstance(auth_info_acc);
0914: }
0915: } catch (AnnotatedException ae) {
0916: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0917: "CertPathReviewer.crlAuthInfoAccError");
0918: addError(msg, index);
0919: }
0920:
0921: Vector crlDistPointUrls = getCRLDistUrls(crlDistPoints);
0922: Vector ocspUrls = getOCSPUrls(authInfoAcc);
0923:
0924: // add notifications with the crl distribution points
0925:
0926: // output crl distribution points
0927: Iterator urlIt = crlDistPointUrls.iterator();
0928: while (urlIt.hasNext()) {
0929: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0930: "CertPathReviewer.crlDistPoint",
0931: new Object[] { new UntrustedUrlInput(urlIt
0932: .next()) });
0933: addNotification(msg, index);
0934: }
0935:
0936: // output ocsp urls
0937: urlIt = ocspUrls.iterator();
0938: while (urlIt.hasNext()) {
0939: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0940: "CertPathReviewer.ocspLocation",
0941: new Object[] { new UntrustedUrlInput(urlIt
0942: .next()) });
0943: addNotification(msg, index);
0944: }
0945:
0946: // TODO also support Netscapes revocation-url and/or OCSP instead of CRLs for revocation checking
0947: // check CRLs
0948: try {
0949: checkRevocation(pkixParams, cert, validDate, sign,
0950: workingPublicKey, crlDistPointUrls,
0951: ocspUrls, index);
0952: } catch (CertPathReviewerException cpre) {
0953: addError(cpre.getErrorMessage(), index);
0954: }
0955: }
0956:
0957: // certificate issuer correct
0958: if (workingIssuerName != null
0959: && !cert.getIssuerX500Principal().equals(
0960: workingIssuerName)) {
0961: ErrorBundle msg = new ErrorBundle(
0962: RESOURCE_NAME,
0963: "CertPathReviewer.certWrongIssuer",
0964: new Object[] { workingIssuerName.getName(),
0965: cert.getIssuerX500Principal().getName() });
0966: addError(msg, index);
0967: }
0968:
0969: //
0970: // prepare for next certificate
0971: //
0972: if (i != n) {
0973:
0974: if (cert != null && cert.getVersion() == 1) {
0975: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
0976: "CertPathReviewer.noCACert");
0977: addError(msg, index);
0978: }
0979:
0980: // k)
0981:
0982: BasicConstraints bc;
0983: try {
0984: bc = BasicConstraints
0985: .getInstance(getExtensionValue(cert,
0986: BASIC_CONSTRAINTS));
0987: if (bc != null) {
0988: if (!bc.isCA()) {
0989: ErrorBundle msg = new ErrorBundle(
0990: RESOURCE_NAME,
0991: "CertPathReviewer.noCACert");
0992: addError(msg, index);
0993: }
0994: } else {
0995: ErrorBundle msg = new ErrorBundle(
0996: RESOURCE_NAME,
0997: "CertPathReviewer.noBasicConstraints");
0998: addError(msg, index);
0999: }
1000: } catch (AnnotatedException ae) {
1001: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1002: "CertPathReviewer.errorProcesingBC");
1003: addError(msg, index);
1004: }
1005:
1006: // n)
1007:
1008: boolean[] _usage = cert.getKeyUsage();
1009:
1010: if ((_usage != null) && !_usage[KEY_CERT_SIGN]) {
1011: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1012: "CertPathReviewer.noCertSign");
1013: addError(msg, index);
1014: }
1015:
1016: } // if
1017:
1018: // set signing certificate for next round
1019: sign = cert;
1020:
1021: // c)
1022:
1023: workingIssuerName = cert.getSubjectX500Principal();
1024:
1025: // d) e) f)
1026:
1027: try {
1028: workingPublicKey = getNextWorkingKey(sign, certs, index);
1029: workingAlgId = getAlgorithmIdentifier(workingPublicKey);
1030: workingPublicKeyAlgorithm = workingAlgId.getObjectId();
1031: workingPublicKeyParameters = workingAlgId
1032: .getParameters();
1033: } catch (CertPathValidatorException ex) {
1034: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1035: "CertPathReviewer.pubKeyError");
1036: addError(msg, index);
1037: workingAlgId = null;
1038: workingPublicKeyAlgorithm = null;
1039: workingPublicKeyParameters = null;
1040: }
1041:
1042: } // for
1043:
1044: trustAnchor = trust;
1045: subjectPublicKey = workingPublicKey;
1046: }
1047:
1048: private void checkPolicy() {
1049: //
1050: // 6.1.1 Inputs
1051: //
1052:
1053: // c) Initial Policy Set
1054:
1055: Set userInitialPolicySet = pkixParams.getInitialPolicies();
1056:
1057: // e) f) g) are part of pkixParams
1058:
1059: //
1060: // 6.1.2 Initialization
1061: //
1062:
1063: // a) valid policy tree
1064:
1065: List[] policyNodes = new ArrayList[n + 1];
1066: for (int j = 0; j < policyNodes.length; j++) {
1067: policyNodes[j] = new ArrayList();
1068: }
1069:
1070: Set policySet = new HashSet();
1071:
1072: policySet.add(ANY_POLICY);
1073:
1074: PKIXPolicyNode validPolicyTree = new PKIXPolicyNode(
1075: new ArrayList(), 0, policySet, null, new HashSet(),
1076: ANY_POLICY, false);
1077:
1078: policyNodes[0].add(validPolicyTree);
1079:
1080: // d) explicit policy
1081:
1082: int explicitPolicy;
1083: if (pkixParams.isExplicitPolicyRequired()) {
1084: explicitPolicy = 0;
1085: } else {
1086: explicitPolicy = n + 1;
1087: }
1088:
1089: // e) inhibit any policy
1090:
1091: int inhibitAnyPolicy;
1092: if (pkixParams.isAnyPolicyInhibited()) {
1093: inhibitAnyPolicy = 0;
1094: } else {
1095: inhibitAnyPolicy = n + 1;
1096: }
1097:
1098: // f) policy mapping
1099:
1100: int policyMapping;
1101: if (pkixParams.isPolicyMappingInhibited()) {
1102: policyMapping = 0;
1103: } else {
1104: policyMapping = n + 1;
1105: }
1106:
1107: Set acceptablePolicies = null;
1108:
1109: //
1110: // 6.1.3 Basic Certificate processing
1111: //
1112:
1113: X509Certificate cert = null;
1114: int index;
1115: int i;
1116:
1117: try {
1118: for (index = certs.size() - 1; index >= 0; index--) {
1119: // i as defined in the algorithm description
1120: i = n - index;
1121:
1122: // set certificate to be checked in this round
1123: cert = (X509Certificate) certs.get(index);
1124:
1125: // d) process policy information
1126:
1127: ASN1Sequence certPolicies;
1128: try {
1129: certPolicies = (ASN1Sequence) getExtensionValue(
1130: cert, CERTIFICATE_POLICIES);
1131: } catch (AnnotatedException ae) {
1132: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1133: "CertPathReviewer.policyExtError");
1134: throw new CertPathReviewerException(msg, ae,
1135: certPath, index);
1136: }
1137: if (certPolicies != null && validPolicyTree != null) {
1138:
1139: // d) 1)
1140:
1141: Enumeration e = certPolicies.getObjects();
1142: Set pols = new HashSet();
1143:
1144: while (e.hasMoreElements()) {
1145: PolicyInformation pInfo = PolicyInformation
1146: .getInstance(e.nextElement());
1147: DERObjectIdentifier pOid = pInfo
1148: .getPolicyIdentifier();
1149:
1150: pols.add(pOid.getId());
1151:
1152: if (!ANY_POLICY.equals(pOid.getId())) {
1153: Set pq;
1154: try {
1155: pq = getQualifierSet(pInfo
1156: .getPolicyQualifiers());
1157: } catch (CertPathValidatorException cpve) {
1158: ErrorBundle msg = new ErrorBundle(
1159: RESOURCE_NAME,
1160: "CertPathReviewer.policyQualifierError");
1161: throw new CertPathReviewerException(
1162: msg, cpve, certPath, index);
1163: }
1164:
1165: boolean match = processCertD1i(i,
1166: policyNodes, pOid, pq);
1167:
1168: if (!match) {
1169: processCertD1ii(i, policyNodes, pOid,
1170: pq);
1171: }
1172: }
1173: }
1174:
1175: if (acceptablePolicies == null
1176: || acceptablePolicies.contains(ANY_POLICY)) {
1177: acceptablePolicies = pols;
1178: } else {
1179: Iterator it = acceptablePolicies.iterator();
1180: Set t1 = new HashSet();
1181:
1182: while (it.hasNext()) {
1183: Object o = it.next();
1184:
1185: if (pols.contains(o)) {
1186: t1.add(o);
1187: }
1188: }
1189:
1190: acceptablePolicies = t1;
1191: }
1192:
1193: // d) 2)
1194:
1195: if ((inhibitAnyPolicy > 0)
1196: || ((i < n) && isSelfIssued(cert))) {
1197: e = certPolicies.getObjects();
1198:
1199: while (e.hasMoreElements()) {
1200: PolicyInformation pInfo = PolicyInformation
1201: .getInstance(e.nextElement());
1202:
1203: if (ANY_POLICY.equals(pInfo
1204: .getPolicyIdentifier().getId())) {
1205: Set _apq;
1206: try {
1207: _apq = getQualifierSet(pInfo
1208: .getPolicyQualifiers());
1209: } catch (CertPathValidatorException cpve) {
1210: ErrorBundle msg = new ErrorBundle(
1211: RESOURCE_NAME,
1212: "CertPathReviewer.policyQualifierError");
1213: throw new CertPathReviewerException(
1214: msg, cpve, certPath, index);
1215: }
1216: List _nodes = policyNodes[i - 1];
1217:
1218: for (int k = 0; k < _nodes.size(); k++) {
1219: PKIXPolicyNode _node = (PKIXPolicyNode) _nodes
1220: .get(k);
1221:
1222: Iterator _policySetIter = _node
1223: .getExpectedPolicies()
1224: .iterator();
1225: while (_policySetIter.hasNext()) {
1226: Object _tmp = _policySetIter
1227: .next();
1228:
1229: String _policy;
1230: if (_tmp instanceof String) {
1231: _policy = (String) _tmp;
1232: } else if (_tmp instanceof DERObjectIdentifier) {
1233: _policy = ((DERObjectIdentifier) _tmp)
1234: .getId();
1235: } else {
1236: continue;
1237: }
1238:
1239: boolean _found = false;
1240: Iterator _childrenIter = _node
1241: .getChildren();
1242:
1243: while (_childrenIter.hasNext()) {
1244: PKIXPolicyNode _child = (PKIXPolicyNode) _childrenIter
1245: .next();
1246:
1247: if (_policy.equals(_child
1248: .getValidPolicy())) {
1249: _found = true;
1250: }
1251: }
1252:
1253: if (!_found) {
1254: Set _newChildExpectedPolicies = new HashSet();
1255: _newChildExpectedPolicies
1256: .add(_policy);
1257:
1258: PKIXPolicyNode _newChild = new PKIXPolicyNode(
1259: new ArrayList(),
1260: i,
1261: _newChildExpectedPolicies,
1262: _node, _apq,
1263: _policy, false);
1264: _node.addChild(_newChild);
1265: policyNodes[i]
1266: .add(_newChild);
1267: }
1268: }
1269: }
1270: break;
1271: }
1272: }
1273: }
1274:
1275: //
1276: // (d) (3)
1277: //
1278: for (int j = (i - 1); j >= 0; j--) {
1279: List nodes = policyNodes[j];
1280:
1281: for (int k = 0; k < nodes.size(); k++) {
1282: PKIXPolicyNode node = (PKIXPolicyNode) nodes
1283: .get(k);
1284: if (!node.hasChildren()) {
1285: validPolicyTree = removePolicyNode(
1286: validPolicyTree, policyNodes,
1287: node);
1288: if (validPolicyTree == null) {
1289: break;
1290: }
1291: }
1292: }
1293: }
1294:
1295: //
1296: // d (4)
1297: //
1298: Set criticalExtensionOids = cert
1299: .getCriticalExtensionOIDs();
1300:
1301: if (criticalExtensionOids != null) {
1302: boolean critical = criticalExtensionOids
1303: .contains(CERTIFICATE_POLICIES);
1304:
1305: List nodes = policyNodes[i];
1306: for (int j = 0; j < nodes.size(); j++) {
1307: PKIXPolicyNode node = (PKIXPolicyNode) nodes
1308: .get(j);
1309: node.setCritical(critical);
1310: }
1311: }
1312:
1313: }
1314:
1315: // e)
1316:
1317: if (certPolicies == null) {
1318: validPolicyTree = null;
1319: }
1320:
1321: // f)
1322:
1323: if (explicitPolicy <= 0 && validPolicyTree == null) {
1324: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1325: "CertPathReviewer.noValidPolicyTree");
1326: throw new CertPathReviewerException(msg);
1327: }
1328:
1329: //
1330: // 6.1.4 preparation for next Certificate
1331: //
1332:
1333: if (i != n) {
1334:
1335: // a)
1336:
1337: DERObject pm;
1338: try {
1339: pm = getExtensionValue(cert, POLICY_MAPPINGS);
1340: } catch (AnnotatedException ae) {
1341: ErrorBundle msg = new ErrorBundle(
1342: RESOURCE_NAME,
1343: "CertPathReviewer.policyMapExtError");
1344: throw new CertPathReviewerException(msg, ae,
1345: certPath, index);
1346: }
1347:
1348: if (pm != null) {
1349: ASN1Sequence mappings = (ASN1Sequence) pm;
1350: for (int j = 0; j < mappings.size(); j++) {
1351: ASN1Sequence mapping = (ASN1Sequence) mappings
1352: .getObjectAt(j);
1353: DERObjectIdentifier ip_id = (DERObjectIdentifier) mapping
1354: .getObjectAt(0);
1355: DERObjectIdentifier sp_id = (DERObjectIdentifier) mapping
1356: .getObjectAt(1);
1357: if (ANY_POLICY.equals(ip_id.getId())) {
1358: ErrorBundle msg = new ErrorBundle(
1359: RESOURCE_NAME,
1360: "CertPathReviewer.invalidPolicyMapping");
1361: throw new CertPathReviewerException(
1362: msg, certPath, index);
1363: }
1364: if (ANY_POLICY.equals(sp_id.getId())) {
1365: ErrorBundle msg = new ErrorBundle(
1366: RESOURCE_NAME,
1367: "CertPathReviewer.invalidPolicyMapping");
1368: throw new CertPathReviewerException(
1369: msg, certPath, index);
1370: }
1371: }
1372: }
1373:
1374: // b)
1375:
1376: if (pm != null) {
1377: ASN1Sequence mappings = (ASN1Sequence) pm;
1378: Map m_idp = new HashMap();
1379: Set s_idp = new HashSet();
1380:
1381: for (int j = 0; j < mappings.size(); j++) {
1382: ASN1Sequence mapping = (ASN1Sequence) mappings
1383: .getObjectAt(j);
1384: String id_p = ((DERObjectIdentifier) mapping
1385: .getObjectAt(0)).getId();
1386: String sd_p = ((DERObjectIdentifier) mapping
1387: .getObjectAt(1)).getId();
1388: Set tmp;
1389:
1390: if (!m_idp.containsKey(id_p)) {
1391: tmp = new HashSet();
1392: tmp.add(sd_p);
1393: m_idp.put(id_p, tmp);
1394: s_idp.add(id_p);
1395: } else {
1396: tmp = (Set) m_idp.get(id_p);
1397: tmp.add(sd_p);
1398: }
1399: }
1400:
1401: Iterator it_idp = s_idp.iterator();
1402: while (it_idp.hasNext()) {
1403: String id_p = (String) it_idp.next();
1404:
1405: //
1406: // (1)
1407: //
1408: if (policyMapping > 0) {
1409: try {
1410: prepareNextCertB1(i, policyNodes,
1411: id_p, m_idp, cert);
1412: } catch (AnnotatedException ae) {
1413: // error processing certificate policies extension
1414: ErrorBundle msg = new ErrorBundle(
1415: RESOURCE_NAME,
1416: "CertPathReviewer.policyExtError");
1417: throw new CertPathReviewerException(
1418: msg, ae, certPath, index);
1419: } catch (CertPathValidatorException cpve) {
1420: // error building qualifier set
1421: ErrorBundle msg = new ErrorBundle(
1422: RESOURCE_NAME,
1423: "CertPathReviewer.policyQualifierError");
1424: throw new CertPathReviewerException(
1425: msg, cpve, certPath, index);
1426: }
1427:
1428: //
1429: // (2)
1430: //
1431: } else if (policyMapping <= 0) {
1432: validPolicyTree = prepareNextCertB2(i,
1433: policyNodes, id_p,
1434: validPolicyTree);
1435: }
1436:
1437: }
1438: }
1439:
1440: //
1441: // h)
1442: //
1443:
1444: if (!isSelfIssued(cert)) {
1445:
1446: // (1)
1447: if (explicitPolicy != 0) {
1448: explicitPolicy--;
1449: }
1450:
1451: // (2)
1452: if (policyMapping != 0) {
1453: policyMapping--;
1454: }
1455:
1456: // (3)
1457: if (inhibitAnyPolicy != 0) {
1458: inhibitAnyPolicy--;
1459: }
1460:
1461: }
1462:
1463: //
1464: // i)
1465: //
1466:
1467: try {
1468: ASN1Sequence pc = (ASN1Sequence) getExtensionValue(
1469: cert, POLICY_CONSTRAINTS);
1470: if (pc != null) {
1471: Enumeration policyConstraints = pc
1472: .getObjects();
1473:
1474: while (policyConstraints.hasMoreElements()) {
1475: ASN1TaggedObject constraint = (ASN1TaggedObject) policyConstraints
1476: .nextElement();
1477: int tmpInt;
1478:
1479: switch (constraint.getTagNo()) {
1480: case 0:
1481: tmpInt = DERInteger.getInstance(
1482: constraint).getValue()
1483: .intValue();
1484: if (tmpInt < explicitPolicy) {
1485: explicitPolicy = tmpInt;
1486: }
1487: break;
1488: case 1:
1489: tmpInt = DERInteger.getInstance(
1490: constraint).getValue()
1491: .intValue();
1492: if (tmpInt < policyMapping) {
1493: policyMapping = tmpInt;
1494: }
1495: break;
1496: }
1497: }
1498: }
1499: } catch (AnnotatedException ae) {
1500: ErrorBundle msg = new ErrorBundle(
1501: RESOURCE_NAME,
1502: "CertPathReviewer.policyConstExtError");
1503: throw new CertPathReviewerException(msg,
1504: certPath, index);
1505: }
1506:
1507: //
1508: // j)
1509: //
1510:
1511: try {
1512: DERInteger iap = (DERInteger) getExtensionValue(
1513: cert, INHIBIT_ANY_POLICY);
1514:
1515: if (iap != null) {
1516: int _inhibitAnyPolicy = iap.getValue()
1517: .intValue();
1518:
1519: if (_inhibitAnyPolicy < inhibitAnyPolicy) {
1520: inhibitAnyPolicy = _inhibitAnyPolicy;
1521: }
1522: }
1523: } catch (AnnotatedException ae) {
1524: ErrorBundle msg = new ErrorBundle(
1525: RESOURCE_NAME,
1526: "CertPathReviewer.policyInhibitExtError");
1527: throw new CertPathReviewerException(msg,
1528: certPath, index);
1529: }
1530: }
1531:
1532: }
1533:
1534: //
1535: // 6.1.5 Wrap up
1536: //
1537:
1538: //
1539: // a)
1540: //
1541:
1542: if (!isSelfIssued(cert) && explicitPolicy > 0) {
1543: explicitPolicy--;
1544: }
1545:
1546: //
1547: // b)
1548: //
1549:
1550: try {
1551: ASN1Sequence pc = (ASN1Sequence) getExtensionValue(
1552: cert, POLICY_CONSTRAINTS);
1553: if (pc != null) {
1554: Enumeration policyConstraints = pc.getObjects();
1555:
1556: while (policyConstraints.hasMoreElements()) {
1557: ASN1TaggedObject constraint = (ASN1TaggedObject) policyConstraints
1558: .nextElement();
1559: switch (constraint.getTagNo()) {
1560: case 0:
1561: int tmpInt = DERInteger.getInstance(
1562: constraint).getValue().intValue();
1563: if (tmpInt == 0) {
1564: explicitPolicy = 0;
1565: }
1566: break;
1567: }
1568: }
1569: }
1570: } catch (AnnotatedException e) {
1571: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1572: "CertPathReviewer.policyConstExtError");
1573: throw new CertPathReviewerException(msg, certPath,
1574: index);
1575: }
1576:
1577: //
1578: // (g)
1579: //
1580: PKIXPolicyNode intersection;
1581:
1582: //
1583: // (g) (i)
1584: //
1585: if (validPolicyTree == null) {
1586: if (pkixParams.isExplicitPolicyRequired()) {
1587: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1588: "CertPathReviewer.explicitPolicy");
1589: throw new CertPathReviewerException(msg, certPath,
1590: index);
1591: }
1592: intersection = null;
1593: } else if (isAnyPolicy(userInitialPolicySet)) // (g) (ii)
1594: {
1595: if (pkixParams.isExplicitPolicyRequired()) {
1596: if (acceptablePolicies.isEmpty()) {
1597: ErrorBundle msg = new ErrorBundle(
1598: RESOURCE_NAME,
1599: "CertPathReviewer.explicitPolicy");
1600: throw new CertPathReviewerException(msg,
1601: certPath, index);
1602: } else {
1603: Set _validPolicyNodeSet = new HashSet();
1604:
1605: for (int j = 0; j < policyNodes.length; j++) {
1606: List _nodeDepth = policyNodes[j];
1607:
1608: for (int k = 0; k < _nodeDepth.size(); k++) {
1609: PKIXPolicyNode _node = (PKIXPolicyNode) _nodeDepth
1610: .get(k);
1611:
1612: if (ANY_POLICY.equals(_node
1613: .getValidPolicy())) {
1614: Iterator _iter = _node
1615: .getChildren();
1616: while (_iter.hasNext()) {
1617: _validPolicyNodeSet.add(_iter
1618: .next());
1619: }
1620: }
1621: }
1622: }
1623:
1624: Iterator _vpnsIter = _validPolicyNodeSet
1625: .iterator();
1626: while (_vpnsIter.hasNext()) {
1627: PKIXPolicyNode _node = (PKIXPolicyNode) _vpnsIter
1628: .next();
1629: String _validPolicy = _node
1630: .getValidPolicy();
1631:
1632: if (!acceptablePolicies
1633: .contains(_validPolicy)) {
1634: //validPolicyTree = removePolicyNode(validPolicyTree, policyNodes, _node);
1635: }
1636: }
1637: if (validPolicyTree != null) {
1638: for (int j = (n - 1); j >= 0; j--) {
1639: List nodes = policyNodes[j];
1640:
1641: for (int k = 0; k < nodes.size(); k++) {
1642: PKIXPolicyNode node = (PKIXPolicyNode) nodes
1643: .get(k);
1644: if (!node.hasChildren()) {
1645: validPolicyTree = removePolicyNode(
1646: validPolicyTree,
1647: policyNodes, node);
1648: }
1649: }
1650: }
1651: }
1652: }
1653: }
1654:
1655: intersection = validPolicyTree;
1656: } else {
1657: //
1658: // (g) (iii)
1659: //
1660: // This implementation is not exactly same as the one described in RFC3280.
1661: // However, as far as the validation result is concerned, both produce
1662: // adequate result. The only difference is whether AnyPolicy is remain
1663: // in the policy tree or not.
1664: //
1665: // (g) (iii) 1
1666: //
1667: Set _validPolicyNodeSet = new HashSet();
1668:
1669: for (int j = 0; j < policyNodes.length; j++) {
1670: List _nodeDepth = policyNodes[j];
1671:
1672: for (int k = 0; k < _nodeDepth.size(); k++) {
1673: PKIXPolicyNode _node = (PKIXPolicyNode) _nodeDepth
1674: .get(k);
1675:
1676: if (ANY_POLICY.equals(_node.getValidPolicy())) {
1677: Iterator _iter = _node.getChildren();
1678: while (_iter.hasNext()) {
1679: PKIXPolicyNode _c_node = (PKIXPolicyNode) _iter
1680: .next();
1681: if (!ANY_POLICY.equals(_c_node
1682: .getValidPolicy())) {
1683: _validPolicyNodeSet.add(_c_node);
1684: }
1685: }
1686: }
1687: }
1688: }
1689:
1690: //
1691: // (g) (iii) 2
1692: //
1693: Iterator _vpnsIter = _validPolicyNodeSet.iterator();
1694: while (_vpnsIter.hasNext()) {
1695: PKIXPolicyNode _node = (PKIXPolicyNode) _vpnsIter
1696: .next();
1697: String _validPolicy = _node.getValidPolicy();
1698:
1699: if (!userInitialPolicySet.contains(_validPolicy)) {
1700: validPolicyTree = removePolicyNode(
1701: validPolicyTree, policyNodes, _node);
1702: }
1703: }
1704:
1705: //
1706: // (g) (iii) 4
1707: //
1708: if (validPolicyTree != null) {
1709: for (int j = (n - 1); j >= 0; j--) {
1710: List nodes = policyNodes[j];
1711:
1712: for (int k = 0; k < nodes.size(); k++) {
1713: PKIXPolicyNode node = (PKIXPolicyNode) nodes
1714: .get(k);
1715: if (!node.hasChildren()) {
1716: validPolicyTree = removePolicyNode(
1717: validPolicyTree, policyNodes,
1718: node);
1719: }
1720: }
1721: }
1722: }
1723:
1724: intersection = validPolicyTree;
1725: }
1726:
1727: if ((explicitPolicy <= 0) && (intersection == null)) {
1728: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1729: "CertPathReviewer.invalidPolicy");
1730: throw new CertPathReviewerException(msg);
1731: }
1732:
1733: validPolicyTree = intersection;
1734: } catch (CertPathReviewerException cpre) {
1735: addError(cpre.getErrorMessage(), cpre.getIndex());
1736: validPolicyTree = null;
1737: }
1738: }
1739:
1740: private void checkCriticalExtensions() {
1741: //
1742: // initialise CertPathChecker's
1743: //
1744: List pathCheckers = pkixParams.getCertPathCheckers();
1745: Iterator certIter = pathCheckers.iterator();
1746:
1747: try {
1748: try {
1749: while (certIter.hasNext()) {
1750: ((PKIXCertPathChecker) certIter.next()).init(false);
1751: }
1752: } catch (CertPathValidatorException cpve) {
1753: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1754: "CertPathReviewer.certPathCheckerError",
1755: new Object[] { cpve.getMessage(), cpve,
1756: cpve.getClass().getName() });
1757: throw new CertPathReviewerException(msg, cpve);
1758: }
1759:
1760: //
1761: // process critical extesions for each certificate
1762: //
1763:
1764: X509Certificate cert = null;
1765:
1766: int index;
1767:
1768: for (index = certs.size() - 1; index >= 0; index--) {
1769: cert = (X509Certificate) certs.get(index);
1770:
1771: Set criticalExtensions = cert
1772: .getCriticalExtensionOIDs();
1773: if (criticalExtensions == null
1774: || criticalExtensions.isEmpty()) {
1775: continue;
1776: }
1777: // remove already processed extensions
1778: criticalExtensions.remove(KEY_USAGE);
1779: criticalExtensions.remove(CERTIFICATE_POLICIES);
1780: criticalExtensions.remove(POLICY_MAPPINGS);
1781: criticalExtensions.remove(INHIBIT_ANY_POLICY);
1782: criticalExtensions.remove(ISSUING_DISTRIBUTION_POINT);
1783: criticalExtensions.remove(DELTA_CRL_INDICATOR);
1784: criticalExtensions.remove(POLICY_CONSTRAINTS);
1785: criticalExtensions.remove(BASIC_CONSTRAINTS);
1786: criticalExtensions.remove(SUBJECT_ALTERNATIVE_NAME);
1787: criticalExtensions.remove(NAME_CONSTRAINTS);
1788:
1789: // process qcStatements extension
1790: if (criticalExtensions.contains(QC_STATEMENT)) {
1791: if (processQcStatements(cert, index)) {
1792: criticalExtensions.remove(QC_STATEMENT);
1793: }
1794: }
1795:
1796: Iterator tmpIter = pathCheckers.iterator();
1797: while (tmpIter.hasNext()) {
1798: try {
1799: ((PKIXCertPathChecker) tmpIter.next()).check(
1800: cert, criticalExtensions);
1801: } catch (CertPathValidatorException e) {
1802: ErrorBundle msg = new ErrorBundle(
1803: RESOURCE_NAME,
1804: "CertPathReviewer.criticalExtensionError",
1805: new Object[] { e.getMessage(), e,
1806: e.getClass().getName() });
1807: throw new CertPathReviewerException(msg, e
1808: .getCause(), certPath, index);
1809: }
1810: }
1811: if (!criticalExtensions.isEmpty()) {
1812: ErrorBundle msg;
1813: Iterator it = criticalExtensions.iterator();
1814: while (it.hasNext()) {
1815: msg = new ErrorBundle(RESOURCE_NAME,
1816: "CertPathReviewer.unknownCriticalExt",
1817: new Object[] { new DERObjectIdentifier(
1818: (String) it.next()) });
1819: addError(msg, index);
1820: }
1821: }
1822: }
1823: } catch (CertPathReviewerException cpre) {
1824: addError(cpre.getErrorMessage(), cpre.getIndex());
1825: }
1826: }
1827:
1828: private boolean processQcStatements(X509Certificate cert, int index) {
1829: try {
1830: boolean unknownStatement = false;
1831:
1832: ASN1Sequence qcSt = (ASN1Sequence) getExtensionValue(cert,
1833: QC_STATEMENT);
1834: for (int j = 0; j < qcSt.size(); j++) {
1835: QCStatement stmt = QCStatement.getInstance(qcSt
1836: .getObjectAt(j));
1837: if (QCStatement.id_etsi_qcs_QcCompliance.equals(stmt
1838: .getStatementId())) {
1839: // process statement - just write a notification that the certificate contains this statement
1840: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1841: "CertPathReviewer.QcEuCompliance");
1842: addNotification(msg, index);
1843: } else if (QCStatement.id_qcs_pkixQCSyntax_v1
1844: .equals(stmt.getStatementId())) {
1845: // process statement - just recognize the statement
1846: } else if (QCStatement.id_etsi_qcs_QcSSCD.equals(stmt
1847: .getStatementId())) {
1848: // process statement - just write a notification that the certificate contains this statement
1849: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1850: "CertPathReviewer.QcSSCD");
1851: addNotification(msg, index);
1852: } else if (QCStatement.id_etsi_qcs_LimiteValue
1853: .equals(stmt.getStatementId())) {
1854: // process statement - write a notification containing the limit value
1855: MonetaryValue limit = MonetaryValue
1856: .getInstance(stmt.getStatementInfo());
1857: Iso4217CurrencyCode currency = limit.getCurrency();
1858: double value = limit.getAmount().doubleValue()
1859: * Math.pow(10, limit.getExponent()
1860: .doubleValue());
1861: ErrorBundle msg;
1862: if (limit.getCurrency().isAlphabetic()) {
1863: msg = new ErrorBundle(RESOURCE_NAME,
1864: "CertPathReviewer.QcLimitValueAlpha",
1865: new Object[] {
1866: limit.getCurrency()
1867: .getAlphabetic(),
1868: new TrustedInput(new Double(
1869: value)), limit });
1870: } else {
1871: msg = new ErrorBundle(RESOURCE_NAME,
1872: "CertPathReviewer.QcLimitValueNum",
1873: new Object[] {
1874: new Integer(limit.getCurrency()
1875: .getNumeric()),
1876: new TrustedInput(new Double(
1877: value)), limit });
1878: }
1879: addNotification(msg, index);
1880: } else {
1881: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1882: "CertPathReviewer.QcUnknownStatement",
1883: new Object[] { stmt.getStatementId(),
1884: new UntrustedInput(stmt) });
1885: addNotification(msg, index);
1886: unknownStatement = true;
1887: }
1888: }
1889:
1890: return !unknownStatement;
1891: } catch (AnnotatedException ae) {
1892: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1893: "CertPathReviewer.QcStatementExtError");
1894: addError(msg, index);
1895: }
1896:
1897: return false;
1898: }
1899:
1900: private String IPtoString(byte[] ip) {
1901: String result;
1902: try {
1903: result = InetAddress.getByAddress(ip).getHostAddress();
1904: } catch (Exception e) {
1905: StringBuffer b = new StringBuffer();
1906:
1907: for (int i = 0; i != ip.length; i++) {
1908: b.append(Integer.toHexString(ip[i] & 0xff));
1909: b.append(' ');
1910: }
1911:
1912: result = b.toString();
1913: }
1914:
1915: return result;
1916: }
1917:
1918: protected void checkRevocation(PKIXParameters paramsPKIX,
1919: X509Certificate cert, Date validDate, X509Certificate sign,
1920: PublicKey workingPublicKey, Vector crlDistPointUrls,
1921: Vector ocspUrls, int index)
1922: throws CertPathReviewerException {
1923: checkCRLs(paramsPKIX, cert, validDate, sign, workingPublicKey,
1924: crlDistPointUrls, index);
1925: }
1926:
1927: protected void checkCRLs(PKIXParameters paramsPKIX,
1928: X509Certificate cert, Date validDate, X509Certificate sign,
1929: PublicKey workingPublicKey, Vector crlDistPointUrls,
1930: int index) throws CertPathReviewerException {
1931: X509CRLSelector crlselect;
1932: crlselect = new X509CRLSelector();
1933:
1934: try {
1935: crlselect.addIssuerName(getEncodedIssuerPrincipal(cert)
1936: .getEncoded());
1937: } catch (IOException e) {
1938: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1939: "CertPathReviewer.crlIssuerException");
1940: throw new CertPathReviewerException(msg, e);
1941: }
1942:
1943: crlselect.setCertificateChecking(cert);
1944:
1945: Iterator crl_iter;
1946: try {
1947: Collection crl_coll = findCRLs(crlselect, paramsPKIX
1948: .getCertStores());
1949: crl_iter = crl_coll.iterator();
1950:
1951: if (crl_coll.isEmpty()) {
1952: // notifcation - no local crls found
1953: crl_coll = findCRLs(new X509CRLSelector(), paramsPKIX
1954: .getCertStores());
1955: Iterator it = crl_coll.iterator();
1956: List nonMatchingCrlNames = new ArrayList();
1957: while (it.hasNext()) {
1958: nonMatchingCrlNames.add(((X509CRL) it.next())
1959: .getIssuerX500Principal());
1960: }
1961: int numbOfCrls = nonMatchingCrlNames.size();
1962: ErrorBundle msg = new ErrorBundle(
1963: RESOURCE_NAME,
1964: "CertPathReviewer.noCrlInCertstore",
1965: new Object[] {
1966: new UntrustedInput(crlselect
1967: .getIssuers()),
1968: new UntrustedInput(nonMatchingCrlNames),
1969: new Integer(numbOfCrls) });
1970: addNotification(msg, index);
1971: }
1972:
1973: } catch (AnnotatedException ae) {
1974: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1975: "CertPathReviewer.crlExtractionError",
1976: new Object[] { ae.getCause().getMessage(),
1977: ae.getCause(),
1978: ae.getCause().getClass().getName() });
1979: addError(msg, index);
1980: crl_iter = new ArrayList().iterator();
1981: }
1982: boolean validCrlFound = false;
1983: X509CRL crl = null;
1984: while (crl_iter.hasNext()) {
1985: crl = (X509CRL) crl_iter.next();
1986:
1987: if (crl.getNextUpdate() == null
1988: || new Date().before(crl.getNextUpdate())) {
1989: validCrlFound = true;
1990: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1991: "CertPathReviewer.localValidCRL", new Object[] {
1992: new TrustedInput(crl.getThisUpdate()),
1993: new TrustedInput(crl.getNextUpdate()) });
1994: addNotification(msg, index);
1995: break;
1996: } else {
1997: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
1998: "CertPathReviewer.localInvalidCRL",
1999: new Object[] {
2000: new TrustedInput(crl.getThisUpdate()),
2001: new TrustedInput(crl.getNextUpdate()) });
2002: addNotification(msg, index);
2003: }
2004: }
2005:
2006: // if no valid crl was found in the CertStores try to get one from a
2007: // crl distribution point
2008: if (!validCrlFound) {
2009: X509CRL onlineCRL = null;
2010: Iterator urlIt = crlDistPointUrls.iterator();
2011: while (urlIt.hasNext()) {
2012: try {
2013: String location = (String) urlIt.next();
2014: onlineCRL = getCRL(location);
2015: if (onlineCRL != null) {
2016: // check if crl issuer is correct
2017: if (!cert.getIssuerX500Principal().equals(
2018: onlineCRL.getIssuerX500Principal())) {
2019: ErrorBundle msg = new ErrorBundle(
2020: RESOURCE_NAME,
2021: "CertPathReviewer.onlineCRLWrongCA",
2022: new Object[] {
2023: new UntrustedInput(
2024: onlineCRL
2025: .getIssuerX500Principal()
2026: .getName()),
2027: new UntrustedInput(
2028: cert
2029: .getIssuerX500Principal()
2030: .getName()),
2031: new UntrustedUrlInput(
2032: location) });
2033: addNotification(msg, index);
2034: continue;
2035: }
2036:
2037: if (onlineCRL.getNextUpdate() == null
2038: || new Date().before(onlineCRL
2039: .getNextUpdate())) {
2040: validCrlFound = true;
2041: ErrorBundle msg = new ErrorBundle(
2042: RESOURCE_NAME,
2043: "CertPathReviewer.onlineValidCRL",
2044: new Object[] {
2045: new TrustedInput(onlineCRL
2046: .getThisUpdate()),
2047: new TrustedInput(onlineCRL
2048: .getNextUpdate()),
2049: new UntrustedUrlInput(
2050: location) });
2051: addNotification(msg, index);
2052: crl = onlineCRL;
2053: break;
2054: } else {
2055: ErrorBundle msg = new ErrorBundle(
2056: RESOURCE_NAME,
2057: "CertPathReviewer.onlineInvalidCRL",
2058: new Object[] {
2059: new TrustedInput(onlineCRL
2060: .getThisUpdate()),
2061: new TrustedInput(onlineCRL
2062: .getNextUpdate()),
2063: new UntrustedUrlInput(
2064: location) });
2065: addNotification(msg, index);
2066: }
2067: }
2068: } catch (CertPathReviewerException cpre) {
2069: addNotification(cpre.getErrorMessage(), index);
2070: }
2071: }
2072: }
2073:
2074: // check the crl
2075: X509CRLEntry crl_entry;
2076: if (crl != null) {
2077: if (sign != null) {
2078: boolean[] keyusage = sign.getKeyUsage();
2079:
2080: if (keyusage != null
2081: && (keyusage.length < 7 || !keyusage[CRL_SIGN])) {
2082: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2083: "CertPathReviewer.noCrlSigningPermited");
2084: throw new CertPathReviewerException(msg);
2085: }
2086: }
2087:
2088: if (workingPublicKey != null) {
2089: try {
2090: crl.verify(workingPublicKey, "BC");
2091: } catch (Exception e) {
2092: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2093: "CertPathReviewer.crlVerifyFailed");
2094: throw new CertPathReviewerException(msg, e);
2095: }
2096: } else // issuer public key not known
2097: {
2098: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2099: "CertPathReviewer.crlNoIssuerPublicKey");
2100: throw new CertPathReviewerException(msg);
2101: }
2102:
2103: crl_entry = crl.getRevokedCertificate(cert
2104: .getSerialNumber());
2105: if (crl_entry != null) {
2106: String reason = null;
2107:
2108: if (crl_entry.hasExtensions()) {
2109: DEREnumerated reasonCode;
2110: try {
2111: reasonCode = DEREnumerated
2112: .getInstance(getExtensionValue(
2113: crl_entry,
2114: X509Extensions.ReasonCode
2115: .getId()));
2116: } catch (AnnotatedException ae) {
2117: ErrorBundle msg = new ErrorBundle(
2118: RESOURCE_NAME,
2119: "CertPathReviewer.crlReasonExtError");
2120: throw new CertPathReviewerException(msg, ae);
2121: }
2122: if (reasonCode != null) {
2123: reason = crlReasons[reasonCode.getValue()
2124: .intValue()];
2125: } else {
2126: reason = crlReasons[7];
2127: }
2128: }
2129:
2130: // i18n reason
2131: LocaleString ls = new LocaleString(RESOURCE_NAME,
2132: reason);
2133:
2134: if (!validDate.before(crl_entry.getRevocationDate())) {
2135: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2136: "CertPathReviewer.certRevoked",
2137: new Object[] {
2138: new TrustedInput(crl_entry
2139: .getRevocationDate()), ls });
2140: throw new CertPathReviewerException(msg);
2141: } else // cert was revoked after validation date
2142: {
2143: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2144: "CertPathReviewer.revokedAfterValidation",
2145: new Object[] {
2146: new TrustedInput(crl_entry
2147: .getRevocationDate()), ls });
2148: addNotification(msg, index);
2149: }
2150: } else // cert is not revoked
2151: {
2152: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2153: "CertPathReviewer.notRevoked");
2154: addNotification(msg, index);
2155: }
2156:
2157: //
2158: // warn if a new crl is available
2159: //
2160: if (crl.getNextUpdate() != null
2161: && crl.getNextUpdate().before(new Date())) {
2162: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2163: "CertPathReviewer.crlUpdateAvailable",
2164: new Object[] { new TrustedInput(crl
2165: .getNextUpdate()) });
2166: addNotification(msg, index);
2167: }
2168:
2169: //
2170: // check the DeltaCRL indicator, base point and the issuing distribution point
2171: //
2172: DERObject idp;
2173: try {
2174: idp = getExtensionValue(crl, ISSUING_DISTRIBUTION_POINT);
2175: } catch (AnnotatedException ae) {
2176: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2177: "CertPathReviewer.distrPtExtError");
2178: throw new CertPathReviewerException(msg);
2179: }
2180: DERObject dci;
2181: try {
2182: dci = getExtensionValue(crl, DELTA_CRL_INDICATOR);
2183: } catch (AnnotatedException ae) {
2184: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2185: "CertPathReviewer.deltaCrlExtError");
2186: throw new CertPathReviewerException(msg);
2187: }
2188:
2189: if (dci != null) {
2190: X509CRLSelector baseSelect = new X509CRLSelector();
2191:
2192: try {
2193: baseSelect.addIssuerName(getIssuerPrincipal(crl)
2194: .getEncoded());
2195: } catch (IOException e) {
2196: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2197: "CertPathReviewer.crlIssuerException");
2198: throw new CertPathReviewerException(msg, e);
2199: }
2200:
2201: baseSelect.setMinCRLNumber(((DERInteger) dci)
2202: .getPositiveValue());
2203: try {
2204: baseSelect
2205: .setMaxCRLNumber(((DERInteger) getExtensionValue(
2206: crl, CRL_NUMBER))
2207: .getPositiveValue().subtract(
2208: BigInteger.valueOf(1)));
2209: } catch (AnnotatedException ae) {
2210: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2211: "CertPathReviewer.crlNbrExtError");
2212: throw new CertPathReviewerException(msg, ae);
2213: }
2214:
2215: boolean foundBase = false;
2216: Iterator it;
2217: try {
2218: it = findCRLs(baseSelect,
2219: paramsPKIX.getCertStores()).iterator();
2220: } catch (AnnotatedException ae) {
2221: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2222: "CertPathReviewer.crlExtractionError");
2223: throw new CertPathReviewerException(msg, ae);
2224: }
2225: while (it.hasNext()) {
2226: X509CRL base = (X509CRL) it.next();
2227:
2228: DERObject baseIdp;
2229: try {
2230: baseIdp = getExtensionValue(base,
2231: ISSUING_DISTRIBUTION_POINT);
2232: } catch (AnnotatedException ae) {
2233: ErrorBundle msg = new ErrorBundle(
2234: RESOURCE_NAME,
2235: "CertPathReviewer.distrPtExtError");
2236: throw new CertPathReviewerException(msg, ae);
2237: }
2238:
2239: if (idp == null) {
2240: if (baseIdp == null) {
2241: foundBase = true;
2242: break;
2243: }
2244: } else {
2245: if (idp.equals(baseIdp)) {
2246: foundBase = true;
2247: break;
2248: }
2249: }
2250: }
2251:
2252: if (!foundBase) {
2253: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2254: "CertPathReviewer.noBaseCRL");
2255: throw new CertPathReviewerException(msg);
2256: }
2257: }
2258:
2259: if (idp != null) {
2260: IssuingDistributionPoint p = IssuingDistributionPoint
2261: .getInstance(idp);
2262: BasicConstraints bc = null;
2263: try {
2264: bc = BasicConstraints
2265: .getInstance(getExtensionValue(cert,
2266: BASIC_CONSTRAINTS));
2267: } catch (AnnotatedException ae) {
2268: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2269: "CertPathReviewer.crlBCExtError");
2270: throw new CertPathReviewerException(msg, ae);
2271: }
2272:
2273: if (p.onlyContainsUserCerts()
2274: && (bc != null && bc.isCA())) {
2275: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2276: "CertPathReviewer.crlOnlyUserCert");
2277: throw new CertPathReviewerException(msg);
2278: }
2279:
2280: if (p.onlyContainsCACerts()
2281: && (bc == null || !bc.isCA())) {
2282: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2283: "CertPathReviewer.crlOnlyCaCert");
2284: throw new CertPathReviewerException(msg);
2285: }
2286:
2287: if (p.onlyContainsAttributeCerts()) {
2288: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2289: "CertPathReviewer.crlOnlyAttrCert");
2290: throw new CertPathReviewerException(msg);
2291: }
2292: }
2293: }
2294:
2295: if (!validCrlFound) {
2296: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2297: "CertPathReviewer.noValidCrlFound");
2298: throw new CertPathReviewerException(msg);
2299: }
2300:
2301: }
2302:
2303: protected Vector getCRLDistUrls(CRLDistPoint crlDistPoints) {
2304: Vector urls = new Vector();
2305:
2306: if (crlDistPoints != null) {
2307: DistributionPoint[] distPoints = crlDistPoints
2308: .getDistributionPoints();
2309: for (int i = 0; i < distPoints.length; i++) {
2310: DistributionPointName dp_name = distPoints[i]
2311: .getDistributionPoint();
2312: if (dp_name.getType() == DistributionPointName.FULL_NAME) {
2313: GeneralName[] generalNames = GeneralNames
2314: .getInstance(dp_name.getName()).getNames();
2315: for (int j = 0; j < generalNames.length; j++) {
2316: if (generalNames[j].getTagNo() == GeneralName.uniformResourceIdentifier) {
2317: String url = ((DERIA5String) generalNames[j]
2318: .getName()).getString();
2319: urls.add(url);
2320: }
2321: }
2322: }
2323: }
2324: }
2325: return urls;
2326: }
2327:
2328: protected Vector getOCSPUrls(
2329: AuthorityInformationAccess authInfoAccess) {
2330: Vector urls = new Vector();
2331:
2332: if (authInfoAccess != null) {
2333: AccessDescription[] ads = authInfoAccess
2334: .getAccessDescriptions();
2335: for (int i = 0; i < ads.length; i++) {
2336: if (ads[i].getAccessMethod().equals(
2337: AccessDescription.id_ad_ocsp)) {
2338: GeneralName name = ads[i].getAccessLocation();
2339: if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
2340: String url = ((DERIA5String) name.getName())
2341: .getString();
2342: urls.add(url);
2343: }
2344: }
2345: }
2346: }
2347:
2348: return urls;
2349: }
2350:
2351: private X509CRL getCRL(String location)
2352: throws CertPathReviewerException {
2353: X509CRL result = null;
2354: try {
2355: URL url = new URL(location);
2356:
2357: if (url.getProtocol().equals("http")
2358: || url.getProtocol().equals("https")) {
2359: HttpURLConnection conn = (HttpURLConnection) url
2360: .openConnection();
2361: conn.setUseCaches(false);
2362: conn.setConnectTimeout(2000);
2363: conn.setDoInput(true);
2364: conn.connect();
2365: if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
2366: CertificateFactory cf = CertificateFactory
2367: .getInstance("X.509", "BC");
2368: result = (X509CRL) cf.generateCRL(conn
2369: .getInputStream());
2370: } else {
2371: throw new Exception(conn.getResponseMessage());
2372: }
2373: }
2374: } catch (Exception e) {
2375: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2376: "CertPathReviewer.loadCrlDistPointError",
2377: new Object[] { new UntrustedInput(location),
2378: e.getMessage(), e, e.getClass().getName() });
2379: throw new CertPathReviewerException(msg);
2380: }
2381: return result;
2382: }
2383:
2384: private Collection getTrustAnchors(X509Certificate cert,
2385: Set trustanchors) throws CertPathReviewerException {
2386: Collection trustColl = new ArrayList();
2387: Iterator it = trustanchors.iterator();
2388:
2389: X509CertSelector certSelectX509 = new X509CertSelector();
2390:
2391: try {
2392: certSelectX509.setSubject(getEncodedIssuerPrincipal(cert)
2393: .getEncoded());
2394: } catch (IOException ex) {
2395: ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
2396: "CertPathReviewer.trustAnchorIssuerError");
2397: throw new CertPathReviewerException(msg);
2398: }
2399:
2400: while (it.hasNext()) {
2401: TrustAnchor trust = (TrustAnchor) it.next();
2402: if (trust.getTrustedCert() != null) {
2403: if (certSelectX509.match(trust.getTrustedCert())) {
2404: trustColl.add(trust);
2405: }
2406: } else if (trust.getCAName() != null
2407: && trust.getCAPublicKey() != null) {
2408: X500Principal certIssuer = getEncodedIssuerPrincipal(cert);
2409: X500Principal caName = new X500Principal(trust
2410: .getCAName());
2411: if (certIssuer.equals(caName)) {
2412: trustColl.add(trust);
2413: }
2414: }
2415: }
2416: return trustColl;
2417: }
2418: }
|