New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography.X509Certificates / X509Certificate20.cs
1 //
2 // X509Certificate20.cs: Partial class to handle new 2.0-only stuff
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-2006,2008 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
31 using System.Runtime.InteropServices;
32 using System.Security.Permissions;
33 using System.Text;
34
35 using Mono.Security;
36 using Mono.Security.X509;
37
38 using System.Runtime.Serialization;
39
40 namespace System.Security.Cryptography.X509Certificates {
41
42         [ComVisible (true)]
43         [MonoTODO ("X509ContentType.SerializedCert isn't supported (anywhere in the class)")]
44 #if MOONLIGHT
45         public partial class X509Certificate {
46 #else
47         public partial class X509Certificate : IDeserializationCallback, ISerializable {
48 #endif
49                 private string issuer_name;
50                 private string subject_name;
51
52
53                 public X509Certificate ()
54                 {
55                         // this allows an empty certificate to exists
56                 }
57
58                 public X509Certificate (byte[] rawData, string password)
59                 {
60                         Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
61                 }
62
63 #if !MOONLIGHT
64                 [MonoTODO ("SecureString support is incomplete")]
65                 public X509Certificate (byte[] rawData, SecureString password)
66                 {
67                         Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
68                 }
69 #endif
70
71                 public X509Certificate (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
72                 {
73                         Import (rawData, password, keyStorageFlags);
74                 }
75
76 #if !MOONLIGHT
77                 [MonoTODO ("SecureString support is incomplete")]
78                 public X509Certificate (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
79                 {
80                         Import (rawData, password, keyStorageFlags);
81                 }
82 #endif
83
84                 public X509Certificate (string fileName)
85                 {
86                         Import (fileName, (string)null, X509KeyStorageFlags.DefaultKeySet);
87                 }
88
89                 public X509Certificate (string fileName, string password)
90                 {
91                         Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
92                 }
93
94 #if !MOONLIGHT
95                 [MonoTODO ("SecureString support is incomplete")]
96                 public X509Certificate (string fileName, SecureString password)
97                 {
98                         Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
99                 }
100 #endif
101
102                 public X509Certificate (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
103                 {
104                         Import (fileName, password, keyStorageFlags);
105                 }
106
107 #if !MOONLIGHT
108                 [MonoTODO ("SecureString support is incomplete")]
109                 public X509Certificate (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
110                 {
111                         Import (fileName, password, keyStorageFlags);
112                 }
113 #endif
114
115                 public X509Certificate (SerializationInfo info, StreamingContext context)
116                 {
117                         byte[] raw = (byte[]) info.GetValue ("RawData", typeof (byte[]));
118                         Import (raw, (string)null, X509KeyStorageFlags.DefaultKeySet);
119                 }
120
121
122                 public string Issuer {
123                         get {
124                                 if (x509 == null)
125                                         throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
126
127                                 if (issuer_name == null)
128                                         issuer_name = X501.ToString (x509.GetIssuerName (), true, ", ", true);
129                                 return issuer_name;
130                         }
131                 }
132
133                 public string Subject {
134                         get {
135                                 if (x509 == null)
136                                         throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
137
138                                 if (subject_name == null)
139                                         subject_name = X501.ToString (x509.GetSubjectName (), true, ", ", true);
140                                 return subject_name;
141                         }
142                 }
143
144                 [ComVisible (false)]
145                 public IntPtr Handle {
146                         get { return IntPtr.Zero; }
147                 }
148
149
150                 [ComVisible (false)]
151                 public override bool Equals (object obj) 
152                 {
153                         X509Certificate x = (obj as X509Certificate);
154                         if (x != null)
155                                 return this.Equals (x);
156                         return false;
157                 }
158
159                 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported")]
160                 [ComVisible (false)]
161                 public virtual byte[] Export (X509ContentType contentType)
162                 {
163                         return Export (contentType, (byte[])null);
164                 }
165
166                 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported")]
167                 [ComVisible (false)]
168                 public virtual byte[] Export (X509ContentType contentType, string password)
169                 {
170                         byte[] pwd = (password == null) ? null : Encoding.UTF8.GetBytes (password);
171                         return Export (contentType, pwd);
172                 }
173
174 #if !MOONLIGHT
175                 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported. SecureString support is incomplete.")]
176                 public virtual byte[] Export (X509ContentType contentType, SecureString password)
177                 {
178                         byte[] pwd = (password == null) ? null : password.GetBuffer ();
179                         return Export (contentType, pwd);
180                 }
181 #endif
182
183                 internal byte[] Export (X509ContentType contentType, byte[] password)
184                 {
185                         if (x509 == null)
186                                 throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
187
188                         try {
189                                 switch (contentType) {
190                                 case X509ContentType.Cert:
191                                         return x509.RawData;
192 #if !MOONLIGHT
193                                 case X509ContentType.Pfx: // this includes Pkcs12
194                                         // TODO
195                                         throw new NotSupportedException ();
196                                 case X509ContentType.SerializedCert:
197                                         // TODO
198                                         throw new NotSupportedException ();
199 #endif
200                                 default:
201                                         string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
202                                         throw new CryptographicException (msg);
203                                 }
204                         }
205                         finally {
206                                 // protect password
207                                 if (password != null)
208                                         Array.Clear (password, 0, password.Length);
209                         }
210                 }
211
212                 [ComVisible (false)]
213                 public virtual void Import (byte[] rawData)
214                 {
215                         Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
216                 }
217
218                 [MonoTODO ("missing KeyStorageFlags support")]
219                 [ComVisible (false)]
220                 public virtual void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
221                 {
222                         Reset ();
223                         if (password == null) {
224                                 try {
225                                         x509 = new Mono.Security.X509.X509Certificate (rawData);
226                                 }
227                                 catch (Exception e) {
228                                         try {
229                                                 PKCS12 pfx = new PKCS12 (rawData);
230                                                 if (pfx.Certificates.Count > 0)
231                                                         x509 = pfx.Certificates [0];
232                                                 else
233                                                         x509 = null;
234                                         }
235                                         catch {
236                                                 string msg = Locale.GetText ("Unable to decode certificate.");
237                                                 // inner exception is the original (not second) exception
238                                                 throw new CryptographicException (msg, e);
239                                         }
240                                 }
241                         } else {
242                                 // try PKCS#12
243                                 try {
244                                         PKCS12 pfx = new PKCS12 (rawData, password);
245                                         if (pfx.Certificates.Count > 0) {
246                                                 x509 = pfx.Certificates [0];
247                                         } else {
248                                                 x509 = null;
249                                         }
250                                 }
251                                 catch {
252                                         // it's possible to supply a (unrequired/unusued) password
253                                         // fix bug #79028
254                                         x509 = new Mono.Security.X509.X509Certificate (rawData);
255                                 }
256                         }
257                 }
258
259 #if !MOONLIGHT
260                 [MonoTODO ("SecureString support is incomplete")]
261                 public virtual void Import (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
262                 {
263                         Import (rawData, (string)null, keyStorageFlags);
264                 }
265 #endif
266
267                 [ComVisible (false)]
268                 public virtual void Import (string fileName)
269                 {
270                         byte[] rawData = Load (fileName);
271                         Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
272                 }
273
274                 [MonoTODO ("missing KeyStorageFlags support")]
275                 [ComVisible (false)]
276                 public virtual void Import (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
277                 {
278                         byte[] rawData = Load (fileName);
279                         Import (rawData, password, keyStorageFlags);
280                 }
281
282 #if !MOONLIGHT
283                 [MonoTODO ("SecureString support is incomplete, missing KeyStorageFlags support")]
284                 public virtual void Import (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
285                 {
286                         byte[] rawData = Load (fileName);
287                         Import (rawData, (string)null, keyStorageFlags);
288                 }
289 #endif
290
291 #if !MOONLIGHT
292                 void IDeserializationCallback.OnDeserialization (object sender)
293                 {
294                 }
295
296                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
297                 {
298                         // will throw a NRE if info is null (just like MS implementation)
299                         info.AddValue ("RawData", x509.RawData);
300                 }
301 #endif
302                 [ComVisible (false)]
303                 public virtual void Reset ()
304                 {
305                         x509 = null;
306                         issuer_name = null;
307                         subject_name = null;
308                         hideDates = false;
309                         cachedCertificateHash = null;
310                 }
311         }
312 }