Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
ossl_x509store.c
Go to the documentation of this file.
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 
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) {
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) {
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  */
107 
108 static void
109 ossl_x509store_free(void *ptr)
110 {
111  X509_STORE_free(ptr);
112 }
113 
114 static const rb_data_type_t ossl_x509store_type = {
115  "OpenSSL/X509/STORE",
116  {
117  0, ossl_x509store_free,
118  },
120 };
121 
122 /*
123  * Public functions
124  */
125 X509_STORE *
127 {
128  X509_STORE *store;
129 
130  GetX509Store(obj, store);
131 
132  return store;
133 }
134 
135 /*
136  * Private functions
137  */
138 static int
139 x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
140 {
141  VALUE proc;
142 
143  proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
144  if (!proc)
146  store_ex_verify_cb_idx);
147  if (!proc)
148  return ok;
149 
150  return ossl_verify_cb_call(proc, ok, ctx);
151 }
152 
153 static VALUE
154 ossl_x509store_alloc(VALUE klass)
155 {
156  X509_STORE *store;
157  VALUE obj;
158 
160  if((store = X509_STORE_new()) == NULL){
162  }
163  SetX509Store(obj, store);
164 
165  return obj;
166 }
167 
168 /*
169  * General callback for OpenSSL verify
170  */
171 static VALUE
172 ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
173 {
174  X509_STORE *store;
175 
176  GetX509Store(self, store);
177  X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
178  rb_iv_set(self, "@verify_callback", cb);
179 
180  return cb;
181 }
182 
183 
184 /*
185  * call-seq:
186  * X509::Store.new => store
187  *
188  * Creates a new X509::Store.
189  */
190 static VALUE
191 ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
192 {
193  X509_STORE *store;
194 
195 /* BUG: This method takes any number of arguments but appears to ignore them. */
196  GetX509Store(self, store);
197 #if !defined(HAVE_OPAQUE_OPENSSL)
198  /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */
199  store->ex_data.sk = NULL;
200 #endif
201  X509_STORE_set_verify_cb(store, x509store_verify_cb);
202  ossl_x509store_set_vfy_cb(self, Qnil);
203 
204  /* last verification status */
205  rb_iv_set(self, "@error", Qnil);
206  rb_iv_set(self, "@error_string", Qnil);
207  rb_iv_set(self, "@chain", Qnil);
208  rb_iv_set(self, "@time", Qnil);
209 
210  return self;
211 }
212 
213 /*
214  * call-seq:
215  * store.flags = flags
216  *
217  * Sets _flags_ to the Store. _flags_ consists of zero or more of the constants
218  * defined in with name V_FLAG_* or'ed together.
219  */
220 static VALUE
221 ossl_x509store_set_flags(VALUE self, VALUE flags)
222 {
223  X509_STORE *store;
224  long f = NUM2LONG(flags);
225 
226  GetX509Store(self, store);
227  X509_STORE_set_flags(store, f);
228 
229  return flags;
230 }
231 
232 /*
233  * call-seq:
234  * store.purpose = purpose
235  *
236  * Sets the store's purpose to _purpose_. If specified, the verifications on
237  * the store will check every untrusted certificate's extensions are consistent
238  * with the purpose. The purpose is specified by constants:
239  *
240  * * X509::PURPOSE_SSL_CLIENT
241  * * X509::PURPOSE_SSL_SERVER
242  * * X509::PURPOSE_NS_SSL_SERVER
243  * * X509::PURPOSE_SMIME_SIGN
244  * * X509::PURPOSE_SMIME_ENCRYPT
245  * * X509::PURPOSE_CRL_SIGN
246  * * X509::PURPOSE_ANY
247  * * X509::PURPOSE_OCSP_HELPER
248  * * X509::PURPOSE_TIMESTAMP_SIGN
249  */
250 static VALUE
251 ossl_x509store_set_purpose(VALUE self, VALUE purpose)
252 {
253  X509_STORE *store;
254  int p = NUM2INT(purpose);
255 
256  GetX509Store(self, store);
257  X509_STORE_set_purpose(store, p);
258 
259  return purpose;
260 }
261 
262 /*
263  * call-seq:
264  * store.trust = trust
265  */
266 static VALUE
267 ossl_x509store_set_trust(VALUE self, VALUE trust)
268 {
269  X509_STORE *store;
270  int t = NUM2INT(trust);
271 
272  GetX509Store(self, store);
273  X509_STORE_set_trust(store, t);
274 
275  return trust;
276 }
277 
278 /*
279  * call-seq:
280  * store.time = time
281  *
282  * Sets the time to be used in verifications.
283  */
284 static VALUE
285 ossl_x509store_set_time(VALUE self, VALUE time)
286 {
287  rb_iv_set(self, "@time", time);
288  return time;
289 }
290 
291 /*
292  * call-seq:
293  * store.add_file(file) -> self
294  *
295  * Adds the certificates in _file_ to the certificate store. _file_ is the path
296  * to the file, and the file contains one or more certificates in PEM format
297  * concatenated together.
298  */
299 static VALUE
300 ossl_x509store_add_file(VALUE self, VALUE file)
301 {
302  X509_STORE *store;
303  X509_LOOKUP *lookup;
304  char *path = NULL;
305 
306  if(file != Qnil){
307  path = StringValueCStr(file);
308  }
309  GetX509Store(self, store);
310  lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
311  if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
312  if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
314  }
315 #if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
316  /*
317  * X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file()
318  * did not check the return value of X509_STORE_add_{cert,crl}(), leaking
319  * "cert already in hash table" errors on the error queue, if duplicate
320  * certificates are found. This will be fixed by OpenSSL 1.1.1.
321  */
323 #endif
324 
325  return self;
326 }
327 
328 /*
329  * call-seq:
330  * store.add_path(path) -> self
331  *
332  * Adds _path_ as the hash dir to be looked up by the store.
333  */
334 static VALUE
335 ossl_x509store_add_path(VALUE self, VALUE dir)
336 {
337  X509_STORE *store;
338  X509_LOOKUP *lookup;
339  char *path = NULL;
340 
341  if(dir != Qnil){
342  path = StringValueCStr(dir);
343  }
344  GetX509Store(self, store);
345  lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
346  if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
347  if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
349  }
350 
351  return self;
352 }
353 
354 /*
355  * call-seq:
356  * store.set_default_paths
357  *
358  * Configures _store_ to look up CA certificates from the system default
359  * certificate store as needed basis. The location of the store can usually be
360  * determined by:
361  *
362  * * OpenSSL::X509::DEFAULT_CERT_FILE
363  * * OpenSSL::X509::DEFAULT_CERT_DIR
364  */
365 static VALUE
366 ossl_x509store_set_default_paths(VALUE self)
367 {
368  X509_STORE *store;
369 
370  GetX509Store(self, store);
371  if (X509_STORE_set_default_paths(store) != 1){
373  }
374 
375  return Qnil;
376 }
377 
378 /*
379  * call-seq:
380  * store.add_cert(cert)
381  *
382  * Adds the OpenSSL::X509::Certificate _cert_ to the certificate store.
383  */
384 static VALUE
385 ossl_x509store_add_cert(VALUE self, VALUE arg)
386 {
387  X509_STORE *store;
388  X509 *cert;
389 
390  cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
391  GetX509Store(self, store);
392  if (X509_STORE_add_cert(store, cert) != 1){
394  }
395 
396  return self;
397 }
398 
399 /*
400  * call-seq:
401  * store.add_crl(crl) -> self
402  *
403  * Adds the OpenSSL::X509::CRL _crl_ to the store.
404  */
405 static VALUE
406 ossl_x509store_add_crl(VALUE self, VALUE arg)
407 {
408  X509_STORE *store;
409  X509_CRL *crl;
410 
411  crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
412  GetX509Store(self, store);
413  if (X509_STORE_add_crl(store, crl) != 1){
415  }
416 
417  return self;
418 }
419 
420 static VALUE ossl_x509stctx_get_err(VALUE);
421 static VALUE ossl_x509stctx_get_err_string(VALUE);
422 static VALUE ossl_x509stctx_get_chain(VALUE);
423 
424 /*
425  * call-seq:
426  * store.verify(cert, chain = nil) -> true | false
427  *
428  * Performs a certificate verification on the OpenSSL::X509::Certificate _cert_.
429  *
430  * _chain_ can be an array of OpenSSL::X509::Certificate that is used to
431  * construct the certificate chain.
432  *
433  * If a block is given, it overrides the callback set by #verify_callback=.
434  *
435  * After finishing the verification, the error information can be retrieved by
436  * #error, #error_string, and the resulting complete certificate chain can be
437  * retrieved by #chain.
438  */
439 static VALUE
440 ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
441 {
442  VALUE cert, chain;
443  VALUE ctx, proc, result;
444 
445  rb_scan_args(argc, argv, "11", &cert, &chain);
446  ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
448  rb_iv_get(self, "@verify_callback");
449  rb_iv_set(ctx, "@verify_callback", proc);
450  result = rb_funcall(ctx, rb_intern("verify"), 0);
451 
452  rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
453  rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
454  rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
455 
456  return result;
457 }
458 
459 /*
460  * Public Functions
461  */
462 static void ossl_x509stctx_free(void*);
463 
464 
465 static const rb_data_type_t ossl_x509stctx_type = {
466  "OpenSSL/X509/STORE_CTX",
467  {
468  0, ossl_x509stctx_free,
469  },
471 };
472 
473 /*
474  * Private functions
475  */
476 static void
477 ossl_x509stctx_free(void *ptr)
478 {
479  X509_STORE_CTX *ctx = ptr;
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 VALUE
488 ossl_x509stctx_alloc(VALUE klass)
489 {
490  X509_STORE_CTX *ctx;
491  VALUE obj;
492 
494  if((ctx = X509_STORE_CTX_new()) == NULL){
496  }
497  SetX509StCtx(obj, ctx);
498 
499  return obj;
500 }
501 
502 static VALUE
503 ossl_x509stctx_new(X509_STORE_CTX *ctx)
504 {
505  VALUE obj;
506 
508  SetX509StCtx(obj, ctx);
509 
510  return obj;
511 }
512 
513 static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
514 static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
515 static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
516 static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
517 
518 /*
519  * call-seq:
520  * StoreContext.new(store, cert = nil, chain = nil)
521  */
522 static VALUE
523 ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
524 {
525  VALUE store, cert, chain, t;
526  X509_STORE_CTX *ctx;
527  X509_STORE *x509st;
528  X509 *x509 = NULL;
529  STACK_OF(X509) *x509s = NULL;
530 
531  rb_scan_args(argc, argv, "12", &store, &cert, &chain);
532  GetX509StCtx(self, ctx);
533  GetX509Store(store, x509st);
534  if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
535  if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
536  if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
537  sk_X509_pop_free(x509s, X509_free);
539  }
540  if (!NIL_P(t = rb_iv_get(store, "@time")))
541  ossl_x509stctx_set_time(self, t);
542  rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
543  rb_iv_set(self, "@cert", cert);
544 
545  return self;
546 }
547 
548 /*
549  * call-seq:
550  * stctx.verify -> true | false
551  */
552 static VALUE
553 ossl_x509stctx_verify(VALUE self)
554 {
555  X509_STORE_CTX *ctx;
556 
557  GetX509StCtx(self, ctx);
558  X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx,
559  (void *)rb_iv_get(self, "@verify_callback"));
560 
561  switch (X509_verify_cert(ctx)) {
562  case 1:
563  return Qtrue;
564  case 0:
566  return Qfalse;
567  default:
569  }
570 }
571 
572 /*
573  * call-seq:
574  * stctx.chain -> Array of X509::Certificate
575  */
576 static VALUE
577 ossl_x509stctx_get_chain(VALUE self)
578 {
579  X509_STORE_CTX *ctx;
580  STACK_OF(X509) *chain;
581  X509 *x509;
582  int i, num;
583  VALUE ary;
584 
585  GetX509StCtx(self, ctx);
586  if((chain = X509_STORE_CTX_get0_chain(ctx)) == NULL){
587  return Qnil;
588  }
589  if((num = sk_X509_num(chain)) < 0){
590  OSSL_Debug("certs in chain < 0???");
591  return rb_ary_new();
592  }
593  ary = rb_ary_new2(num);
594  for(i = 0; i < num; i++) {
595  x509 = sk_X509_value(chain, i);
596  rb_ary_push(ary, ossl_x509_new(x509));
597  }
598 
599  return ary;
600 }
601 
602 /*
603  * call-seq:
604  * stctx.error -> Integer
605  */
606 static VALUE
607 ossl_x509stctx_get_err(VALUE self)
608 {
609  X509_STORE_CTX *ctx;
610 
611  GetX509StCtx(self, ctx);
612 
613  return INT2NUM(X509_STORE_CTX_get_error(ctx));
614 }
615 
616 /*
617  * call-seq:
618  * stctx.error = error_code
619  */
620 static VALUE
621 ossl_x509stctx_set_error(VALUE self, VALUE err)
622 {
623  X509_STORE_CTX *ctx;
624 
625  GetX509StCtx(self, ctx);
626  X509_STORE_CTX_set_error(ctx, NUM2INT(err));
627 
628  return err;
629 }
630 
631 /*
632  * call-seq:
633  * stctx.error_string -> String
634  *
635  * Returns the error string corresponding to the error code retrieved by #error.
636  */
637 static VALUE
638 ossl_x509stctx_get_err_string(VALUE self)
639 {
640  X509_STORE_CTX *ctx;
641  long err;
642 
643  GetX509StCtx(self, ctx);
644  err = X509_STORE_CTX_get_error(ctx);
645 
646  return rb_str_new2(X509_verify_cert_error_string(err));
647 }
648 
649 /*
650  * call-seq:
651  * stctx.error_depth -> Integer
652  */
653 static VALUE
654 ossl_x509stctx_get_err_depth(VALUE self)
655 {
656  X509_STORE_CTX *ctx;
657 
658  GetX509StCtx(self, ctx);
659 
660  return INT2NUM(X509_STORE_CTX_get_error_depth(ctx));
661 }
662 
663 /*
664  * call-seq:
665  * stctx.current_cert -> X509::Certificate
666  */
667 static VALUE
668 ossl_x509stctx_get_curr_cert(VALUE self)
669 {
670  X509_STORE_CTX *ctx;
671 
672  GetX509StCtx(self, ctx);
673 
674  return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
675 }
676 
677 /*
678  * call-seq:
679  * stctx.current_crl -> X509::CRL
680  */
681 static VALUE
682 ossl_x509stctx_get_curr_crl(VALUE self)
683 {
684  X509_STORE_CTX *ctx;
685  X509_CRL *crl;
686 
687  GetX509StCtx(self, ctx);
688  crl = X509_STORE_CTX_get0_current_crl(ctx);
689  if (!crl)
690  return Qnil;
691 
692  return ossl_x509crl_new(crl);
693 }
694 
695 /*
696  * call-seq:
697  * stctx.flags = flags
698  *
699  * Sets the verification flags to the context. See Store#flags=.
700  */
701 static VALUE
702 ossl_x509stctx_set_flags(VALUE self, VALUE flags)
703 {
704  X509_STORE_CTX *store;
705  long f = NUM2LONG(flags);
706 
707  GetX509StCtx(self, store);
708  X509_STORE_CTX_set_flags(store, f);
709 
710  return flags;
711 }
712 
713 /*
714  * call-seq:
715  * stctx.purpose = purpose
716  *
717  * Sets the purpose of the context. See Store#purpose=.
718  */
719 static VALUE
720 ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
721 {
722  X509_STORE_CTX *store;
723  int p = NUM2INT(purpose);
724 
725  GetX509StCtx(self, store);
726  X509_STORE_CTX_set_purpose(store, p);
727 
728  return purpose;
729 }
730 
731 /*
732  * call-seq:
733  * stctx.trust = trust
734  */
735 static VALUE
736 ossl_x509stctx_set_trust(VALUE self, VALUE trust)
737 {
738  X509_STORE_CTX *store;
739  int t = NUM2INT(trust);
740 
741  GetX509StCtx(self, store);
742  X509_STORE_CTX_set_trust(store, t);
743 
744  return trust;
745 }
746 
747 /*
748  * call-seq:
749  * stctx.time = time
750  *
751  * Sets the time used in the verification. If not set, the current time is used.
752  */
753 static VALUE
754 ossl_x509stctx_set_time(VALUE self, VALUE time)
755 {
756  X509_STORE_CTX *store;
757  long t;
758 
759  t = NUM2LONG(rb_Integer(time));
760  GetX509StCtx(self, store);
761  X509_STORE_CTX_set_time(store, 0, t);
762 
763  return time;
764 }
765 
766 /*
767  * INIT
768  */
769 void
771 {
772 #undef rb_intern
773 #if 0
774  mOSSL = rb_define_module("OpenSSL");
777 #endif
778 
779  /* Register ext_data slot for verify callback Proc */
780  stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
781  if (stctx_ex_verify_cb_idx < 0)
782  ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
783  store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
784  if (store_ex_verify_cb_idx < 0)
785  ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
786 
788 
789  /* Document-class: OpenSSL::X509::Store
790  *
791  * The X509 certificate store holds trusted CA certificates used to verify
792  * peer certificates.
793  *
794  * The easiest way to create a useful certificate store is:
795  *
796  * cert_store = OpenSSL::X509::Store.new
797  * cert_store.set_default_paths
798  *
799  * This will use your system's built-in certificates.
800  *
801  * If your system does not have a default set of certificates you can obtain
802  * a set extracted from Mozilla CA certificate store by cURL maintainers
803  * here: https://curl.haxx.se/docs/caextract.html (You may wish to use the
804  * firefox-db2pem.sh script to extract the certificates from a local install
805  * to avoid man-in-the-middle attacks.)
806  *
807  * After downloading or generating a cacert.pem from the above link you
808  * can create a certificate store from the pem file like this:
809  *
810  * cert_store = OpenSSL::X509::Store.new
811  * cert_store.add_file 'cacert.pem'
812  *
813  * The certificate store can be used with an SSLSocket like this:
814  *
815  * ssl_context = OpenSSL::SSL::SSLContext.new
816  * ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
817  * ssl_context.cert_store = cert_store
818  *
819  * tcp_socket = TCPSocket.open 'example.com', 443
820  *
821  * ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context
822  */
823 
825  /*
826  * The callback for additional certificate verification. It is invoked for
827  * each untrusted certificate in the chain.
828  *
829  * The callback is invoked with two values, a boolean that indicates if the
830  * pre-verification by OpenSSL has succeeded or not, and the StoreContext in
831  * use. The callback must return either true or false.
832  */
833  rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
834  /*
835  * The error code set by the last call of #verify.
836  */
837  rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
838  /*
839  * The description for the error code set by the last call of #verify.
840  */
841  rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
842  /*
843  * The certificate chain constructed by the last call of #verify.
844  */
845  rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
846  rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
847  rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
848  rb_undef_method(cX509Store, "initialize_copy");
849  rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
850  rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
851  rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
852  rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
853  rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
854  rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
855  rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
856  rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
857  rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
858  rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
859  rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
860 
861  /*
862  * Document-class: OpenSSL::X509::StoreContext
863  *
864  * A StoreContext is used while validating a single certificate and holds
865  * the status involved.
866  */
868  rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
869  rb_define_method(cX509StoreContext, "initialize", ossl_x509stctx_initialize, -1);
870  rb_undef_method(cX509StoreContext, "initialize_copy");
871  rb_define_method(cX509StoreContext, "verify", ossl_x509stctx_verify, 0);
872  rb_define_method(cX509StoreContext, "chain", ossl_x509stctx_get_chain,0);
873  rb_define_method(cX509StoreContext, "error", ossl_x509stctx_get_err, 0);
874  rb_define_method(cX509StoreContext, "error=", ossl_x509stctx_set_error, 1);
875  rb_define_method(cX509StoreContext, "error_string", ossl_x509stctx_get_err_string,0);
876  rb_define_method(cX509StoreContext, "error_depth", ossl_x509stctx_get_err_depth, 0);
877  rb_define_method(cX509StoreContext, "current_cert", ossl_x509stctx_get_curr_cert, 0);
878  rb_define_method(cX509StoreContext, "current_crl", ossl_x509stctx_get_curr_crl, 0);
879  rb_define_method(cX509StoreContext, "flags=", ossl_x509stctx_set_flags, 1);
880  rb_define_method(cX509StoreContext, "purpose=", ossl_x509stctx_set_purpose, 1);
881  rb_define_method(cX509StoreContext, "trust=", ossl_x509stctx_set_trust, 1);
882  rb_define_method(cX509StoreContext, "time=", ossl_x509stctx_set_time, 1);
883 }
X509_STORE_get_ex_data
#define X509_STORE_get_ex_data(x, idx)
Definition: openssl_missing.h:68
GetX509Store
#define GetX509Store(obj, st)
Definition: ossl_x509store.c:20
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:315
eX509CertError
VALUE eX509CertError
Definition: ossl_x509cert.c:31
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
NewX509StCtx
#define NewX509StCtx(klass)
Definition: ossl_x509store.c:27
i
uint32_t i
Definition: rb_mjit_min_header-2.7.2.h:5460
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_intern
#define rb_intern(str)
ossl_x509_new
VALUE ossl_x509_new(X509 *)
Definition: ossl_x509cert.c:51
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
mX509
VALUE mX509
Definition: ossl_x509.c:12
ossl.h
ossl_clear_error
void ossl_clear_error(void)
Definition: ossl.c:304
ossl_verify_cb_args::store_ctx
VALUE store_ctx
Definition: ossl_x509store.c:51
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
ptr
struct RIMemo * ptr
Definition: debug.c:65
rb_Integer
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
Definition: object.c:3106
Qfalse
#define Qfalse
Definition: ruby.h:467
NULL
#define NULL
Definition: _sdbm.c:101
SetX509Store
#define SetX509Store(obj, st)
Definition: ossl_x509store.c:14
X509_STORE_CTX_get0_chain
#define X509_STORE_CTX_get0_chain(ctx)
Definition: openssl_missing.h:111
ossl_x509crl_new
VALUE ossl_x509crl_new(X509_CRL *)
Definition: ossl_x509crl.c:61
ossl_verify_cb_args::preverify_ok
VALUE preverify_ok
Definition: ossl_x509store.c:50
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
X509_STORE_CTX_get0_store
#define X509_STORE_CTX_get0_store(x)
Definition: openssl_missing.h:29
cX509Store
VALUE cX509Store
Definition: ossl_x509store.c:104
DupX509CertPtr
X509 * DupX509CertPtr(VALUE)
Definition: ossl_x509cert.c:81
X509_STORE_get_ex_new_index
#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef)
Definition: openssl_missing.h:75
mOSSL
VALUE mOSSL
Definition: ossl.c:231
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.2.h:13222
time
time_t time(time_t *_timer)
GetX509CRLPtr
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
ossl_verify_cb_call
int ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
Definition: ossl_x509store.c:62
GetX509CertPtr
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:3305
cX509StoreContext
VALUE cX509StoreContext
Definition: ossl_x509store.c:105
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
OSSL_Debug
#define OSSL_Debug
Definition: ossl.h:148
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:1179
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.2.h:5597
NewX509Store
#define NewX509Store(klass)
Definition: ossl_x509store.c:12
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
GetX509StCtx
#define GetX509StCtx(obj, ctx)
Definition: ossl_x509store.c:35
ossl_verify_cb_args::proc
VALUE proc
Definition: ossl_x509store.c:49
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.2.h:6368
X509_STORE_set_ex_data
#define X509_STORE_set_ex_data(x, idx, data)
Definition: openssl_missing.h:73
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.2.h:5738
argv
char ** argv
Definition: ruby.c:223
f
#define f
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1896
GetX509StorePtr
X509_STORE * GetX509StorePtr(VALUE obj)
Definition: ossl_x509store.c:126
X509_STORE_CTX_get0_cert
#define X509_STORE_CTX_get0_cert(x)
Definition: openssl_missing.h:107
STACK_OF
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
eX509StoreError
VALUE eX509StoreError
Definition: ossl_x509store.c:106
ossl_verify_cb_args
Definition: ossl_x509store.c:48
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
path
VALUE path
Definition: rb_mjit_min_header-2.7.2.h:7336
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.2.h:6581
argc
int argc
Definition: ruby.c:222
err
int err
Definition: win32.c:135
rb_data_type_struct
Definition: ruby.h:1148
Qtrue
#define Qtrue
Definition: ruby.h:468
Init_ossl_x509store
void Init_ossl_x509store(void)
Definition: ossl_x509store.c:770
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
X509_STORE_CTX_get0_untrusted
#define X509_STORE_CTX_get0_untrusted(x)
Definition: openssl_missing.h:103
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:921
rb_attr
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1163
SetX509StCtx
#define SetX509StCtx(obj, ctx)
Definition: ossl_x509store.c:29
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_iv_set
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:3318
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837