Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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
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_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 },
119 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
120 };
121
122 /*
123 * Public functions
124 */
125 X509_STORE *
126 GetX509StorePtr(VALUE obj)
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)
145 proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
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
159 obj = NewX509Store(klass);
160 if((store = X509_STORE_new()) == NULL){
161 ossl_raise(eX509StoreError, 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){
313 ossl_raise(eX509StoreError, NULL);
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 */
322 ossl_clear_error();
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){
348 ossl_raise(eX509StoreError, NULL);
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){
372 ossl_raise(eX509StoreError, NULL);
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){
393 ossl_raise(eX509StoreError, NULL);
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){
414 ossl_raise(eX509StoreError, NULL);
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);
447 proc = rb_block_given_p() ? rb_block_proc() :
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 },
470 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
471 };
472
473 /*
474 * Private functions
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 VALUE
488 ossl_x509stctx_alloc(VALUE klass)
489 {
490 X509_STORE_CTX *ctx;
491 VALUE obj;
492
493 obj = NewX509StCtx(klass);
494 if((ctx = X509_STORE_CTX_new()) == NULL){
495 ossl_raise(eX509StoreError, 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
507 obj = NewX509StCtx(cX509StoreContext);
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);
538 ossl_raise(eX509StoreError, NULL);
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:
565 ossl_clear_error();
566 return Qfalse;
567 default:
568 ossl_raise(eX509CertError, NULL);
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
770 Init_ossl_x509store(void)
771 {
772 #undef rb_intern
773 #if 0
774 mOSSL = rb_define_module("OpenSSL");
775 eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
776 mX509 = rb_define_module_under(mOSSL, "X509");
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
787 eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
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
824 cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
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 */
867 cX509StoreContext = rb_define_class_under(mX509,"StoreContext", rb_cObject);
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
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
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:313
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:897
NewX509StCtx
#define NewX509StCtx(klass)
Definition: ossl_x509store.c:27
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
time
time_t time(time_t *_timer)
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:74
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:1071
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
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
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
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:3294
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
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
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
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
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
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:1895
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)
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
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
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
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:919
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:3307
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837