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 extern alias MonoSecurity;
34 using System.Security.Permissions;
35 using MX = MonoSecurity::Mono.Security.X509;
37 namespace System.Security.Cryptography.X509Certificates {
39 public sealed class X509Store {
42 private StoreLocation _location;
43 private X509Certificate2Collection list;
44 private OpenFlags _flags;
45 private MX.X509Store store;
49 // BUG: MY when using this constructor - My when using StoreName.My
51 : this ("MY", StoreLocation.CurrentUser)
55 public X509Store (string storeName)
56 : this (storeName, StoreLocation.CurrentUser)
60 public X509Store (StoreName storeName)
61 : this (storeName, StoreLocation.CurrentUser)
65 public X509Store (StoreLocation storeLocation)
66 : this ("MY", storeLocation)
70 public X509Store (StoreName storeName, StoreLocation storeLocation)
72 if ((storeName < StoreName.AddressBook) || (storeName > StoreName.TrustedPublisher))
73 throw new ArgumentException ("storeName");
74 if ((storeLocation < StoreLocation.CurrentUser) || (storeLocation > StoreLocation.LocalMachine))
75 throw new ArgumentException ("storeLocation");
78 case StoreName.CertificateAuthority:
82 _name = storeName.ToString ();
85 _location = storeLocation;
88 [MonoTODO ("Mono's stores are fully managed. All handles are invalid.")]
89 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
90 public X509Store (IntPtr storeHandle)
92 if (storeHandle == IntPtr.Zero)
93 throw new ArgumentNullException ("storeHandle");
94 throw new CryptographicException ("Invalid handle.");
97 public X509Store (string storeName, StoreLocation storeLocation)
99 if ((storeLocation < StoreLocation.CurrentUser) || (storeLocation > StoreLocation.LocalMachine))
100 throw new ArgumentException ("storeLocation");
103 _location = storeLocation;
108 public X509Certificate2Collection Certificates {
111 list = new X509Certificate2Collection ();
112 else if (store == null)
119 public StoreLocation Location {
120 get { return _location; }
124 get { return _name; }
127 private MX.X509Stores Factory {
129 if (_location == StoreLocation.CurrentUser)
130 return MX.X509StoreManager.CurrentUser;
132 return MX.X509StoreManager.LocalMachine;
136 private bool IsOpen {
137 get { return (store != null); }
140 private bool IsReadOnly {
141 get { return ((_flags & OpenFlags.ReadWrite) == OpenFlags.ReadOnly); }
144 internal MX.X509Store Store {
145 get { return store; }
148 [MonoTODO ("Mono's stores are fully managed. Always returns IntPtr.Zero.")]
149 public IntPtr StoreHandle {
150 get { return IntPtr.Zero; }
155 public void Add (X509Certificate2 certificate)
157 if (certificate == null)
158 throw new ArgumentNullException ("certificate");
160 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
162 throw new CryptographicException (Locale.GetText ("Store is read-only."));
164 if (!Exists (certificate)) {
166 store.Import (new MX.X509Certificate (certificate.RawData));
169 Certificates.Add (certificate);
174 [MonoTODO ("Method isn't transactional (like documented)")]
175 public void AddRange (X509Certificate2Collection certificates)
177 if (certificates == null)
178 throw new ArgumentNullException ("certificates");
180 if (certificates.Count == 0)
184 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
186 throw new CryptographicException (Locale.GetText ("Store is read-only."));
188 foreach (X509Certificate2 certificate in certificates) {
189 if (!Exists (certificate)) {
191 store.Import (new MX.X509Certificate (certificate.RawData));
194 Certificates.Add (certificate);
207 public void Open (OpenFlags flags)
209 if (String.IsNullOrEmpty (_name))
210 throw new CryptographicException (Locale.GetText ("Invalid store name (null or empty)."));
212 /* keep existing Mono installations (pre 2.0) compatible with new stuff */
223 bool create = ((flags & OpenFlags.OpenExistingOnly) != OpenFlags.OpenExistingOnly);
224 store = Factory.Open (name, create);
226 throw new CryptographicException (Locale.GetText ("Store {0} doesn't exists.", _name));
229 foreach (MX.X509Certificate x in store.Certificates) {
230 var cert2 = new X509Certificate2 (x.RawData);
231 cert2.PrivateKey = x.RSA;
232 Certificates.Add (cert2);
236 public void Remove (X509Certificate2 certificate)
238 if (certificate == null)
239 throw new ArgumentNullException ("certificate");
241 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
243 if (!Exists (certificate))
247 throw new CryptographicException (Locale.GetText ("Store is read-only."));
250 store.Remove (new MX.X509Certificate (certificate.RawData));
253 Certificates.Remove (certificate);
257 [MonoTODO ("Method isn't transactional (like documented)")]
258 public void RemoveRange (X509Certificate2Collection certificates)
260 if (certificates == null)
261 throw new ArgumentNullException ("certificates");
263 if (certificates.Count == 0)
267 throw new CryptographicException (Locale.GetText ("Store isn't opened."));
270 foreach (X509Certificate2 certificate in certificates) {
271 if (Exists (certificate))
278 throw new CryptographicException (Locale.GetText ("Store is read-only."));
281 foreach (X509Certificate2 certificate in certificates)
282 store.Remove (new MX.X509Certificate (certificate.RawData));
285 Certificates.RemoveRange (certificates);
289 private bool Exists (X509Certificate2 certificate)
291 if ((store == null) || (list == null) || (certificate == null))
294 foreach (X509Certificate2 c in list) {
295 if (certificate.Equals (c)) {