using System; using System.Collections; using System.Globalization; using System.IO; using System.Text; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Net; namespace Org.BouncyCastle.Asn1.X509; public class GeneralName : Asn1Encodable, IAsn1Choice { 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 int TagNo => tag; public Asn1Encodable Name => obj; public GeneralName(X509Name directoryName) { obj = directoryName; tag = 4; } public GeneralName(Asn1Object name, int tag) { obj = name; this.tag = tag; } public GeneralName(int tag, Asn1Encodable name) { obj = name; this.tag = tag; } public GeneralName(int tag, string name) { this.tag = tag; switch (tag) { case 1: case 2: case 6: obj = new DerIA5String(name); break; case 8: obj = new DerObjectIdentifier(name); break; case 4: obj = new X509Name(name); break; case 7: { byte[] array = toGeneralNameEncoding(name); if (array == null) { throw new ArgumentException("IP Address is invalid", "name"); } obj = new DerOctetString(array); break; } default: 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 asn1TaggedObject = (Asn1TaggedObject)obj; int tagNo = asn1TaggedObject.TagNo; switch (tagNo) { case 0: return new GeneralName(tagNo, Asn1Sequence.GetInstance(asn1TaggedObject, explicitly: false)); case 1: return new GeneralName(tagNo, DerIA5String.GetInstance(asn1TaggedObject, isExplicit: false)); case 2: return new GeneralName(tagNo, DerIA5String.GetInstance(asn1TaggedObject, isExplicit: false)); case 3: throw new ArgumentException("unknown tag: " + tagNo); case 4: return new GeneralName(tagNo, X509Name.GetInstance(asn1TaggedObject, explicitly: true)); case 5: return new GeneralName(tagNo, Asn1Sequence.GetInstance(asn1TaggedObject, explicitly: false)); case 6: return new GeneralName(tagNo, DerIA5String.GetInstance(asn1TaggedObject, isExplicit: false)); case 7: return new GeneralName(tagNo, Asn1OctetString.GetInstance(asn1TaggedObject, isExplicit: false)); case 8: return new GeneralName(tagNo, DerObjectIdentifier.GetInstance(asn1TaggedObject, explicitly: false)); } } if (obj is byte[]) { try { return GetInstance(Asn1Object.FromByteArray((byte[])obj)); } catch (IOException) { throw new ArgumentException("unable to parse encoded general name"); } } throw new ArgumentException("unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } public static GeneralName GetInstance(Asn1TaggedObject tagObj, bool explicitly) { return GetInstance(Asn1TaggedObject.GetInstance(tagObj, explicitly: true)); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(tag); stringBuilder.Append(": "); switch (tag) { case 1: case 2: case 6: stringBuilder.Append(DerIA5String.GetInstance(obj).GetString()); break; case 4: stringBuilder.Append(X509Name.GetInstance(obj).ToString()); break; default: stringBuilder.Append(obj.ToString()); break; } return stringBuilder.ToString(); } private byte[] toGeneralNameEncoding(string ip) { if (Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv6WithNetmask(ip) || Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv6(ip)) { int num = ip.IndexOf('/'); if (num < 0) { byte[] array = new byte[16]; int[] parsedIp = parseIPv6(ip); copyInts(parsedIp, array, 0); return array; } byte[] array2 = new byte[32]; int[] parsedIp2 = parseIPv6(ip.Substring(0, num)); copyInts(parsedIp2, array2, 0); string text = ip.Substring(num + 1); parsedIp2 = ((text.IndexOf(':') <= 0) ? parseMask(text) : parseIPv6(text)); copyInts(parsedIp2, array2, 16); return array2; } if (Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv4WithNetmask(ip) || Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv4(ip)) { int num2 = ip.IndexOf('/'); if (num2 < 0) { byte[] array3 = new byte[4]; parseIPv4(ip, array3, 0); return array3; } byte[] array4 = new byte[8]; parseIPv4(ip.Substring(0, num2), array4, 0); string text2 = ip.Substring(num2 + 1); if (text2.IndexOf('.') > 0) { parseIPv4(text2, array4, 4); } else { parseIPv4Mask(text2, array4, 4); } return array4; } return null; } private void parseIPv4Mask(string mask, byte[] addr, int offset) { int num = int.Parse(mask); for (int i = 0; i != num; i++) { byte[] array2; byte[] array = (array2 = addr); int num2 = i / 8 + offset; nint num3 = num2; array[num2] = (byte)(array2[num3] | (byte)(1 << i % 8)); } } private void parseIPv4(string ip, byte[] addr, int offset) { string[] array = ip.Split('.', '/'); foreach (string s in array) { addr[offset++] = (byte)int.Parse(s); } } private int[] parseMask(string mask) { int[] array = new int[8]; int num = int.Parse(mask); for (int i = 0; i != num; i++) { int[] array3; int[] array2 = (array3 = array); int num2 = i / 16; nint num3 = num2; array2[num2] = array3[num3] | (1 << i % 16); } return array; } private void copyInts(int[] parsedIp, byte[] addr, int offSet) { for (int i = 0; i != parsedIp.Length; i++) { addr[i * 2 + offSet] = (byte)(parsedIp[i] >> 8); addr[i * 2 + 1 + offSet] = (byte)parsedIp[i]; } } private int[] parseIPv6(string ip) { if (Platform.StartsWith(ip, "::")) { ip = ip.Substring(1); } else if (Platform.EndsWith(ip, "::")) { ip = ip.Substring(0, ip.Length - 1); } IEnumerator enumerator = ip.Split(new char[1] { ':' }).GetEnumerator(); int num = 0; int[] array = new int[8]; int num2 = -1; while (enumerator.MoveNext()) { string text = (string)enumerator.Current; if (text.Length == 0) { num2 = num; array[num++] = 0; continue; } if (text.IndexOf('.') < 0) { array[num++] = int.Parse(text, NumberStyles.AllowHexSpecifier); continue; } string[] array2 = text.Split(new char[1] { '.' }); array[num++] = (int.Parse(array2[0]) << 8) | int.Parse(array2[1]); array[num++] = (int.Parse(array2[2]) << 8) | int.Parse(array2[3]); } if (num != array.Length) { Array.Copy(array, num2, array, array.Length - (num - num2), num - num2); for (int i = num2; i != array.Length - (num - num2); i++) { array[i] = 0; } } return array; } public override Asn1Object ToAsn1Object() { return new DerTaggedObject(tag == 4, tag, obj); } }