1 /*
2  * Copyright (c) 1997, 2004, 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 sun.security.util.*;
30 
31 /**
32  * This class defines the EDIPartyName of the GeneralName choice.
33  * The ASN.1 syntax for this is:
34  * <pre>
35  * EDIPartyName ::= SEQUENCE {
36  *     nameAssigner  [0]  DirectoryString OPTIONAL,
37  *     partyName     [1]  DirectoryString }
38  * </pre>
39  *
40  * @author Hemma Prafullchandra
41  * @see GeneralName
42  * @see GeneralNames
43  * @see GeneralNameInterface
44  */
45 public class EDIPartyName implements GeneralNameInterface {
46 
47     // Private data members
48     private static final byte TAG_ASSIGNER = 0;
49     private static final byte TAG_PARTYNAME = 1;
50 
51     private String assigner = null;
52     private String party = null;
53 
54     private int myhash = -1;
55 
56     /**
57      * Create the EDIPartyName object from the specified names.
58      *
59      * @param assignerName the name of the assigner
60      * @param partyName the name of the EDI party.
61      */
EDIPartyName(String assignerName, String partyName)62     public EDIPartyName(String assignerName, String partyName) {
63         this.assigner = assignerName;
64         this.party = partyName;
65     }
66 
67     /**
68      * Create the EDIPartyName object from the specified name.
69      *
70      * @param partyName the name of the EDI party.
71      */
EDIPartyName(String partyName)72     public EDIPartyName(String partyName) {
73         this.party = partyName;
74     }
75 
76     /**
77      * Create the EDIPartyName object from the passed encoded Der value.
78      *
79      * @param derValue the encoded DER EDIPartyName.
80      * @exception IOException on error.
81      */
EDIPartyName(DerValue derValue)82     public EDIPartyName(DerValue derValue) throws IOException {
83         DerInputStream in = new DerInputStream(derValue.toByteArray());
84         DerValue[] seq = in.getSequence(2);
85 
86         int len = seq.length;
87         if (len < 1 || len > 2)
88             throw new IOException("Invalid encoding of EDIPartyName");
89 
90         for (int i = 0; i < len; i++) {
91             DerValue opt = seq[i];
92             if (opt.isContextSpecific(TAG_ASSIGNER) &&
93                 !opt.isConstructed()) {
94                 if (assigner != null)
95                     throw new IOException("Duplicate nameAssigner found in"
96                                           + " EDIPartyName");
97                 opt = opt.data.getDerValue();
98                 assigner = opt.getAsString();
99             }
100             if (opt.isContextSpecific(TAG_PARTYNAME) &&
101                 !opt.isConstructed()) {
102                 if (party != null)
103                     throw new IOException("Duplicate partyName found in"
104                                           + " EDIPartyName");
105                 opt = opt.data.getDerValue();
106                 party = opt.getAsString();
107             }
108         }
109     }
110 
111     /**
112      * Return the type of the GeneralName.
113      */
getType()114     public int getType() {
115         return (GeneralNameInterface.NAME_EDI);
116     }
117 
118     /**
119      * Encode the EDI party name into the DerOutputStream.
120      *
121      * @param out the DER stream to encode the EDIPartyName to.
122      * @exception IOException on encoding errors.
123      */
encode(DerOutputStream out)124     public void encode(DerOutputStream out) throws IOException {
125         DerOutputStream tagged = new DerOutputStream();
126         DerOutputStream tmp = new DerOutputStream();
127 
128         if (assigner != null) {
129             DerOutputStream tmp2 = new DerOutputStream();
130             // XXX - shd check is chars fit into PrintableString
131             tmp2.putPrintableString(assigner);
132             tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT,
133                                  false, TAG_ASSIGNER), tmp2);
134         }
135         if (party == null)
136             throw  new IOException("Cannot have null partyName");
137 
138         // XXX - shd check is chars fit into PrintableString
139         tmp.putPrintableString(party);
140         tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT,
141                                  false, TAG_PARTYNAME), tmp);
142 
143         out.write(DerValue.tag_Sequence, tagged);
144     }
145 
146     /**
147      * Return the assignerName
148      *
149      * @return String assignerName
150      */
getAssignerName()151     public String getAssignerName() {
152         return assigner;
153     }
154 
155     /**
156      * Return the partyName
157      *
158      * @return String partyName
159      */
getPartyName()160     public String getPartyName() {
161         return party;
162     }
163 
164     /**
165      * Compare this EDIPartyName with another.  Does a byte-string
166      * comparison without regard to type of the partyName and
167      * the assignerName.
168      *
169      * @return true if the two names match
170      */
equals(Object other)171     public boolean equals(Object other) {
172         if (!(other instanceof EDIPartyName))
173             return false;
174         String otherAssigner = ((EDIPartyName)other).assigner;
175         if (this.assigner == null) {
176             if (otherAssigner != null)
177                 return false;
178         } else {
179             if (!(this.assigner.equals(otherAssigner)))
180                 return false;
181         }
182         String otherParty = ((EDIPartyName)other).party;
183         if (this.party == null) {
184             if (otherParty != null)
185                 return false;
186         } else {
187             if (!(this.party.equals(otherParty)))
188                 return false;
189         }
190         return true;
191     }
192 
193     /**
194      * Returns the hash code value for this EDIPartyName.
195      *
196      * @return a hash code value.
197      */
hashCode()198     public int hashCode() {
199         if (myhash == -1) {
200             myhash = 37 + (party == null ? 1 : party.hashCode());
201             if (assigner != null) {
202                 myhash = 37 * myhash + assigner.hashCode();
203             }
204         }
205         return myhash;
206     }
207 
208     /**
209      * Return the printable string.
210      */
toString()211     public String toString() {
212         StringBuilder sb = new StringBuilder("EDIPartyName: ");
213         if (assigner != null) {
214             sb.append("  nameAssigner = ")
215               .append(assigner)
216               .append(',');
217         }
218         sb.append("  partyName = ")
219           .append(party);
220         return sb.toString();
221     }
222 
223     /**
224      * Return constraint type:<ul>
225      *   <li>NAME_DIFF_TYPE = -1: input name is different type from name (i.e. does not constrain)
226      *   <li>NAME_MATCH = 0: input name matches name
227      *   <li>NAME_NARROWS = 1: input name narrows name
228      *   <li>NAME_WIDENS = 2: input name widens name
229      *   <li>NAME_SAME_TYPE = 3: input name does not match or narrow name, but is same type
230      * </ul>.  These results are used in checking NameConstraints during
231      * certification path verification.
232      *
233      * @param inputName to be checked for being constrained
234      * @return constraint type above
235      * @throws UnsupportedOperationException if name is same type, but comparison operations are
236      *          not supported for this name type.
237      */
constrains(GeneralNameInterface inputName)238     public int constrains(GeneralNameInterface inputName) throws UnsupportedOperationException {
239         int constraintType;
240         if (inputName == null)
241             constraintType = NAME_DIFF_TYPE;
242         else if (inputName.getType() != NAME_EDI)
243             constraintType = NAME_DIFF_TYPE;
244         else {
245             throw new UnsupportedOperationException("Narrowing, widening, and matching of names not supported for EDIPartyName");
246         }
247         return constraintType;
248     }
249 
250     /**
251      * Return subtree depth of this name for purposes of determining
252      * NameConstraints minimum and maximum bounds and for calculating
253      * path lengths in name subtrees.
254      *
255      * @return distance of name from root
256      * @throws UnsupportedOperationException if not supported for this name type
257      */
subtreeDepth()258     public int subtreeDepth() throws UnsupportedOperationException {
259         throw new UnsupportedOperationException("subtreeDepth() not supported for EDIPartyName");
260     }
261 
262 }
263