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