certstore_c 0.1.4 → 0.1.5
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/.clang-format +5 -0
- data/README.md +2 -2
- data/certstore_c.gemspec +2 -2
- data/ext/certstore/certstore.h +9 -10
- data/ext/certstore/certstore_util.c +9 -22
- data/ext/certstore/loader.c +241 -172
- data/lib/certstore/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f17868bc6c40ee22029b990df5920db1a54c51495d53907d1eeb18b1ff778f23
|
4
|
+
data.tar.gz: '06048cdc00d4e4613a8c9ea7bdc7f08dcec8d1791b4a8a991bbb04b10e12e560'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73b42304e47fce36a05de43bad75eaa39fc102a77fb04409aa95b67d17e1de7fe901ed13a94a6cfa11f944cbb22f16175078da50a8db58d43da742451c53b7f1
|
7
|
+
data.tar.gz: 8680f9c88dfb5cf78788b6bbf89befad5b5f40a05e074a391ba585980efc7b9038e4462368346fc26da94e97869e9cc83062657e4488c6cc166bdcdb7e0757a4
|
data/.clang-format
ADDED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Certstore
|
2
2
|
|
3
|
-
[](https://ci.appveyor.com/project/cosmo0920/certstore-c-xbglu/branch/master)
|
4
4
|
|
5
5
|
## Prerequisites
|
6
6
|
|
@@ -36,4 +36,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
36
36
|
|
37
37
|
## Contributing
|
38
38
|
|
39
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
39
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/fluent-plugins-nursery/certstore_c.
|
data/certstore_c.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
|
12
12
|
spec.summary = %q{Windows CertStore loader and ruby-openssl extension for TLS connection.}
|
13
13
|
spec.description = spec.summary
|
14
|
-
spec.homepage = "https://github.com/
|
14
|
+
spec.homepage = "https://github.com/fluent-plugins-nursery/certstore_c"
|
15
15
|
|
16
16
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
17
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
20
20
|
|
21
21
|
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
-
spec.metadata["source_code_uri"] = "https://github.com/
|
22
|
+
spec.metadata["source_code_uri"] = "https://github.com/fluent-plugins-nursery/certstore_c"
|
23
23
|
else
|
24
24
|
raise "RubyGems 2.0 or newer is required to protect against " \
|
25
25
|
"public gem pushes."
|
data/ext/certstore/certstore.h
CHANGED
@@ -16,18 +16,17 @@
|
|
16
16
|
#include <ruby/encoding.h>
|
17
17
|
|
18
18
|
#ifdef __GNUC__
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#else
|
22
|
-
#
|
23
|
-
#endif
|
19
|
+
#include <w32api.h>
|
20
|
+
#define MINIMUM_WINDOWS_VERSION WindowsVista
|
21
|
+
#else /* __GNUC__ */
|
22
|
+
#define MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */
|
23
|
+
#endif /* __GNUC__ */
|
24
24
|
|
25
25
|
#ifdef _WIN32_WINNT
|
26
|
-
#
|
26
|
+
#undef _WIN32_WINNT
|
27
27
|
#endif /* WIN32_WINNT */
|
28
28
|
#define _WIN32_WINNT MINIMUM_WINDOWS_VERSION
|
29
29
|
|
30
|
-
#define CERT_THUMBPRINT_STR_LENGTH 40
|
31
30
|
#define CERT_THUMBPRINT_SIZE (160 / 8)
|
32
31
|
|
33
32
|
#include <wincrypt.h>
|
@@ -36,12 +35,12 @@ VALUE rb_mCertstore;
|
|
36
35
|
VALUE rb_cCertLoader;
|
37
36
|
VALUE rb_eCertLoaderError;
|
38
37
|
|
39
|
-
struct CertstoreLoader
|
38
|
+
struct CertstoreLoader
|
39
|
+
{
|
40
40
|
HCERTSTORE hStore;
|
41
41
|
};
|
42
42
|
|
43
|
-
|
44
|
-
char* wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen);
|
43
|
+
void handle_error_code(VALUE self, DWORD errCode);
|
45
44
|
void Init_certstore_loader(VALUE rb_mCertstore);
|
46
45
|
|
47
46
|
#endif // _WINEVT_H
|
@@ -11,35 +11,22 @@
|
|
11
11
|
|
12
12
|
#include <certstore.h>
|
13
13
|
|
14
|
-
|
15
|
-
wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen)
|
16
|
-
{
|
17
|
-
char *ptr;
|
18
|
-
int len = WideCharToMultiByte(cp, 0, wstr, clen, NULL, 0, NULL, NULL);
|
19
|
-
if (!(ptr = xmalloc(len))) return NULL;
|
20
|
-
WideCharToMultiByte(cp, 0, wstr, clen, ptr, len, NULL, NULL);
|
21
|
-
|
22
|
-
return ptr;
|
23
|
-
}
|
24
|
-
|
25
|
-
TCHAR*
|
14
|
+
void
|
26
15
|
handle_error_code(VALUE self, DWORD errCode)
|
27
16
|
{
|
28
17
|
DWORD ret;
|
29
|
-
|
18
|
+
CHAR buffer[1024];
|
30
19
|
|
31
|
-
ret =
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
20
|
+
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
|
21
|
+
NULL,
|
22
|
+
errCode,
|
23
|
+
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
24
|
+
buffer,
|
25
|
+
sizeof(buffer) / sizeof(buffer[0]),
|
26
|
+
NULL);
|
38
27
|
|
39
28
|
if (ret) {
|
40
29
|
rb_ivar_set(self, rb_intern("@error_code"), INT2NUM(errCode));
|
41
30
|
rb_ivar_set(self, rb_intern("@error_message"), rb_utf8_str_new_cstr(buffer));
|
42
31
|
}
|
43
|
-
|
44
|
-
return buffer;
|
45
32
|
}
|
data/ext/certstore/loader.c
CHANGED
@@ -10,21 +10,25 @@
|
|
10
10
|
/* limitations under the License. */
|
11
11
|
|
12
12
|
#include <certstore.h>
|
13
|
-
#include <tchar.h>
|
14
13
|
|
15
|
-
static void certstore_loader_free(void
|
14
|
+
static void certstore_loader_free(void* certstore);
|
16
15
|
|
17
16
|
static const rb_data_type_t rb_win_certstore_loader_type = {
|
18
|
-
"winevt/certstore_loader",
|
19
|
-
|
20
|
-
|
17
|
+
"winevt/certstore_loader",
|
18
|
+
{
|
19
|
+
0,
|
20
|
+
certstore_loader_free,
|
21
|
+
0,
|
22
|
+
},
|
23
|
+
NULL,
|
24
|
+
NULL,
|
21
25
|
RUBY_TYPED_FREE_IMMEDIATELY
|
22
26
|
};
|
23
27
|
|
24
28
|
static void
|
25
|
-
certstore_loader_free(void
|
29
|
+
certstore_loader_free(void* ptr)
|
26
30
|
{
|
27
|
-
struct CertstoreLoader
|
31
|
+
struct CertstoreLoader* loader = (struct CertstoreLoader*)ptr;
|
28
32
|
if (loader->hStore)
|
29
33
|
CertCloseStore(loader->hStore, 0);
|
30
34
|
|
@@ -35,11 +39,9 @@ static VALUE
|
|
35
39
|
rb_win_certstore_loader_alloc(VALUE klass)
|
36
40
|
{
|
37
41
|
VALUE obj;
|
38
|
-
struct CertstoreLoader
|
39
|
-
obj = TypedData_Make_Struct(
|
40
|
-
|
41
|
-
&rb_win_certstore_loader_type,
|
42
|
-
loader);
|
42
|
+
struct CertstoreLoader* loader;
|
43
|
+
obj = TypedData_Make_Struct(
|
44
|
+
klass, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
43
45
|
return obj;
|
44
46
|
}
|
45
47
|
|
@@ -47,55 +49,62 @@ static VALUE
|
|
47
49
|
rb_win_certstore_loader_initialize(VALUE self, VALUE store_name, VALUE use_enterprise)
|
48
50
|
{
|
49
51
|
VALUE vStoreName;
|
50
|
-
struct CertstoreLoader
|
52
|
+
struct CertstoreLoader* loader;
|
51
53
|
DWORD len;
|
52
54
|
DWORD errCode;
|
53
|
-
|
54
|
-
TCHAR errBuffer[1132];
|
55
|
+
CHAR buffer[1024];
|
55
56
|
DWORD ret;
|
56
57
|
|
57
58
|
Check_Type(store_name, T_STRING);
|
58
59
|
|
59
60
|
// store_name : To wide char
|
60
|
-
len = MultiByteToWideChar(
|
61
|
-
|
62
|
-
|
61
|
+
len = MultiByteToWideChar(
|
62
|
+
CP_UTF8, 0, RSTRING_PTR(store_name), RSTRING_LEN(store_name), NULL, 0);
|
63
|
+
PWSTR winStoreName = ALLOCV_N(WCHAR, vStoreName, len + 1);
|
64
|
+
MultiByteToWideChar(
|
65
|
+
CP_UTF8, 0, RSTRING_PTR(store_name), RSTRING_LEN(store_name), winStoreName, len);
|
63
66
|
winStoreName[len] = L'\0';
|
64
67
|
|
65
|
-
TypedData_Get_Struct(
|
68
|
+
TypedData_Get_Struct(
|
69
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
66
70
|
|
67
71
|
if (RTEST(use_enterprise)) {
|
68
|
-
loader->hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
|
72
|
+
loader->hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
|
73
|
+
0,
|
74
|
+
0,
|
75
|
+
CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
|
76
|
+
winStoreName);
|
69
77
|
} else {
|
70
|
-
loader->hStore = CertOpenStore(
|
78
|
+
loader->hStore = CertOpenStore(
|
79
|
+
CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, winStoreName);
|
71
80
|
}
|
81
|
+
ALLOCV_END(vStoreName);
|
82
|
+
|
72
83
|
errCode = GetLastError();
|
73
84
|
switch (errCode) {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
case ERROR_SUCCESS:
|
86
|
+
break;
|
87
|
+
case ERROR_ACCESS_DENIED: {
|
88
|
+
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
|
89
|
+
NULL,
|
90
|
+
errCode,
|
91
|
+
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
92
|
+
buffer,
|
93
|
+
sizeof(buffer) / sizeof(buffer[0]),
|
94
|
+
NULL);
|
95
|
+
if (!ret)
|
96
|
+
buffer[0] = '\0';
|
97
|
+
|
98
|
+
rb_raise(rb_eCertLoaderError,
|
99
|
+
"cannot access specified logical store. Perhaps you should do as an "
|
100
|
+
"administrator. ErrorCode: %lu, Message: %s",
|
101
|
+
errCode,
|
102
|
+
buffer);
|
103
|
+
}
|
104
|
+
default: {
|
105
|
+
handle_error_code(self, errCode);
|
91
106
|
}
|
92
107
|
}
|
93
|
-
default: {
|
94
|
-
handle_error_code(self, errCode);
|
95
|
-
}
|
96
|
-
|
97
|
-
}
|
98
|
-
ALLOCV_END(vStoreName);
|
99
108
|
|
100
109
|
return Qnil;
|
101
110
|
}
|
@@ -103,53 +112,66 @@ rb_win_certstore_loader_initialize(VALUE self, VALUE store_name, VALUE use_enter
|
|
103
112
|
static VALUE
|
104
113
|
certificate_context_to_string(PCCERT_CONTEXT pContext)
|
105
114
|
{
|
106
|
-
|
115
|
+
VALUE vWszString;
|
116
|
+
WCHAR* wszString;
|
107
117
|
DWORD cchString;
|
108
|
-
|
109
|
-
CHAR
|
110
|
-
|
111
|
-
CHAR
|
118
|
+
VALUE vUtf8str;
|
119
|
+
CHAR* utf8str;
|
120
|
+
VALUE vCertificate;
|
121
|
+
CHAR* certificate;
|
122
|
+
CHAR* certHeader = "-----BEGIN CERTIFICATE-----\n";
|
123
|
+
CHAR* certFooter = "\n-----END CERTIFICATE-----";
|
112
124
|
CHAR errBuf[256];
|
113
125
|
DWORD errCode;
|
126
|
+
DWORD len = 0;
|
114
127
|
|
115
128
|
#ifndef CRYPT_STRING_NOCRLF
|
116
|
-
|
129
|
+
#define CRYPT_STRING_NOCRLF 0x40000000
|
117
130
|
#endif
|
118
131
|
|
119
|
-
if (!CryptBinaryToStringW(pContext->pbCertEncoded,
|
132
|
+
if (!CryptBinaryToStringW(pContext->pbCertEncoded,
|
133
|
+
pContext->cbCertEncoded,
|
120
134
|
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
|
121
|
-
NULL,
|
135
|
+
NULL,
|
136
|
+
&cchString)) {
|
122
137
|
rb_raise(rb_eCertLoaderError, "cannot obtain certificate string length.");
|
123
138
|
}
|
124
139
|
|
125
|
-
wszString =
|
126
|
-
CryptBinaryToStringW(pContext->pbCertEncoded,
|
140
|
+
wszString = ALLOCV_N(WCHAR, vWszString, cchString);
|
141
|
+
CryptBinaryToStringW(pContext->pbCertEncoded,
|
142
|
+
pContext->cbCertEncoded,
|
127
143
|
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
|
128
|
-
wszString,
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
144
|
+
wszString,
|
145
|
+
&cchString);
|
146
|
+
|
147
|
+
len = WideCharToMultiByte(CP_UTF8, 0, wszString, -1, NULL, 0, NULL, NULL);
|
148
|
+
utf8str = ALLOCV_N(CHAR, vUtf8str, len);
|
149
|
+
len = WideCharToMultiByte(CP_UTF8, 0, wszString, -1, NULL, 0, NULL, NULL);
|
150
|
+
WideCharToMultiByte(CP_UTF8, 0, wszString, -1, utf8str, len, NULL, NULL);
|
151
|
+
// malloc ((strlen(base64 cert content) + strlen(header) +
|
152
|
+
// strlen(footer) + 1(null terminator)) length).
|
153
|
+
len = strlen(utf8str) + strlen(certHeader) + strlen(certFooter);
|
154
|
+
certificate = ALLOCV_N(CHAR, vCertificate, len + 1);
|
155
|
+
_snprintf_s(certificate, len + 1, len, "%s%s%s", certHeader, utf8str, certFooter);
|
134
156
|
|
135
157
|
errCode = GetLastError();
|
136
158
|
if (ERROR_SUCCESS != errCode && CRYPT_E_NOT_FOUND != errCode) {
|
137
|
-
_snprintf_s(errBuf,
|
159
|
+
_snprintf_s(errBuf, sizeof(errBuf), _TRUNCATE, "ErrorCode(%d)", errCode);
|
138
160
|
|
139
161
|
goto error;
|
140
162
|
}
|
141
163
|
|
142
164
|
VALUE rb_pem = rb_utf8_str_new_cstr(certificate);
|
143
|
-
|
144
|
-
|
145
|
-
|
165
|
+
ALLOCV_END(vUtf8str);
|
166
|
+
ALLOCV_END(vWszString);
|
167
|
+
ALLOCV_END(vCertificate);
|
146
168
|
|
147
169
|
return rb_pem;
|
148
170
|
|
149
171
|
error:
|
150
|
-
|
151
|
-
|
152
|
-
|
172
|
+
ALLOCV_END(vUtf8str);
|
173
|
+
ALLOCV_END(vWszString);
|
174
|
+
ALLOCV_END(vCertificate);
|
153
175
|
|
154
176
|
rb_raise(rb_eCertLoaderError, errBuf);
|
155
177
|
}
|
@@ -158,28 +180,28 @@ static VALUE
|
|
158
180
|
rb_win_certstore_loader_each_pem(VALUE self)
|
159
181
|
{
|
160
182
|
PCCERT_CONTEXT pContext = NULL;
|
161
|
-
struct CertstoreLoader
|
183
|
+
struct CertstoreLoader* loader;
|
162
184
|
|
163
185
|
RETURN_ENUMERATOR(self, 0, 0);
|
164
186
|
|
165
|
-
TypedData_Get_Struct(
|
187
|
+
TypedData_Get_Struct(
|
188
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
166
189
|
|
167
190
|
while ((pContext = CertEnumCertificatesInStore(loader->hStore, pContext)) != NULL) {
|
168
191
|
VALUE rb_certificate = certificate_context_to_string(pContext);
|
169
192
|
rb_yield(rb_certificate);
|
170
193
|
}
|
171
194
|
|
172
|
-
CertFreeCertificateContext(pContext);
|
173
|
-
|
174
195
|
return Qnil;
|
175
196
|
}
|
176
197
|
|
177
198
|
static VALUE
|
178
199
|
rb_win_certstore_loader_dispose(VALUE self)
|
179
200
|
{
|
180
|
-
struct CertstoreLoader
|
201
|
+
struct CertstoreLoader* loader;
|
181
202
|
|
182
|
-
TypedData_Get_Struct(
|
203
|
+
TypedData_Get_Struct(
|
204
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
183
205
|
|
184
206
|
/* What should we dispose here? */
|
185
207
|
|
@@ -190,13 +212,15 @@ static VALUE
|
|
190
212
|
rb_win_certstore_loader_each(VALUE self)
|
191
213
|
{
|
192
214
|
PCCERT_CONTEXT pContext = NULL;
|
193
|
-
struct CertstoreLoader
|
215
|
+
struct CertstoreLoader* loader;
|
194
216
|
|
195
217
|
RETURN_ENUMERATOR(self, 0, 0);
|
196
218
|
|
197
|
-
TypedData_Get_Struct(
|
219
|
+
TypedData_Get_Struct(
|
220
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
198
221
|
|
199
|
-
rb_ensure(
|
222
|
+
rb_ensure(
|
223
|
+
rb_win_certstore_loader_each_pem, self, rb_win_certstore_loader_dispose, self);
|
200
224
|
|
201
225
|
return Qnil;
|
202
226
|
}
|
@@ -206,87 +230,88 @@ rb_win_certstore_loader_find_certificate(VALUE self, VALUE rb_thumbprint)
|
|
206
230
|
{
|
207
231
|
VALUE vThumbprint;
|
208
232
|
PCCERT_CONTEXT pContext = NULL;
|
209
|
-
struct CertstoreLoader
|
233
|
+
struct CertstoreLoader* loader;
|
210
234
|
DWORD len;
|
211
|
-
CHAR errBuf[256];
|
212
235
|
|
213
236
|
Check_Type(rb_thumbprint, T_STRING);
|
214
237
|
|
215
|
-
TypedData_Get_Struct(
|
238
|
+
TypedData_Get_Struct(
|
239
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
216
240
|
|
217
241
|
// thumbprint : To wide char
|
218
|
-
len = MultiByteToWideChar(
|
219
|
-
|
220
|
-
|
242
|
+
len = MultiByteToWideChar(
|
243
|
+
CP_UTF8, 0, RSTRING_PTR(rb_thumbprint), RSTRING_LEN(rb_thumbprint), NULL, 0);
|
244
|
+
WCHAR* winThumbprint = ALLOCV_N(WCHAR, vThumbprint, len + 1);
|
245
|
+
MultiByteToWideChar(CP_UTF8,
|
246
|
+
0,
|
247
|
+
RSTRING_PTR(rb_thumbprint),
|
248
|
+
RSTRING_LEN(rb_thumbprint),
|
249
|
+
winThumbprint,
|
250
|
+
len);
|
221
251
|
winThumbprint[len] = L'\0';
|
222
252
|
|
223
253
|
BYTE pbThumb[CERT_THUMBPRINT_SIZE];
|
224
254
|
CRYPT_HASH_BLOB blob;
|
225
255
|
blob.cbData = CERT_THUMBPRINT_SIZE;
|
226
256
|
blob.pbData = pbThumb;
|
227
|
-
CryptStringToBinaryW(winThumbprint,
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
257
|
+
CryptStringToBinaryW(winThumbprint,
|
258
|
+
0,
|
259
|
+
CRYPT_STRING_HEX,
|
260
|
+
pbThumb,
|
261
|
+
&blob.cbData,
|
262
|
+
NULL,
|
263
|
+
NULL);
|
264
|
+
|
265
|
+
pContext = CertFindCertificateInStore(loader->hStore,
|
266
|
+
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
267
|
+
0,
|
268
|
+
CERT_FIND_HASH,
|
269
|
+
&blob,
|
270
|
+
pContext);
|
271
|
+
|
272
|
+
if (!pContext) {
|
273
|
+
rb_raise(
|
274
|
+
rb_eCertLoaderError, "Cannot find certificates with thumbprint(%S)", winThumbprint);
|
275
|
+
}
|
240
276
|
|
241
277
|
VALUE rb_certificate = certificate_context_to_string(pContext);
|
242
278
|
CertFreeCertificateContext(pContext);
|
243
279
|
ALLOCV_END(vThumbprint);
|
244
280
|
|
245
281
|
return rb_certificate;
|
246
|
-
|
247
|
-
error:
|
248
|
-
|
249
|
-
CertFreeCertificateContext(pContext);
|
250
|
-
|
251
|
-
_snprintf_s(errBuf, 256, _TRUNCATE, "Cannot find certificates with thumbprint(%S)", winThumbprint);
|
252
|
-
rb_raise(rb_eCertLoaderError, errBuf);
|
253
282
|
}
|
254
283
|
|
255
284
|
static VALUE
|
256
285
|
rb_win_certstore_loader_add_certificate(VALUE self, VALUE rb_der_cert_bin_str)
|
257
286
|
{
|
258
|
-
struct CertstoreLoader
|
259
|
-
CHAR errBuf[256];
|
287
|
+
struct CertstoreLoader* loader;
|
260
288
|
|
261
289
|
Check_Type(rb_der_cert_bin_str, T_STRING);
|
262
290
|
|
263
|
-
TypedData_Get_Struct(
|
291
|
+
TypedData_Get_Struct(
|
292
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
264
293
|
|
265
|
-
if (CertAddEncodedCertificateToStore(loader->hStore,
|
266
|
-
|
294
|
+
if (CertAddEncodedCertificateToStore(loader->hStore,
|
295
|
+
X509_ASN_ENCODING,
|
296
|
+
RSTRING_PTR(rb_der_cert_bin_str),
|
297
|
+
RSTRING_LEN(rb_der_cert_bin_str),
|
267
298
|
CERT_STORE_ADD_NEW,
|
268
299
|
NULL)) {
|
269
300
|
return Qtrue;
|
270
301
|
} else {
|
271
302
|
DWORD errCode = GetLastError();
|
272
303
|
|
273
|
-
switch (errCode){
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
goto error;
|
280
|
-
|
304
|
+
switch (errCode) {
|
305
|
+
case CRYPT_E_EXISTS:
|
306
|
+
handle_error_code(self, errCode);
|
307
|
+
return Qfalse;
|
308
|
+
default: {
|
309
|
+
rb_raise(rb_eCertLoaderError, "Cannot add certificates. ErrorCode: %lu", errCode);
|
281
310
|
}
|
282
311
|
}
|
283
312
|
}
|
284
313
|
|
285
314
|
return Qtrue;
|
286
|
-
|
287
|
-
error:
|
288
|
-
|
289
|
-
rb_raise(rb_eCertLoaderError, errBuf);
|
290
315
|
}
|
291
316
|
|
292
317
|
static VALUE
|
@@ -294,37 +319,49 @@ rb_win_certstore_loader_delete_certificate(VALUE self, VALUE rb_thumbprint)
|
|
294
319
|
{
|
295
320
|
VALUE vThumbprint;
|
296
321
|
PCCERT_CONTEXT pContext = NULL;
|
297
|
-
struct CertstoreLoader
|
322
|
+
struct CertstoreLoader* loader;
|
298
323
|
DWORD len;
|
299
|
-
CHAR errBuf[256];
|
300
324
|
|
301
325
|
Check_Type(rb_thumbprint, T_STRING);
|
302
326
|
|
303
|
-
TypedData_Get_Struct(
|
327
|
+
TypedData_Get_Struct(
|
328
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
304
329
|
|
305
330
|
// thumbprint : To wide char
|
306
|
-
len = MultiByteToWideChar(
|
307
|
-
|
308
|
-
|
331
|
+
len = MultiByteToWideChar(
|
332
|
+
CP_UTF8, 0, RSTRING_PTR(rb_thumbprint), RSTRING_LEN(rb_thumbprint), NULL, 0);
|
333
|
+
WCHAR* winThumbprint = ALLOCV_N(WCHAR, vThumbprint, len + 1);
|
334
|
+
MultiByteToWideChar(CP_UTF8,
|
335
|
+
0,
|
336
|
+
RSTRING_PTR(rb_thumbprint),
|
337
|
+
RSTRING_LEN(rb_thumbprint),
|
338
|
+
winThumbprint,
|
339
|
+
len);
|
309
340
|
winThumbprint[len] = L'\0';
|
310
341
|
|
311
342
|
BYTE pbThumb[CERT_THUMBPRINT_SIZE];
|
312
343
|
CRYPT_HASH_BLOB blob;
|
313
344
|
blob.cbData = CERT_THUMBPRINT_SIZE;
|
314
345
|
blob.pbData = pbThumb;
|
315
|
-
CryptStringToBinaryW(winThumbprint,
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
346
|
+
CryptStringToBinaryW(winThumbprint,
|
347
|
+
0,
|
348
|
+
CRYPT_STRING_HEX,
|
349
|
+
pbThumb,
|
350
|
+
&blob.cbData,
|
351
|
+
NULL,
|
352
|
+
NULL);
|
353
|
+
|
354
|
+
pContext = CertFindCertificateInStore(loader->hStore,
|
355
|
+
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
356
|
+
0,
|
357
|
+
CERT_FIND_HASH,
|
358
|
+
&blob,
|
359
|
+
pContext);
|
360
|
+
|
361
|
+
if (!pContext) {
|
362
|
+
rb_raise(
|
363
|
+
rb_eCertLoaderError, "Cannot find certificates with thumbprint(%S)", winThumbprint);
|
364
|
+
}
|
328
365
|
|
329
366
|
BOOL result = CertDeleteCertificateFromStore(pContext);
|
330
367
|
CertFreeCertificateContext(pContext);
|
@@ -334,13 +371,6 @@ rb_win_certstore_loader_delete_certificate(VALUE self, VALUE rb_thumbprint)
|
|
334
371
|
return Qtrue;
|
335
372
|
else
|
336
373
|
return Qfalse;
|
337
|
-
|
338
|
-
error:
|
339
|
-
|
340
|
-
CertFreeCertificateContext(pContext);
|
341
|
-
|
342
|
-
_snprintf_s(errBuf, 256, _TRUNCATE, "Cannot find certificates with thumbprint(%S)", winThumbprint);
|
343
|
-
rb_raise(rb_eCertLoaderError, errBuf);
|
344
374
|
}
|
345
375
|
|
346
376
|
static VALUE
|
@@ -348,42 +378,59 @@ rb_win_certstore_loader_export_pfx(VALUE self, VALUE rb_thumbprint, VALUE rb_pas
|
|
348
378
|
{
|
349
379
|
VALUE vThumbprint;
|
350
380
|
PCCERT_CONTEXT pContext = NULL;
|
351
|
-
struct CertstoreLoader
|
381
|
+
struct CertstoreLoader* loader;
|
352
382
|
DWORD len;
|
353
383
|
CHAR errBuf[256];
|
354
384
|
HCERTSTORE hMemoryStore = NULL;
|
355
385
|
VALUE vPassword;
|
356
386
|
CRYPT_DATA_BLOB pfxPacket;
|
357
387
|
|
358
|
-
TypedData_Get_Struct(
|
388
|
+
TypedData_Get_Struct(
|
389
|
+
self, struct CertstoreLoader, &rb_win_certstore_loader_type, loader);
|
359
390
|
|
360
391
|
// thumbprint : To wide char
|
361
|
-
len = MultiByteToWideChar(
|
362
|
-
|
363
|
-
|
392
|
+
len = MultiByteToWideChar(
|
393
|
+
CP_UTF8, 0, RSTRING_PTR(rb_thumbprint), RSTRING_LEN(rb_thumbprint), NULL, 0);
|
394
|
+
WCHAR* winThumbprint = ALLOCV_N(WCHAR, vThumbprint, len + 1);
|
395
|
+
MultiByteToWideChar(CP_UTF8,
|
396
|
+
0,
|
397
|
+
RSTRING_PTR(rb_thumbprint),
|
398
|
+
RSTRING_LEN(rb_thumbprint),
|
399
|
+
winThumbprint,
|
400
|
+
len);
|
364
401
|
winThumbprint[len] = L'\0';
|
365
402
|
// password : To wide char
|
366
|
-
len = MultiByteToWideChar(
|
367
|
-
|
368
|
-
|
403
|
+
len = MultiByteToWideChar(
|
404
|
+
CP_UTF8, 0, RSTRING_PTR(rb_password), RSTRING_LEN(rb_password), NULL, 0);
|
405
|
+
WCHAR* winPassword = ALLOCV_N(WCHAR, vPassword, len + 1);
|
406
|
+
MultiByteToWideChar(
|
407
|
+
CP_UTF8, 0, RSTRING_PTR(rb_password), RSTRING_LEN(rb_password), winPassword, len);
|
369
408
|
winPassword[len] = L'\0';
|
370
409
|
|
371
410
|
BYTE pbThumb[CERT_THUMBPRINT_SIZE];
|
372
411
|
CRYPT_HASH_BLOB blob;
|
373
412
|
blob.cbData = CERT_THUMBPRINT_SIZE;
|
374
413
|
blob.pbData = pbThumb;
|
375
|
-
CryptStringToBinaryW(winThumbprint,
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
414
|
+
CryptStringToBinaryW(winThumbprint,
|
415
|
+
0,
|
416
|
+
CRYPT_STRING_HEX,
|
417
|
+
pbThumb,
|
418
|
+
&blob.cbData,
|
419
|
+
NULL,
|
420
|
+
NULL);
|
421
|
+
|
422
|
+
pContext = CertFindCertificateInStore(loader->hStore,
|
423
|
+
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
424
|
+
0,
|
425
|
+
CERT_FIND_HASH,
|
426
|
+
&blob,
|
427
|
+
pContext);
|
385
428
|
if (!pContext) {
|
386
|
-
_snprintf_s(errBuf,
|
429
|
+
_snprintf_s(errBuf,
|
430
|
+
sizeof(errBuf),
|
431
|
+
_TRUNCATE,
|
432
|
+
"Cannot find certificates with thumbprint(%S)",
|
433
|
+
winThumbprint);
|
387
434
|
|
388
435
|
goto error;
|
389
436
|
}
|
@@ -392,15 +439,33 @@ rb_win_certstore_loader_export_pfx(VALUE self, VALUE rb_thumbprint, VALUE rb_pas
|
|
392
439
|
CertAddCertificateContextToStore(hMemoryStore, pContext, CERT_STORE_ADD_ALWAYS, NULL);
|
393
440
|
|
394
441
|
pfxPacket.pbData = NULL;
|
395
|
-
if (!PFXExportCertStoreEx(hMemoryStore,
|
396
|
-
|
442
|
+
if (!PFXExportCertStoreEx(hMemoryStore,
|
443
|
+
&pfxPacket,
|
444
|
+
winPassword,
|
445
|
+
NULL,
|
446
|
+
EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY |
|
447
|
+
REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) {
|
448
|
+
_snprintf_s(errBuf,
|
449
|
+
sizeof(errBuf),
|
450
|
+
_TRUNCATE,
|
451
|
+
"Cannot export pfx certificate with thumbprint(%S)",
|
452
|
+
winThumbprint);
|
397
453
|
|
398
454
|
goto error;
|
399
455
|
}
|
400
456
|
|
401
457
|
pfxPacket.pbData = (LPBYTE)CryptMemAlloc(pfxPacket.cbData);
|
402
|
-
if (!PFXExportCertStoreEx(hMemoryStore,
|
403
|
-
|
458
|
+
if (!PFXExportCertStoreEx(hMemoryStore,
|
459
|
+
&pfxPacket,
|
460
|
+
winPassword,
|
461
|
+
NULL,
|
462
|
+
EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY |
|
463
|
+
REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) {
|
464
|
+
_snprintf_s(errBuf,
|
465
|
+
sizeof(errBuf),
|
466
|
+
_TRUNCATE,
|
467
|
+
"Cannot export pfx certificate with thumbprint(%S)",
|
468
|
+
winThumbprint);
|
404
469
|
|
405
470
|
CryptMemFree(pfxPacket.pbData);
|
406
471
|
|
@@ -433,14 +498,18 @@ void
|
|
433
498
|
Init_certstore_loader(VALUE rb_mCertstore)
|
434
499
|
{
|
435
500
|
rb_cCertLoader = rb_define_class_under(rb_mCertstore, "Loader", rb_cObject);
|
436
|
-
rb_eCertLoaderError =
|
501
|
+
rb_eCertLoaderError =
|
502
|
+
rb_define_class_under(rb_cCertLoader, "LoaderError", rb_eStandardError);
|
437
503
|
|
438
504
|
rb_define_alloc_func(rb_cCertLoader, rb_win_certstore_loader_alloc);
|
439
505
|
rb_define_method(rb_cCertLoader, "initialize", rb_win_certstore_loader_initialize, 2);
|
440
506
|
rb_define_method(rb_cCertLoader, "each", rb_win_certstore_loader_each, 0);
|
441
|
-
rb_define_method(
|
442
|
-
|
443
|
-
rb_define_method(
|
507
|
+
rb_define_method(
|
508
|
+
rb_cCertLoader, "find_cert", rb_win_certstore_loader_find_certificate, 1);
|
509
|
+
rb_define_method(
|
510
|
+
rb_cCertLoader, "delete_cert", rb_win_certstore_loader_delete_certificate, 1);
|
511
|
+
rb_define_method(
|
512
|
+
rb_cCertLoader, "add_cert", rb_win_certstore_loader_add_certificate, 1);
|
444
513
|
rb_define_method(rb_cCertLoader, "export_pfx", rb_win_certstore_loader_export_pfx, 2);
|
445
514
|
|
446
515
|
rb_ivar_set(rb_cCertLoader, rb_intern("@error_code"), INT2NUM(0));
|
data/lib/certstore/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: certstore_c
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroshi Hatake
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,7 @@ extensions:
|
|
94
94
|
- ext/certstore/extconf.rb
|
95
95
|
extra_rdoc_files: []
|
96
96
|
files:
|
97
|
+
- ".clang-format"
|
97
98
|
- ".gitignore"
|
98
99
|
- Gemfile
|
99
100
|
- LICENSE.txt
|
@@ -114,13 +115,13 @@ files:
|
|
114
115
|
- lib/certstore/loader.rb
|
115
116
|
- lib/certstore/openssl/loader.rb
|
116
117
|
- lib/certstore/version.rb
|
117
|
-
homepage: https://github.com/
|
118
|
+
homepage: https://github.com/fluent-plugins-nursery/certstore_c
|
118
119
|
licenses:
|
119
120
|
- Apache-2.0
|
120
121
|
metadata:
|
121
122
|
allowed_push_host: https://rubygems.org
|
122
|
-
homepage_uri: https://github.com/
|
123
|
-
source_code_uri: https://github.com/
|
123
|
+
homepage_uri: https://github.com/fluent-plugins-nursery/certstore_c
|
124
|
+
source_code_uri: https://github.com/fluent-plugins-nursery/certstore_c
|
124
125
|
post_install_message:
|
125
126
|
rdoc_options: []
|
126
127
|
require_paths:
|