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 +4 -4
- data/lib/win32/certstore.rb +15 -5
- data/lib/win32/certstore/mixin/crypto.rb +22 -0
- data/lib/win32/certstore/store_base.rb +43 -0
- data/lib/win32/certstore/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5640bf3ab8b678dc92fda6d689d13d080055f29617009a02e36021a9fd1b42bc
|
4
|
+
data.tar.gz: 2140c35decc023314c21b7cb0bfafd1f1715bc2587751109cb3368818fbfe268
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81d031f2d45507b54254c165704f4b8f1de89f7d1958a9a2c803f170fbb07aabcf7c4b5f17f08c843d646fb2c0ebcffbe826d88a77298ae9b9b6c6cc0cbc8718
|
7
|
+
data.tar.gz: 38f969fb096085190123601cda01168bbc77c927306f945b033b83d987d9d649499000ab5ce586dbb30948082addd9aa6c3d5904efdb7ef0c2036cacbbae8a3c
|
data/lib/win32/certstore.rb
CHANGED
@@ -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
|
-
|
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)
|
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.
|
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-
|
11
|
+
date: 2019-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|