certstore_c 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build status](https://ci.appveyor.com/api/projects/status/
|
3
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/ecis54vyb81aset5/branch/master?svg=true)](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:
|