/** * Check if the certificate allows use of the given DNS name. * * <p>From RFC2818: If a subjectAltName extension of type dNSName is present, that MUST be used as * the identity. Otherwise, the (most specific) Common Name field in the Subject field of the * certificate MUST be used. Although the use of the Common Name is existing practice, it is * deprecated and Certification Authorities are encouraged to use the dNSName instead. * * <p>Matching is performed using the matching rules specified by [RFC2459]. If more than one * identity of a given type is present in the certificate (e.g., more than one dNSName name, a * match in any one of the set is considered acceptable.) */ private void matchDNS(String expectedName, X509Certificate cert) throws CertificateException { Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames(); if (subjAltNames != null) { boolean foundDNS = false; for (List<?> next : subjAltNames) { if (((Integer) next.get(0)).intValue() == ALTNAME_DNS) { foundDNS = true; String dnsName = (String) next.get(1); if (isMatched(expectedName, dnsName)) { return; } } } if (foundDNS) { // if certificate contains any subject alt names of type DNS // but none match, reject throw new CertificateException( "No subject alternative DNS " + "name matching " + expectedName + " found."); } } X500Name subjectName = getSubjectX500Name(cert); DerValue derValue = subjectName.findMostSpecificAttribute(X500Name.commonName_oid); if (derValue != null) { try { if (isMatched(expectedName, derValue.getAsString())) { return; } } catch (IOException e) { // ignore } } String msg = "No name matching " + expectedName + " found"; throw new CertificateException(msg); }
private String hostNameMessage(X509Certificate cert, String hostname) { StringBuffer si = new StringBuffer(); si.append(master.getString(R.string.mtm_hostname_mismatch, hostname)); si.append("\n\n"); try { Collection<List<?>> sans = cert.getSubjectAlternativeNames(); if (sans == null) { si.append(cert.getSubjectDN()); si.append("\n"); } else for (List<?> altName : sans) { Object name = altName.get(1); if (name instanceof String) { si.append("["); si.append((Integer) altName.get(0)); si.append("] "); si.append(name); si.append("\n"); } } } catch (CertificateParsingException e) { e.printStackTrace(); si.append("<Parsing error: "); si.append(e.getLocalizedMessage()); si.append(">\n"); } si.append("\n"); si.append(master.getString(R.string.mtm_connect_anyway)); si.append("\n\n"); si.append(master.getString(R.string.mtm_cert_details)); certDetails(si, cert); return si.toString(); }
/** * Check if the certificate allows use of the given IP address. * * <p>From RFC2818: In some cases, the URI is specified as an IP address rather than a hostname. * In this case, the iPAddress subjectAltName must be present in the certificate and must exactly * match the IP in the URI. */ private static void matchIP(String expectedIP, X509Certificate cert) throws CertificateException { Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames(); if (subjAltNames == null) { throw new CertificateException("No subject alternative names present"); } for (List<?> next : subjAltNames) { // For IP address, it needs to be exact match if (((Integer) next.get(0)).intValue() == ALTNAME_IP) { String ipAddress = (String) next.get(1); if (expectedIP.equalsIgnoreCase(ipAddress)) { return; } } } throw new CertificateException( "No subject alternative " + "names matching " + "IP address " + expectedIP + " found"); }