1 /* 2 * Copyright (c) 1997, 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.*; 31 32 import sun.security.util.*; 33 34 /** 35 * Represent the Policy Mappings Extension. 36 * 37 * This extension, if present, identifies the certificate policies considered 38 * identical between the issuing and the subject CA. 39 * <p>Extensions are addiitonal attributes which can be inserted in a X509 40 * v3 certificate. For example a "Driving License Certificate" could have 41 * the driving license number as a extension. 42 * 43 * <p>Extensions are represented as a sequence of the extension identifier 44 * (Object Identifier), a boolean flag stating whether the extension is to 45 * be treated as being critical and the extension value itself (this is again 46 * a DER encoding of the extension value). 47 * 48 * @author Amit Kapoor 49 * @author Hemma Prafullchandra 50 * @see Extension 51 * @see CertAttrSet 52 */ 53 public class PolicyMappingsExtension extends Extension 54 implements CertAttrSet<String> { 55 /** 56 * Identifier for this attribute, to be used with the 57 * get, set, delete methods of Certificate, x509 type. 58 */ 59 public static final String IDENT = "x509.info.extensions.PolicyMappings"; 60 /** 61 * Attribute names. 62 */ 63 public static final String NAME = "PolicyMappings"; 64 public static final String MAP = "map"; 65 66 // Private data members 67 private List<CertificatePolicyMap> maps; 68 69 // Encode this extension value 70 private void encodeThis() throws IOException { 71 if (maps == null || maps.isEmpty()) { 72 this.extensionValue = null; 73 return; 74 } 75 DerOutputStream os = new DerOutputStream(); 76 DerOutputStream tmp = new DerOutputStream(); 77 78 for (CertificatePolicyMap map : maps) { 79 map.encode(tmp); 80 } 81 82 os.write(DerValue.tag_Sequence, tmp); 83 this.extensionValue = os.toByteArray(); 84 } 85 86 /** 87 * Create a PolicyMappings with the List of CertificatePolicyMap. 88 * 89 * @param maps the List of CertificatePolicyMap. 90 */ 91 public PolicyMappingsExtension(List<CertificatePolicyMap> map) 92 throws IOException { 93 this.maps = map; 94 this.extensionId = PKIXExtensions.PolicyMappings_Id; 95 this.critical = false; 96 encodeThis(); 97 } 98 99 /** 100 * Create a default PolicyMappingsExtension. 101 */ 102 public PolicyMappingsExtension() { 103 extensionId = PKIXExtensions.KeyUsage_Id; 104 critical = false; 105 maps = new ArrayList<CertificatePolicyMap>(); 106 } 107 108 /** 109 * Create the extension from the passed DER encoded value. 110 * 111 * @params critical true if the extension is to be treated as critical. 112 * @params value an array of DER encoded bytes of the actual value. 113 * @exception ClassCastException if value is not an array of bytes 114 * @exception IOException on error. 115 */ 116 public PolicyMappingsExtension(Boolean critical, Object value) 117 throws IOException { 118 this.extensionId = PKIXExtensions.PolicyMappings_Id; 119 this.critical = critical.booleanValue(); 120 121 this.extensionValue = (byte[]) value; 122 DerValue val = new DerValue(this.extensionValue); 123 if (val.tag != DerValue.tag_Sequence) { 124 throw new IOException("Invalid encoding for " + 125 "PolicyMappingsExtension."); 126 } 127 maps = new ArrayList<CertificatePolicyMap>(); 128 while (val.data.available() != 0) { 129 DerValue seq = val.data.getDerValue(); 130 CertificatePolicyMap map = new CertificatePolicyMap(seq); 131 maps.add(map); 132 } 133 } 134 135 /** 136 * Returns a printable representation of the policy map. 137 */ 138 public String toString() { 139 if (maps == null) return ""; 140 String s = super.toString() + "PolicyMappings [\n" 141 + maps.toString() + "]\n"; 142 143 return (s); 144 } 145 146 /** 147 * Write the extension to the OutputStream. 148 * 149 * @param out the OutputStream to write the extension to. 150 * @exception IOException on encoding errors. 151 */ 152 public void encode(OutputStream out) throws IOException { 153 DerOutputStream tmp = new DerOutputStream(); 154 if (extensionValue == null) { 155 extensionId = PKIXExtensions.PolicyMappings_Id; 156 critical = false; 157 encodeThis(); 158 } 159 super.encode(tmp); 160 out.write(tmp.toByteArray()); 161 } 162 163 /** 164 * Set the attribute value. 165 */ 166 @SuppressWarnings("unchecked") // Checked with instanceof 167 public void set(String name, Object obj) throws IOException { 168 if (name.equalsIgnoreCase(MAP)) { 169 if (!(obj instanceof List)) { 170 throw new IOException("Attribute value should be of" + 171 " type List."); 172 } 173 maps = (List<CertificatePolicyMap>)obj; 174 } else { 175 throw new IOException("Attribute name not recognized by " + 176 "CertAttrSet:PolicyMappingsExtension."); 177 } 178 encodeThis(); 179 } 180 181 /** 182 * Get the attribute value. 183 */ 184 public List<CertificatePolicyMap> get(String name) throws IOException { 185 if (name.equalsIgnoreCase(MAP)) { 186 return (maps); 187 } else { 188 throw new IOException("Attribute name not recognized by " + 189 "CertAttrSet:PolicyMappingsExtension."); 190 } 191 } 192 193 /** 194 * Delete the attribute value. 195 */ 196 public void delete(String name) throws IOException { 197 if (name.equalsIgnoreCase(MAP)) { 198 maps = null; 199 } else { 200 throw new IOException("Attribute name not recognized by " + 201 "CertAttrSet:PolicyMappingsExtension."); 202 } 203 encodeThis(); 204 } 205 206 /** 207 * Return an enumeration of names of attributes existing within this 208 * attribute. 209 */ 210 public Enumeration<String> getElements () { 211 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 212 elements.addElement(MAP); 213 214 return elements.elements(); 215 } 216 217 /** 218 * Return the name of this attribute. 219 */ 220 public String getName () { 221 return (NAME); 222 } 223 } 224