1 /* 2 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.x509; 27 28 import java.io.IOException; 29 import java.util.*; 30 31 import sun.security.util.BitArray; 32 import sun.security.util.DerOutputStream; 33 import sun.security.util.DerValue; 34 35 /** 36 * Represents the DistributionPointName ASN.1 type. 37 * 38 * It is used in the CRL Distribution Points Extension (OID = 2.5.29.31) 39 * and the Issuing Distribution Point Extension (OID = 2.5.29.28). 40 * <p> 41 * Its ASN.1 definition is: 42 * <pre> 43 * 44 * DistributionPointName ::= CHOICE { 45 * fullName [0] GeneralNames, 46 * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } 47 * 48 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 49 * 50 * GeneralName ::= CHOICE { 51 * otherName [0] INSTANCE OF OTHER-NAME, 52 * rfc822Name [1] IA5String, 53 * dNSName [2] IA5String, 54 * x400Address [3] ORAddress, 55 * directoryName [4] Name, 56 * ediPartyName [5] EDIPartyName, 57 * uniformResourceIdentifier [6] IA5String, 58 * iPAddress [7] OCTET STRING, 59 * registeredID [8] OBJECT IDENTIFIER } 60 * 61 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue 62 * 63 * AttributeTypeAndValue ::= SEQUENCE { 64 * type AttributeType, 65 * value AttributeValue } 66 * 67 * AttributeType ::= OBJECT IDENTIFIER 68 * 69 * AttributeValue ::= ANY DEFINED BY AttributeType 70 * 71 * </pre> 72 * <p> 73 * Instances of this class are designed to be immutable. However, since this 74 * is an internal API we do not use defensive cloning for values for 75 * performance reasons. It is the responsibility of the consumer to ensure 76 * that no mutable elements are modified. 77 * 78 * @see CRLDistributionPointsExtension 79 * @see IssuingDistributionPointExtension 80 * @since 1.6 81 */ 82 public class DistributionPointName { 83 84 // ASN.1 context specific tag values 85 private static final byte TAG_FULL_NAME = 0; 86 private static final byte TAG_RELATIVE_NAME = 1; 87 88 // Only one of fullName and relativeName can be set 89 private GeneralNames fullName = null; 90 private RDN relativeName = null; 91 92 // Cached hashCode value 93 private volatile int hashCode; 94 95 /** 96 * Creates a distribution point name using a full name. 97 * 98 * @param fullName the name for the distribution point. 99 * @exception IllegalArgumentException if <code>fullName</code> is null. 100 */ DistributionPointName(GeneralNames fullName)101 public DistributionPointName(GeneralNames fullName) { 102 103 if (fullName == null) { 104 throw new IllegalArgumentException("fullName must not be null"); 105 } 106 this.fullName = fullName; 107 } 108 109 /** 110 * Creates a distribution point name using a relative name. 111 * 112 * @param relativeName the name of the distribution point relative to 113 * the name of the issuer of the CRL. 114 * @exception IllegalArgumentException if <code>relativeName</code> is null. 115 */ DistributionPointName(RDN relativeName)116 public DistributionPointName(RDN relativeName) { 117 118 if (relativeName == null) { 119 throw new IllegalArgumentException("relativeName must not be null"); 120 } 121 this.relativeName = relativeName; 122 } 123 124 /** 125 * Creates a distribution point name from its DER-encoded form. 126 * 127 * @param encoding the DER-encoded value. 128 * @throws IOException on decoding error. 129 */ DistributionPointName(DerValue encoding)130 public DistributionPointName(DerValue encoding) throws IOException { 131 132 if (encoding.isContextSpecific(TAG_FULL_NAME) && 133 encoding.isConstructed()) { 134 135 encoding.resetTag(DerValue.tag_Sequence); 136 fullName = new GeneralNames(encoding); 137 138 } else if (encoding.isContextSpecific(TAG_RELATIVE_NAME) && 139 encoding.isConstructed()) { 140 141 encoding.resetTag(DerValue.tag_Set); 142 relativeName = new RDN(encoding); 143 144 } else { 145 throw new IOException("Invalid encoding for DistributionPointName"); 146 } 147 148 } 149 150 /** 151 * Returns the full name for the distribution point or null if not set. 152 */ getFullName()153 public GeneralNames getFullName() { 154 return fullName; 155 } 156 157 /** 158 * Returns the relative name for the distribution point or null if not set. 159 */ getRelativeName()160 public RDN getRelativeName() { 161 return relativeName; 162 } 163 164 /** 165 * Encodes the distribution point name and writes it to the DerOutputStream. 166 * 167 * @param out the output stream. 168 * @exception IOException on encoding error. 169 */ encode(DerOutputStream out)170 public void encode(DerOutputStream out) throws IOException { 171 172 DerOutputStream theChoice = new DerOutputStream(); 173 174 if (fullName != null) { 175 fullName.encode(theChoice); 176 out.writeImplicit( 177 DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_FULL_NAME), 178 theChoice); 179 180 } else { 181 relativeName.encode(theChoice); 182 out.writeImplicit( 183 DerValue.createTag(DerValue.TAG_CONTEXT, true, 184 TAG_RELATIVE_NAME), 185 theChoice); 186 } 187 } 188 189 /** 190 * Compare an object to this distribution point name for equality. 191 * 192 * @param obj Object to be compared to this 193 * @return true if objects match; false otherwise 194 */ equals(Object obj)195 public boolean equals(Object obj) { 196 if (this == obj) { 197 return true; 198 } 199 if (obj instanceof DistributionPointName == false) { 200 return false; 201 } 202 DistributionPointName other = (DistributionPointName)obj; 203 204 return Objects.equals(this.fullName, other.fullName) && 205 Objects.equals(this.relativeName, other.relativeName); 206 } 207 208 /** 209 * Returns the hash code for this distribution point name. 210 * 211 * @return the hash code. 212 */ hashCode()213 public int hashCode() { 214 int hash = hashCode; 215 if (hash == 0) { 216 hash = 1; 217 if (fullName != null) { 218 hash += fullName.hashCode(); 219 220 } else { 221 hash += relativeName.hashCode(); 222 } 223 hashCode = hash; 224 } 225 return hash; 226 } 227 228 /** 229 * Returns a printable string of the distribution point name. 230 */ toString()231 public String toString() { 232 StringBuilder sb = new StringBuilder(); 233 if (fullName != null) { 234 sb.append("DistributionPointName:\n " + fullName + "\n"); 235 236 } else { 237 sb.append("DistributionPointName:\n " + relativeName + "\n"); 238 } 239 240 return sb.toString(); 241 } 242 } 243