win32-certstore 0.2.3 → 0.5.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: 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: []