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.io.OutputStream; 30 import java.util.Enumeration; 31 32 import sun.security.util.Debug; 33 import sun.security.util.DerOutputStream; 34 import sun.security.util.DerValue; 35 import sun.security.util.ObjectIdentifier; 36 37 /** 38 * This class represents the Inhibit Any-Policy Extension. 39 * 40 * <p>The inhibit any-policy extension can be used in certificates issued 41 * to CAs. The inhibit any-policy indicates that the special any-policy 42 * OID, with the value {2 5 29 32 0}, is not considered an explicit 43 * match for other certificate policies. The value indicates the number 44 * of additional certificates that may appear in the path before any- 45 * policy is no longer permitted. For example, a value of one indicates 46 * that any-policy may be processed in certificates issued by the sub- 47 * ject of this certificate, but not in additional certificates in the 48 * path. 49 * <p> 50 * This extension MUST be critical. 51 * <p> 52 * The ASN.1 syntax for this extension is: 53 * <code><pre> 54 * id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } 55 * 56 * InhibitAnyPolicy ::= SkipCerts 57 * 58 * SkipCerts ::= INTEGER (0..MAX) 59 * </pre></code> 60 * @author Anne Anderson 61 * @see CertAttrSet 62 * @see Extension 63 */ 64 public class InhibitAnyPolicyExtension extends Extension 65 implements CertAttrSet<String> { 66 67 private static final Debug debug = Debug.getInstance("certpath"); 68 69 /** 70 * Identifier for this attribute, to be used with the 71 * get, set, delete methods of Certificate, x509 type. 72 */ 73 public static final String IDENT = "x509.info.extensions.InhibitAnyPolicy"; 74 75 /** 76 * Object identifier for "any-policy" 77 */ 78 public static ObjectIdentifier AnyPolicy_Id; 79 static { 80 try { 81 AnyPolicy_Id = new ObjectIdentifier("2.5.29.32.0"); 82 } catch (IOException ioe) { 83 // Should not happen 84 } 85 } 86 87 /** 88 * Attribute names. 89 */ 90 public static final String NAME = "InhibitAnyPolicy"; 91 public static final String SKIP_CERTS = "skip_certs"; 92 93 // Private data members 94 private int skipCerts = Integer.MAX_VALUE; 95 96 // Encode this extension value encodeThis()97 private void encodeThis() throws IOException { 98 DerOutputStream out = new DerOutputStream(); 99 out.putInteger(skipCerts); 100 this.extensionValue = out.toByteArray(); 101 } 102 103 /** 104 * Default constructor for this object. 105 * 106 * @param skipCerts specifies the depth of the certification path. 107 * Use value of -1 to request unlimited depth. 108 */ InhibitAnyPolicyExtension(int skipCerts)109 public InhibitAnyPolicyExtension(int skipCerts) throws IOException { 110 if (skipCerts < -1) 111 throw new IOException("Invalid value for skipCerts"); 112 if (skipCerts == -1) 113 this.skipCerts = Integer.MAX_VALUE; 114 else 115 this.skipCerts = skipCerts; 116 this.extensionId = PKIXExtensions.InhibitAnyPolicy_Id; 117 critical = true; 118 encodeThis(); 119 } 120 121 /** 122 * Create the extension from the passed DER encoded value of the same. 123 * 124 * @param critical criticality flag to use. Must be true for this 125 * extension. 126 * @param value a byte array holding the DER-encoded extension value. 127 * @exception ClassCastException if value is not an array of bytes 128 * @exception IOException on error. 129 */ InhibitAnyPolicyExtension(Boolean critical, Object value)130 public InhibitAnyPolicyExtension(Boolean critical, Object value) 131 throws IOException { 132 133 this.extensionId = PKIXExtensions.InhibitAnyPolicy_Id; 134 135 if (!critical.booleanValue()) 136 throw new IOException("Criticality cannot be false for " + 137 "InhibitAnyPolicy"); 138 this.critical = critical.booleanValue(); 139 140 this.extensionValue = (byte[]) value; 141 DerValue val = new DerValue(this.extensionValue); 142 if (val.tag != DerValue.tag_Integer) 143 throw new IOException("Invalid encoding of InhibitAnyPolicy: " 144 + "data not integer"); 145 146 if (val.data == null) 147 throw new IOException("Invalid encoding of InhibitAnyPolicy: " 148 + "null data"); 149 int skipCertsValue = val.getInteger(); 150 if (skipCertsValue < -1) 151 throw new IOException("Invalid value for skipCerts"); 152 if (skipCertsValue == -1) { 153 this.skipCerts = Integer.MAX_VALUE; 154 } else { 155 this.skipCerts = skipCertsValue; 156 } 157 } 158 159 /** 160 * Return user readable form of extension. 161 */ toString()162 public String toString() { 163 String s = super.toString() + "InhibitAnyPolicy: " + skipCerts + "\n"; 164 return s; 165 } 166 167 /** 168 * Encode this extension value to the output stream. 169 * 170 * @param out the DerOutputStream to encode the extension to. 171 */ encode(OutputStream out)172 public void encode(OutputStream out) throws IOException { 173 DerOutputStream tmp = new DerOutputStream(); 174 if (extensionValue == null) { 175 this.extensionId = PKIXExtensions.InhibitAnyPolicy_Id; 176 critical = true; 177 encodeThis(); 178 } 179 super.encode(tmp); 180 181 out.write(tmp.toByteArray()); 182 } 183 184 /** 185 * Set the attribute value. 186 * 187 * @param name name of attribute to set. Must be SKIP_CERTS. 188 * @param obj value to which attribute is to be set. Must be Integer 189 * type. 190 * @throws IOException on error 191 */ set(String name, Object obj)192 public void set(String name, Object obj) throws IOException { 193 if (name.equalsIgnoreCase(SKIP_CERTS)) { 194 if (!(obj instanceof Integer)) 195 throw new IOException("Attribute value should be of type Integer."); 196 int skipCertsValue = ((Integer)obj).intValue(); 197 if (skipCertsValue < -1) 198 throw new IOException("Invalid value for skipCerts"); 199 if (skipCertsValue == -1) { 200 skipCerts = Integer.MAX_VALUE; 201 } else { 202 skipCerts = skipCertsValue; 203 } 204 } else 205 throw new IOException("Attribute name not recognized by " + 206 "CertAttrSet:InhibitAnyPolicy."); 207 encodeThis(); 208 } 209 210 /** 211 * Get the attribute value. 212 * 213 * @param name name of attribute to get. Must be SKIP_CERTS. 214 * @returns value of the attribute. In this case it will be of type 215 * Integer. 216 * @throws IOException on error 217 */ get(String name)218 public Integer get(String name) throws IOException { 219 if (name.equalsIgnoreCase(SKIP_CERTS)) 220 return (new Integer(skipCerts)); 221 else 222 throw new IOException("Attribute name not recognized by " + 223 "CertAttrSet:InhibitAnyPolicy."); 224 } 225 226 /** 227 * Delete the attribute value. 228 * 229 * @param name name of attribute to delete. Must be SKIP_CERTS. 230 * @throws IOException on error. In this case, IOException will always be 231 * thrown, because the only attribute, SKIP_CERTS, is 232 * required. 233 */ delete(String name)234 public void delete(String name) throws IOException { 235 if (name.equalsIgnoreCase(SKIP_CERTS)) 236 throw new IOException("Attribute " + SKIP_CERTS + 237 " may not be deleted."); 238 else 239 throw new IOException("Attribute name not recognized by " + 240 "CertAttrSet:InhibitAnyPolicy."); 241 } 242 243 /** 244 * Return an enumeration of names of attributes existing within this 245 * attribute. 246 * 247 * @returns enumeration of elements 248 */ getElements()249 public Enumeration<String> getElements() { 250 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 251 elements.addElement(SKIP_CERTS); 252 return (elements.elements()); 253 } 254 255 /** 256 * Return the name of this attribute. 257 * 258 * @returns name of attribute. 259 */ getName()260 public String getName() { 261 return (NAME); 262 } 263 } 264