/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Class to check hostnames against the names specified in a certificate as
* required for TLS and LDAP.
*
*/
public class HostnameChecker {
// Constant for a HostnameChecker for TLS
new HostnameChecker(TYPE_TLS);
// Constant for a HostnameChecker for LDAP
new HostnameChecker(TYPE_LDAP);
// constants for subject alt names of type DNS and IP
// the algorithm to follow to perform the check. Currently unused.
private final byte checkType;
}
/**
* Get a HostnameChecker instance. checkType should be one of the
* TYPE_* constants defined in this class.
*/
return INSTANCE_TLS;
return INSTANCE_LDAP;
}
}
/**
* Perform the check.
*
* @exception CertificateException if the name does not match any of
* the names specified in the certificate
*/
throws CertificateException {
if (isIpAddress(expectedName)) {
} else {
}
}
/**
* Perform the check for Kerberos.
*/
}
/**
* Return the Server name from Kerberos principal.
*/
}
/**
* Test whether the given hostname looks like a literal IPv4 or IPv6
* address. The hostname does not need to be a fully qualified name.
*
* This is not a strict check that performs full input validation.
* That means if the method returns true, name need not be a correct
* IP address, rather that it does not represent a valid DNS hostname.
* Likewise for IP addresses when it returns false.
*/
return true;
} else {
return false;
}
}
/**
* Check if the certificate allows use of the given IP address.
*
* 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.
*/
throws CertificateException {
if (subjAltNames == null) {
throw new CertificateException
("No subject alternative names present");
}
// For IP address, it needs to be exact match
return;
}
}
}
throw new CertificateException("No subject alternative " +
"names matching " + "IP address " +
expectedIP + " found");
}
/**
* Check if the certificate allows use of the given DNS name.
*
* 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.
*
* 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.)
*/
throws CertificateException {
if (subjAltNames != null) {
boolean foundDNS = false;
foundDNS = true;
return;
}
}
}
if (foundDNS) {
// if certificate contains any subject alt names of type DNS
// but none match, reject
throw new CertificateException("No subject alternative DNS "
}
}
try {
return;
}
} catch (IOException e) {
// ignore
}
}
throw new CertificateException(msg);
}
/**
* Return the subject of a certificate as X500Name, by reparsing if
* necessary. X500Name should only be used if access to name components
* is required, in other cases X500Principal is to be prefered.
*
* This method is currently used from within JSSE, do not remove.
*/
throws CertificateParsingException {
try {
} else {
}
} catch (IOException e) {
throw(CertificateParsingException)
new CertificateParsingException().initCause(e);
}
}
/**
* Returns true if name matches against template.<p>
*
* The matching is performed as per RFC 2818 rules for TLS and
* RFC 2830 rules for LDAP.<p>
*
* The <code>name</code> parameter should represent a DNS name.
* The <code>template</code> parameter
* may contain the wildcard character *
*/
} else {
return false;
}
}
/**
* Returns true if name matches against template.<p>
*
* According to RFC 2818, section 3.1 -
* Names may contain the wildcard character * which is
* considered to match any single domain name component
* or component fragment.
* E.g., *.a.com matches foo.a.com but not
* bar.foo.a.com. f*.com matches foo.com but not bar.com.
*/
return false;
}
while (nameSt.hasMoreTokens()) {
templateSt.nextToken())) {
return false;
}
}
return true;
}
/**
* Returns true if name matches against template.<p>
*
* As per RFC 2830, section 3.6 -
* The "*" wildcard character is allowed. If present, it applies only
* to the left-most name component.
* E.g. *.bar.com would match a.bar.com, b.bar.com, etc. but not
* bar.com.
*/
// Retreive leftmost component
if (templateIdx == -1)
if (nameIdx == -1)
// match rest of the name
} else {
return false;
}
}
/**
* Returns true if the name matches against the template that may
* contain wildcard char * <p>
*/
if (wildcardIdx == -1)
boolean isBeginning = true;
while (wildcardIdx != -1) {
// match in sequence the non-wildcard chars in the template.
if ((beforeStartIdx == -1) ||
return false;
}
isBeginning = false;
// update the match scope
}
}
}