win32-certstore 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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