Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/x509/DNSName.java
38831 views
/*1* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.x509;2627import java.io.IOException;28import java.util.Locale;2930import sun.security.util.*;3132/**33* This class implements the DNSName as required by the GeneralNames34* ASN.1 object.35* <p>36* [RFC5280] When the subjectAltName extension contains a domain name system37* label, the domain name MUST be stored in the dNSName (an IA5String).38* The name MUST be in the "preferred name syntax", as specified by39* Section 3.5 of [RFC1034] and as modified by Section 2.1 of40* [RFC1123]. Note that while uppercase and lowercase letters are41* allowed in domain names, no significance is attached to the case. In42* addition, while the string " " is a legal domain name, subjectAltName43* extensions with a dNSName of " " MUST NOT be used. Finally, the use44* of the DNS representation for Internet mail addresses45* (subscriber.example.com instead of [email protected]) MUST NOT46* be used; such identities are to be encoded as rfc822Name.47* <p>48* @author Amit Kapoor49* @author Hemma Prafullchandra50*/51public class DNSName implements GeneralNameInterface {52private String name;5354private static final String alphaDigits =55"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";5657/**58* Create the DNSName object from the passed encoded Der value.59*60* @param derValue the encoded DER DNSName.61* @exception IOException on error.62*/63public DNSName(DerValue derValue) throws IOException {64name = derValue.getIA5String();65}6667/**68* Create the DNSName object with the specified name.69*70* @param name the DNSName.71* @throws IOException if the name is not a valid DNSName subjectAltName72*/73public DNSName(String name) throws IOException {74if (name == null || name.length() == 0)75throw new IOException("DNSName must not be null or empty");76if (name.contains(" "))77throw new IOException("DNSName with blank components is not permitted");78if (name.startsWith(".") || name.endsWith("."))79throw new IOException("DNSName may not begin or end with a .");80/*81* Name will consist of label components separated by "."82* startIndex is the index of the first character of a component83* endIndex is the index of the last character of a component plus 184*/85for (int endIndex,startIndex = 0; startIndex < name.length(); startIndex = endIndex+1) {86endIndex = name.indexOf('.', startIndex);87if (endIndex < 0) {88endIndex = name.length();89}90if (endIndex - startIndex < 1)91throw new IOException("DNSName with empty components are not permitted");9293// RFC 1123: DNSName components must begin with a letter or digit94if (alphaDigits.indexOf(name.charAt(startIndex)) < 0)95throw new IOException("DNSName components must begin with a letter or digit");96//nonStartIndex: index for characters in the component beyond the first one97for (int nonStartIndex=startIndex+1; nonStartIndex < endIndex; nonStartIndex++) {98char x = name.charAt(nonStartIndex);99if ((alphaDigits).indexOf(x) < 0 && x != '-')100throw new IOException("DNSName components must consist of letters, digits, and hyphens");101}102}103this.name = name;104}105106107/**108* Return the type of the GeneralName.109*/110public int getType() {111return (GeneralNameInterface.NAME_DNS);112}113114/**115* Return the actual name value of the GeneralName.116*/117public String getName() {118return name;119}120121/**122* Encode the DNSName into the DerOutputStream.123*124* @param out the DER stream to encode the DNSName to.125* @exception IOException on encoding errors.126*/127public void encode(DerOutputStream out) throws IOException {128out.putIA5String(name);129}130131/**132* Convert the name into user readable string.133*/134public String toString() {135return ("DNSName: " + name);136}137138/**139* Compares this name with another, for equality.140*141* @return true iff the names are equivalent142* according to RFC5280.143*/144public boolean equals(Object obj) {145if (this == obj)146return true;147148if (!(obj instanceof DNSName))149return false;150151DNSName other = (DNSName)obj;152153// RFC5280 mandates that these names are154// not case-sensitive155return name.equalsIgnoreCase(other.name);156}157158/**159* Returns the hash code value for this object.160*161* @return a hash code value for this object.162*/163public int hashCode() {164return name.toUpperCase(Locale.ENGLISH).hashCode();165}166167/**168* Return type of constraint inputName places on this name:<ul>169* <li>NAME_DIFF_TYPE = -1: input name is different type from name (i.e. does not constrain).170* <li>NAME_MATCH = 0: input name matches name.171* <li>NAME_NARROWS = 1: input name narrows name (is lower in the naming subtree)172* <li>NAME_WIDENS = 2: input name widens name (is higher in the naming subtree)173* <li>NAME_SAME_TYPE = 3: input name does not match or narrow name, but is same type.174* </ul>. These results are used in checking NameConstraints during175* certification path verification.176* <p>177* RFC5280: DNS name restrictions are expressed as host.example.com.178* Any DNS name that can be constructed by simply adding zero or more179* labels to the left-hand side of the name satisfies the name constraint.180* For example, www.host.example.com would satisfy the constraint but181* host1.example.com would not.182* <p>183* draft-ietf-pkix-new-part1-00.txt: DNSName restrictions are expressed as foo.bar.com.184* Any DNSName that185* can be constructed by simply adding to the left hand side of the name186* satisfies the name constraint. For example, www.foo.bar.com would187* satisfy the constraint but foo1.bar.com would not.188* <p>189* RFC1034: By convention, domain names can be stored with arbitrary case, but190* domain name comparisons for all present domain functions are done in a191* case-insensitive manner, assuming an ASCII character set, and a high192* order zero bit.193* <p>194* @param inputName to be checked for being constrained195* @returns constraint type above196* @throws UnsupportedOperationException if name is not exact match, but narrowing and widening are197* not supported for this name type.198*/199public int constrains(GeneralNameInterface inputName) throws UnsupportedOperationException {200int constraintType;201if (inputName == null)202constraintType = NAME_DIFF_TYPE;203else if (inputName.getType() != NAME_DNS)204constraintType = NAME_DIFF_TYPE;205else {206String inName =207(((DNSName)inputName).getName()).toLowerCase(Locale.ENGLISH);208String thisName = name.toLowerCase(Locale.ENGLISH);209if (inName.equals(thisName))210constraintType = NAME_MATCH;211else if (thisName.endsWith(inName)) {212int inNdx = thisName.lastIndexOf(inName);213if (thisName.charAt(inNdx-1) == '.' )214constraintType = NAME_WIDENS;215else216constraintType = NAME_SAME_TYPE;217} else if (inName.endsWith(thisName)) {218int ndx = inName.lastIndexOf(thisName);219if (inName.charAt(ndx-1) == '.' )220constraintType = NAME_NARROWS;221else222constraintType = NAME_SAME_TYPE;223} else {224constraintType = NAME_SAME_TYPE;225}226}227return constraintType;228}229230/**231* Return subtree depth of this name for purposes of determining232* NameConstraints minimum and maximum bounds and for calculating233* path lengths in name subtrees.234*235* @returns distance of name from root236* @throws UnsupportedOperationException if not supported for this name type237*/238public int subtreeDepth() throws UnsupportedOperationException {239// subtree depth is always at least 1240int sum = 1;241242// count dots243for (int i = name.indexOf('.'); i >= 0; i = name.indexOf('.', i + 1)) {244++sum;245}246247return sum;248}249250}251252253