001: package org.bouncycastle.asn1.x509;
002:
003: import org.bouncycastle.asn1.ASN1Choice;
004: import org.bouncycastle.asn1.ASN1Encodable;
005: import org.bouncycastle.asn1.ASN1OctetString;
006: import org.bouncycastle.asn1.ASN1Sequence;
007: import org.bouncycastle.asn1.ASN1TaggedObject;
008: import org.bouncycastle.asn1.DEREncodable;
009: import org.bouncycastle.asn1.DERIA5String;
010: import org.bouncycastle.asn1.DERObject;
011: import org.bouncycastle.asn1.DERObjectIdentifier;
012: import org.bouncycastle.asn1.DEROctetString;
013: import org.bouncycastle.asn1.DERTaggedObject;
014: import org.bouncycastle.util.IPAddress;
015: import org.bouncycastle.util.Strings;
016:
017: /**
018: * The GeneralName object.
019: * <pre>
020: * GeneralName ::= CHOICE {
021: * otherName [0] OtherName,
022: * rfc822Name [1] IA5String,
023: * dNSName [2] IA5String,
024: * x400Address [3] ORAddress,
025: * directoryName [4] Name,
026: * ediPartyName [5] EDIPartyName,
027: * uniformResourceIdentifier [6] IA5String,
028: * iPAddress [7] OCTET STRING,
029: * registeredID [8] OBJECT IDENTIFIER}
030: *
031: * OtherName ::= SEQUENCE {
032: * type-id OBJECT IDENTIFIER,
033: * value [0] EXPLICIT ANY DEFINED BY type-id }
034: *
035: * EDIPartyName ::= SEQUENCE {
036: * nameAssigner [0] DirectoryString OPTIONAL,
037: * partyName [1] DirectoryString }
038: *
039: * Name ::= CHOICE { RDNSequence }
040: * </pre>
041: */
042: public class GeneralName extends ASN1Encodable implements ASN1Choice {
043: public static final int otherName = 0;
044: public static final int rfc822Name = 1;
045: public static final int dNSName = 2;
046: public static final int x400Address = 3;
047: public static final int directoryName = 4;
048: public static final int ediPartyName = 5;
049: public static final int uniformResourceIdentifier = 6;
050: public static final int iPAddress = 7;
051: public static final int registeredID = 8;
052:
053: DEREncodable obj;
054: int tag;
055:
056: public GeneralName(X509Name dirName) {
057: this .obj = dirName;
058: this .tag = 4;
059: }
060:
061: /**
062: * @deprecated this constructor seems the wrong way round! Use GeneralName(tag, name).
063: */
064: public GeneralName(DERObject name, int tag) {
065: this .obj = name;
066: this .tag = tag;
067: }
068:
069: /**
070: * When the subjectAltName extension contains an Internet mail address,
071: * the address MUST be included as an rfc822Name. The format of an
072: * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
073: *
074: * When the subjectAltName extension contains a domain name service
075: * label, the domain name MUST be stored in the dNSName (an IA5String).
076: * The name MUST be in the "preferred name syntax," as specified by RFC
077: * 1034 [RFC 1034].
078: *
079: * When the subjectAltName extension contains a URI, the name MUST be
080: * stored in the uniformResourceIdentifier (an IA5String). The name MUST
081: * be a non-relative URL, and MUST follow the URL syntax and encoding
082: * rules specified in [RFC 1738]. The name must include both a scheme
083: * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
084: * specific-part must include a fully qualified domain name or IP
085: * address as the host.
086: *
087: * When the subjectAltName extension contains a iPAddress, the address
088: * MUST be stored in the octet string in "network byte order," as
089: * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
090: * each octet is the LSB of the corresponding byte in the network
091: * address. For IP Version 4, as specified in RFC 791, the octet string
092: * MUST contain exactly four octets. For IP Version 6, as specified in
093: * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
094: * 1883].
095: */
096: public GeneralName(int tag, ASN1Encodable name) {
097: this .obj = name;
098: this .tag = tag;
099: }
100:
101: /**
102: * Create a GeneralName for the given tag from the passed in String.
103: * <p>
104: * This constructor can handle:
105: * <ul>
106: * <li>rfc822Name
107: * <li>iPAddress
108: * <li>directoryName
109: * <li>dNSName
110: * <li>uniformResourceIdentifier
111: * <li>registeredID
112: * </ul>
113: * For x400Address, otherName and ediPartyName there is no common string
114: * format defined.
115: * <p>
116: * Note: A directory name can be encoded in different ways into a byte
117: * representation. Be aware of this if the byte representation is used for
118: * comparing results.
119: *
120: * @param tag tag number
121: * @param name string representation of name
122: * @throws IllegalArgumentException if the string encoding is not correct or * not supported.
123: */
124: public GeneralName(int tag, String name) {
125: this .tag = tag;
126:
127: if (tag == rfc822Name || tag == dNSName
128: || tag == uniformResourceIdentifier) {
129: this .obj = new DERIA5String(name);
130: } else if (tag == registeredID) {
131: this .obj = new DERObjectIdentifier(name);
132: } else if (tag == directoryName) {
133: this .obj = new X509Name(name);
134: } else if (tag == iPAddress) {
135: if (IPAddress.isValid(name)) {
136: this .obj = new DEROctetString(Strings
137: .toUTF8ByteArray(name));
138: } else {
139: throw new IllegalArgumentException(
140: "IP Address is invalid");
141: }
142: } else {
143: throw new IllegalArgumentException(
144: "can't process String for tag: " + tag);
145: }
146: }
147:
148: public static GeneralName getInstance(Object obj) {
149: if (obj == null || obj instanceof GeneralName) {
150: return (GeneralName) obj;
151: }
152:
153: if (obj instanceof ASN1TaggedObject) {
154: ASN1TaggedObject tagObj = (ASN1TaggedObject) obj;
155: int tag = tagObj.getTagNo();
156:
157: switch (tag) {
158: case otherName:
159: return new GeneralName(tag, ASN1Sequence.getInstance(
160: tagObj, false));
161: case rfc822Name:
162: return new GeneralName(tag, DERIA5String.getInstance(
163: tagObj, false));
164: case dNSName:
165: return new GeneralName(tag, DERIA5String.getInstance(
166: tagObj, false));
167: case x400Address:
168: throw new IllegalArgumentException("unknown tag: "
169: + tag);
170: case directoryName:
171: return new GeneralName(tag, ASN1Sequence.getInstance(
172: tagObj, true));
173: case ediPartyName:
174: return new GeneralName(tag, ASN1Sequence.getInstance(
175: tagObj, false));
176: case uniformResourceIdentifier:
177: return new GeneralName(tag, DERIA5String.getInstance(
178: tagObj, false));
179: case iPAddress:
180: return new GeneralName(tag, ASN1OctetString
181: .getInstance(tagObj, false));
182: case registeredID:
183: return new GeneralName(tag, DERObjectIdentifier
184: .getInstance(tagObj, false));
185: }
186: }
187:
188: throw new IllegalArgumentException(
189: "unknown object in getInstance");
190: }
191:
192: public static GeneralName getInstance(ASN1TaggedObject tagObj,
193: boolean explicit) {
194: return GeneralName.getInstance(ASN1TaggedObject.getInstance(
195: tagObj, true));
196: }
197:
198: public int getTagNo() {
199: return tag;
200: }
201:
202: public DEREncodable getName() {
203: return obj;
204: }
205:
206: public String toString() {
207: StringBuffer buf = new StringBuffer();
208:
209: buf.append(tag);
210: buf.append(": ");
211: switch (tag) {
212: case rfc822Name:
213: case dNSName:
214: case uniformResourceIdentifier:
215: buf.append(DERIA5String.getInstance(obj).getString());
216: break;
217: case directoryName:
218: buf.append(X509Name.getInstance(obj).toString());
219: break;
220: default:
221: buf.append(obj.toString());
222: }
223: return buf.toString();
224: }
225:
226: public DERObject toASN1Object() {
227: if (tag == directoryName) // directoryName is explicitly tagged as it is a CHOICE
228: {
229: return new DERTaggedObject(true, tag, obj);
230: } else {
231: return new DERTaggedObject(false, tag, obj);
232: }
233: }
234: }
|