2 // X501Name.cs: X.501 Distinguished Names stuff
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
15 namespace Mono.Security.X509 {
18 // 1. Information technology - Open Systems Interconnection - The Directory: Models
19 // http://www.itu.int/rec/recommendation.asp?type=items&lang=e&parent=T-REC-X.501-200102-I
20 // 2. RFC2253: Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
21 // http://www.ietf.org/rfc/rfc2253.txt
24 * Name ::= CHOICE { RDNSequence }
26 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
28 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
37 static byte[] countryName = { 0x55, 0x04, 0x06 };
38 static byte[] organizationName = { 0x55, 0x04, 0x0A };
39 static byte[] organizationalUnitName = { 0x55, 0x04, 0x0B };
40 static byte[] commonName = { 0x55, 0x04, 0x03 };
41 static byte[] localityName = { 0x55, 0x04, 0x07 };
42 static byte[] stateOrProvinceName = { 0x55, 0x04, 0x08 };
43 static byte[] streetAddress = { 0x55, 0x04, 0x09 };
44 static byte[] serialNumber = { 0x55, 0x04, 0x05 };
45 static byte[] domainComponent = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19 };
46 static byte[] userid = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x01 };
47 static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
49 static public string ToString (ASN1 seq)
51 StringBuilder sb = new StringBuilder ();
52 for (int i = 0; i < seq.Count; i++) {
54 ASN1 pair = entry [0];
64 if (poid.CompareValue (countryName))
66 else if (poid.CompareValue (organizationName))
68 else if (poid.CompareValue (organizationalUnitName))
70 else if (poid.CompareValue (commonName))
72 else if (poid.CompareValue (localityName))
74 else if (poid.CompareValue (stateOrProvinceName))
75 sb.Append ("S="); // NOTE: RFC2253 uses ST=
76 else if (poid.CompareValue (streetAddress))
77 sb.Append ("STREET=");
78 else if (poid.CompareValue (domainComponent))
80 else if (poid.CompareValue (userid))
82 else if (poid.CompareValue (email))
83 sb.Append ("E="); // NOTE: Not part of RFC2253
86 sb.Append ("OID."); // NOTE: Not present as RFC2253
87 sb.Append (ASN1Convert.ToOID (poid));
92 // 16bits or 8bits string ? TODO not complete (+special chars!)
95 StringBuilder sb2 = new StringBuilder ();
96 for (int j = 1; j < s.Value.Length; j+=2)
97 sb2.Append ((char) s.Value[j]);
98 sValue = sb2.ToString ();
101 sValue = System.Text.Encoding.UTF8.GetString (s.Value);
102 // in some cases we must quote (") the value
103 // Note: this doesn't seems to conform to RFC2253
104 char[] specials = { ',', '+', '"', '\\', '<', '>', ';' };
105 if (sValue.IndexOfAny(specials, 0, sValue.Length) > 0)
106 sValue = "\"" + sValue + "\"";
107 else if (sValue.StartsWith (" "))
108 sValue = "\"" + sValue + "\"";
109 else if (sValue.EndsWith (" "))
110 sValue = "\"" + sValue + "\"";
115 // separator (not on last iteration)
116 if (i < seq.Count - 1)
119 return sb.ToString ();
122 static private X520.AttributeTypeAndValue GetAttributeFromOID (string attributeType)
124 switch (attributeType.ToUpper ().Trim ()) {
126 return new X520.CountryName ();
128 return new X520.OrganizationName ();
130 return new X520.OrganizationalUnitName ();
132 return new X520.CommonName ();
134 return new X520.LocalityName ();
135 case "S": // Microsoft
136 case "ST": // RFC2253
137 return new X520.StateOrProvinceName ();
139 // return streetAddress;
141 // return domainComponent;
149 static public ASN1 FromString (string rdn)
152 throw new ArgumentNullException ("rdn");
153 // get string from here to ',' or end of string
156 ASN1 asn1 = new ASN1 (0x30);
157 while (start < rdn.Length) {
158 end = rdn.IndexOf (',', end) + 1;
160 end = rdn.Length + 1;
161 string av = rdn.Substring (start, end - start - 1);
162 // get '=' position in substring
163 int equal = av.IndexOf ('=');
165 string attributeType = av.Substring (0, equal);
167 string attributeValue = av.Substring (equal + 1);
169 X520.AttributeTypeAndValue atv = GetAttributeFromOID (attributeType);
170 atv.Value = attributeValue;
171 asn1.Add (new ASN1 (0x31, atv.GetBytes ()));
176 if (end > rdn.Length)