2 // System.Security.Cryptography.X509Certificates.X509Store class
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
32 #if MONO_SECURITY_ALIAS
33 extern alias MonoSecurity;
34 using MX = MonoSecurity::Mono.Security.X509;
36 using MX = Mono.Security.X509;
39 using System.Security.Permissions;
41 namespace System.Security.Cryptography.X509Certificates {
43 public sealed class X509Store : IDisposable {
46 private StoreLocation _location;
47 private X509Certificate2Collection list;
48 private OpenFlags _flags;
49 private MX.X509Store store;
53 // BUG: MY when using this constructor - My when using StoreName.My
55 : this ("MY", StoreLocation.CurrentUser)
59 public X509Store (string storeName)
60 : this (storeName, StoreLocation.CurrentUser)
64 public X509Store (StoreName storeName)
65 : this (storeName, StoreLocation.CurrentUser)
69 public X509Store (StoreLocation storeLocation)
70 : this ("MY", storeLocation)
74 public X509Store (StoreName storeName, StoreLocation storeLocation)
76 if ((storeName < StoreName.AddressBook) || (storeName > StoreName.TrustedPublisher))
77 throw new ArgumentException ("storeName");
78 if ((storeLocation < StoreLocation.CurrentUser) || (storeLocation > StoreLocation.LocalMachine))
79 throw new ArgumentException ("storeLocation");
82 case StoreName.CertificateAuthority:
86 _name = storeName.ToString ();
89 _location = storeLocation;
92 [MonoTODO ("Mono's stores are fully managed. All handles are invalid.")]
93 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
94 public X509Store (IntPtr storeHandle)
96 if (storeHandle == IntPtr.Zero)
97 throw new ArgumentNullException ("storeHandle");
98 throw new CryptographicException ("Invalid handle.");
101 public X509Store (string storeName, StoreLocation storeLocation)
103 if ((storeLocation < StoreLocation.CurrentUser) || (storeLocation > StoreLocation.LocalMachine))
104 throw new ArgumentException ("storeLocation");
107 _location = storeLocation;
110 public void Dispose ()
116 public X509Certificate2Collection Certificates {
119 list = new X509Certificate2Collection ();
120 else if (store == null)
127 public StoreLocation Location {
128 get { return _location; }
132 get { return _name; }
135 private MX.X509Stores Factory {
137 if (_location == StoreLocation.CurrentUser)
138 return MX.X509StoreManager.CurrentUser;
140 return MX.X509StoreManager.LocalMachine;
144 private bool IsOpen {
145 get { return (store != null); }
148 private bool IsReadOnly {
149 get { return ((_flags & OpenFlags.ReadWrite) == OpenFlags.ReadOnly); }
152 internal MX.X509Store Store {
153 get { return store; }
156 [MonoTODO ("Mono's stores are fully managed. Always returns IntPtr.Zero.")]
157 public IntPtr StoreHandle {
158 get { return IntPtr.Zero; }
163 public void Add (X509Certificate2 certificate)
165 if (certificate == null)
166 throw new ArgumentNullException ("certificate");
168 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
170 throw new CryptographicException (Locale.GetText ("Store is read-only."));
172 if (!Exists (certificate)) {
174 store.Import (new MX.X509Certificate (certificate.RawData));
177 Certificates.Add (certificate);
182 [MonoTODO ("Method isn't transactional (like documented)")]
183 public void AddRange (X509Certificate2Collection certificates)
185 if (certificates == null)
186 throw new ArgumentNullException ("certificates");
188 if (certificates.Count == 0)
192 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
194 throw new CryptographicException (Locale.GetText ("Store is read-only."));
196 foreach (X509Certificate2 certificate in certificates) {
197 if (!Exists (certificate)) {
199 store.Import (new MX.X509Certificate (certificate.RawData));
202 Certificates.Add (certificate);
215 public void Open (OpenFlags flags)
217 if (String.IsNullOrEmpty (_name))
218 throw new CryptographicException (Locale.GetText ("Invalid store name (null or empty)."));
220 /* keep existing Mono installations (pre 2.0) compatible with new stuff */
231 bool create = ((flags & OpenFlags.OpenExistingOnly) != OpenFlags.OpenExistingOnly);
232 store = Factory.Open (name, create);
234 throw new CryptographicException (Locale.GetText ("Store {0} doesn't exists.", _name));
237 foreach (MX.X509Certificate x in store.Certificates) {
238 var cert2 = new X509Certificate2 (x.RawData);
239 cert2.PrivateKey = x.RSA;
240 Certificates.Add (cert2);
244 public void Remove (X509Certificate2 certificate)
246 if (certificate == null)
247 throw new ArgumentNullException ("certificate");
249 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
251 if (!Exists (certificate))
255 throw new CryptographicException (Locale.GetText ("Store is read-only."));
258 store.Remove (new MX.X509Certificate (certificate.RawData));
261 Certificates.Remove (certificate);
265 [MonoTODO ("Method isn't transactional (like documented)")]
266 public void RemoveRange (X509Certificate2Collection certificates)
268 if (certificates == null)
269 throw new ArgumentNullException ("certificates");
271 if (certificates.Count == 0)
275 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
278 foreach (X509Certificate2 certificate in certificates) {
279 if (Exists (certificate))
286 throw new CryptographicException (Locale.GetText ("Store is read-only."));
289 foreach (X509Certificate2 certificate in certificates)
290 store.Remove (new MX.X509Certificate (certificate.RawData));
293 Certificates.RemoveRange (certificates);
297 private bool Exists (X509Certificate2 certificate)
299 if ((store == null) || (list == null) || (certificate == null))
302 foreach (X509Certificate2 c in list) {
303 if (certificate.Equals (c)) {