win32-certstore 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdfde36cb468d1ce15e0d5fd317783347f07c96f0282519b56b86b424d89e92e
4
- data.tar.gz: a4ce61aafb784b12bf5e7ee28958221c4318500d78ec2ac23f3d700e7528d466
3
+ metadata.gz: 5640bf3ab8b678dc92fda6d689d13d080055f29617009a02e36021a9fd1b42bc
4
+ data.tar.gz: 2140c35decc023314c21b7cb0bfafd1f1715bc2587751109cb3368818fbfe268
5
5
  SHA512:
6
- metadata.gz: 3f1ff03dc3ac803b951179683c48bdef81ea481f12c0a1838e9d236085e4451d2698a3f488da855bbc44bdbf037d6fdc753113309ef0838b2b61fab425cc8040
7
- data.tar.gz: 61ac2a5b3f1cbceb606822c07dfdfec2b5b76e1ba91820f4f7571c094f16c10ffeba292e9772abf3938eba537951426d8c8ef8f09ddcf5b1bc74cbf0367435ce
6
+ metadata.gz: 81d031f2d45507b54254c165704f4b8f1de89f7d1958a9a2c803f170fbb07aabcf7c4b5f17f08c843d646fb2c0ebcffbe826d88a77298ae9b9b6c6cc0cbc8718
7
+ data.tar.gz: 38f969fb096085190123601cda01168bbc77c927306f945b033b83d987d9d649499000ab5ce586dbb30948082addd9aa6c3d5904efdb7ef0c2036cacbbae8a3c
@@ -53,6 +53,20 @@ module Win32
53
53
  cert_add(certstore_handler, certificate_obj)
54
54
  end
55
55
 
56
+ # Adds a PFX certificate to certificate store
57
+ #
58
+ # @note Unlike other certificates, PFX can be password protected and may contain a private key.
59
+ # Therefore we need a different approach to import them.
60
+ #
61
+ # @param path [String] Path of the certificate that should be imported
62
+ # @param password [String] Password of the certificate if it is protected
63
+ #
64
+ # @return [Boolean]
65
+ #
66
+ def add_pfx(path, password)
67
+ cert_add_pfx(certstore_handler, path, password)
68
+ end
69
+
56
70
  # Return `OpenSSL::X509` certificate object
57
71
  # @param request [thumbprint<string>] of certificate
58
72
  # @return [Object] of certificates in OpenSSL::X509 format
@@ -90,11 +104,7 @@ module Win32
90
104
 
91
105
  # To close and destroy pointer of open certificate store handler
92
106
  def close
93
- closed = CertCloseStore(@certstore_handler, CERT_CLOSE_STORE_FORCE_FLAG)
94
- unless closed
95
- last_error = FFI::LastError.error
96
- raise SystemCallError.new("Unable to close the Certificate Store.", last_error)
97
- end
107
+ close_cert_store
98
108
  remove_finalizer
99
109
  end
100
110
 
@@ -68,12 +68,17 @@ module Win32
68
68
  CERT_NAME_UPN_TYPE = 8
69
69
 
70
70
  # Retrieve Certificates flag
71
+ CERT_COMPARE_ANY = 0
71
72
  CERT_COMPARE_SHA1_HASH = 1
72
73
  CERT_INFO_SUBJECT_FLAG = 7
73
74
  CERT_COMPARE_NAME_STR_W = 8
74
75
  CERT_COMPARE_SHIFT = 16
75
76
  CERT_FIND_SHA1_HASH = CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT
76
77
  CERT_FIND_SUBJECT_STR = CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG
78
+ CERT_FIND_ANY = CERT_COMPARE_ANY << CERT_COMPARE_SHIFT
79
+
80
+ CERT_STORE_ADD_USE_EXISTING = 2
81
+ CERT_STORE_ADD_REPLACE_EXISTING = 3
77
82
 
78
83
  # List Certificates Flag
79
84
  CERT_NAME_ISSUER_FLAG = 0x1
@@ -144,6 +149,19 @@ module Win32
144
149
  end
145
150
  end
146
151
 
152
+ class CRYPT_DATA_BLOB < FFI::Struct
153
+ layout :cbData, DWORD, # Count, in bytes, of data
154
+ :pbData, :pointer # Pointer to data buffer
155
+
156
+ def initialize(str = nil)
157
+ super(nil)
158
+ if str
159
+ self[:pbData] = FFI::MemoryPointer.from_string(str)
160
+ self[:cbData] = str.size
161
+ end
162
+ end
163
+ end
164
+
147
165
  class CERT_EXTENSION < FFI::Struct
148
166
  layout :pszObjId, LPTSTR,
149
167
  :fCritical, BOOL,
@@ -224,6 +242,10 @@ module Win32
224
242
  safe_attach_function :CertFindCertificateInStore, [HCERTSTORE, DWORD, DWORD, DWORD, LPVOID, PCCERT_CONTEXT], PCCERT_CONTEXT
225
243
 
226
244
  safe_attach_function :PFXExportCertStoreEx, [HCERTSTORE, CRYPT_INTEGER_BLOB, LPCTSTR, LPVOID, DWORD], BOOL
245
+
246
+ # Fetches store handler of a PFX certificate
247
+ attach_function :PFXImportCertStore, [CRYPT_DATA_BLOB, LPCTSTR, DWORD], HCERTSTORE
248
+ attach_function :CertAddCertificateContextToStore, [HCERTSTORE, PCCERT_CONTEXT, DWORD, PCCERT_CONTEXT], BOOL
227
249
  end
228
250
  end
229
251
  end
@@ -49,6 +49,36 @@ module Win32
49
49
  end
50
50
  end
51
51
 
52
+ # Adds a PFX certificate to certificate store
53
+ #
54
+ # @see https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-pfximportcertstore PFXImportCertStore function
55
+ # @see https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certaddcertificatecontexttostore CertAddCertificateContextToStore
56
+ #
57
+ # @param certstore_handler [FFI::Pointer] Handle of the store where certificate should be imported
58
+ # @param path [String] Path of the certificate that should be imported
59
+ # @param password [String] Password of the certificate
60
+ #
61
+ # @return [Boolean]
62
+ #
63
+ # @raise [SystemCallError] when Crypt API would not be able to perform some action
64
+ #
65
+ def cert_add_pfx(certstore_handler, path, password = "")
66
+ # Imports a PFX BLOB and returns the handle of a store
67
+ pfx_cert_store = PFXImportCertStore(CRYPT_DATA_BLOB.new(File.binread(path)), wstring(password), 0)
68
+ raise if pfx_cert_store.null?
69
+ # Find the certificate context in certificate store
70
+ cert_context = CertFindCertificateInStore(pfx_cert_store, ENCODING_TYPE, 0, CERT_FIND_ANY, nil, nil)
71
+ close_cert_store(pfx_cert_store)
72
+ raise if cert_context.null?
73
+ # Add certificate context to the certificate store
74
+ args = add_certcontxt_args(certstore_handler, cert_context)
75
+ cert_added = CertAddCertificateContextToStore(*args)
76
+ raise unless cert_added
77
+ cert_added
78
+ rescue
79
+ lookup_error("Add a PFX")
80
+ end
81
+
52
82
  # Get certificate from open certificate store and return certificate object
53
83
  # certificate_thumbprint => thumbprint is a hash. which could be sha1 or md5.
54
84
  def cert_get(certificate_thumbprint)
@@ -130,6 +160,14 @@ module Win32
130
160
  certificate_list
131
161
  end
132
162
 
163
+ # To close and destroy pointer of open certificate store handler
164
+ def close_cert_store(certstore_handler = @certstore_handler)
165
+ closed = CertCloseStore(certstore_handler, CERT_CLOSE_STORE_FORCE_FLAG)
166
+ raise unless closed
167
+ rescue
168
+ lookup_error("close")
169
+ end
170
+
133
171
  private
134
172
 
135
173
  # Build arguments for CertAddEncodedCertificateToStore
@@ -142,6 +180,11 @@ module Win32
142
180
  [store_handler, ENCODING_TYPE, 0, CERT_FIND_SHA1_HASH, CRYPT_HASH_BLOB.new(thumbprint), nil]
143
181
  end
144
182
 
183
+ # Build arguments for CertAddCertificateContextToStore
184
+ def add_certcontxt_args(certstore_handler, cert_context)
185
+ [certstore_handler, cert_context, CERT_STORE_ADD_REPLACE_EXISTING, nil]
186
+ end
187
+
145
188
  # Match certificate CN exist in cert_rdn
146
189
  def is_cn_match?(cert_rdn, certificate_name)
147
190
  cert_rdn.read_wstring.match(/(^|\W)#{certificate_name}($|\W)/i)
@@ -1,6 +1,6 @@
1
1
  module Win32
2
2
  class Certstore
3
- VERSION = "0.2.2".freeze
3
+ VERSION = "0.2.3".freeze
4
4
  MAJOR, MINOR, TINY = VERSION.split(".")
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-certstore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-16 00:00:00.000000000 Z
11
+ date: 2019-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler