openssl-custom 2.2.2

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