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
encodeThis()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      */
PolicyMappingsExtension(List<CertificatePolicyMap> map)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      */
PolicyMappingsExtension()102     public PolicyMappingsExtension() {
103         extensionId = PKIXExtensions.KeyUsage_Id;
104         critical = false;
105         maps = Collections.<CertificatePolicyMap>emptyList();
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      */
PolicyMappingsExtension(Boolean critical, Object value)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      */
toString()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      */
encode(OutputStream out)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
set(String name, Object obj)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      */
get(String name)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      */
delete(String name)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      */
getElements()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      */
getName()220     public String getName () {
221         return (NAME);
222     }
223 }
224