001package org.apache.commons.ssl.org.bouncycastle.asn1.isismtt.x509;
002
003import java.util.Enumeration;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
009import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
010import org.apache.commons.ssl.org.bouncycastle.asn1.x509.GeneralName;
011
012/**
013 * Attribute to indicate admissions to certain professions.
014 *
015 * <pre>
016 *     AdmissionSyntax ::= SEQUENCE
017 *     {
018 *       admissionAuthority GeneralName OPTIONAL,
019 *       contentsOfAdmissions SEQUENCE OF Admissions
020 *     }
021 *
022 *     Admissions ::= SEQUENCE
023 *     {
024 *       admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
025 *       namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
026 *       professionInfos SEQUENCE OF ProfessionInfo
027 *     }
028 *
029 *     NamingAuthority ::= SEQUENCE
030 *     {
031 *       namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
032 *       namingAuthorityUrl IA5String OPTIONAL,
033 *       namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
034 *     }
035 *
036 *     ProfessionInfo ::= SEQUENCE
037 *     {
038 *       namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
039 *       professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
040 *       professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
041 *       registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
042 *       addProfessionInfo OCTET STRING OPTIONAL
043 *     }
044 * </pre>
045 * <p>
046 * ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
047 * supports the following concepts and requirements:
048 * <ul>
049 * <li> External institutions (e.g. professional associations, chambers, unions,
050 * administrative bodies, companies, etc.), which are responsible for granting
051 * and verifying professional admissions, are indicated by means of the data
052 * field admissionAuthority. An admission authority is indicated by a
053 * GeneralName object. Here an X.501 directory name (distinguished name) can be
054 * indicated in the field directoryName, a URL address can be indicated in the
055 * field uniformResourceIdentifier, and an object identifier can be indicated in
056 * the field registeredId.
057 * <li> The names of authorities which are responsible for the administration of
058 * title registers are indicated in the data field namingAuthority. The name of
059 * the authority can be identified by an object identifier in the field
060 * namingAuthorityId, by means of a text string in the field
061 * namingAuthorityText, by means of a URL address in the field
062 * namingAuthorityUrl, or by a combination of them. For example, the text string
063 * can contain the name of the authority, the country and the name of the title
064 * register. The URL-option refers to a web page which contains lists with
065 * �officially� registered professions (text and possibly OID) as well as
066 * further information on these professions. Object identifiers for the
067 * component namingAuthorityId are grouped under the OID-branch
068 * id-isis-at-namingAuthorities and must be applied for.
069 * <li>See
070 * http://www.teletrust.de/anwend.asp?Id=30200&amp;Sprache=E_&amp;HomePG=0 for
071 * an application form and http://www.teletrust.de/links.asp?id=30220,11
072 * for an overview of registered naming authorities.
073 * <li> By means of the data type ProfessionInfo certain professions,
074 * specializations, disciplines, fields of activity, etc. are identified. A
075 * profession is represented by one or more text strings, resp. profession OIDs
076 * in the fields professionItems and professionOIDs and by a registration number
077 * in the field registrationNumber. An indication in text form must always be
078 * present, whereas the other indications are optional. The component
079 * addProfessionInfo may contain additional applicationspecific information in
080 * DER-encoded form.
081 * </ul>
082 * <p>
083 * By means of different namingAuthority-OIDs or profession OIDs hierarchies of
084 * professions, specializations, disciplines, fields of activity, etc. can be
085 * expressed. The issuing admission authority should always be indicated (field
086 * admissionAuthority), whenever a registration number is presented. Still,
087 * information on admissions can be given without indicating an admission or a
088 * naming authority by the exclusive use of the component professionItems. In
089 * this case the certification authority is responsible for the verification of
090 * the admission information.
091 * <p>
092 * This attribute is single-valued. Still, several admissions can be captured in
093 * the sequence structure of the component contentsOfAdmissions of
094 * AdmissionSyntax or in the component professionInfos of Admissions. The
095 * component admissionAuthority of AdmissionSyntax serves as default value for
096 * the component admissionAuthority of Admissions. Within the latter component
097 * the default value can be overwritten, in case that another authority is
098 * responsible. The component namingAuthority of Admissions serves as a default
099 * value for the component namingAuthority of ProfessionInfo. Within the latter
100 * component the default value can be overwritten, in case that another naming
101 * authority needs to be recorded.
102 * <p>
103 * The length of the string objects is limited to 128 characters. It is
104 * recommended to indicate a namingAuthorityURL in all issued attribute
105 * certificates. If a namingAuthorityURL is indicated, the field professionItems
106 * of ProfessionInfo should contain only registered titles. If the field
107 * professionOIDs exists, it has to contain the OIDs of the professions listed
108 * in professionItems in the same order. In general, the field professionInfos
109 * should contain only one entry, unless the admissions that are to be listed
110 * are logically connected (e.g. they have been issued under the same admission
111 * number).
112 *
113 * @see org.bouncycastle.asn1.isismtt.x509.Admissions
114 * @see org.bouncycastle.asn1.isismtt.x509.ProfessionInfo
115 * @see org.bouncycastle.asn1.isismtt.x509.NamingAuthority
116 */
117public class AdmissionSyntax
118    extends ASN1Object
119{
120
121    private GeneralName admissionAuthority;
122
123    private ASN1Sequence contentsOfAdmissions;
124
125    public static AdmissionSyntax getInstance(Object obj)
126    {
127        if (obj == null || obj instanceof AdmissionSyntax)
128        {
129            return (AdmissionSyntax)obj;
130        }
131
132        if (obj instanceof ASN1Sequence)
133        {
134            return new AdmissionSyntax((ASN1Sequence)obj);
135        }
136
137        throw new IllegalArgumentException("illegal object in getInstance: "
138            + obj.getClass().getName());
139    }
140
141    /**
142     * Constructor from ASN1Sequence.
143     * <p>
144     * The sequence is of type ProcurationSyntax:
145     * <pre>
146     *     AdmissionSyntax ::= SEQUENCE
147     *     {
148     *       admissionAuthority GeneralName OPTIONAL,
149     *       contentsOfAdmissions SEQUENCE OF Admissions
150     *     }
151     *
152     *     Admissions ::= SEQUENCE
153     *     {
154     *       admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
155     *       namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
156     *       professionInfos SEQUENCE OF ProfessionInfo
157     *     }
158     *
159     *     NamingAuthority ::= SEQUENCE
160     *     {
161     *       namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
162     *       namingAuthorityUrl IA5String OPTIONAL,
163     *       namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
164     *     }
165     *
166     *     ProfessionInfo ::= SEQUENCE
167     *     {
168     *       namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
169     *       professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
170     *       professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
171     *       registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
172     *       addProfessionInfo OCTET STRING OPTIONAL
173     *     }
174     * </pre>
175     * </p>
176     * @param seq The ASN.1 sequence.
177     */
178    private AdmissionSyntax(ASN1Sequence seq)
179    {
180        switch (seq.size())
181        {
182        case 1:
183            contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(0));
184            break;
185        case 2:
186            admissionAuthority = GeneralName.getInstance(seq.getObjectAt(0));
187            contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(1));
188            break;
189        default:
190            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
191        }
192    }
193
194    /**
195     * Constructor from given details.
196     *
197     * @param admissionAuthority   The admission authority.
198     * @param contentsOfAdmissions The admissions.
199     */
200    public AdmissionSyntax(GeneralName admissionAuthority, ASN1Sequence contentsOfAdmissions)
201    {
202        this.admissionAuthority = admissionAuthority;
203        this.contentsOfAdmissions = contentsOfAdmissions;
204    }
205
206    /**
207     * Produce an object suitable for an ASN1OutputStream.
208     * <p>
209     * Returns:
210     * <pre>
211     *     AdmissionSyntax ::= SEQUENCE
212     *     {
213     *       admissionAuthority GeneralName OPTIONAL,
214     *       contentsOfAdmissions SEQUENCE OF Admissions
215     *     }
216     *
217     *     Admissions ::= SEQUENCE
218     *     {
219     *       admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
220     *       namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
221     *       professionInfos SEQUENCE OF ProfessionInfo
222     *     }
223     *
224     *     NamingAuthority ::= SEQUENCE
225     *     {
226     *       namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
227     *       namingAuthorityUrl IA5String OPTIONAL,
228     *       namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
229     *     }
230     *
231     *     ProfessionInfo ::= SEQUENCE
232     *     {
233     *       namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
234     *       professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
235     *       professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
236     *       registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
237     *       addProfessionInfo OCTET STRING OPTIONAL
238     *     }
239     * </pre>
240     *
241     * @return a DERObject
242     */
243    public ASN1Primitive toASN1Primitive()
244    {
245        ASN1EncodableVector vec = new ASN1EncodableVector();
246        if (admissionAuthority != null)
247        {
248            vec.add(admissionAuthority);
249        }
250        vec.add(contentsOfAdmissions);
251        return new DERSequence(vec);
252    }
253
254    /**
255     * @return Returns the admissionAuthority if present, null otherwise.
256     */
257    public GeneralName getAdmissionAuthority()
258    {
259        return admissionAuthority;
260    }
261
262    /**
263     * @return Returns the contentsOfAdmissions.
264     */
265    public Admissions[] getContentsOfAdmissions()
266    {
267        Admissions[] admissions = new Admissions[contentsOfAdmissions.size()];
268        int count = 0;
269        for (Enumeration e = contentsOfAdmissions.getObjects(); e.hasMoreElements();)
270        {
271            admissions[count++] = Admissions.getInstance(e.nextElement());
272        }
273        return admissions;
274    }
275}