2 // X509Store.cs: Handles a X.509 certificates/CRLs store
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2004 Novell (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Globalization;
37 using Mono.Security.X509.Extensions;
39 namespace Mono.Security.X509 {
48 private string _storePath;
49 private X509CertificateCollection _certificates;
50 private ArrayList _crls;
54 internal X509Store (string path, bool crl)
62 public X509CertificateCollection Certificates {
64 if (_certificates == null) {
65 _certificates = BuildCertificatesCollection (_storePath);
71 public ArrayList Crls {
73 // CRL aren't applicable to all stores
74 // but returning null is a little rude
76 _crls = new ArrayList ();
79 _crls = BuildCrlsCollection (_storePath);
88 int n = _storePath.LastIndexOf (Path.DirectorySeparatorChar);
89 _name = _storePath.Substring (n+1);
99 if (_certificates != null)
100 _certificates.Clear ();
101 _certificates = null;
107 public void Import (X509Certificate certificate)
109 if (!Directory.Exists (_storePath)) {
110 Directory.CreateDirectory (_storePath);
113 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
114 if (!File.Exists (filename)) {
115 using (FileStream fs = File.OpenWrite (filename)) {
116 byte[] data = certificate.RawData;
117 fs.Write (data, 0, data.Length);
123 public void Remove (X509Certificate certificate)
125 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
126 if (File.Exists (filename)) {
127 File.Delete (filename);
133 private string GetUniqueName (X509Certificate certificate)
135 string method = null;
138 // We prefer Subject Key Identifier as the unique name
139 // as it will provide faster lookups
140 X509Extension ext = certificate.Extensions ["2.5.29.14"];
142 SubjectKeyIdentifierExtension ski = new SubjectKeyIdentifierExtension (ext);
143 name = ski.Identifier;
147 method = "tbp"; // thumbprint
148 name = certificate.Hash;
151 StringBuilder sb = new StringBuilder (method);
153 foreach (byte b in name) {
154 sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
158 return sb.ToString ();
161 private byte[] Load (string filename)
164 using (FileStream fs = File.OpenRead (filename)) {
165 data = new byte [fs.Length];
166 fs.Read (data, 0, data.Length);
172 private X509Certificate LoadCertificate (string filename)
174 byte[] data = Load (filename);
175 X509Certificate cert = new X509Certificate (data);
179 private X509Crl LoadCrl (string filename)
181 byte[] data = Load (filename);
182 X509Crl crl = new X509Crl (data);
186 private X509CertificateCollection BuildCertificatesCollection (string storeName)
188 string path = Path.Combine (_storePath, storeName);
189 if (!Directory.Exists (path)) {
190 Directory.CreateDirectory (path);
193 X509CertificateCollection coll = new X509CertificateCollection ();
194 string[] files = Directory.GetFiles (path, "*.cer");
195 if ((files != null) && (files.Length > 0)) {
196 foreach (string file in files) {
198 X509Certificate cert = LoadCertificate (file);
202 // in case someone is dumb enough
203 // (like me) to include a base64
204 // encoded certs (or other junk
212 private ArrayList BuildCrlsCollection (string storeName)
214 ArrayList list = new ArrayList ();
215 string path = Path.Combine (_storePath, storeName);
216 string[] files = Directory.GetFiles (path, "*.crl");
217 if ((files != null) && (files.Length > 0)) {
218 foreach (string file in files) {
220 X509Crl crl = LoadCrl (file);