1 7 8 package java.security.cert; 9 10 import java.io.IOException ; 11 import java.math.BigInteger ; 12 import java.security.PublicKey ; 13 import java.util.*; 14 import javax.security.auth.x500.X500Principal ; 15 16 import sun.misc.HexDumpEncoder; 17 import sun.security.util.Debug; 18 import sun.security.util.DerInputStream; 19 import sun.security.util.DerValue; 20 import sun.security.util.ObjectIdentifier; 21 import sun.security.x509.*; 22 23 68 public class X509CertSelector implements CertSelector { 69 70 private static final Debug debug = Debug.getInstance("certpath"); 71 72 private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE = 73 ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0}); 74 75 static { 76 CertPathHelperImpl.initialize(); 77 } 78 79 private BigInteger serialNumber; 80 private X500Principal issuer; 81 private X500Principal subject; 82 private byte[] subjectKeyID; 83 private byte[] authorityKeyID; 84 private Date certificateValid; 85 private Date privateKeyValid; 86 private ObjectIdentifier subjectPublicKeyAlgID; 87 private PublicKey subjectPublicKey; 88 private byte[] subjectPublicKeyBytes; 89 private boolean[] keyUsage; 90 private Set<String > keyPurposeSet; 91 private Set<ObjectIdentifier> keyPurposeOIDSet; 92 private Set<List<?>> subjectAlternativeNames; 93 private Set<GeneralNameInterface> subjectAlternativeGeneralNames; 94 private CertificatePolicySet policy; 95 private Set<String > policySet; 96 private Set<List<?>> pathToNames; 97 private Set<GeneralNameInterface> pathToGeneralNames; 98 private NameConstraintsExtension nc; 99 private byte[] ncBytes; 100 private int basicConstraints = -1; 101 private X509Certificate x509Cert; 102 private boolean matchAllSubjectAltNames = true; 103 104 private static final Boolean FALSE = Boolean.FALSE; 105 106 private static final int PRIVATE_KEY_USAGE_ID = 0; 107 private static final int SUBJECT_ALT_NAME_ID = 1; 108 private static final int NAME_CONSTRAINTS_ID = 2; 109 private static final int CERT_POLICIES_ID = 3; 110 private static final int EXTENDED_KEY_USAGE_ID = 4; 111 private static final int NUM_OF_EXTENSIONS = 5; 112 private static final String [] EXTENSION_OIDS = new String [NUM_OF_EXTENSIONS]; 113 114 static { 115 EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16"; 116 EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17"; 117 EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30"; 118 EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32"; 119 EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37"; 120 }; 121 122 123 static final int NAME_ANY = 0; 124 static final int NAME_RFC822 = 1; 125 static final int NAME_DNS = 2; 126 static final int NAME_X400 = 3; 127 static final int NAME_DIRECTORY = 4; 128 static final int NAME_EDI = 5; 129 static final int NAME_URI = 6; 130 static final int NAME_IP = 7; 131 static final int NAME_OID = 8; 132 133 137 public X509CertSelector() { 138 } 140 141 156 public void setCertificate(X509Certificate cert) { 157 x509Cert = cert; 158 } 159 160 170 public void setSerialNumber(BigInteger serial) { 171 serialNumber = serial; 172 } 173 174 184 public void setIssuer(X500Principal issuer) { 185 this.issuer = issuer; 186 } 187 188 207 public void setIssuer(String issuerDN) throws IOException { 208 if (issuerDN == null) { 209 issuer = null; 210 } else { 211 issuer = new X500Name(issuerDN).asX500Principal(); 212 } 213 } 214 215 257 public void setIssuer(byte[] issuerDN) throws IOException { 258 try { 259 issuer = (issuerDN == null ? null : new X500Principal (issuerDN)); 260 } catch (IllegalArgumentException e) { 261 throw (IOException )new IOException ("Invalid name").initCause(e); 262 } 263 } 264 265 275 public void setSubject(X500Principal subject) { 276 this.subject = subject; 277 } 278 279 298 public void setSubject(String subjectDN) throws IOException { 299 if (subjectDN == null) { 300 subject = null; 301 } else { 302 subject = new X500Name(subjectDN).asX500Principal(); 303 } 304 } 305 306 321 public void setSubject(byte[] subjectDN) throws IOException { 322 try { 323 subject = (subjectDN == null ? null : new X500Principal (subjectDN)); 324 } catch (IllegalArgumentException e) { 325 throw (IOException )new IOException ("Invalid name").initCause(e); 326 } 327 } 328 329 361 public void setSubjectKeyIdentifier(byte[] subjectKeyID) { 362 if (subjectKeyID == null) { 363 this.subjectKeyID = null; 364 } else { 365 this.subjectKeyID = (byte[])subjectKeyID.clone(); 366 } 367 } 368 369 422 public void setAuthorityKeyIdentifier(byte[] authorityKeyID) { 423 if (authorityKeyID == null) { 424 this.authorityKeyID = null; 425 } else { 426 this.authorityKeyID = (byte[])authorityKeyID.clone(); 427 } 428 } 429 430 442 public void setCertificateValid(Date certValid) { 443 if (certValid == null) { 444 certificateValid = null; 445 } else { 446 certificateValid = (Date)certValid.clone(); 447 } 448 } 449 450 463 public void setPrivateKeyValid(Date privateKeyValid) { 464 if (privateKeyValid == null) { 465 this.privateKeyValid = null; 466 } else { 467 this.privateKeyValid = (Date)privateKeyValid.clone(); 468 } 469 } 470 471 486 public void setSubjectPublicKeyAlgID(String oid) throws IOException { 487 if (oid == null) { 488 subjectPublicKeyAlgID = null; 489 } else { 490 subjectPublicKeyAlgID = new ObjectIdentifier(oid); 491 } 492 } 493 494 502 public void setSubjectPublicKey(PublicKey key) { 503 if (key == null) { 504 subjectPublicKey = null; 505 subjectPublicKeyBytes = null; 506 } else { 507 subjectPublicKey = key; 508 subjectPublicKeyBytes = key.getEncoded(); 509 } 510 } 511 512 545 public void setSubjectPublicKey(byte[] key) throws IOException { 546 if (key == null) { 547 subjectPublicKey = null; 548 subjectPublicKeyBytes = null; 549 } else { 550 subjectPublicKeyBytes = (byte[])key.clone(); 551 subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes)); 552 } 553 } 554 555 570 public void setKeyUsage(boolean[] keyUsage) { 571 if (keyUsage == null) { 572 this.keyUsage = null; 573 } else { 574 this.keyUsage = (boolean[])keyUsage.clone(); 575 } 576 } 577 578 597 public void setExtendedKeyUsage(Set<String > keyPurposeSet) throws IOException { 598 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) { 599 this.keyPurposeSet = null; 600 keyPurposeOIDSet = null; 601 } else { 602 this.keyPurposeSet = 603 Collections.unmodifiableSet(new HashSet<String >(keyPurposeSet)); 604 keyPurposeOIDSet = new HashSet<ObjectIdentifier>(); 605 for (String s : this.keyPurposeSet) { 606 keyPurposeOIDSet.add(new ObjectIdentifier(s)); 607 } 608 } 609 } 610 611 627 public void setMatchAllSubjectAltNames(boolean matchAllNames) { 628 this.matchAllSubjectAltNames = matchAllNames; 629 } 630 631 678 public void setSubjectAlternativeNames(Collection<List<?>> names) 679 throws IOException { 680 if (names == null) { 681 subjectAlternativeNames = null; 682 subjectAlternativeGeneralNames = null; 683 } else { 684 if (names.isEmpty()) { 685 subjectAlternativeNames = null; 686 subjectAlternativeGeneralNames = null; 687 return; 688 } 689 Set<List<?>> tempNames = cloneAndCheckNames(names); 690 subjectAlternativeGeneralNames = parseNames(tempNames); 692 subjectAlternativeNames = tempNames; 693 } 694 } 695 696 733 public void addSubjectAlternativeName(int type, String name) 734 throws IOException { 735 addSubjectAlternativeNameInternal(type, name); 736 } 737 738 777 public void addSubjectAlternativeName(int type, byte[] name) 778 throws IOException { 779 addSubjectAlternativeNameInternal(type, name.clone()); 781 } 782 783 793 private void addSubjectAlternativeNameInternal(int type, Object name) 794 throws IOException { 795 GeneralNameInterface tempName = makeGeneralNameInterface(type, name); 797 if (subjectAlternativeNames == null) { 798 subjectAlternativeNames = new HashSet<List<?>>(); 799 } 800 if (subjectAlternativeGeneralNames == null) { 801 subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>(); 802 } 803 List<Object > list = new ArrayList<Object >(2); 804 list.add(Integer.valueOf(type)); 805 list.add(name); 806 subjectAlternativeNames.add(list); 807 subjectAlternativeGeneralNames.add(tempName); 808 } 809 810 827 private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException { 828 Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>(); 829 Iterator<List<?>> i = names.iterator(); 830 while (i.hasNext()) { 831 Object o = i.next(); 832 if (!(o instanceof List)) { 833 throw new IOException ("expected List"); 834 } 835 List<Object > nameList = (List<Object >)o; 836 if (nameList.size() != 2) { 837 throw new IOException ("name list size not 2"); 838 } 839 o = nameList.get(0); 840 if (!(o instanceof Integer )) { 841 throw new IOException ("expected an Integer"); 842 } 843 int nameType = ((Integer )o).intValue(); 844 o = nameList.get(1); 845 genNames.add(makeGeneralNameInterface(nameType, o)); 846 } 847 return genNames; 848 } 849 850 860 static boolean equalNames(Collection object1, Collection object2) { 861 if ((object1 == null) || (object2 == null)) { 862 return object1 == object2; 863 } 864 return object1.equals(object2); 865 } 866 867 882 static GeneralNameInterface makeGeneralNameInterface(int type, Object name) 883 throws IOException { 884 GeneralNameInterface result; 885 if (debug != null) { 886 debug.println("X509CertSelector.makeGeneralNameInterface(" 887 + type + ")..."); 888 } 889 890 if (name instanceof String ) { 891 if (debug != null) { 892 debug.println("X509CertSelector.makeGeneralNameInterface() " 893 + "name is String: " + name); 894 } 895 switch (type) { 896 case NAME_RFC822: 897 result = new RFC822Name((String )name); 898 break; 899 case NAME_DNS: 900 result = new DNSName((String )name); 901 break; 902 case NAME_DIRECTORY: 903 result = new X500Name((String )name); 904 break; 905 case NAME_URI: 906 result = new URIName((String )name); 907 break; 908 case NAME_IP: 909 result = new IPAddressName((String )name); 910 break; 911 case NAME_OID: 912 result = new OIDName((String )name); 913 break; 914 default: 915 throw new IOException ("unable to parse String names of type " 916 + type); 917 } 918 if (debug != null) { 919 debug.println("X509CertSelector.makeGeneralNameInterface() " 920 + "result: " + result.toString()); 921 } 922 } else if (name instanceof byte[]) { 923 DerValue val = new DerValue((byte[]) name); 924 if (debug != null) { 925 debug.println 926 ("X509CertSelector.makeGeneralNameInterface() is byte[]"); 927 } 928 929 switch (type) { 930 case NAME_ANY: 931 result = new OtherName(val); 932 break; 933 case NAME_RFC822: 934 result = new RFC822Name(val); 935 break; 936 case NAME_DNS: 937 result = new DNSName(val); 938 break; 939 case NAME_X400: 940 result = new X400Address(val); 941 break; 942 case NAME_DIRECTORY: 943 result = new X500Name(val); 944 break; 945 case NAME_EDI: 946 result = new EDIPartyName(val); 947 break; 948 case NAME_URI: 949 result = new URIName(val); 950 break; 951 case NAME_IP: 952 result = new IPAddressName(val); 953 break; 954 case NAME_OID: 955 result = new OIDName(val); 956 break; 957 default: 958 throw new IOException ("unable to parse byte array names of " 959 + "type " + type); 960 } 961 if (debug != null) { 962 debug.println("X509CertSelector.makeGeneralNameInterface() result: " 963 + result.toString()); 964 } 965 } else { 966 if (debug != null) { 967 debug.println("X509CertSelector.makeGeneralName() input name " 968 + "not String or byte array"); 969 } 970 throw new IOException ("name not String or byte array"); 971 } 972 return result; 973 } 974 975 976 1024 public void setNameConstraints(byte[] bytes) throws IOException { 1025 if (bytes == null) { 1026 ncBytes = null; 1027 nc = null; 1028 } else { 1029 ncBytes = (byte[])bytes.clone(); 1030 nc = new NameConstraintsExtension(FALSE, bytes); 1031 } 1032 } 1033 1034 1050 public void setBasicConstraints(int minMaxPathLen) { 1051 if (minMaxPathLen < -2) { 1052 throw new IllegalArgumentException ("basic constraints less than -2"); 1053 } 1054 basicConstraints = minMaxPathLen; 1055 } 1056 1057 1077 public void setPolicy(Set<String > certPolicySet) throws IOException { 1078 if (certPolicySet == null) { 1079 policySet = null; 1080 policy = null; 1081 } else { 1082 Set<String > tempSet = Collections.unmodifiableSet 1084 (new HashSet<String >(certPolicySet)); 1085 1086 Iterator i = tempSet.iterator(); 1087 Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>(); 1088 while (i.hasNext()) { 1089 Object o = i.next(); 1090 if (!(o instanceof String )) { 1091 throw new IOException ("non String in certPolicySet"); 1092 } 1093 polIdVector.add(new CertificatePolicyId(new ObjectIdentifier( 1094 (String )o))); 1095 } 1096 policySet = tempSet; 1098 policy = new CertificatePolicySet(polIdVector); 1099 } 1100 } 1101 1102 1153 public void setPathToNames(Collection<List<?>> names) throws IOException { 1154 if ((names == null) || names.isEmpty()) { 1155 pathToNames = null; 1156 pathToGeneralNames = null; 1157 } else { 1158 Set<List<?>> tempNames = cloneAndCheckNames(names); 1159 pathToGeneralNames = parseNames(tempNames); 1160 pathToNames = tempNames; 1162 } 1163 } 1164 1165 void setPathToNamesInternal(Set<GeneralNameInterface> names) { 1167 pathToNames = Collections.<List<?>>emptySet(); 1170 pathToGeneralNames = names; 1171 } 1172 1173 1206 public void addPathToName(int type, String name) throws IOException { 1207 addPathToNameInternal(type, name); 1208 } 1209 1210 1235 public void addPathToName(int type, byte [] name) throws IOException { 1236 addPathToNameInternal(type, name.clone()); 1238 } 1239 1240 1250 private void addPathToNameInternal(int type, Object name) 1251 throws IOException { 1252 GeneralNameInterface tempName = makeGeneralNameInterface(type, name); 1254 if (pathToGeneralNames == null) { 1255 pathToNames = new HashSet<List<?>>(); 1256 pathToGeneralNames = new HashSet<GeneralNameInterface>(); 1257 } 1258 List<Object > list = new ArrayList<Object >(2); 1259 list.add(Integer.valueOf(type)); 1260 list.add(name); 1261 pathToNames.add(list); 1262 pathToGeneralNames.add(tempName); 1263 } 1264 1265 1274 public X509Certificate getCertificate() { 1275 return x509Cert; 1276 } 1277 1278 1288 public BigInteger getSerialNumber() { 1289 return serialNumber; 1290 } 1291 1292 1302 public X500Principal getIssuer() { 1303 return issuer; 1304 } 1305 1306 1324 public String getIssuerAsString() { 1325 return (issuer == null ? null : issuer.getName()); 1326 } 1327 1328 1347 public byte[] getIssuerAsBytes() throws IOException { 1348 return (issuer == null ? null: issuer.getEncoded()); 1349 } 1350 1351 1361 public X500Principal getSubject() { 1362 return subject; 1363 } 1364 1365 1383 public String getSubjectAsString() { 1384 return (subject == null ? null : subject.getName()); 1385 } 1386 1387 1406 public byte[] getSubjectAsBytes() throws IOException { 1407 return (subject == null ? null : subject.getEncoded()); 1408 } 1409 1410 1422 public byte[] getSubjectKeyIdentifier() { 1423 if (subjectKeyID == null) { 1424 return null; 1425 } 1426 return (byte[])subjectKeyID.clone(); 1427 } 1428 1429 1441 public byte[] getAuthorityKeyIdentifier() { 1442 if (authorityKeyID == null) { 1443 return null; 1444 } 1445 return (byte[])authorityKeyID.clone(); 1446 } 1447 1448 1460 public Date getCertificateValid() { 1461 if (certificateValid == null) { 1462 return null; 1463 } 1464 return (Date)certificateValid.clone(); 1465 } 1466 1467 1479 public Date getPrivateKeyValid() { 1480 if (privateKeyValid == null) { 1481 return null; 1482 } 1483 return (Date)privateKeyValid.clone(); 1484 } 1485 1486 1497 public String getSubjectPublicKeyAlgID() { 1498 if (subjectPublicKeyAlgID == null) { 1499 return null; 1500 } 1501 return subjectPublicKeyAlgID.toString(); 1502 } 1503 1504 1512 public PublicKey getSubjectPublicKey() { 1513 return subjectPublicKey; 1514 } 1515 1516 1530 public boolean[] getKeyUsage() { 1531 if (keyUsage == null) { 1532 return null; 1533 } 1534 return (boolean[])keyUsage.clone(); 1535 } 1536 1537 1549 public Set<String > getExtendedKeyUsage() { 1550 return keyPurposeSet; 1551 } 1552 1553 1569 public boolean getMatchAllSubjectAltNames() { 1570 return matchAllSubjectAltNames; 1571 } 1572 1573 1606 public Collection<List<?>> getSubjectAlternativeNames() { 1607 if (subjectAlternativeNames == null) { 1608 return null; 1609 } 1610 return cloneNames(subjectAlternativeNames); 1611 } 1612 1613 1633 private static Set<List<?>> cloneNames(Collection<List<?>> names) { 1634 try { 1635 return cloneAndCheckNames(names); 1636 } catch (IOException e) { 1637 throw new RuntimeException ("cloneNames encountered IOException: " + 1638 e.getMessage()); 1639 } 1640 } 1641 1642 1657 private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException { 1658 Set<List<?>> namesCopy = new HashSet<List<?>>(); 1660 Iterator<List<?>> i = names.iterator(); 1661 while (i.hasNext()) { 1662 Object o = i.next(); 1663 if (!(o instanceof List)) { 1664 throw new IOException ("expected a List"); 1665 } 1666 namesCopy.add(new ArrayList<Object >((List<?>)o)); 1667 } 1668 1669 i = namesCopy.iterator(); 1671 while (i.hasNext()) { 1672 List<Object > nameList = (List<Object >)i.next(); 1673 if (nameList.size() != 2) { 1674 throw new IOException ("name list size not 2"); 1675 } 1676 Object o = nameList.get(0); 1677 if (!(o instanceof Integer )) { 1678 throw new IOException ("expected an Integer"); 1679 } 1680 int nameType = ((Integer ) o).intValue(); 1681 if ((nameType < 0) || (nameType > 8)) { 1682 throw new IOException ("name type not 0-8"); 1683 } 1684 Object nameObject = nameList.get(1); 1685 if (!(nameObject instanceof byte[]) && 1686 !(nameObject instanceof String )) { 1687 if (debug != null) { 1688 debug.println("X509CertSelector.cloneAndCheckNames() " 1689 + "name not byte array"); 1690 } 1691 throw new IOException ("name not byte array or String"); 1692 } 1693 if (nameObject instanceof byte[]) { 1694 nameList.set(1, ((byte[]) nameObject).clone()); 1695 } 1696 } 1697 return namesCopy; 1698 } 1699 1700 1720 public byte[] getNameConstraints() { 1721 if (ncBytes == null) { 1722 return null; 1723 } else { 1724 return (byte[]) ncBytes.clone(); 1725 } 1726 } 1727 1728 1738 public int getBasicConstraints() { 1739 return basicConstraints; 1740 } 1741 1742 1754 public Set<String > getPolicy() { 1755 return policySet; 1756 } 1757 1758 1789 public Collection<List<?>> getPathToNames() { 1790 if (pathToNames == null) { 1791 return null; 1792 } 1793 return cloneNames(pathToNames); 1794 } 1795 1796 1802 public String toString() { 1803 StringBuffer sb = new StringBuffer (); 1804 sb.append("X509CertSelector: [\n"); 1805 if (x509Cert != null) { 1806 sb.append(" Certificate: " + x509Cert.toString() + "\n"); 1807 } 1808 if (serialNumber != null) { 1809 sb.append(" Serial Number: " + serialNumber.toString() + "\n"); 1810 } 1811 if (issuer != null) { 1812 sb.append(" Issuer: " + getIssuerAsString() + "\n"); 1813 } 1814 if (subject != null) { 1815 sb.append(" Subject: " + getSubjectAsString() + "\n"); 1816 } 1817 sb.append(" matchAllSubjectAltNames flag: " 1818 + String.valueOf(matchAllSubjectAltNames) + "\n"); 1819 if (subjectAlternativeNames != null) { 1820 sb.append(" SubjectAlternativeNames:\n"); 1821 Iterator i = subjectAlternativeNames.iterator(); 1822 while (i.hasNext()) { 1823 List list = (List) i.next(); 1824 sb.append(" type " + list.get(0) + 1825 ", name " + list.get(1) + "\n"); 1826 } 1827 } 1828 if (subjectKeyID != null) { 1829 HexDumpEncoder enc = new HexDumpEncoder(); 1830 sb.append(" Subject Key Identifier: " + 1831 enc.encodeBuffer(subjectKeyID) + "\n"); 1832 } 1833 if (authorityKeyID != null) { 1834 HexDumpEncoder enc = new HexDumpEncoder(); 1835 sb.append(" Authority Key Identifier: " + 1836 enc.encodeBuffer(authorityKeyID) + "\n"); 1837 } 1838 if (certificateValid != null) { 1839 sb.append(" Certificate Valid: " + 1840 certificateValid.toString() + "\n"); 1841 } 1842 if (privateKeyValid != null) { 1843 sb.append(" Private Key Valid: " + 1844 privateKeyValid.toString() + "\n"); 1845 } 1846 if (subjectPublicKeyAlgID != null) { 1847 sb.append(" Subject Public Key AlgID: " + 1848 subjectPublicKeyAlgID.toString() + "\n"); 1849 } 1850 if (subjectPublicKey != null) { 1851 sb.append(" Subject Public Key: " + 1852 subjectPublicKey.toString() + "\n"); 1853 } 1854 if (keyUsage != null) { 1855 sb.append(" Key Usage: " + keyUsageToString(keyUsage) + "\n"); 1856 } 1857 if (keyPurposeSet != null) { 1858 sb.append(" Extended Key Usage: " + 1859 keyPurposeSet.toString() + "\n"); 1860 } 1861 if (policy != null) { 1862 sb.append(" Policy: " + policy.toString() + "\n"); 1863 } 1864 if (pathToGeneralNames != null) { 1865 sb.append(" Path to names:\n"); 1866 Iterator i = pathToGeneralNames.iterator(); 1867 while (i.hasNext()) { 1868 sb.append(" " + i.next() + "\n"); 1869 } 1870 } 1871 sb.append("]"); 1872 return sb.toString(); 1873 } 1874 1875 1880 private static String keyUsageToString(boolean[] k) { 1881 String s = "KeyUsage [\n"; 1882 try { 1883 if (k[0]) { 1884 s += " DigitalSignature\n"; 1885 } 1886 if (k[1]) { 1887 s += " Non_repudiation\n"; 1888 } 1889 if (k[2]) { 1890 s += " Key_Encipherment\n"; 1891 } 1892 if (k[3]) { 1893 s += " Data_Encipherment\n"; 1894 } 1895 if (k[4]) { 1896 s += " Key_Agreement\n"; 1897 } 1898 if (k[5]) { 1899 s += " Key_CertSign\n"; 1900 } 1901 if (k[6]) { 1902 s += " Crl_Sign\n"; 1903 } 1904 if (k[7]) { 1905 s += " Encipher_Only\n"; 1906 } 1907 if (k[8]) { 1908 s += " Decipher_Only\n"; 1909 } 1910 } catch (ArrayIndexOutOfBoundsException ex) {} 1911 1912 s += "]\n"; 1913 1914 return (s); 1915 } 1916 1917 1936 private static Extension getExtensionObject(X509Certificate cert, int extId) 1937 throws IOException { 1938 if (cert instanceof X509CertImpl) { 1939 X509CertImpl impl = (X509CertImpl)cert; 1940 switch (extId) { 1941 case PRIVATE_KEY_USAGE_ID: 1942 return impl.getPrivateKeyUsageExtension(); 1943 case SUBJECT_ALT_NAME_ID: 1944 return impl.getSubjectAlternativeNameExtension(); 1945 case NAME_CONSTRAINTS_ID: 1946 return impl.getNameConstraintsExtension(); 1947 case CERT_POLICIES_ID: 1948 return impl.getCertificatePoliciesExtension(); 1949 case EXTENDED_KEY_USAGE_ID: 1950 return impl.getExtendedKeyUsageExtension(); 1951 default: 1952 return null; 1953 } 1954 } 1955 byte[] rawExtVal = cert.getExtensionValue(EXTENSION_OIDS[extId]); 1956 if (rawExtVal == null) { 1957 return null; 1958 } 1959 DerInputStream in = new DerInputStream(rawExtVal); 1960 byte[] encoded = in.getOctetString(); 1961 switch (extId) { 1962 case PRIVATE_KEY_USAGE_ID: 1963 try { 1964 return new PrivateKeyUsageExtension(FALSE, encoded); 1965 } catch (CertificateException ex) { 1966 throw new IOException (ex.getMessage()); 1967 } 1968 case SUBJECT_ALT_NAME_ID: 1969 return new SubjectAlternativeNameExtension(FALSE, encoded); 1970 case NAME_CONSTRAINTS_ID: 1971 return new NameConstraintsExtension(FALSE, encoded); 1972 case CERT_POLICIES_ID: 1973 return new CertificatePoliciesExtension(FALSE, encoded); 1974 case EXTENDED_KEY_USAGE_ID: 1975 return new ExtendedKeyUsageExtension(FALSE, encoded); 1976 default: 1977 return null; 1978 } 1979 } 1980 1981 1988 public boolean match(Certificate cert) { 1989 if (!(cert instanceof X509Certificate )) { 1990 return false; 1991 } 1992 X509Certificate xcert = (X509Certificate )cert; 1993 1994 if (debug != null) { 1995 debug.println("X509CertSelector.match(SN: " 1996 + (xcert.getSerialNumber()).toString(16) + "\n Issuer: " 1997 + xcert.getIssuerDN() + "\n Subject: " + xcert.getSubjectDN() 1998 + ")"); 1999 } 2000 2001 2002 if (x509Cert != null) { 2003 if (!x509Cert.equals(xcert)) { 2004 if (debug != null) { 2005 debug.println("X509CertSelector.match: " 2006 + "certs don't match"); 2007 } 2008 return false; 2009 } 2010 } 2011 2012 2013 if (serialNumber != null) { 2014 if (!serialNumber.equals(xcert.getSerialNumber())) { 2015 if (debug != null) { 2016 debug.println("X509CertSelector.match: " 2017 + "serial numbers don't match"); 2018 } 2019 return false; 2020 } 2021 } 2022 2023 2024 if (issuer != null) { 2025 if (!issuer.equals(xcert.getIssuerX500Principal())) { 2026 if (debug != null) { 2027 debug.println("X509CertSelector.match: " 2028 + "issuer DNs don't match"); 2029 } 2030 return false; 2031 } 2032 } 2033 2034 2035 if (subject != null) { 2036 if (!subject.equals(xcert.getSubjectX500Principal())) { 2037 if (debug != null) { 2038 debug.println("X509CertSelector.match: " 2039 + "subject DNs don't match"); 2040 } 2041 return false; 2042 } 2043 } 2044 2045 2046 if (certificateValid != null) { 2047 try { 2048 xcert.checkValidity(certificateValid); 2049 } catch (CertificateException e) { 2050 if (debug != null) { 2051 debug.println("X509CertSelector.match: " 2052 + "certificate not within validity period"); 2053 } 2054 return false; 2055 } 2056 } 2057 2058 2059 if (subjectPublicKeyBytes != null) { 2060 byte[] certKey = xcert.getPublicKey().getEncoded(); 2061 if (!Arrays.equals(subjectPublicKeyBytes, certKey)) { 2062 if (debug != null) { 2063 debug.println("X509CertSelector.match: " 2064 + "subject public keys don't match"); 2065 } 2066 return false; 2067 } 2068 } 2069 2070 boolean result = matchBasicConstraints(xcert) 2071 && matchKeyUsage(xcert) 2072 && matchExtendedKeyUsage(xcert) 2073 && matchSubjectKeyID(xcert) 2074 && matchAuthorityKeyID(xcert) 2075 && matchPrivateKeyValid(xcert) 2076 && matchSubjectPublicKeyAlgID(xcert) 2077 && matchPolicy(xcert) 2078 && matchSubjectAlternativeNames(xcert) 2079 && matchPathToNames(xcert) 2080 && matchNameConstraints(xcert); 2081 2082 if (result && (debug != null)) { 2083 debug.println("X509CertSelector.match returning: true"); 2084 } 2085 return result; 2086 } 2087 2088 2089 private boolean matchSubjectKeyID(X509Certificate xcert) { 2090 if (subjectKeyID == null) { 2091 return true; 2092 } 2093 try { 2094 byte[] extVal = xcert.getExtensionValue("2.5.29.14"); 2095 if (extVal == null) { 2096 if (debug != null) { 2097 debug.println("X509CertSelector.match: " 2098 + "no subject key ID extension"); 2099 } 2100 return false; 2101 } 2102 DerInputStream in = new DerInputStream(extVal); 2103 byte[] certSubjectKeyID = in.getOctetString(); 2104 if (certSubjectKeyID == null || 2105 !Arrays.equals(subjectKeyID, certSubjectKeyID)) { 2106 if (debug != null) { 2107 debug.println("X509CertSelector.match: " 2108 + "subject key IDs don't match"); 2109 } 2110 return false; 2111 } 2112 } catch (IOException ex) { 2113 if (debug != null) { 2114 debug.println("X509CertSelector.match: " 2115 + "exception in subject key ID check"); 2116 } 2117 return false; 2118 } 2119 return true; 2120 } 2121 2122 2123 private boolean matchAuthorityKeyID(X509Certificate xcert) { 2124 if (authorityKeyID == null) { 2125 return true; 2126 } 2127 try { 2128 byte[] extVal = xcert.getExtensionValue("2.5.29.35"); 2129 if (extVal == null) { 2130 if (debug != null) { 2131 debug.println("X509CertSelector.match: " 2132 + "no authority key ID extension"); 2133 } 2134 return false; 2135 } 2136 DerInputStream in = new DerInputStream(extVal); 2137 byte[] certAuthKeyID = in.getOctetString(); 2138 if (certAuthKeyID == null || 2139 !Arrays.equals(authorityKeyID, certAuthKeyID)) { 2140 if (debug != null) { 2141 debug.println("X509CertSelector.match: " 2142 + "authority key IDs don't match"); 2143 } 2144 return false; 2145 } 2146 } catch (IOException ex) { 2147 if (debug != null) { 2148 debug.println("X509CertSelector.match: " 2149 + "exception in authority key ID check"); 2150 } 2151 return false; 2152 } 2153 return true; 2154 } 2155 2156 2157 private boolean matchPrivateKeyValid(X509Certificate xcert) { 2158 if (privateKeyValid == null) { 2159 return true; 2160 } 2161 PrivateKeyUsageExtension ext = null; 2162 try { 2163 ext = (PrivateKeyUsageExtension) 2164 getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID); 2165 if (ext != null) { 2166 ext.valid(privateKeyValid); 2167 } 2168 } catch (CertificateExpiredException e1) { 2169 if (debug != null) { 2170 String time = "n/a"; 2171 try { 2172 Date notAfter = 2173 (Date)ext.get(PrivateKeyUsageExtension.NOT_AFTER); 2174 time = notAfter.toString(); 2175 } catch (CertificateException ex) { 2176 } 2178 debug.println("X509CertSelector.match: private key usage not " 2179 + "within validity date; ext.NOT_After: " 2180 + time + "; X509CertSelector: " 2181 + this.toString()); 2182 e1.printStackTrace(); 2183 } 2184 return false; 2185 } catch (CertificateNotYetValidException e2) { 2186 if (debug != null) { 2187 String time = "n/a"; 2188 try { 2189 Date notBefore = (Date) 2190 ext.get(PrivateKeyUsageExtension.NOT_BEFORE); 2191 time = notBefore.toString(); 2192 } catch (CertificateException ex) { 2193 } 2195 debug.println("X509CertSelector.match: private key usage not " 2196 + "within validity date; ext.NOT_BEFORE: " 2197 + time + "; X509CertSelector: " 2198 + this.toString()); 2199 e2.printStackTrace(); 2200 } 2201 return false; 2202 } catch (CertificateException e3) { 2203 if (debug != null) { 2204 debug.println("X509CertSelector.match: CertificateException " 2205 + "in private key usage check; X509CertSelector: " 2206 + this.toString()); 2207 e3.printStackTrace(); 2208 } 2209 return false; 2210 } catch (IOException e4) { 2211 if (debug != null) { 2212 debug.println("X509CertSelector.match: IOException in " 2213 + "private key usage check; X509CertSelector: " 2214 + this.toString()); 2215 e4.printStackTrace(); 2216 } 2217 return false; 2218 } 2219 return true; 2220 } 2221 2222 2223 private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) { 2224 if (subjectPublicKeyAlgID == null) { 2225 return true; 2226 } 2227 try { 2228 byte[] encodedKey = xcert.getPublicKey().getEncoded(); 2229 DerValue val = new DerValue(encodedKey); 2230 if (val.tag != DerValue.tag_Sequence) { 2231 throw new IOException ("invalid key format"); 2232 } 2233 2234 AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue()); 2235 if (debug != null) { 2236 debug.println("X509CertSelector.match: subjectPublicKeyAlgID = " 2237 + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = " 2238 + algID.getOID()); 2239 } 2240 if (!subjectPublicKeyAlgID.equals(algID.getOID())) { 2241 if (debug != null) { 2242 debug.println("X509CertSelector.match: " 2243 + "subject public key alg IDs don't match"); 2244 } 2245 return false; 2246 } 2247 } catch (IOException e5) { 2248 if (debug != null) { 2249 debug.println("X509CertSelector.match: IOException in subject " 2250 + "public key algorithm OID check"); 2251 } 2252 return false; 2253 } 2254 return true; 2255 } 2256 2257 2258 private boolean matchKeyUsage(X509Certificate xcert) { 2259 if (keyUsage == null) { 2260 return true; 2261 } 2262 boolean[] certKeyUsage = xcert.getKeyUsage(); 2263 if (certKeyUsage != null) { 2264 for (int keyBit = 0; keyBit < keyUsage.length; keyBit++) { 2265 if (keyUsage[keyBit] && 2266 ((keyBit >= certKeyUsage.length) || !certKeyUsage[keyBit])) { 2267 if (debug != null) { 2268 debug.println("X509CertSelector.match: " 2269 + "key usage bits don't match"); 2270 } 2271 return false; 2272 } 2273 } 2274 } 2275 return true; 2276 } 2277 2278 2279 private boolean matchExtendedKeyUsage(X509Certificate xcert) { 2280 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) { 2281 return true; 2282 } 2283 try { 2284 ExtendedKeyUsageExtension ext = 2285 (ExtendedKeyUsageExtension)getExtensionObject(xcert, 2286 EXTENDED_KEY_USAGE_ID); 2287 if (ext != null) { 2288 Vector<ObjectIdentifier> certKeyPurposeVector = 2289 (Vector<ObjectIdentifier>)ext.get(ExtendedKeyUsageExtension.USAGES); 2290 if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE) 2291 && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) { 2292 if (debug != null) { 2293 debug.println("X509CertSelector.match: cert failed " 2294 + "extendedKeyUsage criterion"); 2295 } 2296 return false; 2297 } 2298 } 2299 } catch (IOException ex) { 2300 if (debug != null) { 2301 debug.println("X509CertSelector.match: " 2302 + "IOException in extended key usage check"); 2303 } 2304 return false; 2305 } 2306 return true; 2307 } 2308 2309 2310 private boolean matchSubjectAlternativeNames(X509Certificate xcert) { 2311 if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) { 2312 return true; 2313 } 2314 try { 2315 SubjectAlternativeNameExtension sanExt = 2316 (SubjectAlternativeNameExtension) getExtensionObject(xcert, 2317 SUBJECT_ALT_NAME_ID); 2318 if (sanExt == null) { 2319 if (debug != null) { 2320 debug.println("X509CertSelector.match: " 2321 + "no subject alternative name extension"); 2322 } 2323 return false; 2324 } 2325 GeneralNames certNames = (GeneralNames) 2326 sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME); 2327 Iterator i = subjectAlternativeGeneralNames.iterator(); 2328 while (i.hasNext()) { 2329 GeneralNameInterface matchName = (GeneralNameInterface) i.next(); 2330 boolean found = false; 2331 for (Iterator t = certNames.iterator(); t.hasNext() && !found; ) { 2332 GeneralNameInterface certName = 2333 ((GeneralName)t.next()).getName(); 2334 found = certName.equals(matchName); 2335 } 2336 if (!found && (matchAllSubjectAltNames || !i.hasNext())) { 2337 if (debug != null) { 2338 debug.println("X509CertSelector.match: subject alternative " 2339 + "name " + matchName + " not found"); 2340 } 2341 return false; 2342 } else if (found && !matchAllSubjectAltNames) { 2343 break; 2344 } 2345 } 2346 } catch (IOException ex) { 2347 if (debug != null) 2348 debug.println("X509CertSelector.match: IOException in subject " 2349 + "alternative name check"); 2350 return false; 2351 } 2352 return true; 2353 } 2354 2355 2356 private boolean matchNameConstraints(X509Certificate xcert) { 2357 if (nc == null) { 2358 return true; 2359 } 2360 try { 2361 if (!nc.verify(xcert)) { 2362 if (debug != null) { 2363 debug.println("X509CertSelector.match: " 2364 + "name constraints not satisfied"); 2365 } 2366 return false; 2367 } 2368 } catch (IOException e) { 2369 if (debug != null) { 2370 debug.println("X509CertSelector.match: " 2371 + "IOException in name constraints check"); 2372 } 2373 return false; 2374 } 2375 return true; 2376 } 2377 2378 2379 private boolean matchPolicy(X509Certificate xcert) { 2380 if (policy == null) { 2381 return true; 2382 } 2383 try { 2384 CertificatePoliciesExtension ext = (CertificatePoliciesExtension) 2385 getExtensionObject(xcert, CERT_POLICIES_ID); 2386 if (ext == null) { 2387 if (debug != null) { 2388 debug.println("X509CertSelector.match: " 2389 + "no certificate policy extension"); 2390 } 2391 return false; 2392 } 2393 List<PolicyInformation> policies = (List<PolicyInformation>)ext.get(CertificatePoliciesExtension.POLICIES); 2394 2398 List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size()); 2399 for (PolicyInformation info : policies) { 2400 policyIDs.add(info.getPolicyIdentifier()); 2401 } 2402 if (policy != null) { 2403 boolean foundOne = false; 2404 2409 if (policy.getCertPolicyIds().isEmpty()) { 2410 if (policyIDs.isEmpty()) { 2411 if (debug != null) { 2412 debug.println("X509CertSelector.match: " 2413 + "cert failed policyAny criterion"); 2414 } 2415 return false; 2416 } 2417 } else { 2418 for (CertificatePolicyId id : policy.getCertPolicyIds()) { 2419 if (policyIDs.contains(id)) { 2420 foundOne = true; 2421 break; 2422 } 2423 } 2424 if (!foundOne) { 2425 if (debug != null) { 2426 debug.println("X509CertSelector.match: " 2427 + "cert failed policyAny criterion"); 2428 } 2429 return false; 2430 } 2431 } 2432 } 2433 } catch (IOException ex) { 2434 if (debug != null) { 2435 debug.println("X509CertSelector.match: " 2436 + "IOException in certificate policy ID check"); 2437 } 2438 return false; 2439 } 2440 return true; 2441 } 2442 2443 2444 private boolean matchPathToNames(X509Certificate xcert) { 2445 if (pathToGeneralNames == null) { 2446 return true; 2447 } 2448 try { 2449 NameConstraintsExtension ext = (NameConstraintsExtension) 2450 getExtensionObject(xcert, NAME_CONSTRAINTS_ID); 2451 if (ext == null) { 2452 return true; 2453 } 2454 if ((debug != null) && debug.isOn("certpath")) { 2455 debug.println("X509CertSelector.match pathToNames:\n"); 2456 Iterator i = pathToGeneralNames.iterator(); 2457 while (i.hasNext()) { 2458 debug.println(" " + i.next() + "\n"); 2459 } 2460 } 2461 2462 GeneralSubtrees permitted = (GeneralSubtrees) 2463 ext.get(NameConstraintsExtension.PERMITTED_SUBTREES); 2464 GeneralSubtrees excluded = (GeneralSubtrees) 2465 ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES); 2466 if (excluded != null) { 2467 if (matchExcluded(excluded) == false) { 2468 return false; 2469 } 2470 } 2471 if (permitted != null) { 2472 if (matchPermitted(permitted) == false) { 2473 return false; 2474 } 2475 } 2476 } catch (IOException ex) { 2477 if (debug != null) { 2478 debug.println("X509CertSelector.match: " 2479 + "IOException in name constraints check"); 2480 } 2481 return false; 2482 } 2483 return true; 2484 } 2485 2486 private boolean matchExcluded(GeneralSubtrees excluded) { 2487 2492 for (Iterator t = excluded.iterator(); t.hasNext(); ) { 2493 GeneralSubtree tree = (GeneralSubtree)t.next(); 2494 GeneralNameInterface excludedName = tree.getName().getName(); 2495 Iterator i = pathToGeneralNames.iterator(); 2496 while (i.hasNext()) { 2497 GeneralNameInterface pathToName = (GeneralNameInterface) i.next(); 2498 if (excludedName.getType() == pathToName.getType()) { 2499 switch (pathToName.constrains(excludedName)) { 2500 case GeneralNameInterface.NAME_WIDENS: 2501 case GeneralNameInterface.NAME_MATCH: 2502 if (debug != null) { 2503 debug.println("X509CertSelector.match: name constraints " 2504 + "inhibit path to specified name"); 2505 debug.println("X509CertSelector.match: excluded name: " + 2506 pathToName); 2507 } 2508 return false; 2509 default: 2510 } 2511 } 2512 } 2513 } 2514 return true; 2515 } 2516 2517 private boolean matchPermitted(GeneralSubtrees permitted) { 2518 2524 Iterator i = pathToGeneralNames.iterator(); 2525 while (i.hasNext()) { 2526 GeneralNameInterface pathToName = (GeneralNameInterface)i.next(); 2527 Iterator t = permitted.iterator(); 2528 boolean permittedNameFound = false; 2529 boolean nameTypeFound = false; 2530 String names = ""; 2531 while (t.hasNext() && !permittedNameFound) { 2532 GeneralSubtree tree = (GeneralSubtree)t.next(); 2533 GeneralNameInterface permittedName = tree.getName().getName(); 2534 if (permittedName.getType() == pathToName.getType()) { 2535 nameTypeFound = true; 2536 names = names + " " + permittedName; 2537 switch (pathToName.constrains(permittedName)) { 2538 case GeneralNameInterface.NAME_WIDENS: 2539 case GeneralNameInterface.NAME_MATCH: 2540 permittedNameFound = true; 2541 break; 2542 default: 2543 } 2544 } 2545 } 2546 if (!permittedNameFound && nameTypeFound) { 2547 if (debug != null) 2548 debug.println("X509CertSelector.match: " + 2549 "name constraints inhibit path to specified name; " + 2550 "permitted names of type " + pathToName.getType() + 2551 ": " + names); 2552 return false; 2553 } 2554 } 2555 return true; 2556 } 2557 2558 2559 private boolean matchBasicConstraints(X509Certificate xcert) { 2560 if (basicConstraints == -1) { 2561 return true; 2562 } 2563 int maxPathLen = xcert.getBasicConstraints(); 2564 if (basicConstraints == -2) { 2565 if (maxPathLen != -1) { 2566 if (debug != null) { 2567 debug.println("X509CertSelector.match: not an EE cert"); 2568 } 2569 return false; 2570 } 2571 } else { 2572 if (maxPathLen < basicConstraints) { 2573 if (debug != null) { 2574 debug.println("X509CertSelector.match: maxPathLen too small (" 2575 + maxPathLen + " < " + basicConstraints + ")"); 2576 } 2577 return false; 2578 } 2579 } 2580 return true; 2581 } 2582 2583 private static Set<?> cloneSet(Set<?> set) { 2584 if (set instanceof HashSet) { 2585 Object clone = ((HashSet<?>)set).clone(); 2586 return (Set<?>)clone; 2587 } else { 2588 return new HashSet<Object >(set); 2589 } 2590 } 2591 2592 2597 public Object clone() { 2598 try { 2599 X509CertSelector copy = (X509CertSelector )super.clone(); 2600 if (subjectAlternativeNames != null) { 2602 copy.subjectAlternativeNames = 2603 (Set<List<?>>)cloneSet(subjectAlternativeNames); 2604 copy.subjectAlternativeGeneralNames = 2605 (Set<GeneralNameInterface>)cloneSet 2606 (subjectAlternativeGeneralNames); 2607 } 2608 if (pathToGeneralNames != null) { 2609 copy.pathToNames = 2610 (Set<List<?>>)cloneSet(pathToNames); 2611 copy.pathToGeneralNames = 2612 (Set<GeneralNameInterface>)cloneSet 2613 (pathToGeneralNames); 2614 } 2615 return copy; 2616 } catch (CloneNotSupportedException e) { 2617 2618 throw new InternalError (e.toString()); 2619 } 2620 } 2621} 2622 | Popular Tags |