win32-certstore 0.2.3 → 0.5.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: 5640bf3ab8b678dc92fda6d689d13d080055f29617009a02e36021a9fd1b42bc
4
- data.tar.gz: 2140c35decc023314c21b7cb0bfafd1f1715bc2587751109cb3368818fbfe268
3
+ metadata.gz: b391e4d81e324162538a2a3644aea74f0da1f8679409733a58dcf4c590734a6c
4
+ data.tar.gz: 5ed7821ec5bffe58cb09608cfc008b287874b5ddafe8556662fa27f42a25c1b1
5
5
  SHA512:
6
- metadata.gz: 81d031f2d45507b54254c165704f4b8f1de89f7d1958a9a2c803f170fbb07aabcf7c4b5f17f08c843d646fb2c0ebcffbe826d88a77298ae9b9b6c6cc0cbc8718
7
- data.tar.gz: 38f969fb096085190123601cda01168bbc77c927306f945b033b83d987d9d649499000ab5ce586dbb30948082addd9aa6c3d5904efdb7ef0c2036cacbbae8a3c
6
+ metadata.gz: fc5c77cd659695ac3a58480ab875a6c5daa2b93cd83e45f1fcdfcd1bd89e0cf9653d38d63ae9e5260ecff90a7277f6ee600b91137665d53e672fbb77e1543cfb
7
+ data.tar.gz: 5b6a8025b85ae8ce026a9a7b603a35137000525ba182bbbcc8fc9667fb78dd6cf179ad1cfbb1cbdcdf582dd4749f82795a17df01181720d7f77a36a4477dc639
@@ -31,18 +31,21 @@ module Win32
31
31
 
32
32
  attr_accessor :store_name
33
33
 
34
- def initialize(store_name)
34
+ # Initializes a new instance of a certificate store.
35
+ # takes 2 parameters - the store name (My, Root, etc) and the location (CurrentUser or LocalMachine), it defaults to LocalMachine for backwards compatibility
36
+ def initialize(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
35
37
  @store_name = store_name
36
- @certstore_handler = open(store_name)
38
+ @store_location = store_location
39
+ @certstore_handler = open(store_name, store_location: store_location)
37
40
  end
38
41
 
39
42
  # To open given certificate store
40
- def self.open(store_name)
43
+ def self.open(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
41
44
  validate_store(store_name)
42
45
  if block_given?
43
- yield new(store_name)
46
+ yield new(store_name, store_location: store_location)
44
47
  else
45
- new(store_name)
48
+ new(store_name, store_location: store_location)
46
49
  end
47
50
  end
48
51
 
@@ -60,11 +63,12 @@ module Win32
60
63
  #
61
64
  # @param path [String] Path of the certificate that should be imported
62
65
  # @param password [String] Password of the certificate if it is protected
66
+ # @param key_properties [Integer] dwFlags used to specify properties of the pfx key, see certstore/store_base.rb cert_add_pfx function
63
67
  #
64
68
  # @return [Boolean]
65
69
  #
66
- def add_pfx(path, password)
67
- cert_add_pfx(certstore_handler, path, password)
70
+ def add_pfx(path, password, key_properties = 0)
71
+ cert_add_pfx(certstore_handler, path, password, key_properties)
68
72
  end
69
73
 
70
74
  # Return `OpenSSL::X509` certificate object
@@ -117,8 +121,9 @@ module Win32
117
121
  attr_reader :certstore_handler
118
122
 
119
123
  # To open certstore and return open certificate store pointer
120
- def open(store_name)
121
- certstore_handler = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, nil, CERT_SYSTEM_STORE_LOCAL_MACHINE, wstring(store_name))
124
+
125
+ def open(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
126
+ certstore_handler = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, nil, store_location, wstring(store_name))
122
127
  unless certstore_handler
123
128
  last_error = FFI::LastError.error
124
129
  raise SystemCallError.new("Unable to open the Certificate Store `#{store_name}`.", last_error)
@@ -14,7 +14,7 @@
14
14
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
- require "openssl"
17
+ require "openssl" unless defined?(OpenSSL)
18
18
 
19
19
  module Win32
20
20
  class Certstore
@@ -16,7 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require "ffi"
19
+ require "ffi" unless defined?(FFI)
20
20
 
21
21
  module Win32
22
22
  class Certstore
@@ -88,6 +88,9 @@ module Win32
88
88
 
89
89
  CERT_STORE_PROV_SYSTEM = 10
90
90
  CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
91
+ CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
92
+ CERT_SYSTEM_STORE_SERVICES = 0x00050000
93
+ CERT_SYSTEM_STORE_USERS = 0x00060000
91
94
 
92
95
  # Define ffi pointer
93
96
  HCERTSTORE = FFI::TypeDefs[:pointer]
@@ -113,17 +116,17 @@ module Win32
113
116
 
114
117
  class FILETIME < FFI::Struct
115
118
  layout :dwLowDateTime, DWORD,
116
- :dwHighDateTime, DWORD
119
+ :dwHighDateTime, DWORD
117
120
  end
118
121
 
119
122
  class CRYPT_INTEGER_BLOB < FFI::Struct
120
123
  layout :cbData, DWORD, # Count, in bytes, of data
121
- :pbData, :pointer # Pointer to data buffer
124
+ :pbData, :pointer # Pointer to data buffer
122
125
  end
123
126
 
124
127
  class CRYPT_NAME_BLOB < FFI::Struct
125
128
  layout :cbData, DWORD, # Count, in bytes, of data
126
- :pbData, :pointer # Pointer to data buffer
129
+ :pbData, :pointer # Pointer to data buffer
127
130
  def initialize(str = nil)
128
131
  super(nil)
129
132
  if str
@@ -134,7 +137,7 @@ module Win32
134
137
 
135
138
  class CRYPT_HASH_BLOB < FFI::Struct
136
139
  layout :cbData, DWORD, # Count, in bytes, of data
137
- :pbData, :pointer # Pointer to data buffer
140
+ :pbData, :pointer # Pointer to data buffer
138
141
 
139
142
  def initialize(str = nil)
140
143
  super(nil)
@@ -151,7 +154,7 @@ module Win32
151
154
 
152
155
  class CRYPT_DATA_BLOB < FFI::Struct
153
156
  layout :cbData, DWORD, # Count, in bytes, of data
154
- :pbData, :pointer # Pointer to data buffer
157
+ :pbData, :pointer # Pointer to data buffer
155
158
 
156
159
  def initialize(str = nil)
157
160
  super(nil)
@@ -164,47 +167,47 @@ module Win32
164
167
 
165
168
  class CERT_EXTENSION < FFI::Struct
166
169
  layout :pszObjId, LPTSTR,
167
- :fCritical, BOOL,
168
- :Value, CRYPT_INTEGER_BLOB
170
+ :fCritical, BOOL,
171
+ :Value, CRYPT_INTEGER_BLOB
169
172
  end
170
173
 
171
174
  class CRYPT_BIT_BLOB < FFI::Struct
172
175
  layout :cbData, DWORD,
173
- :pbData, BYTE,
174
- :cUnusedBits, DWORD
176
+ :pbData, BYTE,
177
+ :cUnusedBits, DWORD
175
178
  end
176
179
 
177
180
  class CRYPT_ALGORITHM_IDENTIFIER < FFI::Struct
178
181
  layout :pszObjId, LPSTR,
179
- :Parameters, CRYPT_INTEGER_BLOB
182
+ :Parameters, CRYPT_INTEGER_BLOB
180
183
  end
181
184
 
182
185
  class CERT_PUBLIC_KEY_INFO < FFI::Struct
183
186
  layout :Algorithm, CRYPT_ALGORITHM_IDENTIFIER,
184
- :PublicKey, CRYPT_BIT_BLOB
187
+ :PublicKey, CRYPT_BIT_BLOB
185
188
  end
186
189
 
187
190
  class CERT_INFO < FFI::Struct
188
191
  layout :dwVersion, DWORD,
189
- :SerialNumber, CRYPT_INTEGER_BLOB,
190
- :SignatureAlgorithm, CRYPT_ALGORITHM_IDENTIFIER,
191
- :Issuer, CRYPT_NAME_BLOB,
192
- :NotBefore, FILETIME,
193
- :NotAfter, FILETIME,
194
- :Subject, CRYPT_NAME_BLOB,
195
- :SubjectPublicKeyInfo, CERT_PUBLIC_KEY_INFO,
196
- :IssuerUniqueId, CRYPT_BIT_BLOB,
197
- :SubjectUniqueId, CRYPT_BIT_BLOB,
198
- :cExtension, DWORD,
199
- :rgExtension, CERT_EXTENSION
192
+ :SerialNumber, CRYPT_INTEGER_BLOB,
193
+ :SignatureAlgorithm, CRYPT_ALGORITHM_IDENTIFIER,
194
+ :Issuer, CRYPT_NAME_BLOB,
195
+ :NotBefore, FILETIME,
196
+ :NotAfter, FILETIME,
197
+ :Subject, CRYPT_NAME_BLOB,
198
+ :SubjectPublicKeyInfo, CERT_PUBLIC_KEY_INFO,
199
+ :IssuerUniqueId, CRYPT_BIT_BLOB,
200
+ :SubjectUniqueId, CRYPT_BIT_BLOB,
201
+ :cExtension, DWORD,
202
+ :rgExtension, CERT_EXTENSION
200
203
  end
201
204
 
202
205
  class CERT_CONTEXT < FFI::Struct
203
206
  layout :dwCertEncodingType, DWORD,
204
- :pbCertEncoded, BYTE,
205
- :cbCertEncoded, DWORD,
206
- :pCertInfo, CERT_INFO,
207
- :hCertStore, HCERTSTORE
207
+ :pbCertEncoded, BYTE,
208
+ :cbCertEncoded, DWORD,
209
+ :pCertInfo, CERT_INFO,
210
+ :hCertStore, HCERTSTORE
208
211
  end
209
212
 
210
213
  ###############################################################################
@@ -21,12 +21,11 @@ module Win32
21
21
  class Certstore
22
22
  module Mixin
23
23
  module Helper
24
-
25
24
  # PSCommand to search certificate from thumbprint and convert in pem
26
- def cert_ps_cmd(thumbprint, store_name)
25
+ def cert_ps_cmd(thumbprint, store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
27
26
  <<-EOH
28
27
  $content = $null
29
- $cert = Get-ChildItem Cert:\\LocalMachine\\'#{store_name}' -Recurse | Where { $_.Thumbprint -eq '#{thumbprint}' }
28
+ $cert = Get-ChildItem Cert:\\'#{store_location}'\\'#{store_name}' -Recurse | Where { $_.Thumbprint -eq '#{thumbprint}' }
30
29
  if($cert -ne $null)
31
30
  {
32
31
  $content = @(
@@ -43,7 +42,6 @@ module Win32
43
42
  def valid_duration?(cert_obj)
44
43
  cert_obj.not_before < Time.now.utc && cert_obj.not_after > Time.now.utc
45
44
  end
46
-
47
45
  end
48
46
  end
49
47
  end
@@ -15,12 +15,12 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require "mixlib/shellout"
18
+ require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
19
19
 
20
20
  module Win32
21
21
  class Certstore
22
22
  module Mixin
23
- module ShellOut
23
+ module ShellExec
24
24
  def shell_out_command(*command_args)
25
25
  cmd = Mixlib::ShellOut.new(*command_args)
26
26
  cmd.live_stream
@@ -28,6 +28,7 @@ module Win32
28
28
  if cmd.error!
29
29
  raise Mixlib::ShellOut::ShellCommandFailed, cmd.error!
30
30
  end
31
+
31
32
  cmd
32
33
  end
33
34
 
@@ -38,7 +39,7 @@ module Win32
38
39
  # @param script [String] script to run
39
40
  # @param options [Hash] options hash
40
41
  # @return [Mixlib::Shellout] mixlib-shellout object
41
- def powershell_out(*command_args)
42
+ def powershell_exec(*command_args)
42
43
  script = command_args.first
43
44
  options = command_args.last.is_a?(Hash) ? command_args.last : nil
44
45
 
@@ -51,8 +52,8 @@ module Win32
51
52
  # @param script [String] script to run
52
53
  # @param options [Hash] options hash
53
54
  # @return [Mixlib::Shellout] mixlib-shellout object
54
- def powershell_out!(*command_args)
55
- cmd = powershell_out(*command_args)
55
+ def powershell_exec!(*command_args)
56
+ cmd = powershell_exec(*command_args)
56
57
  cmd.error!
57
58
  cmd
58
59
  end
@@ -96,7 +97,7 @@ module Win32
96
97
  "-InputFormat None",
97
98
  ]
98
99
 
99
- "powershell.exe #{flags.join(' ')} -Command \"#{script.gsub('"', '\"')}\""
100
+ "powershell.exe #{flags.join(" ")} -Command \"#{script.gsub('"', '\"')}\""
100
101
  end
101
102
  end
102
103
  end
@@ -17,10 +17,10 @@
17
17
 
18
18
  require_relative "mixin/crypto"
19
19
  require_relative "mixin/string"
20
- require_relative "mixin/shell_out"
20
+ require_relative "mixin/shell_exec"
21
21
  require_relative "mixin/unicode"
22
- require "openssl"
23
- require "json"
22
+ require "openssl" unless defined?(OpenSSL)
23
+ require "json" unless defined?(JSON)
24
24
 
25
25
  module Win32
26
26
  class Certstore
@@ -28,7 +28,7 @@ module Win32
28
28
  include Win32::Certstore::Mixin::Crypto
29
29
  include Win32::Certstore::Mixin::Assertions
30
30
  include Win32::Certstore::Mixin::String
31
- include Win32::Certstore::Mixin::ShellOut
31
+ include Win32::Certstore::Mixin::ShellExec
32
32
  include Win32::Certstore::Mixin::Unicode
33
33
  include Win32::Certstore::Mixin::Helper
34
34
 
@@ -57,26 +57,32 @@ module Win32
57
57
  # @param certstore_handler [FFI::Pointer] Handle of the store where certificate should be imported
58
58
  # @param path [String] Path of the certificate that should be imported
59
59
  # @param password [String] Password of the certificate
60
+ # @param key_properties [Integer] dwFlags used to specify properties of the pfx key, see link above
60
61
  #
61
62
  # @return [Boolean]
62
63
  #
63
64
  # @raise [SystemCallError] when Crypt API would not be able to perform some action
64
65
  #
65
- def cert_add_pfx(certstore_handler, path, password = "")
66
+ def cert_add_pfx(certstore_handler, path, password = "", key_properties = 0)
67
+ cert_added = false
66
68
  # 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)
69
+ pfx_cert_store = PFXImportCertStore(CRYPT_DATA_BLOB.new(File.binread(path)), wstring(password), key_properties)
68
70
  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
71
+
72
+ # Find all the certificate contexts in certificate store and add them ino the store
73
+ while (cert_context = CertEnumCertificatesInStore(pfx_cert_store, cert_context)) && (not cert_context.null?)
74
+ # Add certificate context to the certificate store
75
+ args = add_certcontxt_args(certstore_handler, cert_context)
76
+ cert_added = CertAddCertificateContextToStore(*args)
77
+ raise unless cert_added
78
+ end
77
79
  cert_added
78
80
  rescue
79
81
  lookup_error("Add a PFX")
82
+ ensure
83
+ if pfx_cert_store && !pfx_cert_store.null?
84
+ close_cert_store(pfx_cert_store)
85
+ end
80
86
  end
81
87
 
82
88
  # Get certificate from open certificate store and return certificate object
@@ -119,7 +125,7 @@ module Win32
119
125
  begin
120
126
  cert_args = cert_find_args(store_handler, thumbprint)
121
127
  pcert_context = CertFindCertificateInStore(*cert_args)
122
- if !pcert_context.null?
128
+ unless pcert_context.null?
123
129
  cert_delete_flag = CertDeleteCertificateFromStore(CertDuplicateCertificateContext(pcert_context)) || lookup_error
124
130
  end
125
131
  CertFreeCertificateContext(pcert_context)
@@ -145,6 +151,7 @@ module Win32
145
151
  # search_token => CN, RDN or any certificate attribute
146
152
  def cert_search(store_handler, search_token)
147
153
  raise ArgumentError, "Invalid search token" if !search_token || search_token.strip.empty?
154
+
148
155
  certificate_list = []
149
156
  begin
150
157
  while (pcert_context = CertEnumCertificatesInStore(store_handler, pcert_context)) && !pcert_context.null?
@@ -163,9 +170,7 @@ module Win32
163
170
  # To close and destroy pointer of open certificate store handler
164
171
  def close_cert_store(certstore_handler = @certstore_handler)
165
172
  closed = CertCloseStore(certstore_handler, CERT_CLOSE_STORE_FORCE_FLAG)
166
- raise unless closed
167
- rescue
168
- lookup_error("close")
173
+ lookup_error("close") unless closed
169
174
  end
170
175
 
171
176
  private
@@ -215,6 +220,7 @@ module Win32
215
220
  # Verify OpenSSL::X509::Certificate object
216
221
  def verify_certificate(cert_pem)
217
222
  return "Certificate not found" if cert_pem.empty?
223
+
218
224
  valid_duration?(build_openssl_obj(cert_pem))
219
225
  end
220
226
 
@@ -225,8 +231,14 @@ module Win32
225
231
 
226
232
  # Get certificate pem
227
233
  def get_cert_pem(thumbprint)
228
- get_data = powershell_out!(cert_ps_cmd(thumbprint, store_name))
234
+ converted_store = if @store_location == CERT_SYSTEM_STORE_LOCAL_MACHINE
235
+ "LocalMachine"
236
+ else
237
+ "CurrentUser"
238
+ end
239
+ get_data = powershell_exec!(cert_ps_cmd(thumbprint, store_name, store_location: converted_store))
229
240
  get_data.stdout
241
+ # get_data.result
230
242
  end
231
243
 
232
244
  # Format pem
@@ -1,6 +1,6 @@
1
1
  module Win32
2
2
  class Certstore
3
- VERSION = "0.2.3".freeze
3
+ VERSION = "0.5.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.3
4
+ version: 0.5.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-29 00:00:00.000000000 Z
11
+ date: 2021-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,7 +79,7 @@ files:
79
79
  - lib/win32/certstore/mixin/assertions.rb
80
80
  - lib/win32/certstore/mixin/crypto.rb
81
81
  - lib/win32/certstore/mixin/helper.rb
82
- - lib/win32/certstore/mixin/shell_out.rb
82
+ - lib/win32/certstore/mixin/shell_exec.rb
83
83
  - lib/win32/certstore/mixin/string.rb
84
84
  - lib/win32/certstore/mixin/unicode.rb
85
85
  - lib/win32/certstore/store_base.rb
@@ -97,16 +97,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
97
  requirements:
98
98
  - - ">="
99
99
  - !ruby/object:Gem::Version
100
- version: '2.3'
100
+ version: '2.5'
101
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  requirements:
103
103
  - - ">="
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.7.6
107
+ rubygems_version: 3.1.4
109
108
  signing_key:
110
109
  specification_version: 4
111
- summary: Ruby library for accessing the certificate store on Windows.
110
+ summary: Ruby library for accessing the certificate stores on Windows.
112
111
  test_files: []