disable broken tests on net_4_0
[mcs.git] / class / corlib / Mono.Security.X509 / X509Store.cs
blob1acd57d890e4b0b7ebd0668dea996ffc0f23b3f8
1 //
2 // X509Store.cs: Handles a X.509 certificates/CRLs store
3 //
4 // Author:
5 // Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.Collections;
31 using System.Globalization;
32 using System.IO;
33 using System.Text;
35 using Mono.Security.X509.Extensions;
37 namespace Mono.Security.X509 {
39 #if INSIDE_CORLIB
40 internal
41 #else
42 public
43 #endif
44 class X509Store {
46 private string _storePath;
47 private X509CertificateCollection _certificates;
48 private ArrayList _crls;
49 private bool _crl;
50 private string _name;
52 internal X509Store (string path, bool crl)
54 _storePath = path;
55 _crl = crl;
58 // properties
60 public X509CertificateCollection Certificates {
61 get {
62 if (_certificates == null) {
63 _certificates = BuildCertificatesCollection (_storePath);
65 return _certificates;
69 public ArrayList Crls {
70 get {
71 // CRL aren't applicable to all stores
72 // but returning null is a little rude
73 if (!_crl) {
74 _crls = new ArrayList ();
76 if (_crls == null) {
77 _crls = BuildCrlsCollection (_storePath);
79 return _crls;
83 public string Name {
84 get {
85 if (_name == null) {
86 int n = _storePath.LastIndexOf (Path.DirectorySeparatorChar);
87 _name = _storePath.Substring (n+1);
89 return _name;
93 // methods
95 public void Clear ()
97 if (_certificates != null)
98 _certificates.Clear ();
99 _certificates = null;
100 if (_crls != null)
101 _crls.Clear ();
102 _crls = null;
105 public void Import (X509Certificate certificate)
107 CheckStore (_storePath, true);
109 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
110 if (!File.Exists (filename)) {
111 using (FileStream fs = File.Create (filename)) {
112 byte[] data = certificate.RawData;
113 fs.Write (data, 0, data.Length);
114 fs.Close ();
119 public void Import (X509Crl crl)
121 CheckStore (_storePath, true);
123 string filename = Path.Combine (_storePath, GetUniqueName (crl));
124 if (!File.Exists (filename)) {
125 using (FileStream fs = File.Create (filename)) {
126 byte[] data = crl.RawData;
127 fs.Write (data, 0, data.Length);
132 public void Remove (X509Certificate certificate)
134 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
135 if (File.Exists (filename)) {
136 File.Delete (filename);
140 public void Remove (X509Crl crl)
142 string filename = Path.Combine (_storePath, GetUniqueName (crl));
143 if (File.Exists (filename)) {
144 File.Delete (filename);
148 // private stuff
150 private string GetUniqueName (X509Certificate certificate)
152 string method;
153 byte[] name = GetUniqueName (certificate.Extensions);
154 if (name == null) {
155 method = "tbp"; // thumbprint
156 name = certificate.Hash;
157 } else {
158 method = "ski";
160 return GetUniqueName (method, name, ".cer");
163 private string GetUniqueName (X509Crl crl)
165 string method;
166 byte[] name = GetUniqueName (crl.Extensions);
167 if (name == null) {
168 method = "tbp"; // thumbprint
169 name = crl.Hash;
170 } else {
171 method = "ski";
173 return GetUniqueName (method, name, ".crl");
176 private byte[] GetUniqueName (X509ExtensionCollection extensions)
178 // We prefer Subject Key Identifier as the unique name
179 // as it will provide faster lookups
180 X509Extension ext = extensions ["2.5.29.14"];
181 if (ext == null)
182 return null;
184 SubjectKeyIdentifierExtension ski = new SubjectKeyIdentifierExtension (ext);
185 return ski.Identifier;
188 private string GetUniqueName (string method, byte[] name, string fileExtension)
190 StringBuilder sb = new StringBuilder (method);
191 sb.Append ("-");
192 foreach (byte b in name) {
193 sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
195 sb.Append (fileExtension);
197 return sb.ToString ();
200 private byte[] Load (string filename)
202 byte[] data = null;
203 using (FileStream fs = File.OpenRead (filename)) {
204 data = new byte [fs.Length];
205 fs.Read (data, 0, data.Length);
206 fs.Close ();
208 return data;
211 private X509Certificate LoadCertificate (string filename)
213 byte[] data = Load (filename);
214 X509Certificate cert = new X509Certificate (data);
215 return cert;
218 private X509Crl LoadCrl (string filename)
220 byte[] data = Load (filename);
221 X509Crl crl = new X509Crl (data);
222 return crl;
225 private bool CheckStore (string path, bool throwException)
227 try {
228 if (Directory.Exists (path))
229 return true;
230 Directory.CreateDirectory (path);
231 return Directory.Exists (path);
233 catch {
234 if (throwException)
235 throw;
236 return false;
240 private X509CertificateCollection BuildCertificatesCollection (string storeName)
242 X509CertificateCollection coll = new X509CertificateCollection ();
243 string path = Path.Combine (_storePath, storeName);
244 if (!CheckStore (path, false))
245 return coll; // empty collection
247 string[] files = Directory.GetFiles (path, "*.cer");
248 if ((files != null) && (files.Length > 0)) {
249 foreach (string file in files) {
250 try {
251 X509Certificate cert = LoadCertificate (file);
252 coll.Add (cert);
254 catch {
255 // in case someone is dumb enough
256 // (like me) to include a base64
257 // encoded certs (or other junk
258 // into the store).
262 return coll;
265 private ArrayList BuildCrlsCollection (string storeName)
267 ArrayList list = new ArrayList ();
268 string path = Path.Combine (_storePath, storeName);
269 if (!CheckStore (path, false))
270 return list; // empty list
272 string[] files = Directory.GetFiles (path, "*.crl");
273 if ((files != null) && (files.Length > 0)) {
274 foreach (string file in files) {
275 try {
276 X509Crl crl = LoadCrl (file);
277 list.Add (crl);
279 catch {
280 // junk catcher
284 return list;