rubysl-openssl 2.10 → 2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/ext/rubysl/openssl/deprecation.rb +7 -3
- data/ext/rubysl/openssl/extconf.rb +148 -103
- data/ext/rubysl/openssl/openssl_missing.c +94 -275
- data/ext/rubysl/openssl/openssl_missing.h +167 -98
- data/ext/rubysl/openssl/ossl.c +266 -212
- data/ext/rubysl/openssl/ossl.h +27 -89
- data/ext/rubysl/openssl/ossl_asn1.c +157 -221
- data/ext/rubysl/openssl/ossl_asn1.h +11 -3
- data/ext/rubysl/openssl/ossl_bio.c +10 -40
- data/ext/rubysl/openssl/ossl_bio.h +1 -2
- data/ext/rubysl/openssl/ossl_bn.c +144 -100
- data/ext/rubysl/openssl/ossl_bn.h +3 -1
- data/ext/rubysl/openssl/ossl_cipher.c +270 -195
- data/ext/rubysl/openssl/ossl_config.c +7 -1
- data/ext/rubysl/openssl/ossl_config.h +0 -1
- data/ext/rubysl/openssl/ossl_digest.c +40 -29
- data/ext/rubysl/openssl/ossl_engine.c +23 -62
- data/ext/rubysl/openssl/ossl_hmac.c +82 -55
- data/ext/rubysl/openssl/ossl_ns_spki.c +22 -22
- data/ext/rubysl/openssl/ossl_ocsp.c +894 -144
- data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs12.c +47 -19
- data/ext/rubysl/openssl/ossl_pkcs5.c +7 -15
- data/ext/rubysl/openssl/ossl_pkcs7.c +38 -15
- data/ext/rubysl/openssl/ossl_pkey.c +151 -99
- data/ext/rubysl/openssl/ossl_pkey.h +123 -29
- data/ext/rubysl/openssl/ossl_pkey_dh.c +143 -92
- data/ext/rubysl/openssl/ossl_pkey_dsa.c +149 -104
- data/ext/rubysl/openssl/ossl_pkey_ec.c +646 -524
- data/ext/rubysl/openssl/ossl_pkey_rsa.c +180 -121
- data/ext/rubysl/openssl/ossl_rand.c +25 -21
- data/ext/rubysl/openssl/ossl_ssl.c +795 -413
- data/ext/rubysl/openssl/ossl_ssl.h +3 -0
- data/ext/rubysl/openssl/ossl_ssl_session.c +83 -77
- data/ext/rubysl/openssl/ossl_version.h +1 -1
- data/ext/rubysl/openssl/ossl_x509.c +92 -8
- data/ext/rubysl/openssl/ossl_x509.h +14 -5
- data/ext/rubysl/openssl/ossl_x509attr.c +77 -41
- data/ext/rubysl/openssl/ossl_x509cert.c +45 -46
- data/ext/rubysl/openssl/ossl_x509crl.c +51 -57
- data/ext/rubysl/openssl/ossl_x509ext.c +39 -33
- data/ext/rubysl/openssl/ossl_x509name.c +68 -45
- data/ext/rubysl/openssl/ossl_x509req.c +32 -38
- data/ext/rubysl/openssl/ossl_x509revoked.c +43 -9
- data/ext/rubysl/openssl/ossl_x509store.c +309 -104
- data/ext/rubysl/openssl/ruby_missing.h +8 -6
- data/lib/openssl/buffering.rb +11 -5
- data/lib/openssl/cipher.rb +23 -15
- data/lib/openssl/digest.rb +7 -10
- data/lib/openssl/pkey.rb +15 -8
- data/lib/openssl/ssl.rb +81 -105
- data/lib/rubysl/openssl.rb +1 -4
- data/lib/rubysl/openssl/version.rb +1 -1
- metadata +3 -4
@@ -109,6 +109,25 @@ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
|
|
109
109
|
return self;
|
110
110
|
}
|
111
111
|
|
112
|
+
static VALUE
|
113
|
+
ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
|
114
|
+
{
|
115
|
+
X509_REVOKED *rev, *rev_other, *rev_new;
|
116
|
+
|
117
|
+
rb_check_frozen(self);
|
118
|
+
GetX509Rev(self, rev);
|
119
|
+
SafeGetX509Rev(other, rev_other);
|
120
|
+
|
121
|
+
rev_new = X509_REVOKED_dup(rev_other);
|
122
|
+
if (!rev_new)
|
123
|
+
ossl_raise(eX509RevError, "X509_REVOKED_dup");
|
124
|
+
|
125
|
+
SetX509Rev(self, rev_new);
|
126
|
+
X509_REVOKED_free(rev);
|
127
|
+
|
128
|
+
return self;
|
129
|
+
}
|
130
|
+
|
112
131
|
static VALUE
|
113
132
|
ossl_x509revoked_get_serial(VALUE self)
|
114
133
|
{
|
@@ -116,16 +135,22 @@ ossl_x509revoked_get_serial(VALUE self)
|
|
116
135
|
|
117
136
|
GetX509Rev(self, rev);
|
118
137
|
|
119
|
-
return asn1integer_to_num(rev
|
138
|
+
return asn1integer_to_num(X509_REVOKED_get0_serialNumber(rev));
|
120
139
|
}
|
121
140
|
|
122
141
|
static VALUE
|
123
142
|
ossl_x509revoked_set_serial(VALUE self, VALUE num)
|
124
143
|
{
|
125
144
|
X509_REVOKED *rev;
|
145
|
+
ASN1_INTEGER *asn1int;
|
126
146
|
|
127
147
|
GetX509Rev(self, rev);
|
128
|
-
|
148
|
+
asn1int = num_to_asn1integer(num, NULL);
|
149
|
+
if (!X509_REVOKED_set_serialNumber(rev, asn1int)) {
|
150
|
+
ASN1_INTEGER_free(asn1int);
|
151
|
+
ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
|
152
|
+
}
|
153
|
+
ASN1_INTEGER_free(asn1int);
|
129
154
|
|
130
155
|
return num;
|
131
156
|
}
|
@@ -137,20 +162,22 @@ ossl_x509revoked_get_time(VALUE self)
|
|
137
162
|
|
138
163
|
GetX509Rev(self, rev);
|
139
164
|
|
140
|
-
return asn1time_to_time(rev
|
165
|
+
return asn1time_to_time(X509_REVOKED_get0_revocationDate(rev));
|
141
166
|
}
|
142
167
|
|
143
168
|
static VALUE
|
144
169
|
ossl_x509revoked_set_time(VALUE self, VALUE time)
|
145
170
|
{
|
146
171
|
X509_REVOKED *rev;
|
147
|
-
|
172
|
+
ASN1_TIME *asn1time;
|
148
173
|
|
149
|
-
sec = time_to_time_t(time);
|
150
174
|
GetX509Rev(self, rev);
|
151
|
-
|
152
|
-
|
175
|
+
asn1time = ossl_x509_time_adjust(NULL, time);
|
176
|
+
if (!X509_REVOKED_set_revocationDate(rev, asn1time)) {
|
177
|
+
ASN1_TIME_free(asn1time);
|
178
|
+
ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
|
153
179
|
}
|
180
|
+
ASN1_TIME_free(asn1time);
|
154
181
|
|
155
182
|
return time;
|
156
183
|
}
|
@@ -196,8 +223,8 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
|
|
196
223
|
OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
|
197
224
|
}
|
198
225
|
GetX509Rev(self, rev);
|
199
|
-
|
200
|
-
|
226
|
+
while ((ext = X509_REVOKED_delete_ext(rev, 0)))
|
227
|
+
X509_EXTENSION_free(ext);
|
201
228
|
for (i=0; i<RARRAY_LEN(ary); i++) {
|
202
229
|
item = RARRAY_AREF(ary, i);
|
203
230
|
ext = GetX509ExtPtr(item);
|
@@ -228,12 +255,19 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
|
|
228
255
|
void
|
229
256
|
Init_ossl_x509revoked(void)
|
230
257
|
{
|
258
|
+
#if 0
|
259
|
+
mOSSL = rb_define_module("OpenSSL");
|
260
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
261
|
+
mX509 = rb_define_module_under(mOSSL, "X509");
|
262
|
+
#endif
|
263
|
+
|
231
264
|
eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
|
232
265
|
|
233
266
|
cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject);
|
234
267
|
|
235
268
|
rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc);
|
236
269
|
rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1);
|
270
|
+
rb_define_copy_func(cX509Rev, ossl_x509revoked_initialize_copy);
|
237
271
|
|
238
272
|
rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0);
|
239
273
|
rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1);
|
@@ -47,6 +47,65 @@
|
|
47
47
|
GetX509Store((obj), (ctx)); \
|
48
48
|
} while (0)
|
49
49
|
|
50
|
+
/*
|
51
|
+
* Verify callback stuff
|
52
|
+
*/
|
53
|
+
static int stctx_ex_verify_cb_idx, store_ex_verify_cb_idx;
|
54
|
+
static VALUE ossl_x509stctx_new(X509_STORE_CTX *);
|
55
|
+
|
56
|
+
struct ossl_verify_cb_args {
|
57
|
+
VALUE proc;
|
58
|
+
VALUE preverify_ok;
|
59
|
+
VALUE store_ctx;
|
60
|
+
};
|
61
|
+
|
62
|
+
static VALUE
|
63
|
+
call_verify_cb_proc(struct ossl_verify_cb_args *args)
|
64
|
+
{
|
65
|
+
return rb_funcall(args->proc, rb_intern("call"), 2,
|
66
|
+
args->preverify_ok, args->store_ctx);
|
67
|
+
}
|
68
|
+
|
69
|
+
int
|
70
|
+
ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
|
71
|
+
{
|
72
|
+
VALUE rctx, ret;
|
73
|
+
struct ossl_verify_cb_args args;
|
74
|
+
int state;
|
75
|
+
|
76
|
+
if (NIL_P(proc))
|
77
|
+
return ok;
|
78
|
+
|
79
|
+
ret = Qfalse;
|
80
|
+
rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
|
81
|
+
if (state) {
|
82
|
+
rb_set_errinfo(Qnil);
|
83
|
+
rb_warn("StoreContext initialization failure");
|
84
|
+
}
|
85
|
+
else {
|
86
|
+
args.proc = proc;
|
87
|
+
args.preverify_ok = ok ? Qtrue : Qfalse;
|
88
|
+
args.store_ctx = rctx;
|
89
|
+
ret = rb_protect((VALUE(*)(VALUE))call_verify_cb_proc, (VALUE)&args, &state);
|
90
|
+
if (state) {
|
91
|
+
rb_set_errinfo(Qnil);
|
92
|
+
rb_warn("exception in verify_callback is ignored");
|
93
|
+
}
|
94
|
+
RTYPEDDATA_DATA(rctx) = NULL;
|
95
|
+
}
|
96
|
+
if (ret == Qtrue) {
|
97
|
+
X509_STORE_CTX_set_error(ctx, X509_V_OK);
|
98
|
+
ok = 1;
|
99
|
+
}
|
100
|
+
else {
|
101
|
+
if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
|
102
|
+
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
|
103
|
+
ok = 0;
|
104
|
+
}
|
105
|
+
|
106
|
+
return ok;
|
107
|
+
}
|
108
|
+
|
50
109
|
/*
|
51
110
|
* Classes
|
52
111
|
*/
|
@@ -98,7 +157,7 @@ DupX509StorePtr(VALUE obj)
|
|
98
157
|
X509_STORE *store;
|
99
158
|
|
100
159
|
SafeGetX509Store(obj, store);
|
101
|
-
|
160
|
+
X509_STORE_up_ref(store);
|
102
161
|
|
103
162
|
return store;
|
104
163
|
}
|
@@ -106,6 +165,21 @@ DupX509StorePtr(VALUE obj)
|
|
106
165
|
/*
|
107
166
|
* Private functions
|
108
167
|
*/
|
168
|
+
static int
|
169
|
+
x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
|
170
|
+
{
|
171
|
+
VALUE proc;
|
172
|
+
|
173
|
+
proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
|
174
|
+
if (!proc)
|
175
|
+
proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
|
176
|
+
store_ex_verify_cb_idx);
|
177
|
+
if (!proc)
|
178
|
+
return ok;
|
179
|
+
|
180
|
+
return ossl_verify_cb_call(proc, ok, ctx);
|
181
|
+
}
|
182
|
+
|
109
183
|
static VALUE
|
110
184
|
ossl_x509store_alloc(VALUE klass)
|
111
185
|
{
|
@@ -130,7 +204,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
|
|
130
204
|
X509_STORE *store;
|
131
205
|
|
132
206
|
GetX509Store(self, store);
|
133
|
-
X509_STORE_set_ex_data(store,
|
207
|
+
X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
|
134
208
|
rb_iv_set(self, "@verify_callback", cb);
|
135
209
|
|
136
210
|
return cb;
|
@@ -141,6 +215,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
|
|
141
215
|
* call-seq:
|
142
216
|
* X509::Store.new => store
|
143
217
|
*
|
218
|
+
* Creates a new X509::Store.
|
144
219
|
*/
|
145
220
|
static VALUE
|
146
221
|
ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
|
@@ -149,15 +224,12 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
|
|
149
224
|
|
150
225
|
/* BUG: This method takes any number of arguments but appears to ignore them. */
|
151
226
|
GetX509Store(self, store);
|
227
|
+
#if !defined(HAVE_OPAQUE_OPENSSL)
|
228
|
+
/* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */
|
152
229
|
store->ex_data.sk = NULL;
|
153
|
-
X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
|
154
|
-
ossl_x509store_set_vfy_cb(self, Qnil);
|
155
|
-
|
156
|
-
#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
|
157
|
-
rb_iv_set(self, "@flags", INT2FIX(0));
|
158
|
-
rb_iv_set(self, "@purpose", INT2FIX(0));
|
159
|
-
rb_iv_set(self, "@trust", INT2FIX(0));
|
160
230
|
#endif
|
231
|
+
X509_STORE_set_verify_cb(store, x509store_verify_cb);
|
232
|
+
ossl_x509store_set_vfy_cb(self, Qnil);
|
161
233
|
|
162
234
|
/* last verification status */
|
163
235
|
rb_iv_set(self, "@error", Qnil);
|
@@ -168,54 +240,77 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
|
|
168
240
|
return self;
|
169
241
|
}
|
170
242
|
|
243
|
+
/*
|
244
|
+
* call-seq:
|
245
|
+
* store.flags = flag
|
246
|
+
*
|
247
|
+
* Sets +flag+ to the Store. +flag+ consists of zero or more of the constants
|
248
|
+
* defined in with name V_FLAG_* or'ed together.
|
249
|
+
*/
|
171
250
|
static VALUE
|
172
251
|
ossl_x509store_set_flags(VALUE self, VALUE flags)
|
173
252
|
{
|
174
|
-
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
|
175
253
|
X509_STORE *store;
|
176
254
|
long f = NUM2LONG(flags);
|
177
255
|
|
178
256
|
GetX509Store(self, store);
|
179
257
|
X509_STORE_set_flags(store, f);
|
180
|
-
#else
|
181
|
-
rb_iv_set(self, "@flags", flags);
|
182
|
-
#endif
|
183
258
|
|
184
259
|
return flags;
|
185
260
|
}
|
186
261
|
|
262
|
+
/*
|
263
|
+
* call-seq:
|
264
|
+
* store.purpose = purpose
|
265
|
+
*
|
266
|
+
* Sets the store's purpose to +purpose+. If specified, the verifications on
|
267
|
+
* the store will check every untrusted certificate's extensions are consistent
|
268
|
+
* with the purpose. The purpose is specified by constants:
|
269
|
+
*
|
270
|
+
* * X509::PURPOSE_SSL_CLIENT
|
271
|
+
* * X509::PURPOSE_SSL_SERVER
|
272
|
+
* * X509::PURPOSE_NS_SSL_SERVER
|
273
|
+
* * X509::PURPOSE_SMIME_SIGN
|
274
|
+
* * X509::PURPOSE_SMIME_ENCRYPT
|
275
|
+
* * X509::PURPOSE_CRL_SIGN
|
276
|
+
* * X509::PURPOSE_ANY
|
277
|
+
* * X509::PURPOSE_OCSP_HELPER
|
278
|
+
* * X509::PURPOSE_TIMESTAMP_SIGN
|
279
|
+
*/
|
187
280
|
static VALUE
|
188
281
|
ossl_x509store_set_purpose(VALUE self, VALUE purpose)
|
189
282
|
{
|
190
|
-
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
|
191
283
|
X509_STORE *store;
|
192
284
|
int p = NUM2INT(purpose);
|
193
285
|
|
194
286
|
GetX509Store(self, store);
|
195
287
|
X509_STORE_set_purpose(store, p);
|
196
|
-
#else
|
197
|
-
rb_iv_set(self, "@purpose", purpose);
|
198
|
-
#endif
|
199
288
|
|
200
289
|
return purpose;
|
201
290
|
}
|
202
291
|
|
292
|
+
/*
|
293
|
+
* call-seq:
|
294
|
+
* store.trust = trust
|
295
|
+
*/
|
203
296
|
static VALUE
|
204
297
|
ossl_x509store_set_trust(VALUE self, VALUE trust)
|
205
298
|
{
|
206
|
-
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
|
207
299
|
X509_STORE *store;
|
208
300
|
int t = NUM2INT(trust);
|
209
301
|
|
210
302
|
GetX509Store(self, store);
|
211
303
|
X509_STORE_set_trust(store, t);
|
212
|
-
#else
|
213
|
-
rb_iv_set(self, "@trust", trust);
|
214
|
-
#endif
|
215
304
|
|
216
305
|
return trust;
|
217
306
|
}
|
218
307
|
|
308
|
+
/*
|
309
|
+
* call-seq:
|
310
|
+
* store.time = time
|
311
|
+
*
|
312
|
+
* Sets the time to be used in verifications.
|
313
|
+
*/
|
219
314
|
static VALUE
|
220
315
|
ossl_x509store_set_time(VALUE self, VALUE time)
|
221
316
|
{
|
@@ -225,13 +320,11 @@ ossl_x509store_set_time(VALUE self, VALUE time)
|
|
225
320
|
|
226
321
|
/*
|
227
322
|
* call-seq:
|
228
|
-
* store.add_file(file) ->
|
229
|
-
*
|
323
|
+
* store.add_file(file) -> self
|
230
324
|
*
|
231
325
|
* Adds the certificates in +file+ to the certificate store. The +file+ can
|
232
326
|
* contain multiple PEM-encoded certificates.
|
233
327
|
*/
|
234
|
-
|
235
328
|
static VALUE
|
236
329
|
ossl_x509store_add_file(VALUE self, VALUE file)
|
237
330
|
{
|
@@ -240,8 +333,8 @@ ossl_x509store_add_file(VALUE self, VALUE file)
|
|
240
333
|
char *path = NULL;
|
241
334
|
|
242
335
|
if(file != Qnil){
|
243
|
-
|
244
|
-
path =
|
336
|
+
rb_check_safe_obj(file);
|
337
|
+
path = StringValueCStr(file);
|
245
338
|
}
|
246
339
|
GetX509Store(self, store);
|
247
340
|
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
|
@@ -249,10 +342,25 @@ ossl_x509store_add_file(VALUE self, VALUE file)
|
|
249
342
|
if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
|
250
343
|
ossl_raise(eX509StoreError, NULL);
|
251
344
|
}
|
345
|
+
#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
|
346
|
+
/*
|
347
|
+
* X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file()
|
348
|
+
* did not check the return value of X509_STORE_add_{cert,crl}(), leaking
|
349
|
+
* "cert already in hash table" errors on the error queue, if duplicate
|
350
|
+
* certificates are found. This will be fixed by OpenSSL 1.1.1.
|
351
|
+
*/
|
352
|
+
ossl_clear_error();
|
353
|
+
#endif
|
252
354
|
|
253
355
|
return self;
|
254
356
|
}
|
255
357
|
|
358
|
+
/*
|
359
|
+
* call-seq:
|
360
|
+
* store.add_path(path) -> self
|
361
|
+
*
|
362
|
+
* Adds +path+ as the hash dir to be looked up by the store.
|
363
|
+
*/
|
256
364
|
static VALUE
|
257
365
|
ossl_x509store_add_path(VALUE self, VALUE dir)
|
258
366
|
{
|
@@ -261,8 +369,8 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
|
|
261
369
|
char *path = NULL;
|
262
370
|
|
263
371
|
if(dir != Qnil){
|
264
|
-
|
265
|
-
path =
|
372
|
+
rb_check_safe_obj(dir);
|
373
|
+
path = StringValueCStr(dir);
|
266
374
|
}
|
267
375
|
GetX509Store(self, store);
|
268
376
|
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
|
@@ -278,11 +386,12 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
|
|
278
386
|
* call-seq:
|
279
387
|
* store.set_default_paths
|
280
388
|
*
|
281
|
-
*
|
282
|
-
*
|
389
|
+
* Configures +store+ to look up CA certificates from the system default
|
390
|
+
* certificate store as needed basis. The location of the store can usually be
|
283
391
|
* determined by:
|
284
392
|
*
|
285
|
-
*
|
393
|
+
* * OpenSSL::X509::DEFAULT_CERT_FILE
|
394
|
+
* * OpenSSL::X509::DEFAULT_CERT_DIR
|
286
395
|
*/
|
287
396
|
static VALUE
|
288
397
|
ossl_x509store_set_default_paths(VALUE self)
|
@@ -303,7 +412,6 @@ ossl_x509store_set_default_paths(VALUE self)
|
|
303
412
|
*
|
304
413
|
* Adds the OpenSSL::X509::Certificate +cert+ to the certificate store.
|
305
414
|
*/
|
306
|
-
|
307
415
|
static VALUE
|
308
416
|
ossl_x509store_add_cert(VALUE self, VALUE arg)
|
309
417
|
{
|
@@ -319,6 +427,12 @@ ossl_x509store_add_cert(VALUE self, VALUE arg)
|
|
319
427
|
return self;
|
320
428
|
}
|
321
429
|
|
430
|
+
/*
|
431
|
+
* call-seq:
|
432
|
+
* store.add_crl(crl) -> self
|
433
|
+
*
|
434
|
+
* Adds the OpenSSL::X509::CRL +crl+ to the store.
|
435
|
+
*/
|
322
436
|
static VALUE
|
323
437
|
ossl_x509store_add_crl(VALUE self, VALUE arg)
|
324
438
|
{
|
@@ -338,6 +452,21 @@ static VALUE ossl_x509stctx_get_err(VALUE);
|
|
338
452
|
static VALUE ossl_x509stctx_get_err_string(VALUE);
|
339
453
|
static VALUE ossl_x509stctx_get_chain(VALUE);
|
340
454
|
|
455
|
+
/*
|
456
|
+
* call-seq:
|
457
|
+
* store.verify(cert, chain = nil) -> true | false
|
458
|
+
*
|
459
|
+
* Performs a certificate verification on the OpenSSL::X509::Certificate +cert+.
|
460
|
+
*
|
461
|
+
* +chain+ can be an array of OpenSSL::X509::Certificate that is used to
|
462
|
+
* construct the certificate chain.
|
463
|
+
*
|
464
|
+
* If a block is given, it overrides the callback set by #verify_callback=.
|
465
|
+
*
|
466
|
+
* After finishing the verification, the error information can be retrieved by
|
467
|
+
* #error, #error_string, and the resuting complete certificate chain can be
|
468
|
+
* retrieved by #chain.
|
469
|
+
*/
|
341
470
|
static VALUE
|
342
471
|
ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
|
343
472
|
{
|
@@ -372,27 +501,6 @@ static const rb_data_type_t ossl_x509stctx_type = {
|
|
372
501
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
373
502
|
};
|
374
503
|
|
375
|
-
|
376
|
-
VALUE
|
377
|
-
ossl_x509stctx_new(X509_STORE_CTX *ctx)
|
378
|
-
{
|
379
|
-
VALUE obj;
|
380
|
-
|
381
|
-
obj = NewX509StCtx(cX509StoreContext);
|
382
|
-
SetX509StCtx(obj, ctx);
|
383
|
-
|
384
|
-
return obj;
|
385
|
-
}
|
386
|
-
|
387
|
-
VALUE
|
388
|
-
ossl_x509stctx_clear_ptr(VALUE obj)
|
389
|
-
{
|
390
|
-
OSSL_Check_Kind(obj, cX509StoreContext);
|
391
|
-
RDATA(obj)->data = NULL;
|
392
|
-
|
393
|
-
return obj;
|
394
|
-
}
|
395
|
-
|
396
504
|
/*
|
397
505
|
* Private functions
|
398
506
|
*/
|
@@ -400,10 +508,10 @@ static void
|
|
400
508
|
ossl_x509stctx_free(void *ptr)
|
401
509
|
{
|
402
510
|
X509_STORE_CTX *ctx = ptr;
|
403
|
-
if(ctx
|
404
|
-
sk_X509_pop_free(ctx
|
405
|
-
if(ctx
|
406
|
-
X509_free(ctx
|
511
|
+
if (X509_STORE_CTX_get0_untrusted(ctx))
|
512
|
+
sk_X509_pop_free(X509_STORE_CTX_get0_untrusted(ctx), X509_free);
|
513
|
+
if (X509_STORE_CTX_get0_cert(ctx))
|
514
|
+
X509_free(X509_STORE_CTX_get0_cert(ctx));
|
407
515
|
X509_STORE_CTX_free(ctx);
|
408
516
|
}
|
409
517
|
|
@@ -422,11 +530,26 @@ ossl_x509stctx_alloc(VALUE klass)
|
|
422
530
|
return obj;
|
423
531
|
}
|
424
532
|
|
533
|
+
static VALUE
|
534
|
+
ossl_x509stctx_new(X509_STORE_CTX *ctx)
|
535
|
+
{
|
536
|
+
VALUE obj;
|
537
|
+
|
538
|
+
obj = NewX509StCtx(cX509StoreContext);
|
539
|
+
SetX509StCtx(obj, ctx);
|
540
|
+
|
541
|
+
return obj;
|
542
|
+
}
|
543
|
+
|
425
544
|
static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
|
426
545
|
static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
|
427
546
|
static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
|
428
547
|
static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
|
429
548
|
|
549
|
+
/*
|
550
|
+
* call-seq:
|
551
|
+
* StoreContext.new(store, cert = nil, chain = nil)
|
552
|
+
*/
|
430
553
|
static VALUE
|
431
554
|
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
|
432
555
|
{
|
@@ -441,17 +564,10 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
|
|
441
564
|
SafeGetX509Store(store, x509st);
|
442
565
|
if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
|
443
566
|
if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
|
444
|
-
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
|
445
567
|
if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
|
446
568
|
sk_X509_pop_free(x509s, X509_free);
|
447
569
|
ossl_raise(eX509StoreError, NULL);
|
448
570
|
}
|
449
|
-
#else
|
450
|
-
X509_STORE_CTX_init(ctx, x509st, x509, x509s);
|
451
|
-
ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
|
452
|
-
ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
|
453
|
-
ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
|
454
|
-
#endif
|
455
571
|
if (!NIL_P(t = rb_iv_get(store, "@time")))
|
456
572
|
ossl_x509stctx_set_time(self, t);
|
457
573
|
rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
|
@@ -460,20 +576,34 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
|
|
460
576
|
return self;
|
461
577
|
}
|
462
578
|
|
579
|
+
/*
|
580
|
+
* call-seq:
|
581
|
+
* stctx.verify -> true | false
|
582
|
+
*/
|
463
583
|
static VALUE
|
464
584
|
ossl_x509stctx_verify(VALUE self)
|
465
585
|
{
|
466
586
|
X509_STORE_CTX *ctx;
|
467
|
-
int result;
|
468
587
|
|
469
588
|
GetX509StCtx(self, ctx);
|
470
|
-
X509_STORE_CTX_set_ex_data(ctx,
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
589
|
+
X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx,
|
590
|
+
(void *)rb_iv_get(self, "@verify_callback"));
|
591
|
+
|
592
|
+
switch (X509_verify_cert(ctx)) {
|
593
|
+
case 1:
|
594
|
+
return Qtrue;
|
595
|
+
case 0:
|
596
|
+
ossl_clear_error();
|
597
|
+
return Qfalse;
|
598
|
+
default:
|
599
|
+
ossl_raise(eX509CertError, NULL);
|
600
|
+
}
|
475
601
|
}
|
476
602
|
|
603
|
+
/*
|
604
|
+
* call-seq:
|
605
|
+
* stctx.chain -> Array of X509::Certificate
|
606
|
+
*/
|
477
607
|
static VALUE
|
478
608
|
ossl_x509stctx_get_chain(VALUE self)
|
479
609
|
{
|
@@ -484,7 +614,7 @@ ossl_x509stctx_get_chain(VALUE self)
|
|
484
614
|
VALUE ary;
|
485
615
|
|
486
616
|
GetX509StCtx(self, ctx);
|
487
|
-
if((chain =
|
617
|
+
if((chain = X509_STORE_CTX_get0_chain(ctx)) == NULL){
|
488
618
|
return Qnil;
|
489
619
|
}
|
490
620
|
if((num = sk_X509_num(chain)) < 0){
|
@@ -500,6 +630,10 @@ ossl_x509stctx_get_chain(VALUE self)
|
|
500
630
|
return ary;
|
501
631
|
}
|
502
632
|
|
633
|
+
/*
|
634
|
+
* call-seq:
|
635
|
+
* stctx.error -> Integer
|
636
|
+
*/
|
503
637
|
static VALUE
|
504
638
|
ossl_x509stctx_get_err(VALUE self)
|
505
639
|
{
|
@@ -507,9 +641,13 @@ ossl_x509stctx_get_err(VALUE self)
|
|
507
641
|
|
508
642
|
GetX509StCtx(self, ctx);
|
509
643
|
|
510
|
-
return
|
644
|
+
return INT2NUM(X509_STORE_CTX_get_error(ctx));
|
511
645
|
}
|
512
646
|
|
647
|
+
/*
|
648
|
+
* call-seq:
|
649
|
+
* stctx.error = error_code
|
650
|
+
*/
|
513
651
|
static VALUE
|
514
652
|
ossl_x509stctx_set_error(VALUE self, VALUE err)
|
515
653
|
{
|
@@ -521,6 +659,12 @@ ossl_x509stctx_set_error(VALUE self, VALUE err)
|
|
521
659
|
return err;
|
522
660
|
}
|
523
661
|
|
662
|
+
/*
|
663
|
+
* call-seq:
|
664
|
+
* stctx.error_string -> String
|
665
|
+
*
|
666
|
+
* Returns the error string corresponding to the error code retrieved by #error.
|
667
|
+
*/
|
524
668
|
static VALUE
|
525
669
|
ossl_x509stctx_get_err_string(VALUE self)
|
526
670
|
{
|
@@ -533,6 +677,10 @@ ossl_x509stctx_get_err_string(VALUE self)
|
|
533
677
|
return rb_str_new2(X509_verify_cert_error_string(err));
|
534
678
|
}
|
535
679
|
|
680
|
+
/*
|
681
|
+
* call-seq:
|
682
|
+
* stctx.error_depth -> Integer
|
683
|
+
*/
|
536
684
|
static VALUE
|
537
685
|
ossl_x509stctx_get_err_depth(VALUE self)
|
538
686
|
{
|
@@ -540,9 +688,13 @@ ossl_x509stctx_get_err_depth(VALUE self)
|
|
540
688
|
|
541
689
|
GetX509StCtx(self, ctx);
|
542
690
|
|
543
|
-
return
|
691
|
+
return INT2NUM(X509_STORE_CTX_get_error_depth(ctx));
|
544
692
|
}
|
545
693
|
|
694
|
+
/*
|
695
|
+
* call-seq:
|
696
|
+
* stctx.current_cert -> X509::Certificate
|
697
|
+
*/
|
546
698
|
static VALUE
|
547
699
|
ossl_x509stctx_get_curr_cert(VALUE self)
|
548
700
|
{
|
@@ -553,21 +705,30 @@ ossl_x509stctx_get_curr_cert(VALUE self)
|
|
553
705
|
return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
|
554
706
|
}
|
555
707
|
|
708
|
+
/*
|
709
|
+
* call-seq:
|
710
|
+
* stctx.current_crl -> X509::CRL
|
711
|
+
*/
|
556
712
|
static VALUE
|
557
713
|
ossl_x509stctx_get_curr_crl(VALUE self)
|
558
714
|
{
|
559
|
-
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
|
560
715
|
X509_STORE_CTX *ctx;
|
716
|
+
X509_CRL *crl;
|
561
717
|
|
562
718
|
GetX509StCtx(self, ctx);
|
563
|
-
|
719
|
+
crl = X509_STORE_CTX_get0_current_crl(ctx);
|
720
|
+
if (!crl)
|
721
|
+
return Qnil;
|
564
722
|
|
565
|
-
return ossl_x509crl_new(
|
566
|
-
#else
|
567
|
-
return Qnil;
|
568
|
-
#endif
|
723
|
+
return ossl_x509crl_new(crl);
|
569
724
|
}
|
570
725
|
|
726
|
+
/*
|
727
|
+
* call-seq:
|
728
|
+
* stctx.flags = flags
|
729
|
+
*
|
730
|
+
* Sets the verification flags to the context. See Store#flags=.
|
731
|
+
*/
|
571
732
|
static VALUE
|
572
733
|
ossl_x509stctx_set_flags(VALUE self, VALUE flags)
|
573
734
|
{
|
@@ -580,6 +741,12 @@ ossl_x509stctx_set_flags(VALUE self, VALUE flags)
|
|
580
741
|
return flags;
|
581
742
|
}
|
582
743
|
|
744
|
+
/*
|
745
|
+
* call-seq:
|
746
|
+
* stctx.purpose = purpose
|
747
|
+
*
|
748
|
+
* Sets the purpose of the context. See Store#purpose=.
|
749
|
+
*/
|
583
750
|
static VALUE
|
584
751
|
ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
|
585
752
|
{
|
@@ -592,6 +759,10 @@ ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
|
|
592
759
|
return purpose;
|
593
760
|
}
|
594
761
|
|
762
|
+
/*
|
763
|
+
* call-seq:
|
764
|
+
* stctx.trust = trust
|
765
|
+
*/
|
595
766
|
static VALUE
|
596
767
|
ossl_x509stctx_set_trust(VALUE self, VALUE trust)
|
597
768
|
{
|
@@ -606,7 +777,9 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust)
|
|
606
777
|
|
607
778
|
/*
|
608
779
|
* call-seq:
|
609
|
-
*
|
780
|
+
* stctx.time = time
|
781
|
+
*
|
782
|
+
* Sets the time used in the verification. If not set, the current time is used.
|
610
783
|
*/
|
611
784
|
static VALUE
|
612
785
|
ossl_x509stctx_set_time(VALUE self, VALUE time)
|
@@ -627,13 +800,21 @@ ossl_x509stctx_set_time(VALUE self, VALUE time)
|
|
627
800
|
void
|
628
801
|
Init_ossl_x509store(void)
|
629
802
|
{
|
630
|
-
|
631
|
-
|
803
|
+
#undef rb_intern
|
632
804
|
#if 0
|
633
|
-
mOSSL = rb_define_module("OpenSSL");
|
805
|
+
mOSSL = rb_define_module("OpenSSL");
|
806
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
634
807
|
mX509 = rb_define_module_under(mOSSL, "X509");
|
635
808
|
#endif
|
636
809
|
|
810
|
+
/* Register ext_data slot for verify callback Proc */
|
811
|
+
stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
|
812
|
+
if (stctx_ex_verify_cb_idx < 0)
|
813
|
+
ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
|
814
|
+
store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
|
815
|
+
if (store_ex_verify_cb_idx < 0)
|
816
|
+
ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
|
817
|
+
|
637
818
|
eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
|
638
819
|
|
639
820
|
/* Document-class: OpenSSL::X509::Store
|
@@ -648,11 +829,11 @@ Init_ossl_x509store(void)
|
|
648
829
|
*
|
649
830
|
* This will use your system's built-in certificates.
|
650
831
|
*
|
651
|
-
* If your system does not have a default set of certificates you can
|
652
|
-
*
|
653
|
-
*
|
654
|
-
*
|
655
|
-
*
|
832
|
+
* If your system does not have a default set of certificates you can obtain
|
833
|
+
* a set extracted from Mozilla CA certificate store by cURL maintainers
|
834
|
+
* here: https://curl.haxx.se/docs/caextract.html (You may wish to use the
|
835
|
+
* firefox-db2pem.sh script to extract the certificates from a local install
|
836
|
+
* to avoid man-in-the-middle attacks.)
|
656
837
|
*
|
657
838
|
* After downloading or generating a cacert.pem from the above link you
|
658
839
|
* can create a certificate store from the pem file like this:
|
@@ -663,6 +844,7 @@ Init_ossl_x509store(void)
|
|
663
844
|
* The certificate store can be used with an SSLSocket like this:
|
664
845
|
*
|
665
846
|
* ssl_context = OpenSSL::SSL::SSLContext.new
|
847
|
+
* ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
666
848
|
* ssl_context.cert_store = cert_store
|
667
849
|
*
|
668
850
|
* tcp_socket = TCPSocket.open 'example.com', 443
|
@@ -671,12 +853,30 @@ Init_ossl_x509store(void)
|
|
671
853
|
*/
|
672
854
|
|
673
855
|
cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
|
856
|
+
/*
|
857
|
+
* The callback for additional certificate verification. It is invoked for
|
858
|
+
* each untrusted certificate in the chain.
|
859
|
+
*
|
860
|
+
* The callback is invoked with two values, a boolean that indicates if the
|
861
|
+
* pre-verification by OpenSSL has succeeded or not, and the StoreContext in
|
862
|
+
* use. The callback must return either true or false.
|
863
|
+
*/
|
674
864
|
rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
|
865
|
+
/*
|
866
|
+
* The error code set by the last call of #verify.
|
867
|
+
*/
|
675
868
|
rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
|
869
|
+
/*
|
870
|
+
* The description for the error code set by the last call of #verify.
|
871
|
+
*/
|
676
872
|
rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
|
873
|
+
/*
|
874
|
+
* The certificate chain constructed by the last call of #verify.
|
875
|
+
*/
|
677
876
|
rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
|
678
877
|
rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
|
679
878
|
rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
|
879
|
+
rb_undef_method(cX509Store, "initialize_copy");
|
680
880
|
rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
|
681
881
|
rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
|
682
882
|
rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
|
@@ -689,21 +889,26 @@ Init_ossl_x509store(void)
|
|
689
889
|
rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
|
690
890
|
rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
|
691
891
|
|
692
|
-
|
693
|
-
|
892
|
+
/*
|
893
|
+
* Document-class: OpenSSL::X509::StoreContext
|
894
|
+
*
|
895
|
+
* A StoreContext is used while validating a single certificate and holds
|
896
|
+
* the status involved.
|
897
|
+
*/
|
898
|
+
cX509StoreContext = rb_define_class_under(mX509,"StoreContext", rb_cObject);
|
694
899
|
rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
|
695
|
-
rb_define_method(
|
696
|
-
|
697
|
-
rb_define_method(
|
698
|
-
rb_define_method(
|
699
|
-
rb_define_method(
|
700
|
-
rb_define_method(
|
701
|
-
rb_define_method(
|
702
|
-
rb_define_method(
|
703
|
-
rb_define_method(
|
704
|
-
rb_define_method(
|
705
|
-
rb_define_method(
|
706
|
-
rb_define_method(
|
707
|
-
rb_define_method(
|
708
|
-
|
900
|
+
rb_define_method(cX509StoreContext, "initialize", ossl_x509stctx_initialize, -1);
|
901
|
+
rb_undef_method(cX509StoreContext, "initialize_copy");
|
902
|
+
rb_define_method(cX509StoreContext, "verify", ossl_x509stctx_verify, 0);
|
903
|
+
rb_define_method(cX509StoreContext, "chain", ossl_x509stctx_get_chain,0);
|
904
|
+
rb_define_method(cX509StoreContext, "error", ossl_x509stctx_get_err, 0);
|
905
|
+
rb_define_method(cX509StoreContext, "error=", ossl_x509stctx_set_error, 1);
|
906
|
+
rb_define_method(cX509StoreContext, "error_string", ossl_x509stctx_get_err_string,0);
|
907
|
+
rb_define_method(cX509StoreContext, "error_depth", ossl_x509stctx_get_err_depth, 0);
|
908
|
+
rb_define_method(cX509StoreContext, "current_cert", ossl_x509stctx_get_curr_cert, 0);
|
909
|
+
rb_define_method(cX509StoreContext, "current_crl", ossl_x509stctx_get_curr_crl, 0);
|
910
|
+
rb_define_method(cX509StoreContext, "flags=", ossl_x509stctx_set_flags, 1);
|
911
|
+
rb_define_method(cX509StoreContext, "purpose=", ossl_x509stctx_set_purpose, 1);
|
912
|
+
rb_define_method(cX509StoreContext, "trust=", ossl_x509stctx_set_trust, 1);
|
913
|
+
rb_define_method(cX509StoreContext, "time=", ossl_x509stctx_set_time, 1);
|
709
914
|
}
|