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 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Globalization;
39 using Mono.Security.X509.Extensions;
41 namespace Mono.Security.X509 {
50 private string _storePath;
51 private X509CertificateCollection _certificates;
52 private ArrayList _crls;
56 internal X509Store (string path, bool crl)
64 public X509CertificateCollection Certificates {
66 if (_certificates == null) {
67 _certificates = BuildCertificatesCollection (_storePath);
73 public ArrayList Crls {
75 // CRL aren't applicable to all stores
76 // but returning null is a little rude
78 _crls = new ArrayList ();
81 _crls = BuildCrlsCollection (_storePath);
90 int n = _storePath.LastIndexOf (Path.DirectorySeparatorChar);
91 _name = _storePath.Substring (n+1);
101 if (_certificates != null)
102 _certificates.Clear ();
103 _certificates = null;
109 public void Import (X509Certificate certificate)
111 if (!Directory.Exists (_storePath)) {
112 Directory.CreateDirectory (_storePath);
115 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
116 if (!File.Exists (filename)) {
117 using (FileStream fs = File.OpenWrite (filename)) {
118 byte[] data = certificate.RawData;
119 fs.Write (data, 0, data.Length);
125 public void Remove (X509Certificate certificate)
127 string filename = Path.Combine (_storePath, GetUniqueName (certificate));
128 if (File.Exists (filename)) {
129 File.Delete (filename);
135 private string GetUniqueName (X509Certificate certificate)
137 string method = null;
140 // We prefer Subject Key Identifier as the unique name
141 // as it will provide faster lookups
142 X509Extension ext = certificate.Extensions ["2.5.29.14"];
144 SubjectKeyIdentifierExtension ski = new SubjectKeyIdentifierExtension (ext);
145 name = ski.Identifier;
149 method = "tbp"; // thumbprint
150 name = certificate.Hash;
153 StringBuilder sb = new StringBuilder (method);
155 foreach (byte b in name) {
156 sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
160 return sb.ToString ();
163 private byte[] Load (string filename)
166 using (FileStream fs = File.OpenRead (filename)) {
167 data = new byte [fs.Length];
168 fs.Read (data, 0, data.Length);
174 private X509Certificate LoadCertificate (string filename)
176 byte[] data = Load (filename);
177 X509Certificate cert = new X509Certificate (data);
181 private X509Crl LoadCrl (string filename)
183 byte[] data = Load (filename);
184 X509Crl crl = new X509Crl (data);
188 private X509CertificateCollection BuildCertificatesCollection (string storeName)
190 string path = Path.Combine (_storePath, storeName);
191 if (!Directory.Exists (path)) {
192 Directory.CreateDirectory (path);
195 X509CertificateCollection coll = new X509CertificateCollection ();
196 string[] files = Directory.GetFiles (path, "*.cer");
197 if ((files != null) && (files.Length > 0)) {
198 foreach (string file in files) {
200 X509Certificate cert = LoadCertificate (file);
204 // in case someone is dumb enough
205 // (like me) to include a base64
206 // encoded certs (or other junk
214 private ArrayList BuildCrlsCollection (string storeName)
216 ArrayList list = new ArrayList ();
217 string path = Path.Combine (_storePath, storeName);
218 string[] files = Directory.GetFiles (path, "*.crl");
219 if ((files != null) && (files.Length > 0)) {
220 foreach (string file in files) {
222 X509Crl crl = LoadCrl (file);