1package org.bouncycastle.asn1.x509; 2 3import org.bouncycastle.asn1.ASN1Choice; 4import org.bouncycastle.asn1.ASN1Encodable; 5import org.bouncycastle.asn1.ASN1OctetString; 6import org.bouncycastle.asn1.ASN1Sequence; 7import org.bouncycastle.asn1.ASN1TaggedObject; 8import org.bouncycastle.asn1.DEREncodable; 9import org.bouncycastle.asn1.DERIA5String; 10import org.bouncycastle.asn1.DERObject; 11import org.bouncycastle.asn1.DERObjectIdentifier; 12import org.bouncycastle.asn1.DERTaggedObject; 13 14/** 15 * The GeneralName object. 16 * <pre> 17 * GeneralName ::= CHOICE { 18 * otherName [0] OtherName, 19 * rfc822Name [1] IA5String, 20 * dNSName [2] IA5String, 21 * x400Address [3] ORAddress, 22 * directoryName [4] Name, 23 * ediPartyName [5] EDIPartyName, 24 * uniformResourceIdentifier [6] IA5String, 25 * iPAddress [7] OCTET STRING, 26 * registeredID [8] OBJECT IDENTIFIER} 27 * 28 * OtherName ::= SEQUENCE { 29 * type-id OBJECT IDENTIFIER, 30 * value [0] EXPLICIT ANY DEFINED BY type-id } 31 * 32 * EDIPartyName ::= SEQUENCE { 33 * nameAssigner [0] DirectoryString OPTIONAL, 34 * partyName [1] DirectoryString } 35 * 36 * Name ::= CHOICE { RDNSequence } 37 * </pre> 38 */ 39public class GeneralName 40 extends ASN1Encodable 41 implements ASN1Choice 42{ 43 public static final int otherName = 0; 44 public static final int rfc822Name = 1; 45 public static final int dNSName = 2; 46 public static final int x400Address = 3; 47 public static final int directoryName = 4; 48 public static final int ediPartyName = 5; 49 public static final int uniformResourceIdentifier = 6; 50 public static final int iPAddress = 7; 51 public static final int registeredID = 8; 52 53 DEREncodable obj; 54 int tag; 55 56 public GeneralName( 57 X509Name dirName) 58 { 59 this.obj = dirName; 60 this.tag = 4; 61 } 62 63 /** 64 * @deprecated this constructor seems the wrong way round! Use GeneralName(tag, name). 65 */ 66 public GeneralName( 67 DERObject name, int tag) 68 { 69 this.obj = name; 70 this.tag = tag; 71 } 72 73 /** 74 * When the subjectAltName extension contains an Internet mail address, 75 * the address MUST be included as an rfc822Name. The format of an 76 * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822]. 77 * 78 * When the subjectAltName extension contains a domain name service 79 * label, the domain name MUST be stored in the dNSName (an IA5String). 80 * The name MUST be in the "preferred name syntax," as specified by RFC 81 * 1034 [RFC 1034]. 82 * 83 * When the subjectAltName extension contains a URI, the name MUST be 84 * stored in the uniformResourceIdentifier (an IA5String). The name MUST 85 * be a non-relative URL, and MUST follow the URL syntax and encoding 86 * rules specified in [RFC 1738]. The name must include both a scheme 87 * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme- 88 * specific-part must include a fully qualified domain name or IP 89 * address as the host. 90 * 91 * When the subjectAltName extension contains a iPAddress, the address 92 * MUST be stored in the octet string in "network byte order," as 93 * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of 94 * each octet is the LSB of the corresponding byte in the network 95 * address. For IP Version 4, as specified in RFC 791, the octet string 96 * MUST contain exactly four octets. For IP Version 6, as specified in 97 * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC 98 * 1883]. 99 */ 100 public GeneralName( 101 int tag, 102 ASN1Encodable name) 103 { 104 this.obj = name; 105 this.tag = tag; 106 } 107 108 /** 109 * Create a General name for the given tag from the passed in String. 110 * 111 * @param tag tag number 112 * @param name string representation of name 113 */ 114 public GeneralName( 115 int tag, 116 String name) 117 { 118 if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier) 119 { 120 this.tag = tag; 121 this.obj = new DERIA5String(name); 122 } 123 else if (tag == registeredID) 124 { 125 this.tag = tag; 126 this.obj = new DERObjectIdentifier(name); 127 } 128 else 129 { 130 throw new IllegalArgumentException("can't process String for tag: " + tag); 131 } 132 } 133 134 public static GeneralName getInstance( 135 Object obj) 136 { 137 if (obj == null || obj instanceof GeneralName) 138 { 139 return (GeneralName)obj; 140 } 141 142 if (obj instanceof ASN1TaggedObject) 143 { 144 ASN1TaggedObject tagObj = (ASN1TaggedObject)obj; 145 int tag = tagObj.getTagNo(); 146 147 switch (tag) 148 { 149 case otherName: 150 return new GeneralName(ASN1Sequence.getInstance(tagObj, false), tag); 151 case rfc822Name: 152 return new GeneralName(DERIA5String.getInstance(tagObj, false), tag); 153 case dNSName: 154 return new GeneralName(DERIA5String.getInstance(tagObj, false), tag); 155 case x400Address: 156 throw new IllegalArgumentException("unknown tag: " + tag); 157 case directoryName: 158 return new GeneralName(ASN1Sequence.getInstance(tagObj, true), tag); 159 case ediPartyName: 160 return new GeneralName(ASN1Sequence.getInstance(tagObj, false), tag); 161 case uniformResourceIdentifier: 162 return new GeneralName(DERIA5String.getInstance(tagObj, false), tag); 163 case iPAddress: 164 return new GeneralName(ASN1OctetString.getInstance(tagObj, false), tag); 165 case registeredID: 166 return new GeneralName(DERObjectIdentifier.getInstance(tagObj, false), tag); 167 } 168 } 169 170 throw new IllegalArgumentException("unknown object in getInstance"); 171 } 172 173 public static GeneralName getInstance( 174 ASN1TaggedObject tagObj, 175 boolean explicit) 176 { 177 return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true)); 178 } 179 180 public int getTagNo() 181 { 182 return tag; 183 } 184 185 public DEREncodable getName() 186 { 187 return obj; 188 } 189 190 public DERObject toASN1Object() 191 { 192 if (tag == directoryName) // directoryName is explicitly tagged as it is a CHOICE 193 { 194 return new DERTaggedObject(true, tag, obj); 195 } 196 else 197 { 198 return new DERTaggedObject(false, tag, obj); 199 } 200 } 201} 202