2 // X509Store.cs: Handles a X.509 certificates/CRLs store
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System.Collections;
31 using System.Globalization;
35 using Mono.Security.X509.Extensions;
37 namespace Mono.Security.X509 {
46 private string _storePath;
47 private X509CertificateCollection _certificates;
48 private ArrayList _crls;
52 internal X509Store (string path, bool crl)
60 public X509CertificateCollection Certificates {
62 if (_certificates == null) {
63 _certificates = BuildCertificatesCollection (_storePath);
69 public ArrayList Crls {
71 // CRL aren't applicable to all stores
72 // but returning null is a little rude
74 _crls = new ArrayList ();
77 _crls = BuildCrlsCollection (_storePath);
86 int n = _storePath.LastIndexOf (Path.DirectorySeparatorChar);
87 _name = _storePath.Substring (n+1);
97 if (_certificates != null)
98 _certificates.Clear ();
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.OpenWrite (filename)) {
112 byte[] data = certificate.RawData;
113 fs.Write (data, 0, data.Length);
119 public void Remove (X509Certificate certificate)
121 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
122 if (File.Exists (filename)) {
123 File.Delete (filename);
129 private string GetUniqueName (X509Certificate certificate)
131 string method = null;
134 // We prefer Subject Key Identifier as the unique name
135 // as it will provide faster lookups
136 X509Extension ext = certificate.Extensions ["2.5.29.14"];
138 SubjectKeyIdentifierExtension ski = new SubjectKeyIdentifierExtension (ext);
139 name = ski.Identifier;
143 method = "tbp"; // thumbprint
144 name = certificate.Hash;
147 StringBuilder sb = new StringBuilder (method);
149 foreach (byte b in name) {
150 sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
154 return sb.ToString ();
157 private byte[] Load (string filename)
160 using (FileStream fs = File.OpenRead (filename)) {
161 data = new byte [fs.Length];
162 fs.Read (data, 0, data.Length);
168 private X509Certificate LoadCertificate (string filename)
170 byte[] data = Load (filename);
171 X509Certificate cert = new X509Certificate (data);
175 private X509Crl LoadCrl (string filename)
177 byte[] data = Load (filename);
178 X509Crl crl = new X509Crl (data);
182 private bool CheckStore (string path, bool throwException)
185 if (Directory.Exists (path))
187 Directory.CreateDirectory (path);
188 return Directory.Exists (path);
197 private X509CertificateCollection BuildCertificatesCollection (string storeName)
199 X509CertificateCollection coll = new X509CertificateCollection ();
200 string path = Path.Combine (_storePath, storeName);
201 if (!CheckStore (path, false))
202 return coll; // empty collection
204 string[] files = Directory.GetFiles (path, "*.cer");
205 if ((files != null) && (files.Length > 0)) {
206 foreach (string file in files) {
208 X509Certificate cert = LoadCertificate (file);
212 // in case someone is dumb enough
213 // (like me) to include a base64
214 // encoded certs (or other junk
222 private ArrayList BuildCrlsCollection (string storeName)
224 ArrayList list = new ArrayList ();
225 string path = Path.Combine (_storePath, storeName);
226 if (!CheckStore (path, false))
227 return list; // empty list
229 string[] files = Directory.GetFiles (path, "*.crl");
230 if ((files != null) && (files.Length > 0)) {
231 foreach (string file in files) {
233 X509Crl crl = LoadCrl (file);