using System; using System.Text; using Org.BouncyCastle.Utilities.Net; namespace Org.BouncyCastle.Asn1.X509 { /** * The GeneralName object. *
     * GeneralName ::= CHOICE {
     *      otherName                       [0]     OtherName,
     *      rfc822Name                      [1]     IA5String,
     *      dNSName                         [2]     IA5String,
     *      x400Address                     [3]     ORAddress,
     *      directoryName                   [4]     Name,
     *      ediPartyName                    [5]     EDIPartyName,
     *      uniformResourceIdentifier       [6]     IA5String,
     *      iPAddress                       [7]     OCTET STRING,
     *      registeredID                    [8]     OBJECT IDENTIFIER}
     *
     * OtherName ::= Sequence {
     *      type-id    OBJECT IDENTIFIER,
     *      value      [0] EXPLICIT ANY DEFINED BY type-id }
     *
     * EDIPartyName ::= Sequence {
     *      nameAssigner            [0]     DirectoryString OPTIONAL,
     *      partyName               [1]     DirectoryString }
     * 
*/ public class GeneralName : Asn1Encodable { public const int OtherName = 0; public const int Rfc822Name = 1; public const int DnsName = 2; public const int X400Address = 3; public const int DirectoryName = 4; public const int EdiPartyName = 5; public const int UniformResourceIdentifier = 6; public const int IPAddress = 7; public const int RegisteredID = 8; internal readonly Asn1Encodable obj; internal readonly int tag; public GeneralName( X509Name directoryName) { this.obj = directoryName; this.tag = 4; } /** * When the subjectAltName extension contains an Internet mail address, * the address MUST be included as an rfc822Name. The format of an * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822]. * * When the subjectAltName extension contains a domain name service * label, the domain name MUST be stored in the dNSName (an IA5String). * The name MUST be in the "preferred name syntax," as specified by RFC * 1034 [RFC 1034]. * * When the subjectAltName extension contains a URI, the name MUST be * stored in the uniformResourceIdentifier (an IA5String). The name MUST * be a non-relative URL, and MUST follow the URL syntax and encoding * rules specified in [RFC 1738]. The name must include both a scheme * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme- * specific-part must include a fully qualified domain name or IP * address as the host. * * When the subjectAltName extension contains a iPAddress, the address * MUST be stored in the octet string in "network byte order," as * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of * each octet is the LSB of the corresponding byte in the network * address. For IP Version 4, as specified in RFC 791, the octet string * MUST contain exactly four octets. For IP Version 6, as specified in * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC * 1883]. */ public GeneralName( Asn1Object name, int tag) { this.obj = name; this.tag = tag; } public GeneralName( int tag, Asn1Encodable name) { this.obj = name; this.tag = tag; } /** * Create a GeneralName for the given tag from the passed in String. *

* This constructor can handle: *

* For x400Address, otherName and ediPartyName there is no common string * format defined. *

* Note: A directory name can be encoded in different ways into a byte * representation. Be aware of this if the byte representation is used for * comparing results. *

* * @param tag tag number * @param name string representation of name * @throws ArgumentException if the string encoding is not correct or * not supported. */ public GeneralName( int tag, string name) { this.tag = tag; if (tag == Rfc822Name || tag == DnsName || tag == UniformResourceIdentifier) { this.obj = new DerIA5String(name); } else if (tag == RegisteredID) { this.obj = new DerObjectIdentifier(name); } else if (tag == DirectoryName) { this.obj = new X509Name(name); } else if (tag == IPAddress) { if (!Org.BouncyCastle.Utilities.Net.IPAddress.IsValid(name)) throw new ArgumentException("IP Address is invalid", "name"); this.obj = new DerOctetString(Encoding.UTF8.GetBytes(name)); } else { throw new ArgumentException("can't process string for tag: " + tag, "tag"); } } public static GeneralName GetInstance( object obj) { if (obj == null || obj is GeneralName) { return (GeneralName) obj; } if (obj is Asn1TaggedObject) { Asn1TaggedObject tagObj = (Asn1TaggedObject) obj; int tag = tagObj.TagNo; switch (tag) { case OtherName: return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false)); case Rfc822Name: return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false)); case DnsName: return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false)); case X400Address: throw new ArgumentException("unknown tag: " + tag); case DirectoryName: return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, true)); case EdiPartyName: return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false)); case UniformResourceIdentifier: return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false)); case IPAddress: return new GeneralName(tag, Asn1OctetString.GetInstance(tagObj, false)); case RegisteredID: return new GeneralName(tag, DerObjectIdentifier.GetInstance(tagObj, false)); } } throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj"); } public static GeneralName GetInstance( Asn1TaggedObject tagObj, bool explicitly) { return GetInstance(Asn1TaggedObject.GetInstance(tagObj, explicitly)); } public int TagNo { get { return tag; } } public Asn1Encodable Name { get { return obj; } } public override string ToString() { StringBuilder buf = new StringBuilder(); buf.Append(tag); buf.Append(": "); switch (tag) { case Rfc822Name: case DnsName: case UniformResourceIdentifier: buf.Append(DerIA5String.GetInstance(obj).GetString()); break; case DirectoryName: buf.Append(X509Name.GetInstance(obj).ToString()); break; default: buf.Append(obj.ToString()); break; } return buf.ToString(); } public override Asn1Object ToAsn1Object() { // Explicitly tagged if DirectoryName return new DerTaggedObject(tag == 4, tag, obj); } } }