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 +4 -4
- data/lib/win32/certstore.rb +14 -9
- data/lib/win32/certstore/mixin/assertions.rb +1 -1
- data/lib/win32/certstore/mixin/crypto.rb +30 -27
- data/lib/win32/certstore/mixin/helper.rb +2 -4
- data/lib/win32/certstore/mixin/{shell_out.rb → shell_exec.rb} +7 -6
- data/lib/win32/certstore/store_base.rb +31 -19
- data/lib/win32/certstore/version.rb +1 -1
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b391e4d81e324162538a2a3644aea74f0da1f8679409733a58dcf4c590734a6c
|
4
|
+
data.tar.gz: 5ed7821ec5bffe58cb09608cfc008b287874b5ddafe8556662fa27f42a25c1b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc5c77cd659695ac3a58480ab875a6c5daa2b93cd83e45f1fcdfcd1bd89e0cf9653d38d63ae9e5260ecff90a7277f6ee600b91137665d53e672fbb77e1543cfb
|
7
|
+
data.tar.gz: 5b6a8025b85ae8ce026a9a7b603a35137000525ba182bbbcc8fc9667fb78dd6cf179ad1cfbb1cbdcdf582dd4749f82795a17df01181720d7f77a36a4477dc639
|
data/lib/win32/certstore.rb
CHANGED
@@ -31,18 +31,21 @@ module Win32
|
|
31
31
|
|
32
32
|
attr_accessor :store_name
|
33
33
|
|
34
|
-
|
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
|
-
@
|
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
|
-
|
121
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
168
|
-
|
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
|
-
|
174
|
-
|
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
|
-
|
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
|
-
|
187
|
+
:PublicKey, CRYPT_BIT_BLOB
|
185
188
|
end
|
186
189
|
|
187
190
|
class CERT_INFO < FFI::Struct
|
188
191
|
layout :dwVersion, DWORD,
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
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
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
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:\\
|
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
|
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
|
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
|
55
|
-
cmd =
|
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(
|
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/
|
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::
|
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),
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
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:
|
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/
|
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.
|
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
|
-
|
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
|
110
|
+
summary: Ruby library for accessing the certificate stores on Windows.
|
112
111
|
test_files: []
|