rubysl-openssl 2.10 → 2.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/ext/rubysl/openssl/deprecation.rb +7 -3
  3. data/ext/rubysl/openssl/extconf.rb +148 -103
  4. data/ext/rubysl/openssl/openssl_missing.c +94 -275
  5. data/ext/rubysl/openssl/openssl_missing.h +167 -98
  6. data/ext/rubysl/openssl/ossl.c +266 -212
  7. data/ext/rubysl/openssl/ossl.h +27 -89
  8. data/ext/rubysl/openssl/ossl_asn1.c +157 -221
  9. data/ext/rubysl/openssl/ossl_asn1.h +11 -3
  10. data/ext/rubysl/openssl/ossl_bio.c +10 -40
  11. data/ext/rubysl/openssl/ossl_bio.h +1 -2
  12. data/ext/rubysl/openssl/ossl_bn.c +144 -100
  13. data/ext/rubysl/openssl/ossl_bn.h +3 -1
  14. data/ext/rubysl/openssl/ossl_cipher.c +270 -195
  15. data/ext/rubysl/openssl/ossl_config.c +7 -1
  16. data/ext/rubysl/openssl/ossl_config.h +0 -1
  17. data/ext/rubysl/openssl/ossl_digest.c +40 -29
  18. data/ext/rubysl/openssl/ossl_engine.c +23 -62
  19. data/ext/rubysl/openssl/ossl_hmac.c +82 -55
  20. data/ext/rubysl/openssl/ossl_ns_spki.c +22 -22
  21. data/ext/rubysl/openssl/ossl_ocsp.c +894 -144
  22. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  23. data/ext/rubysl/openssl/ossl_pkcs12.c +47 -19
  24. data/ext/rubysl/openssl/ossl_pkcs5.c +7 -15
  25. data/ext/rubysl/openssl/ossl_pkcs7.c +38 -15
  26. data/ext/rubysl/openssl/ossl_pkey.c +151 -99
  27. data/ext/rubysl/openssl/ossl_pkey.h +123 -29
  28. data/ext/rubysl/openssl/ossl_pkey_dh.c +143 -92
  29. data/ext/rubysl/openssl/ossl_pkey_dsa.c +149 -104
  30. data/ext/rubysl/openssl/ossl_pkey_ec.c +646 -524
  31. data/ext/rubysl/openssl/ossl_pkey_rsa.c +180 -121
  32. data/ext/rubysl/openssl/ossl_rand.c +25 -21
  33. data/ext/rubysl/openssl/ossl_ssl.c +795 -413
  34. data/ext/rubysl/openssl/ossl_ssl.h +3 -0
  35. data/ext/rubysl/openssl/ossl_ssl_session.c +83 -77
  36. data/ext/rubysl/openssl/ossl_version.h +1 -1
  37. data/ext/rubysl/openssl/ossl_x509.c +92 -8
  38. data/ext/rubysl/openssl/ossl_x509.h +14 -5
  39. data/ext/rubysl/openssl/ossl_x509attr.c +77 -41
  40. data/ext/rubysl/openssl/ossl_x509cert.c +45 -46
  41. data/ext/rubysl/openssl/ossl_x509crl.c +51 -57
  42. data/ext/rubysl/openssl/ossl_x509ext.c +39 -33
  43. data/ext/rubysl/openssl/ossl_x509name.c +68 -45
  44. data/ext/rubysl/openssl/ossl_x509req.c +32 -38
  45. data/ext/rubysl/openssl/ossl_x509revoked.c +43 -9
  46. data/ext/rubysl/openssl/ossl_x509store.c +309 -104
  47. data/ext/rubysl/openssl/ruby_missing.h +8 -6
  48. data/lib/openssl/buffering.rb +11 -5
  49. data/lib/openssl/cipher.rb +23 -15
  50. data/lib/openssl/digest.rb +7 -10
  51. data/lib/openssl/pkey.rb +15 -8
  52. data/lib/openssl/ssl.rb +81 -105
  53. data/lib/rubysl/openssl.rb +1 -4
  54. data/lib/rubysl/openssl/version.rb +1 -1
  55. 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->serialNumber);
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
- rev->serialNumber = num_to_asn1integer(num, rev->serialNumber);
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->revocationDate);
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
- time_t sec;
172
+ ASN1_TIME *asn1time;
148
173
 
149
- sec = time_to_time_t(time);
150
174
  GetX509Rev(self, rev);
151
- if (!X509_time_adj(rev->revocationDate, 0, &sec)) {
152
- ossl_raise(eX509RevError, NULL);
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
- sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free);
200
- rev->extensions = NULL;
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
- CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
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, ossl_verify_cb_idx, (void*)cb);
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) -> store
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
- SafeStringValue(file);
244
- path = RSTRING_PTR(file);
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
- SafeStringValue(dir);
265
- path = RSTRING_PTR(dir);
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
- * Adds the default certificates to the certificate store. These certificates
282
- * are loaded from the default configuration directory which can usually be
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
- * File.dirname OpenSSL::Config::DEFAULT_CONFIG_FILE
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->untrusted)
404
- sk_X509_pop_free(ctx->untrusted, X509_free);
405
- if(ctx->cert)
406
- X509_free(ctx->cert);
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, ossl_verify_cb_idx,
471
- (void*)rb_iv_get(self, "@verify_callback"));
472
- result = X509_verify_cert(ctx);
473
-
474
- return result ? Qtrue : Qfalse;
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 = X509_STORE_CTX_get_chain(ctx)) == NULL){
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 INT2FIX(X509_STORE_CTX_get_error(ctx));
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 INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
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
- if(!ctx->current_crl) return Qnil;
719
+ crl = X509_STORE_CTX_get0_current_crl(ctx);
720
+ if (!crl)
721
+ return Qnil;
564
722
 
565
- return ossl_x509crl_new(ctx->current_crl);
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
- * storectx.time = time => time
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
- VALUE x509stctx;
631
-
803
+ #undef rb_intern
632
804
  #if 0
633
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
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
- * obtain a set from Mozilla here: http://curl.haxx.se/docs/caextract.html
653
- * (Note that this set does not have an HTTPS download option so you may
654
- * wish to use the firefox-db2pem.sh script to extract the certificates
655
- * from a local install to avoid man-in-the-middle attacks.)
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
- cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject);
693
- x509stctx = cX509StoreContext;
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(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
696
- rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
697
- rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
698
- rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
699
- rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
700
- rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
701
- rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
702
- rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
703
- rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
704
- rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
705
- rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
706
- rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
707
- rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
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
  }