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