b8506aab791a2a9c52935c15bddb2fa3545bcd64
[mono.git] / mcs / class / Mono.Security / Mono.Security.X509 / X520Attributes.cs
1 //
2 // X520.cs: X.520 related stuff (attributes, RDN)
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Globalization;
32 using System.Text;
33
34 using Mono.Security;
35
36 namespace Mono.Security.X509 {
37
38         // References:
39         // 1.   Information technology - Open Systems Interconnection - The Directory: Selected attribute types 
40         //      http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-X.520 
41         // 2.   Internet X.509 Public Key Infrastructure Certificate and CRL Profile
42         //      http://www.ietf.org/rfc/rfc3280.txt
43         // 3.   A Summary of the X.500(96) User Schema for use with LDAPv3
44         //      http://www.faqs.org/rfcs/rfc2256.html
45         // 4.   RFC 2247 - Using Domains in LDAP/X.500 Distinguished Names
46         //      http://www.faqs.org/rfcs/rfc2247.html
47
48         /* 
49          * AttributeTypeAndValue ::= SEQUENCE {
50          *      type     AttributeType,
51          *      value    AttributeValue 
52          * }
53          * 
54          * AttributeType ::= OBJECT IDENTIFIER
55          * 
56          * AttributeValue ::= ANY DEFINED BY AttributeType
57          */
58 #if INSIDE_CORLIB
59         internal
60 #else
61         public 
62 #endif
63         class X520 {
64
65                 public abstract class AttributeTypeAndValue {
66                         private string oid;
67                         private string attrValue;
68                         private int upperBound;
69                         private byte encoding;
70
71                         protected AttributeTypeAndValue (string oid, int upperBound)
72                         {
73                                 this.oid = oid;
74                                 this.upperBound = upperBound;
75                                 this.encoding = 0xFF;
76                         }
77
78                         protected AttributeTypeAndValue (string oid, int upperBound, byte encoding) 
79                         {
80                                 this.oid = oid;
81                                 this.upperBound = upperBound;
82                                 this.encoding = encoding;
83                         }
84
85                         public string Value {
86                                 get { return attrValue; }
87                                 set { 
88                                         if ((attrValue != null) && (attrValue.Length > upperBound)) {
89                                                 string msg = Locale.GetText ("Value length bigger than upperbound ({0}).");
90                                                 throw new FormatException (String.Format (msg, upperBound));
91                                         }
92                                         attrValue = value; 
93                                 }
94                         }
95
96                         public ASN1 ASN1 {
97                                 get { return GetASN1 (); }
98                         }
99
100                         internal ASN1 GetASN1 (byte encoding) 
101                         {
102                                 byte encode = encoding;
103                                 if (encode == 0xFF)
104                                         encode = SelectBestEncoding ();
105                                         
106                                 ASN1 asn1 = new ASN1 (0x30);
107                                 asn1.Add (ASN1Convert.FromOid (oid));
108                                 switch (encode) {
109                                         case 0x13:
110                                                 // PRINTABLESTRING
111                                                 asn1.Add (new ASN1 (0x13, Encoding.ASCII.GetBytes (attrValue)));
112                                                 break;
113                                         case 0x16:
114                                                 // IA5STRING
115                                                 asn1.Add (new ASN1 (0x16, Encoding.ASCII.GetBytes (attrValue)));
116                                                 break;
117                                         case 0x1E:
118                                                 // BMPSTRING
119                                                 asn1.Add (new ASN1 (0x1E, Encoding.BigEndianUnicode.GetBytes (attrValue)));
120                                                 break;
121                                 }
122                                 return asn1;
123                         }
124
125                         internal ASN1 GetASN1 () 
126                         {
127                                 return GetASN1 (encoding);
128                         }
129
130                         public byte[] GetBytes (byte encoding) 
131                         {
132                                 return GetASN1 (encoding) .GetBytes ();
133                         }
134
135                         public byte[] GetBytes () 
136                         {
137                                 return GetASN1 () .GetBytes ();
138                         }
139
140                         private byte SelectBestEncoding ()
141                         {
142                                 foreach (char c in attrValue) {
143                                         switch (c) {
144                                         case '@':
145                                         case '_':
146                                                 return 0x1E; // BMPSTRING
147                                         default:
148                                                 if (c > 127)
149                                                         return 0x1E; // BMPSTRING
150                                                 break;
151                                         }
152                                 }
153                                 return 0x13; // PRINTABLESTRING
154                         }
155                 }
156
157                 public class Name : AttributeTypeAndValue {
158
159                         public Name () : base ("2.5.4.41", 32768) 
160                         {
161                         }
162                 }
163
164                 public class CommonName : AttributeTypeAndValue {
165
166                         public CommonName () : base ("2.5.4.3", 64) 
167                         {
168                         }
169                 }
170
171                 // RFC2256, Section 5.6
172                 public class SerialNumber : AttributeTypeAndValue {
173
174                         // max length 64 bytes, Printable String only
175                         public SerialNumber ()
176                                 : base ("2.5.4.5", 64, 0x13)
177                         {
178                         }
179                 }
180
181                 public class LocalityName : AttributeTypeAndValue {
182
183                         public LocalityName () : base ("2.5.4.7", 128)
184                         {
185                         }
186                 }
187
188                 public class StateOrProvinceName : AttributeTypeAndValue {
189
190                         public StateOrProvinceName () : base ("2.5.4.8", 128) 
191                         {
192                         }
193                 }
194                  
195                 public class OrganizationName : AttributeTypeAndValue {
196
197                         public OrganizationName () : base ("2.5.4.10", 64)
198                         {
199                         }
200                 }
201                  
202                 public class OrganizationalUnitName : AttributeTypeAndValue {
203
204                         public OrganizationalUnitName () : base ("2.5.4.11", 64)
205                         {
206                         }
207                 }
208
209                 // NOTE: Not part of RFC2253
210                 public class EmailAddress : AttributeTypeAndValue {
211
212                         public EmailAddress () : base ("1.2.840.113549.1.9.1", 128, 0x16)
213                         {
214                         }
215                 }
216
217                 // RFC2247, Section 4
218                 public class DomainComponent : AttributeTypeAndValue {
219
220                         // no maximum length defined
221                         public DomainComponent ()
222                                 : base ("0.9.2342.19200300.100.1.25", Int32.MaxValue, 0x16)
223                         {
224                         }
225                 }
226
227                 // RFC1274, Section 9.3.1
228                 public class UserId : AttributeTypeAndValue {
229
230                         public UserId ()
231                                 : base ("0.9.2342.19200300.100.1.1", 256)
232                         {
233                         }
234                 }
235
236                 public class Oid : AttributeTypeAndValue {
237
238                         public Oid (string oid)
239                                 : base (oid, Int32.MaxValue)
240                         {
241                         }
242                 }
243
244                 /* -- Naming attributes of type X520Title
245                  * id-at-title             AttributeType ::= { id-at 12 }
246                  * 
247                  * X520Title ::= CHOICE {
248                  *       teletexString     TeletexString   (SIZE (1..ub-title)),
249                  *       printableString   PrintableString (SIZE (1..ub-title)),
250                  *       universalString   UniversalString (SIZE (1..ub-title)),
251                  *       utf8String        UTF8String      (SIZE (1..ub-title)),
252                  *       bmpString         BMPString       (SIZE (1..ub-title)) 
253                  * }
254                  */
255                 public class Title : AttributeTypeAndValue {
256
257                         public Title () : base ("2.5.4.12", 64)
258                         {
259                         }
260                 }
261
262                 public class CountryName : AttributeTypeAndValue {
263
264                         // (0x13) PRINTABLESTRING
265                         public CountryName () : base ("2.5.4.6", 2, 0x13) 
266                         {
267                         }
268                 }
269
270                 public class DnQualifier : AttributeTypeAndValue {
271
272                         // (0x13) PRINTABLESTRING
273                         public DnQualifier () : base ("2.5.4.46", 2, 0x13) 
274                         {
275                         }
276                 }
277
278                 public class Surname : AttributeTypeAndValue {
279
280                         public Surname () : base ("2.5.4.4", 32768) 
281                         {
282                         }
283                 }
284
285                 public class GivenName : AttributeTypeAndValue {
286
287                         public GivenName () : base ("2.5.4.42", 16) 
288                         {
289                         }
290                 }
291
292                 public class Initial : AttributeTypeAndValue {
293
294                         public Initial () : base ("2.5.4.43", 5) 
295                         {
296                         }
297                 }
298
299         }
300         
301         /* From RFC3280
302          * --  specifications of Upper Bounds MUST be regarded as mandatory
303          * --  from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
304          * 
305          * --  Upper Bounds
306          * 
307          * ub-name INTEGER ::= 32768
308          * ub-common-name INTEGER ::= 64
309          * ub-locality-name INTEGER ::= 128
310          * ub-state-name INTEGER ::= 128
311          * ub-organization-name INTEGER ::= 64
312          * ub-organizational-unit-name INTEGER ::= 64
313          * ub-title INTEGER ::= 64
314          * ub-serial-number INTEGER ::= 64
315          * ub-match INTEGER ::= 128
316          * ub-emailaddress-length INTEGER ::= 128
317          * ub-common-name-length INTEGER ::= 64
318          * ub-country-name-alpha-length INTEGER ::= 2
319          * ub-country-name-numeric-length INTEGER ::= 3
320          * ub-domain-defined-attributes INTEGER ::= 4
321          * ub-domain-defined-attribute-type-length INTEGER ::= 8
322          * ub-domain-defined-attribute-value-length INTEGER ::= 128
323          * ub-domain-name-length INTEGER ::= 16
324          * ub-extension-attributes INTEGER ::= 256
325          * ub-e163-4-number-length INTEGER ::= 15
326          * ub-e163-4-sub-address-length INTEGER ::= 40
327          * ub-generation-qualifier-length INTEGER ::= 3
328          * ub-given-name-length INTEGER ::= 16
329          * ub-initials-length INTEGER ::= 5
330          * ub-integer-options INTEGER ::= 256
331          * ub-numeric-user-id-length INTEGER ::= 32
332          * ub-organization-name-length INTEGER ::= 64
333          * ub-organizational-unit-name-length INTEGER ::= 32
334          * ub-organizational-units INTEGER ::= 4
335          * ub-pds-name-length INTEGER ::= 16
336          * ub-pds-parameter-length INTEGER ::= 30
337          * ub-pds-physical-address-lines INTEGER ::= 6
338          * ub-postal-code-length INTEGER ::= 16
339          * ub-pseudonym INTEGER ::= 128
340          * ub-surname-length INTEGER ::= 40
341          * ub-terminal-id-length INTEGER ::= 24
342          * ub-unformatted-address-length INTEGER ::= 180
343          * ub-x121-address-length INTEGER ::= 16
344          * 
345          * -- Note - upper bounds on string types, such as TeletexString, are
346          * -- measured in characters.  Excepting PrintableString or IA5String, a
347          * -- significantly greater number of octets will be required to hold
348          * -- such a value.  As a minimum, 16 octets, or twice the specified
349          * -- upper bound, whichever is the larger, should be allowed for
350          * -- TeletexString.  For UTF8String or UniversalString at least four
351          * -- times the upper bound should be allowed.
352          */
353 }