Ruby: ext/openssl/ossl_x509store.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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 */
45static int stctx_ex_verify_cb_idx, store_ex_verify_cb_idx;
46static 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
54static VALUE
55call_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
61int
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
108static void
109ossl_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
115static void
116ossl_x509store_free(void *ptr)
117{
118 X509_STORE_free(ptr);
119}
120
121static 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 */
132X509_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 */
145static int
146x509store_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
160static VALUE
161ossl_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 */
178static VALUE
179ossl_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 */
197static VALUE
198ossl_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 */
227static VALUE
228ossl_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 */
257static VALUE
258ossl_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 */
273static VALUE
274ossl_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 */
291static VALUE
292ossl_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 */
306static VALUE
307ossl_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 */
341static VALUE
342ossl_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 */
372static VALUE
373ossl_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 */
391static VALUE
392ossl_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 */
412static VALUE
413ossl_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
427static VALUE ossl_x509stctx_get_err(VALUE);
428static VALUE ossl_x509stctx_get_err_string(VALUE);
429static 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 */
446static VALUE
447ossl_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 */
469static void
470ossl_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
476static void
477ossl_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
487static 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
495static VALUE
496ossl_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
510static VALUE
511ossl_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
521static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
522static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
523static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
524static 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 */
532static VALUE
533ossl_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 */
571static VALUE
572ossl_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 */
595static VALUE
596ossl_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 */
625static VALUE
626ossl_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 */
639static VALUE
640ossl_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 */
656static VALUE
657ossl_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 */
672static VALUE
673ossl_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 */
686static VALUE
687ossl_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 */
700static VALUE
701ossl_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 */
720static VALUE
721ossl_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 */
738static VALUE
739ossl_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 */
754static VALUE
755ossl_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 */
772static VALUE
773ossl_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 */
788void
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}
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:749
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
ptr
struct RIMemo * ptr
Definition: debug.c:88
num
big_t * num
Definition: enough.c:232
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
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:797
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:871
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:895
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1777
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2296
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:935
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:1054
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1925
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:1105
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:408
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:921
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:49
rb_Integer
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
Definition: object.c:3138
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1077
rb_ary_new2
#define rb_ary_new2
Definition: array.h:72
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:826
rb_str_new2
#define rb_str_new2
Definition: string.h:276
rb_attr
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1508
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:785
rb_iv_set
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:3580
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:3569
NUM2INT
#define NUM2INT
Definition: int.h:44
INT2NUM
#define INT2NUM
Definition: int.h:43
NUM2LONG
#define NUM2LONG
Definition: long.h:51
X509_STORE_CTX_get0_chain
#define X509_STORE_CTX_get0_chain(ctx)
Definition: openssl_missing.h:114
X509_STORE_set_ex_data
#define X509_STORE_set_ex_data(x, idx, data)
Definition: openssl_missing.h:73
X509_STORE_get_ex_data
#define X509_STORE_get_ex_data(x, idx)
Definition: openssl_missing.h:68
X509_STORE_CTX_get0_cert
#define X509_STORE_CTX_get0_cert(x)
Definition: openssl_missing.h:110
X509_STORE_CTX_get0_store
#define X509_STORE_CTX_get0_store(x)
Definition: openssl_missing.h:29
X509_STORE_get_ex_new_index
#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef)
Definition: openssl_missing.h:78
X509_STORE_CTX_get0_untrusted
#define X509_STORE_CTX_get0_untrusted(x)
Definition: openssl_missing.h:106
mOSSL
VALUE mOSSL
Definition: ossl.c:231
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
ossl_clear_error
void ossl_clear_error(void)
Definition: ossl.c:304
ossl.h
OSSL_Debug
#define OSSL_Debug(...)
Definition: ossl.h:140
STACK_OF
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
mX509
VALUE mX509
Definition: ossl_x509.c:12
ossl_x509_new
VALUE ossl_x509_new(X509 *)
Definition: ossl_x509cert.c:51
DupX509CertPtr
X509 * DupX509CertPtr(VALUE)
Definition: ossl_x509cert.c:81
GetX509CertPtr
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
GetX509CRLPtr
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
eX509CertError
VALUE eX509CertError
Definition: ossl_x509cert.c:31
ossl_x509crl_new
VALUE ossl_x509crl_new(X509_CRL *)
Definition: ossl_x509crl.c:61
GetX509StCtx
#define GetX509StCtx(obj, ctx)
Definition: ossl_x509store.c:35
NewX509StCtx
#define NewX509StCtx(klass)
Definition: ossl_x509store.c:27
SetX509StCtx
#define SetX509StCtx(obj, ctx)
Definition: ossl_x509store.c:29
GetX509Store
#define GetX509Store(obj, st)
Definition: ossl_x509store.c:20
cX509Store
VALUE cX509Store
Definition: ossl_x509store.c:104
Init_ossl_x509store
void Init_ossl_x509store(void)
Definition: ossl_x509store.c:789
GetX509StorePtr
X509_STORE * GetX509StorePtr(VALUE obj)
Definition: ossl_x509store.c:133
NewX509Store
#define NewX509Store(klass)
Definition: ossl_x509store.c:12
ossl_verify_cb_call
int ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
Definition: ossl_x509store.c:62
cX509StoreContext
VALUE cX509StoreContext
Definition: ossl_x509store.c:105
SetX509Store
#define SetX509Store(obj, st)
Definition: ossl_x509store.c:14
eX509StoreError
VALUE eX509StoreError
Definition: ossl_x509store.c:106
NULL
#define NULL
Definition: regenc.h:69
StringValueCStr
#define StringValueCStr(v)
Definition: rstring.h:52
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: rtypeddata.h:47
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
argc
int argc
Definition: ruby.c:240
argv
char ** argv
Definition: ruby.c:241
Qtrue
#define Qtrue
Definition: special_consts.h:52
Qnil
#define Qnil
Definition: special_consts.h:51
Qfalse
#define Qfalse
Definition: special_consts.h:50
NIL_P
#define NIL_P
Definition: special_consts.h:46
f
#define f
file
Definition: gzappend.c:170
ossl_verify_cb_args
Definition: ossl_x509store.c:48
ossl_verify_cb_args::preverify_ok
VALUE preverify_ok
Definition: ossl_x509store.c:50
ossl_verify_cb_args::store_ctx
VALUE store_ctx
Definition: ossl_x509store.c:51
ossl_verify_cb_args::proc
VALUE proc
Definition: ossl_x509store.c:49
rb_data_type_struct
Definition: rtypeddata.h:70
state
Definition: blast.c:41
t
#define t
Definition: symbol.c:253
VALUE
unsigned long VALUE
Definition: value.h:38
err
int err
Definition: win32.c:142