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