602 * {@code X509Certificate} that has no extendedKeyUsage extension
603 * implicitly allows all key purposes.
604 * <p>
605 * Note that the {@code Set} is cloned to protect against
606 * subsequent modifications.
607 *
608 * @param keyPurposeSet a {@code Set} of key purpose OIDs in string
609 * format (or {@code null}). Each OID is represented by a set of
610 * nonnegative integers separated by periods.
611 * @throws IOException if the OID is invalid, such as
612 * the first component being not 0, 1 or 2 or the second component
613 * being greater than 39.
614 * @see #getExtendedKeyUsage
615 */
616 public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException {
617 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
618 this.keyPurposeSet = null;
619 keyPurposeOIDSet = null;
620 } else {
621 this.keyPurposeSet =
622 Collections.unmodifiableSet(new HashSet<String>(keyPurposeSet));
623 keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
624 for (String s : this.keyPurposeSet) {
625 keyPurposeOIDSet.add(new ObjectIdentifier(s));
626 }
627 }
628 }
629
630 /**
631 * Enables/disables matching all of the subjectAlternativeNames
632 * specified in the {@link #setSubjectAlternativeNames
633 * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
634 * addSubjectAlternativeName} methods. If enabled,
635 * the {@code X509Certificate} must contain all of the
636 * specified subject alternative names. If disabled, the
637 * {@code X509Certificate} must contain at least one of the
638 * specified subject alternative names.
639 *
640 * <p>The matchAllNames flag is {@code true} by default.
641 *
642 * @param matchAllNames if {@code true}, the flag is enabled;
643 * if {@code false}, the flag is disabled.
798 throws IOException {
799 // clone because byte arrays are modifiable
800 addSubjectAlternativeNameInternal(type, name.clone());
801 }
802
803 /**
804 * A private method that adds a name (String or byte array) to the
805 * subjectAlternativeNames criterion. The {@code X509Certificate}
806 * must contain the specified subjectAlternativeName.
807 *
808 * @param type the name type (0-8, as specified in
809 * RFC 5280, section 4.2.1.6)
810 * @param name the name in string or byte array form
811 * @throws IOException if a parsing error occurs
812 */
813 private void addSubjectAlternativeNameInternal(int type, Object name)
814 throws IOException {
815 // First, ensure that the name parses
816 GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
817 if (subjectAlternativeNames == null) {
818 subjectAlternativeNames = new HashSet<List<?>>();
819 }
820 if (subjectAlternativeGeneralNames == null) {
821 subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
822 }
823 List<Object> list = new ArrayList<Object>(2);
824 list.add(Integer.valueOf(type));
825 list.add(name);
826 subjectAlternativeNames.add(list);
827 subjectAlternativeGeneralNames.add(tempName);
828 }
829
830 /**
831 * Parse an argument of the form passed to setSubjectAlternativeNames,
832 * returning a {@code Collection} of
833 * {@code GeneralNameInterface}s.
834 * Throw an IllegalArgumentException or a ClassCastException
835 * if the argument is malformed.
836 *
837 * @param names a Collection with one entry per name.
838 * Each entry is a {@code List} whose first entry
839 * is an Integer (the name type, 0-8) and whose second
840 * entry is a String or a byte array (the name, in
841 * string or ASN.1 DER encoded form, respectively).
842 * There can be multiple names of the same type. Null is
843 * not an acceptable value.
844 * @return a Set of {@code GeneralNameInterface}s
845 * @throws IOException if a parsing error occurs
846 */
847 private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException {
848 Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
849 for (List<?> nameList : names) {
850 if (nameList.size() != 2) {
851 throw new IOException("name list size not 2");
852 }
853 Object o = nameList.get(0);
854 if (!(o instanceof Integer)) {
855 throw new IOException("expected an Integer");
856 }
857 int nameType = ((Integer)o).intValue();
858 o = nameList.get(1);
859 genNames.add(makeGeneralNameInterface(nameType, o));
860 }
861
862 return genNames;
863 }
864
865 /**
866 * Compare for equality two objects of the form passed to
867 * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
868 * Throw an {@code IllegalArgumentException} or a
1079 * <p>
1080 * Note that the {@code Set} is cloned to protect against
1081 * subsequent modifications.
1082 *
1083 * @param certPolicySet a {@code Set} of certificate policy OIDs in
1084 * string format (or {@code null}). Each OID is
1085 * represented by a set of nonnegative integers
1086 * separated by periods.
1087 * @throws IOException if a parsing error occurs on the OID such as
1088 * the first component is not 0, 1 or 2 or the second component is
1089 * greater than 39.
1090 * @see #getPolicy
1091 */
1092 public void setPolicy(Set<String> certPolicySet) throws IOException {
1093 if (certPolicySet == null) {
1094 policySet = null;
1095 policy = null;
1096 } else {
1097 // Snapshot set and parse it
1098 Set<String> tempSet = Collections.unmodifiableSet
1099 (new HashSet<String>(certPolicySet));
1100 /* Convert to Vector of ObjectIdentifiers */
1101 Iterator<String> i = tempSet.iterator();
1102 Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>();
1103 while (i.hasNext()) {
1104 Object o = i.next();
1105 if (!(o instanceof String)) {
1106 throw new IOException("non String in certPolicySet");
1107 }
1108 polIdVector.add(new CertificatePolicyId(new ObjectIdentifier(
1109 (String)o)));
1110 }
1111 // If everything went OK, make the changes
1112 policySet = tempSet;
1113 policy = new CertificatePolicySet(polIdVector);
1114 }
1115 }
1116
1117 /**
1118 * Sets the pathToNames criterion. The {@code X509Certificate} must
1119 * not include name constraints that would prohibit building a
1120 * path to the specified names.
1121 * <p>
1122 * This method allows the caller to specify, with a single method call,
1250 public void addPathToName(int type, byte [] name) throws IOException {
1251 // clone because byte arrays are modifiable
1252 addPathToNameInternal(type, name.clone());
1253 }
1254
1255 /**
1256 * A private method that adds a name (String or byte array) to the
1257 * pathToNames criterion. The {@code X509Certificate} must contain
1258 * the specified pathToName.
1259 *
1260 * @param type the name type (0-8, as specified in
1261 * RFC 5280, section 4.2.1.6)
1262 * @param name the name in string or byte array form
1263 * @throws IOException if an encoding error occurs (incorrect form for DN)
1264 */
1265 private void addPathToNameInternal(int type, Object name)
1266 throws IOException {
1267 // First, ensure that the name parses
1268 GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
1269 if (pathToGeneralNames == null) {
1270 pathToNames = new HashSet<List<?>>();
1271 pathToGeneralNames = new HashSet<GeneralNameInterface>();
1272 }
1273 List<Object> list = new ArrayList<Object>(2);
1274 list.add(Integer.valueOf(type));
1275 list.add(name);
1276 pathToNames.add(list);
1277 pathToGeneralNames.add(tempName);
1278 }
1279
1280 /**
1281 * Returns the certificateEquals criterion. The specified
1282 * {@code X509Certificate} must be equal to the
1283 * {@code X509Certificate} passed to the {@code match} method.
1284 * If {@code null}, this check is not applied.
1285 *
1286 * @return the {@code X509Certificate} to match (or {@code null})
1287 * @see #setCertificate
1288 */
1289 public X509Certificate getCertificate() {
1290 return x509Cert;
1291 }
1292
1293 /**
1654 }
1655 }
1656
1657 /**
1658 * Clone and check an argument of the form passed to
1659 * setSubjectAlternativeNames and setPathToNames.
1660 * Throw an {@code IOException} if the argument is malformed.
1661 *
1662 * @param names a {@code Collection} with one entry per name.
1663 * Each entry is a {@code List} whose first entry
1664 * is an Integer (the name type, 0-8) and whose second
1665 * entry is a String or a byte array (the name, in
1666 * string or ASN.1 DER encoded form, respectively).
1667 * There can be multiple names of the same type.
1668 * {@code null} is not an acceptable value.
1669 * @return a deep copy of the specified {@code Collection}
1670 * @throws IOException if a parsing error occurs
1671 */
1672 private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
1673 // Copy the Lists and Collection
1674 Set<List<?>> namesCopy = new HashSet<List<?>>();
1675 for (List<?> o : names)
1676 {
1677 namesCopy.add(new ArrayList<Object>(o));
1678 }
1679
1680 // Check the contents of the Lists and clone any byte arrays
1681 for (List<?> list : namesCopy) {
1682 @SuppressWarnings("unchecked") // See javadoc for parameter "names".
1683 List<Object> nameList = (List<Object>)list;
1684 if (nameList.size() != 2) {
1685 throw new IOException("name list size not 2");
1686 }
1687 Object o = nameList.get(0);
1688 if (!(o instanceof Integer)) {
1689 throw new IOException("expected an Integer");
1690 }
1691 int nameType = ((Integer)o).intValue();
1692 if ((nameType < 0) || (nameType > 8)) {
1693 throw new IOException("name type not 0-8");
1694 }
1695 Object nameObject = nameList.get(1);
1696 if (!(nameObject instanceof byte[]) &&
1697 !(nameObject instanceof String)) {
2380 /* match on policy OIDs */
2381 private boolean matchPolicy(X509Certificate xcert) {
2382 if (policy == null) {
2383 return true;
2384 }
2385 try {
2386 CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
2387 getExtensionObject(xcert, CERT_POLICIES_ID);
2388 if (ext == null) {
2389 if (debug != null) {
2390 debug.println("X509CertSelector.match: "
2391 + "no certificate policy extension");
2392 }
2393 return false;
2394 }
2395 List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);
2396 /*
2397 * Convert the Vector of PolicyInformation to a Vector
2398 * of CertificatePolicyIds for easier comparison.
2399 */
2400 List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
2401 for (PolicyInformation info : policies) {
2402 policyIDs.add(info.getPolicyIdentifier());
2403 }
2404 if (policy != null) {
2405 boolean foundOne = false;
2406 /*
2407 * if the user passes in an empty policy Set, then
2408 * we just want to make sure that the candidate certificate
2409 * has some policy OID in its CertPoliciesExtension
2410 */
2411 if (policy.getCertPolicyIds().isEmpty()) {
2412 if (policyIDs.isEmpty()) {
2413 if (debug != null) {
2414 debug.println("X509CertSelector.match: "
2415 + "cert failed policyAny criterion");
2416 }
2417 return false;
2418 }
2419 } else {
2420 for (CertificatePolicyId id : policy.getCertPolicyIds()) {
|
602 * {@code X509Certificate} that has no extendedKeyUsage extension
603 * implicitly allows all key purposes.
604 * <p>
605 * Note that the {@code Set} is cloned to protect against
606 * subsequent modifications.
607 *
608 * @param keyPurposeSet a {@code Set} of key purpose OIDs in string
609 * format (or {@code null}). Each OID is represented by a set of
610 * nonnegative integers separated by periods.
611 * @throws IOException if the OID is invalid, such as
612 * the first component being not 0, 1 or 2 or the second component
613 * being greater than 39.
614 * @see #getExtendedKeyUsage
615 */
616 public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException {
617 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
618 this.keyPurposeSet = null;
619 keyPurposeOIDSet = null;
620 } else {
621 this.keyPurposeSet =
622 Collections.unmodifiableSet(new HashSet<>(keyPurposeSet));
623 keyPurposeOIDSet = new HashSet<>();
624 for (String s : this.keyPurposeSet) {
625 keyPurposeOIDSet.add(new ObjectIdentifier(s));
626 }
627 }
628 }
629
630 /**
631 * Enables/disables matching all of the subjectAlternativeNames
632 * specified in the {@link #setSubjectAlternativeNames
633 * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
634 * addSubjectAlternativeName} methods. If enabled,
635 * the {@code X509Certificate} must contain all of the
636 * specified subject alternative names. If disabled, the
637 * {@code X509Certificate} must contain at least one of the
638 * specified subject alternative names.
639 *
640 * <p>The matchAllNames flag is {@code true} by default.
641 *
642 * @param matchAllNames if {@code true}, the flag is enabled;
643 * if {@code false}, the flag is disabled.
798 throws IOException {
799 // clone because byte arrays are modifiable
800 addSubjectAlternativeNameInternal(type, name.clone());
801 }
802
803 /**
804 * A private method that adds a name (String or byte array) to the
805 * subjectAlternativeNames criterion. The {@code X509Certificate}
806 * must contain the specified subjectAlternativeName.
807 *
808 * @param type the name type (0-8, as specified in
809 * RFC 5280, section 4.2.1.6)
810 * @param name the name in string or byte array form
811 * @throws IOException if a parsing error occurs
812 */
813 private void addSubjectAlternativeNameInternal(int type, Object name)
814 throws IOException {
815 // First, ensure that the name parses
816 GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
817 if (subjectAlternativeNames == null) {
818 subjectAlternativeNames = new HashSet<>();
819 }
820 if (subjectAlternativeGeneralNames == null) {
821 subjectAlternativeGeneralNames = new HashSet<>();
822 }
823 List<Object> list = new ArrayList<>(2);
824 list.add(Integer.valueOf(type));
825 list.add(name);
826 subjectAlternativeNames.add(list);
827 subjectAlternativeGeneralNames.add(tempName);
828 }
829
830 /**
831 * Parse an argument of the form passed to setSubjectAlternativeNames,
832 * returning a {@code Collection} of
833 * {@code GeneralNameInterface}s.
834 * Throw an IllegalArgumentException or a ClassCastException
835 * if the argument is malformed.
836 *
837 * @param names a Collection with one entry per name.
838 * Each entry is a {@code List} whose first entry
839 * is an Integer (the name type, 0-8) and whose second
840 * entry is a String or a byte array (the name, in
841 * string or ASN.1 DER encoded form, respectively).
842 * There can be multiple names of the same type. Null is
843 * not an acceptable value.
844 * @return a Set of {@code GeneralNameInterface}s
845 * @throws IOException if a parsing error occurs
846 */
847 private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException {
848 Set<GeneralNameInterface> genNames = new HashSet<>();
849 for (List<?> nameList : names) {
850 if (nameList.size() != 2) {
851 throw new IOException("name list size not 2");
852 }
853 Object o = nameList.get(0);
854 if (!(o instanceof Integer)) {
855 throw new IOException("expected an Integer");
856 }
857 int nameType = ((Integer)o).intValue();
858 o = nameList.get(1);
859 genNames.add(makeGeneralNameInterface(nameType, o));
860 }
861
862 return genNames;
863 }
864
865 /**
866 * Compare for equality two objects of the form passed to
867 * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
868 * Throw an {@code IllegalArgumentException} or a
1079 * <p>
1080 * Note that the {@code Set} is cloned to protect against
1081 * subsequent modifications.
1082 *
1083 * @param certPolicySet a {@code Set} of certificate policy OIDs in
1084 * string format (or {@code null}). Each OID is
1085 * represented by a set of nonnegative integers
1086 * separated by periods.
1087 * @throws IOException if a parsing error occurs on the OID such as
1088 * the first component is not 0, 1 or 2 or the second component is
1089 * greater than 39.
1090 * @see #getPolicy
1091 */
1092 public void setPolicy(Set<String> certPolicySet) throws IOException {
1093 if (certPolicySet == null) {
1094 policySet = null;
1095 policy = null;
1096 } else {
1097 // Snapshot set and parse it
1098 Set<String> tempSet = Collections.unmodifiableSet
1099 (new HashSet<>(certPolicySet));
1100 /* Convert to Vector of ObjectIdentifiers */
1101 Iterator<String> i = tempSet.iterator();
1102 Vector<CertificatePolicyId> polIdVector = new Vector<>();
1103 while (i.hasNext()) {
1104 Object o = i.next();
1105 if (!(o instanceof String)) {
1106 throw new IOException("non String in certPolicySet");
1107 }
1108 polIdVector.add(new CertificatePolicyId(new ObjectIdentifier(
1109 (String)o)));
1110 }
1111 // If everything went OK, make the changes
1112 policySet = tempSet;
1113 policy = new CertificatePolicySet(polIdVector);
1114 }
1115 }
1116
1117 /**
1118 * Sets the pathToNames criterion. The {@code X509Certificate} must
1119 * not include name constraints that would prohibit building a
1120 * path to the specified names.
1121 * <p>
1122 * This method allows the caller to specify, with a single method call,
1250 public void addPathToName(int type, byte [] name) throws IOException {
1251 // clone because byte arrays are modifiable
1252 addPathToNameInternal(type, name.clone());
1253 }
1254
1255 /**
1256 * A private method that adds a name (String or byte array) to the
1257 * pathToNames criterion. The {@code X509Certificate} must contain
1258 * the specified pathToName.
1259 *
1260 * @param type the name type (0-8, as specified in
1261 * RFC 5280, section 4.2.1.6)
1262 * @param name the name in string or byte array form
1263 * @throws IOException if an encoding error occurs (incorrect form for DN)
1264 */
1265 private void addPathToNameInternal(int type, Object name)
1266 throws IOException {
1267 // First, ensure that the name parses
1268 GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
1269 if (pathToGeneralNames == null) {
1270 pathToNames = new HashSet<>();
1271 pathToGeneralNames = new HashSet<>();
1272 }
1273 List<Object> list = new ArrayList<>(2);
1274 list.add(Integer.valueOf(type));
1275 list.add(name);
1276 pathToNames.add(list);
1277 pathToGeneralNames.add(tempName);
1278 }
1279
1280 /**
1281 * Returns the certificateEquals criterion. The specified
1282 * {@code X509Certificate} must be equal to the
1283 * {@code X509Certificate} passed to the {@code match} method.
1284 * If {@code null}, this check is not applied.
1285 *
1286 * @return the {@code X509Certificate} to match (or {@code null})
1287 * @see #setCertificate
1288 */
1289 public X509Certificate getCertificate() {
1290 return x509Cert;
1291 }
1292
1293 /**
1654 }
1655 }
1656
1657 /**
1658 * Clone and check an argument of the form passed to
1659 * setSubjectAlternativeNames and setPathToNames.
1660 * Throw an {@code IOException} if the argument is malformed.
1661 *
1662 * @param names a {@code Collection} with one entry per name.
1663 * Each entry is a {@code List} whose first entry
1664 * is an Integer (the name type, 0-8) and whose second
1665 * entry is a String or a byte array (the name, in
1666 * string or ASN.1 DER encoded form, respectively).
1667 * There can be multiple names of the same type.
1668 * {@code null} is not an acceptable value.
1669 * @return a deep copy of the specified {@code Collection}
1670 * @throws IOException if a parsing error occurs
1671 */
1672 private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
1673 // Copy the Lists and Collection
1674 Set<List<?>> namesCopy = new HashSet<>();
1675 for (List<?> o : names)
1676 {
1677 namesCopy.add(new ArrayList<>(o));
1678 }
1679
1680 // Check the contents of the Lists and clone any byte arrays
1681 for (List<?> list : namesCopy) {
1682 @SuppressWarnings("unchecked") // See javadoc for parameter "names".
1683 List<Object> nameList = (List<Object>)list;
1684 if (nameList.size() != 2) {
1685 throw new IOException("name list size not 2");
1686 }
1687 Object o = nameList.get(0);
1688 if (!(o instanceof Integer)) {
1689 throw new IOException("expected an Integer");
1690 }
1691 int nameType = ((Integer)o).intValue();
1692 if ((nameType < 0) || (nameType > 8)) {
1693 throw new IOException("name type not 0-8");
1694 }
1695 Object nameObject = nameList.get(1);
1696 if (!(nameObject instanceof byte[]) &&
1697 !(nameObject instanceof String)) {
2380 /* match on policy OIDs */
2381 private boolean matchPolicy(X509Certificate xcert) {
2382 if (policy == null) {
2383 return true;
2384 }
2385 try {
2386 CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
2387 getExtensionObject(xcert, CERT_POLICIES_ID);
2388 if (ext == null) {
2389 if (debug != null) {
2390 debug.println("X509CertSelector.match: "
2391 + "no certificate policy extension");
2392 }
2393 return false;
2394 }
2395 List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);
2396 /*
2397 * Convert the Vector of PolicyInformation to a Vector
2398 * of CertificatePolicyIds for easier comparison.
2399 */
2400 List<CertificatePolicyId> policyIDs = new ArrayList<>(policies.size());
2401 for (PolicyInformation info : policies) {
2402 policyIDs.add(info.getPolicyIdentifier());
2403 }
2404 if (policy != null) {
2405 boolean foundOne = false;
2406 /*
2407 * if the user passes in an empty policy Set, then
2408 * we just want to make sure that the candidate certificate
2409 * has some policy OID in its CertPoliciesExtension
2410 */
2411 if (policy.getCertPolicyIds().isEmpty()) {
2412 if (policyIDs.isEmpty()) {
2413 if (debug != null) {
2414 debug.println("X509CertSelector.match: "
2415 + "cert failed policyAny criterion");
2416 }
2417 return false;
2418 }
2419 } else {
2420 for (CertificatePolicyId id : policy.getCertPolicyIds()) {
|