diff --git a/smack-java7/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java b/smack-java7/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java index d9aba87f1..61ba37994 100644 --- a/smack-java7/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java +++ b/smack-java7/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java @@ -41,10 +41,13 @@ import javax.security.auth.kerberos.KerberosPrincipal; import org.jivesoftware.smack.util.IpAddressUtil; /** - * HostnameVerifier implementation for XMPP. + * HostnameVerifier implementation for XMPP. Verifies a given name, the 'hostname' argument, which + * should be the XMPP domain of the used XMPP service. The verifier compares the name with the + * servers TLS certificate's Subject + * Alternative Name (SAN) DNS name ('dNSName'), and, if there are no SANs, which the Common Name + * (CN). *

- * Based on the work by Kevin + * Based on the work by Kevin * Locke (released under CC0 1.0 Universal / Public Domain Dedication). *

*/ @@ -108,8 +111,26 @@ public class XmppHostnameVerifier implements HostnameVerifier { return false; } + /** + * As defined in RFC 5280 ยง 4.2.1.6 + *
+     * GeneralName ::= CHOICE {
+     *   ...
+     *   dNSName                         [2]     IA5String,
+     *   ...
+     * }
+     * 
+ */ private static final int ALTNAME_DNS = 2; + /** + * Try to match a certificate with a DNS name. This method returns if the certificate matches or + * throws a {@link CertificateException} if not. + * + * @param name the DNS name. + * @param cert the certificate. + * @throws CertificateException if the DNS name does not match the certificate. + */ private static void matchDns(String name, X509Certificate cert) throws CertificateException { Collection> subjAltNames = cert.getSubjectAlternativeNames(); if (subjAltNames != null) { @@ -120,6 +141,7 @@ public class XmppHostnameVerifier implements HostnameVerifier { } String dnsName = (String) san.get(1); if (matchesPerRfc2818(name, dnsName)) { + // Signal success by returning. return; } else { @@ -137,6 +159,8 @@ public class XmppHostnameVerifier implements HostnameVerifier { } } + // Control flow will end here if the X509 certificate does not have *any* Subject + // Alternative Names (SANs). Fallback trying to validate against the CN of the subject. LdapName dn = null; try { dn = new LdapName(cert.getSubjectX500Principal().getName()); @@ -147,6 +171,7 @@ public class XmppHostnameVerifier implements HostnameVerifier { for (Rdn rdn : dn.getRdns()) { if (rdn.getType().equalsIgnoreCase("CN")) { if (matchesPerRfc2818(name, rdn.getValue().toString())) { + // Signal success by returning. return; } break;