1 /* 2 * Copyright (c) 2000, 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.security.cert.PolicyQualifierInfo; 30 import java.util.Collections; 31 import java.util.Enumeration; 32 import java.util.Iterator; 33 import java.util.LinkedHashSet; 34 import java.util.Set; 35 36 import sun.security.util.DerValue; 37 import sun.security.util.DerOutputStream; 38 /** 39 * PolicyInformation is the class that contains a specific certificate policy 40 * that is part of the CertificatePoliciesExtension. A 41 * CertificatePolicyExtension value consists of a vector of these objects. 42 * <p> 43 * The ASN.1 syntax for PolicyInformation (IMPLICIT tagging is defined in the 44 * module definition): 45 * <pre> 46 * 47 * PolicyInformation ::= SEQUENCE { 48 * policyIdentifier CertPolicyId, 49 * policyQualifiers SEQUENCE SIZE (1..MAX) OF 50 * PolicyQualifierInfo OPTIONAL } 51 * 52 * CertPolicyId ::= OBJECT IDENTIFIER 53 * 54 * PolicyQualifierInfo ::= SEQUENCE { 55 * policyQualifierId PolicyQualifierId, 56 * qualifier ANY DEFINED BY policyQualifierId } 57 * </pre> 58 * 59 * @author Sean Mullan 60 * @author Anne Anderson 61 * @since 1.4 62 */ 63 public class PolicyInformation { 64 65 // Attribute names 66 public static final String NAME = "PolicyInformation"; 67 public static final String ID = "id"; 68 public static final String QUALIFIERS = "qualifiers"; 69 70 /* The policy OID */ 71 private CertificatePolicyId policyIdentifier; 72 73 /* A Set of java.security.cert.PolicyQualifierInfo objects */ 74 private Set<PolicyQualifierInfo> policyQualifiers; 75 76 /** 77 * Create an instance of PolicyInformation 78 * 79 * @param policyIdentifier the policyIdentifier as a 80 * CertificatePolicyId 81 * @param policyQualifiers a Set of PolicyQualifierInfo objects. 82 * Must not be NULL. Specify an empty Set for no qualifiers. 83 * @exception IOException on decoding errors. 84 */ PolicyInformation(CertificatePolicyId policyIdentifier, Set<PolicyQualifierInfo> policyQualifiers)85 public PolicyInformation(CertificatePolicyId policyIdentifier, 86 Set<PolicyQualifierInfo> policyQualifiers) throws IOException { 87 if (policyQualifiers == null) { 88 throw new NullPointerException("policyQualifiers is null"); 89 } 90 this.policyQualifiers = 91 new LinkedHashSet<PolicyQualifierInfo>(policyQualifiers); 92 this.policyIdentifier = policyIdentifier; 93 } 94 95 /** 96 * Create an instance of PolicyInformation, decoding from 97 * the passed DerValue. 98 * 99 * @param val the DerValue to construct the PolicyInformation from. 100 * @exception IOException on decoding errors. 101 */ PolicyInformation(DerValue val)102 public PolicyInformation(DerValue val) throws IOException { 103 if (val.tag != DerValue.tag_Sequence) { 104 throw new IOException("Invalid encoding of PolicyInformation"); 105 } 106 policyIdentifier = new CertificatePolicyId(val.data.getDerValue()); 107 if (val.data.available() != 0) { 108 policyQualifiers = new LinkedHashSet<PolicyQualifierInfo>(); 109 DerValue opt = val.data.getDerValue(); 110 if (opt.tag != DerValue.tag_Sequence) 111 throw new IOException("Invalid encoding of PolicyInformation"); 112 if (opt.data.available() == 0) 113 throw new IOException("No data available in policyQualifiers"); 114 while (opt.data.available() != 0) 115 policyQualifiers.add(new PolicyQualifierInfo 116 (opt.data.getDerValue().toByteArray())); 117 } else { 118 policyQualifiers = Collections.emptySet(); 119 } 120 } 121 122 /** 123 * Compare this PolicyInformation with another object for equality 124 * 125 * @param other object to be compared with this 126 * @return true iff the PolicyInformation objects match 127 */ equals(Object other)128 public boolean equals(Object other) { 129 if (!(other instanceof PolicyInformation)) 130 return false; 131 PolicyInformation piOther = (PolicyInformation)other; 132 133 if (!policyIdentifier.equals(piOther.getPolicyIdentifier())) 134 return false; 135 136 return policyQualifiers.equals(piOther.getPolicyQualifiers()); 137 } 138 139 /** 140 * Returns the hash code for this PolicyInformation. 141 * 142 * @return a hash code value. 143 */ hashCode()144 public int hashCode() { 145 int myhash = 37 + policyIdentifier.hashCode(); 146 myhash = 37 * myhash + policyQualifiers.hashCode(); 147 return myhash; 148 } 149 150 /** 151 * Return the policyIdentifier value 152 * 153 * @return The CertificatePolicyId object containing 154 * the policyIdentifier (not a copy). 155 */ getPolicyIdentifier()156 public CertificatePolicyId getPolicyIdentifier() { 157 return policyIdentifier; 158 } 159 160 /** 161 * Return the policyQualifiers value 162 * 163 * @return a Set of PolicyQualifierInfo objects associated 164 * with this certificate policy (not a copy). 165 * Returns an empty Set if there are no qualifiers. 166 * Never returns null. 167 */ getPolicyQualifiers()168 public Set<PolicyQualifierInfo> getPolicyQualifiers() { 169 return policyQualifiers; 170 } 171 172 /** 173 * Get the attribute value. 174 */ get(String name)175 public Object get(String name) throws IOException { 176 if (name.equalsIgnoreCase(ID)) { 177 return policyIdentifier; 178 } else if (name.equalsIgnoreCase(QUALIFIERS)) { 179 return policyQualifiers; 180 } else { 181 throw new IOException("Attribute name [" + name + 182 "] not recognized by PolicyInformation."); 183 } 184 } 185 186 /** 187 * Set the attribute value. 188 */ 189 @SuppressWarnings("unchecked") // Checked with instanceof set(String name, Object obj)190 public void set(String name, Object obj) throws IOException { 191 if (name.equalsIgnoreCase(ID)) { 192 if (obj instanceof CertificatePolicyId) 193 policyIdentifier = (CertificatePolicyId)obj; 194 else 195 throw new IOException("Attribute value must be instance " + 196 "of CertificatePolicyId."); 197 } else if (name.equalsIgnoreCase(QUALIFIERS)) { 198 if (policyIdentifier == null) { 199 throw new IOException("Attribute must have a " + 200 "CertificatePolicyIdentifier value before " + 201 "PolicyQualifierInfo can be set."); 202 } 203 if (obj instanceof Set) { 204 Iterator<?> i = ((Set<?>)obj).iterator(); 205 while (i.hasNext()) { 206 Object obj1 = i.next(); 207 if (!(obj1 instanceof PolicyQualifierInfo)) { 208 throw new IOException("Attribute value must be a" + 209 "Set of PolicyQualifierInfo objects."); 210 } 211 } 212 policyQualifiers = (Set<PolicyQualifierInfo>) obj; 213 } else { 214 throw new IOException("Attribute value must be of type Set."); 215 } 216 } else { 217 throw new IOException("Attribute name [" + name + 218 "] not recognized by PolicyInformation"); 219 } 220 } 221 222 /** 223 * Delete the attribute value. 224 */ delete(String name)225 public void delete(String name) throws IOException { 226 if (name.equalsIgnoreCase(QUALIFIERS)) { 227 policyQualifiers = Collections.emptySet(); 228 } else if (name.equalsIgnoreCase(ID)) { 229 throw new IOException("Attribute ID may not be deleted from " + 230 "PolicyInformation."); 231 } else { 232 //ID may not be deleted 233 throw new IOException("Attribute name [" + name + 234 "] not recognized by PolicyInformation."); 235 } 236 } 237 238 /** 239 * Return an enumeration of names of attributes existing within this 240 * attribute. 241 */ getElements()242 public Enumeration<String> getElements() { 243 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 244 elements.addElement(ID); 245 elements.addElement(QUALIFIERS); 246 247 return elements.elements(); 248 } 249 250 /** 251 * Return the name of this attribute. 252 */ getName()253 public String getName() { 254 return NAME; 255 } 256 257 /** 258 * Return a printable representation of the PolicyInformation. 259 */ toString()260 public String toString() { 261 StringBuilder s = new StringBuilder(" [" + policyIdentifier.toString()); 262 s.append(policyQualifiers + " ]\n"); 263 return s.toString(); 264 } 265 266 /** 267 * Write the PolicyInformation to the DerOutputStream. 268 * 269 * @param out the DerOutputStream to write the extension to. 270 * @exception IOException on encoding errors. 271 */ encode(DerOutputStream out)272 public void encode(DerOutputStream out) throws IOException { 273 DerOutputStream tmp = new DerOutputStream(); 274 policyIdentifier.encode(tmp); 275 if (!policyQualifiers.isEmpty()) { 276 DerOutputStream tmp2 = new DerOutputStream(); 277 for (PolicyQualifierInfo pq : policyQualifiers) { 278 tmp2.write(pq.getEncoded()); 279 } 280 tmp.write(DerValue.tag_Sequence, tmp2); 281 } 282 out.write(DerValue.tag_Sequence, tmp); 283 } 284 } 285