PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/referencesource/System/security/system/security/cryptography/x509/x509store.cs

https://github.com/pruiz/mono
C# | 297 lines | 229 code | 45 blank | 23 comment | 57 complexity | b5a5bebf1531ea75f068386e147580d6 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. //
  7. // X509Store.cs
  8. //
  9. namespace System.Security.Cryptography.X509Certificates {
  10. using System.Globalization;
  11. using System.Runtime.InteropServices;
  12. using System.Runtime.Versioning;
  13. using System.Security.Cryptography;
  14. using System.Security.Permissions;
  15. public enum StoreLocation {
  16. CurrentUser = 0x01,
  17. LocalMachine = 0x02
  18. }
  19. [Flags]
  20. // this enum defines the Open modes. Read/ReadWrite/MaxAllowed are mutually exclusive.
  21. public enum OpenFlags {
  22. ReadOnly = 0x00,
  23. ReadWrite = 0x01,
  24. MaxAllowed = 0x02,
  25. OpenExistingOnly = 0x04,
  26. IncludeArchived = 0x08
  27. }
  28. public enum StoreName {
  29. AddressBook = 1, // other people.
  30. AuthRoot, // third party trusted roots.
  31. CertificateAuthority, // intermediate CAs.
  32. Disallowed, // revoked certificates.
  33. My, // personal certificates.
  34. Root, // trusted root CAs.
  35. TrustedPeople, // trusted people (used in EFS).
  36. TrustedPublisher, // trusted publishers (used in Authenticode).
  37. }
  38. public sealed class X509Store : IDisposable{
  39. private string m_storeName;
  40. private StoreLocation m_location;
  41. #if FEATURE_CORESYSTEM
  42. [SecurityCritical]
  43. #endif
  44. private SafeCertStoreHandle m_safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle;
  45. public X509Store () : this("MY", StoreLocation.CurrentUser) {}
  46. public X509Store (string storeName) : this (storeName, StoreLocation.CurrentUser) {}
  47. public X509Store (StoreName storeName) : this(storeName, StoreLocation.CurrentUser) {}
  48. public X509Store (StoreLocation storeLocation) : this ("MY", storeLocation) {}
  49. #if FEATURE_CORESYSTEM
  50. [SecuritySafeCritical]
  51. #endif
  52. public X509Store (StoreName storeName, StoreLocation storeLocation) {
  53. if (storeLocation != StoreLocation.CurrentUser && storeLocation != StoreLocation.LocalMachine)
  54. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "storeLocation"));
  55. switch (storeName) {
  56. case StoreName.AddressBook:
  57. m_storeName = "AddressBook";
  58. break;
  59. case StoreName.AuthRoot:
  60. m_storeName = "AuthRoot";
  61. break;
  62. case StoreName.CertificateAuthority:
  63. m_storeName = "CA";
  64. break;
  65. case StoreName.Disallowed:
  66. m_storeName = "Disallowed";
  67. break;
  68. case StoreName.My:
  69. m_storeName = "My";
  70. break;
  71. case StoreName.Root:
  72. m_storeName = "Root";
  73. break;
  74. case StoreName.TrustedPeople:
  75. m_storeName = "TrustedPeople";
  76. break;
  77. case StoreName.TrustedPublisher:
  78. m_storeName = "TrustedPublisher";
  79. break;
  80. default:
  81. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "storeName"));
  82. }
  83. m_location = storeLocation;
  84. }
  85. #if FEATURE_CORESYSTEM
  86. [SecuritySafeCritical]
  87. #endif
  88. public X509Store (string storeName, StoreLocation storeLocation) {
  89. if (storeLocation != StoreLocation.CurrentUser && storeLocation != StoreLocation.LocalMachine)
  90. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "storeLocation"));
  91. m_storeName = storeName;
  92. m_location = storeLocation;
  93. }
  94. // Package protected constructor for creating a chain from a HCERTSTORE
  95. [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
  96. [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
  97. public X509Store (IntPtr storeHandle) {
  98. if (storeHandle == IntPtr.Zero)
  99. throw new ArgumentNullException("storeHandle");
  100. m_safeCertStoreHandle = CAPI.CertDuplicateStore(storeHandle);
  101. if (m_safeCertStoreHandle == null || m_safeCertStoreHandle.IsInvalid)
  102. throw new CryptographicException(SR.GetString(SR.Cryptography_InvalidStoreHandle), "storeHandle");
  103. }
  104. public IntPtr StoreHandle {
  105. [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
  106. [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
  107. get {
  108. if (m_safeCertStoreHandle == null || m_safeCertStoreHandle.IsInvalid || m_safeCertStoreHandle.IsClosed)
  109. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_StoreNotOpen));
  110. return m_safeCertStoreHandle.DangerousGetHandle();
  111. }
  112. }
  113. public StoreLocation Location {
  114. get { return m_location; }
  115. }
  116. public string Name {
  117. get { return m_storeName; }
  118. }
  119. #if FEATURE_CORESYSTEM
  120. [SecuritySafeCritical]
  121. #endif
  122. [ResourceExposure(ResourceScope.None)]
  123. #if !FEATURE_CORESYSTEM
  124. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  125. #endif
  126. public void Open(OpenFlags flags) {
  127. if (m_location != StoreLocation.CurrentUser && m_location != StoreLocation.LocalMachine)
  128. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "m_location"));
  129. uint storeFlags = X509Utils.MapX509StoreFlags(m_location, flags);
  130. if (!m_safeCertStoreHandle.IsInvalid)
  131. // Free the current store handle
  132. m_safeCertStoreHandle.Dispose();
  133. m_safeCertStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_SYSTEM),
  134. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  135. IntPtr.Zero,
  136. storeFlags,
  137. m_storeName);
  138. if (m_safeCertStoreHandle == null || m_safeCertStoreHandle.IsInvalid)
  139. throw new CryptographicException(Marshal.GetLastWin32Error());
  140. //
  141. // We want the store to auto-resync when requesting a snapshot so that
  142. // updates to the store will be taken into account.
  143. //
  144. CAPI.CertControlStore(m_safeCertStoreHandle,
  145. 0,
  146. CAPI.CERT_STORE_CTRL_AUTO_RESYNC,
  147. IntPtr.Zero);
  148. }
  149. public void Dispose() {
  150. Close();
  151. }
  152. #if FEATURE_CORESYSTEM
  153. [SecuritySafeCritical]
  154. #endif
  155. public void Close() {
  156. if (m_safeCertStoreHandle != null && !m_safeCertStoreHandle.IsClosed)
  157. m_safeCertStoreHandle.Dispose();
  158. }
  159. #if FEATURE_CORESYSTEM
  160. [SecuritySafeCritical]
  161. #endif
  162. public void Add(X509Certificate2 certificate) {
  163. if (certificate == null)
  164. throw new ArgumentNullException("certificate");
  165. if (m_safeCertStoreHandle == null || m_safeCertStoreHandle.IsInvalid || m_safeCertStoreHandle.IsClosed)
  166. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_StoreNotOpen));
  167. if (!CAPI.CertAddCertificateContextToStore(m_safeCertStoreHandle,
  168. certificate.CertContext,
  169. CAPI.CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES,
  170. SafeCertContextHandle.InvalidHandle))
  171. throw new CryptographicException(Marshal.GetLastWin32Error());
  172. }
  173. public void AddRange(X509Certificate2Collection certificates) {
  174. if (certificates == null)
  175. throw new ArgumentNullException("certificates");
  176. int i = 0;
  177. try {
  178. foreach (X509Certificate2 certificate in certificates) {
  179. Add(certificate);
  180. i++;
  181. }
  182. } catch {
  183. for (int j=0; j<i; j++) {
  184. Remove(certificates[j]);
  185. }
  186. throw;
  187. }
  188. }
  189. #if FEATURE_CORESYSTEM
  190. [SecuritySafeCritical]
  191. #endif
  192. public void Remove(X509Certificate2 certificate) {
  193. if (certificate == null)
  194. throw new ArgumentNullException("certificate");
  195. RemoveCertificateFromStore(m_safeCertStoreHandle, certificate.CertContext);
  196. }
  197. public void RemoveRange(X509Certificate2Collection certificates) {
  198. if (certificates == null)
  199. throw new ArgumentNullException("certificates");
  200. int i = 0;
  201. try {
  202. foreach (X509Certificate2 certificate in certificates) {
  203. Remove(certificate);
  204. i++;
  205. }
  206. } catch {
  207. for (int j=0; j<i; j++) {
  208. Add(certificates[j]);
  209. }
  210. throw;
  211. }
  212. }
  213. public X509Certificate2Collection Certificates {
  214. #if FEATURE_CORESYSTEM
  215. [SecuritySafeCritical]
  216. #endif
  217. get {
  218. if (m_safeCertStoreHandle.IsInvalid || m_safeCertStoreHandle.IsClosed)
  219. return new X509Certificate2Collection();
  220. return X509Utils.GetCertificates(m_safeCertStoreHandle);
  221. }
  222. }
  223. //
  224. // private static methods
  225. //
  226. #if FEATURE_CORESYSTEM
  227. [SecuritySafeCritical]
  228. #endif
  229. private static void RemoveCertificateFromStore(SafeCertStoreHandle safeCertStoreHandle, SafeCertContextHandle safeCertContext) {
  230. if (safeCertContext == null || safeCertContext.IsInvalid)
  231. return;
  232. if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid || safeCertStoreHandle.IsClosed)
  233. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_StoreNotOpen));
  234. // Find the certificate in the store.
  235. SafeCertContextHandle safeCertContext2 = CAPI.CertFindCertificateInStore(safeCertStoreHandle,
  236. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  237. 0,
  238. CAPI.CERT_FIND_EXISTING,
  239. safeCertContext.DangerousGetHandle(),
  240. SafeCertContextHandle.InvalidHandle);
  241. // The certificate is not present in the store, simply return.
  242. if (safeCertContext2 == null || safeCertContext2.IsInvalid)
  243. return;
  244. // CertDeleteCertificateFromStore always releases the context regardless of success
  245. // or failure so we don't need to manually release it
  246. GC.SuppressFinalize(safeCertContext2);
  247. // Remove from the store.
  248. if (!CAPI.CertDeleteCertificateFromStore(safeCertContext2))
  249. throw new CryptographicException(Marshal.GetLastWin32Error());
  250. }
  251. }
  252. }