3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
14 #define WrapX509Store(klass, obj, st) do { \
16 ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
18 obj = Data_Wrap_Struct(klass, 0, X509_STORE_free, st); \
20 #define GetX509Store(obj, st) do { \
21 Data_Get_Struct(obj, X509_STORE, st); \
23 ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
26 #define SafeGetX509Store(obj, st) do { \
27 OSSL_Check_Kind(obj, cX509Store); \
28 GetX509Store(obj, st); \
31 #define WrapX509StCtx(klass, obj, ctx) do { \
33 ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
35 obj = Data_Wrap_Struct(klass, 0, ossl_x509stctx_free, ctx); \
37 #define GetX509StCtx(obj, ctx) do { \
38 Data_Get_Struct(obj, X509_STORE_CTX, ctx); \
40 ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
43 #define SafeGetX509StCtx(obj, storep) do { \
44 OSSL_Check_Kind(obj, cX509StoreContext); \
45 GetX509Store(obj, ctx); \
52 VALUE cX509StoreContext
;
53 VALUE eX509StoreError
;
59 ossl_x509store_new(X509_STORE
*store
)
63 WrapX509Store(cX509Store
, obj
, store
);
69 GetX509StorePtr(VALUE obj
)
73 SafeGetX509Store(obj
, store
);
79 DupX509StorePtr(VALUE obj
)
83 SafeGetX509Store(obj
, store
);
84 CRYPTO_add(&store
->references
, 1, CRYPTO_LOCK_X509_STORE
);
93 ossl_x509store_alloc(VALUE klass
)
98 if((store
= X509_STORE_new()) == NULL
){
99 ossl_raise(eX509StoreError
, NULL
);
101 WrapX509Store(klass
, obj
, store
);
107 * General callback for OpenSSL verify
110 ossl_x509store_set_vfy_cb(VALUE self
, VALUE cb
)
114 GetX509Store(self
, store
);
115 X509_STORE_set_ex_data(store
, ossl_verify_cb_idx
, (void*)cb
);
116 rb_iv_set(self
, "@verify_callback", cb
);
124 * X509::Store.new => store
128 ossl_x509store_initialize(int argc
, VALUE
*argv
, VALUE self
)
132 /* BUG: This method takes any number of arguments but appears to ignore them. */
133 GetX509Store(self
, store
);
134 X509_STORE_set_verify_cb_func(store
, ossl_verify_cb
);
135 ossl_x509store_set_vfy_cb(self
, Qnil
);
137 #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
138 rb_iv_set(self
, "@flags", INT2NUM(0));
139 rb_iv_set(self
, "@purpose", INT2NUM(0));
140 rb_iv_set(self
, "@trust", INT2NUM(0));
143 /* last verification status */
144 rb_iv_set(self
, "@error", Qnil
);
145 rb_iv_set(self
, "@error_string", Qnil
);
146 rb_iv_set(self
, "@chain", Qnil
);
147 rb_iv_set(self
, "@time", Qnil
);
153 ossl_x509store_set_flags(VALUE self
, VALUE flags
)
155 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
157 long f
= NUM2LONG(flags
);
159 GetX509Store(self
, store
);
160 X509_STORE_set_flags(store
, f
);
162 rb_iv_set(self
, "@flags", flags
);
169 ossl_x509store_set_purpose(VALUE self
, VALUE purpose
)
171 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
173 long p
= NUM2LONG(purpose
);
175 GetX509Store(self
, store
);
176 X509_STORE_set_purpose(store
, p
);
178 rb_iv_set(self
, "@purpose", purpose
);
185 ossl_x509store_set_trust(VALUE self
, VALUE trust
)
187 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
189 long t
= NUM2LONG(trust
);
191 GetX509Store(self
, store
);
192 X509_STORE_set_trust(store
, t
);
194 rb_iv_set(self
, "@trust", trust
);
201 ossl_x509store_set_time(VALUE self
, VALUE time
)
203 rb_iv_set(self
, "@time", time
);
208 ossl_x509store_add_file(VALUE self
, VALUE file
)
216 path
= RSTRING_PTR(file
);
218 GetX509Store(self
, store
);
219 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file());
220 if(lookup
== NULL
) ossl_raise(eX509StoreError
, NULL
);
221 if(X509_LOOKUP_load_file(lookup
, path
, X509_FILETYPE_PEM
) != 1){
222 ossl_raise(eX509StoreError
, NULL
);
229 ossl_x509store_add_path(VALUE self
, VALUE dir
)
237 path
= RSTRING_PTR(dir
);
239 GetX509Store(self
, store
);
240 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_hash_dir());
241 if(lookup
== NULL
) ossl_raise(eX509StoreError
, NULL
);
242 if(X509_LOOKUP_add_dir(lookup
, path
, X509_FILETYPE_PEM
) != 1){
243 ossl_raise(eX509StoreError
, NULL
);
250 ossl_x509store_set_default_paths(VALUE self
)
254 GetX509Store(self
, store
);
255 if (X509_STORE_set_default_paths(store
) != 1){
256 ossl_raise(eX509StoreError
, NULL
);
263 ossl_x509store_add_cert(VALUE self
, VALUE arg
)
268 cert
= GetX509CertPtr(arg
); /* NO NEED TO DUP */
269 GetX509Store(self
, store
);
270 if (X509_STORE_add_cert(store
, cert
) != 1){
271 ossl_raise(eX509StoreError
, NULL
);
278 ossl_x509store_add_crl(VALUE self
, VALUE arg
)
283 crl
= GetX509CRLPtr(arg
); /* NO NEED TO DUP */
284 GetX509Store(self
, store
);
285 if (X509_STORE_add_crl(store
, crl
) != 1){
286 ossl_raise(eX509StoreError
, NULL
);
292 static VALUE
ossl_x509stctx_get_err(VALUE
);
293 static VALUE
ossl_x509stctx_get_err_string(VALUE
);
294 static VALUE
ossl_x509stctx_get_chain(VALUE
);
297 ossl_x509store_verify(int argc
, VALUE
*argv
, VALUE self
)
300 VALUE ctx
, proc
, result
;
302 rb_scan_args(argc
, argv
, "11", &cert
, &chain
);
303 ctx
= rb_funcall(cX509StoreContext
, rb_intern("new"), 3, self
, cert
, chain
);
304 proc
= rb_block_given_p() ? rb_block_proc() :
305 rb_iv_get(self
, "@verify_callback");
306 rb_iv_set(ctx
, "@verify_callback", proc
);
307 result
= rb_funcall(ctx
, rb_intern("verify"), 0);
309 rb_iv_set(self
, "@error", ossl_x509stctx_get_err(ctx
));
310 rb_iv_set(self
, "@error_string", ossl_x509stctx_get_err_string(ctx
));
311 rb_iv_set(self
, "@chain", ossl_x509stctx_get_chain(ctx
));
319 static void ossl_x509stctx_free(X509_STORE_CTX
*);
322 ossl_x509stctx_new(X509_STORE_CTX
*ctx
)
326 WrapX509StCtx(cX509StoreContext
, obj
, ctx
);
332 ossl_x509stctx_clear_ptr(VALUE obj
)
334 OSSL_Check_Kind(obj
, cX509StoreContext
);
335 RDATA(obj
)->data
= NULL
;
344 ossl_x509stctx_free(X509_STORE_CTX
*ctx
)
347 sk_X509_pop_free(ctx
->untrusted
, X509_free
);
349 X509_free(ctx
->cert
);
350 X509_STORE_CTX_free(ctx
);
354 ossl_x509stctx_alloc(VALUE klass
)
359 if((ctx
= X509_STORE_CTX_new()) == NULL
){
360 ossl_raise(eX509StoreError
, NULL
);
362 WrapX509StCtx(klass
, obj
, ctx
);
367 static VALUE
ossl_x509stctx_set_flags(VALUE
, VALUE
);
368 static VALUE
ossl_x509stctx_set_purpose(VALUE
, VALUE
);
369 static VALUE
ossl_x509stctx_set_trust(VALUE
, VALUE
);
370 static VALUE
ossl_x509stctx_set_time(VALUE
, VALUE
);
373 ossl_x509stctx_initialize(int argc
, VALUE
*argv
, VALUE self
)
375 VALUE store
, cert
, chain
, t
;
379 STACK_OF(X509
) *x509s
= NULL
;
381 rb_scan_args(argc
, argv
, "12", &store
, &cert
, &chain
);
382 GetX509StCtx(self
, ctx
);
383 SafeGetX509Store(store
, x509st
);
384 if(!NIL_P(cert
)) x509
= DupX509CertPtr(cert
); /* NEED TO DUP */
385 if(!NIL_P(chain
)) x509s
= ossl_x509_ary2sk(chain
);
386 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
387 if(X509_STORE_CTX_init(ctx
, x509st
, x509
, x509s
) != 1){
388 sk_X509_pop_free(x509s
, X509_free
);
389 ossl_raise(eX509StoreError
, NULL
);
392 X509_STORE_CTX_init(ctx
, x509st
, x509
, x509s
);
393 ossl_x509stctx_set_flags(self
, rb_iv_get(store
, "@flags"));
394 ossl_x509stctx_set_purpose(self
, rb_iv_get(store
, "@purpose"));
395 ossl_x509stctx_set_trust(self
, rb_iv_get(store
, "@trust"));
397 if (!NIL_P(t
= rb_iv_get(store
, "@time")))
398 ossl_x509stctx_set_time(self
, t
);
399 rb_iv_set(self
, "@verify_callback", rb_iv_get(store
, "@verify_callback"));
400 rb_iv_set(self
, "@cert", cert
);
406 ossl_x509stctx_verify(VALUE self
)
411 GetX509StCtx(self
, ctx
);
412 X509_STORE_CTX_set_ex_data(ctx
, ossl_verify_cb_idx
,
413 (void*)rb_iv_get(self
, "@verify_callback"));
414 result
= X509_verify_cert(ctx
);
416 return result
? Qtrue
: Qfalse
;
420 ossl_x509stctx_get_chain(VALUE self
)
423 STACK_OF(X509
) *chain
;
428 GetX509StCtx(self
, ctx
);
429 if((chain
= X509_STORE_CTX_get_chain(ctx
)) == NULL
){
432 if((num
= sk_X509_num(chain
)) < 0){
433 OSSL_Debug("certs in chain < 0???");
436 ary
= rb_ary_new2(num
);
437 for(i
= 0; i
< num
; i
++) {
438 x509
= sk_X509_value(chain
, i
);
439 rb_ary_push(ary
, ossl_x509_new(x509
));
446 ossl_x509stctx_get_err(VALUE self
)
450 GetX509StCtx(self
, ctx
);
452 return INT2FIX(X509_STORE_CTX_get_error(ctx
));
456 ossl_x509stctx_set_error(VALUE self
, VALUE err
)
460 GetX509StCtx(self
, ctx
);
461 X509_STORE_CTX_set_error(ctx
, NUM2INT(err
));
467 ossl_x509stctx_get_err_string(VALUE self
)
472 GetX509StCtx(self
, ctx
);
473 err
= X509_STORE_CTX_get_error(ctx
);
475 return rb_str_new2(X509_verify_cert_error_string(err
));
479 ossl_x509stctx_get_err_depth(VALUE self
)
483 GetX509StCtx(self
, ctx
);
485 return INT2FIX(X509_STORE_CTX_get_error_depth(ctx
));
489 ossl_x509stctx_get_curr_cert(VALUE self
)
493 GetX509StCtx(self
, ctx
);
495 return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx
));
499 ossl_x509stctx_get_curr_crl(VALUE self
)
501 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
504 GetX509StCtx(self
, ctx
);
505 if(!ctx
->current_crl
) return Qnil
;
507 return ossl_x509crl_new(ctx
->current_crl
);
514 ossl_x509stctx_cleanup(VALUE self
)
518 GetX509StCtx(self
, ctx
);
519 X509_STORE_CTX_cleanup(ctx
);
525 ossl_x509stctx_set_flags(VALUE self
, VALUE flags
)
527 X509_STORE_CTX
*store
;
528 long f
= NUM2LONG(flags
);
530 GetX509StCtx(self
, store
);
531 X509_STORE_CTX_set_flags(store
, f
);
537 ossl_x509stctx_set_purpose(VALUE self
, VALUE purpose
)
539 X509_STORE_CTX
*store
;
540 long p
= NUM2LONG(purpose
);
542 GetX509StCtx(self
, store
);
543 X509_STORE_CTX_set_purpose(store
, p
);
549 ossl_x509stctx_set_trust(VALUE self
, VALUE trust
)
551 X509_STORE_CTX
*store
;
552 long t
= NUM2LONG(trust
);
554 GetX509StCtx(self
, store
);
555 X509_STORE_CTX_set_trust(store
, t
);
562 * storectx.time = time => time
565 ossl_x509stctx_set_time(VALUE self
, VALUE time
)
567 X509_STORE_CTX
*store
;
570 t
= NUM2LONG(rb_Integer(time
));
571 GetX509StCtx(self
, store
);
572 X509_STORE_CTX_set_time(store
, 0, t
);
581 Init_ossl_x509store()
585 eX509StoreError
= rb_define_class_under(mX509
, "StoreError", eOSSLError
);
587 cX509Store
= rb_define_class_under(mX509
, "Store", rb_cObject
);
588 rb_attr(cX509Store
, rb_intern("verify_callback"), 1, 0, Qfalse
);
589 rb_attr(cX509Store
, rb_intern("error"), 1, 0, Qfalse
);
590 rb_attr(cX509Store
, rb_intern("error_string"), 1, 0, Qfalse
);
591 rb_attr(cX509Store
, rb_intern("chain"), 1, 0, Qfalse
);
592 rb_define_alloc_func(cX509Store
, ossl_x509store_alloc
);
593 rb_define_method(cX509Store
, "initialize", ossl_x509store_initialize
, -1);
594 rb_define_method(cX509Store
, "verify_callback=", ossl_x509store_set_vfy_cb
, 1);
595 rb_define_method(cX509Store
, "flags=", ossl_x509store_set_flags
, 1);
596 rb_define_method(cX509Store
, "purpose=", ossl_x509store_set_purpose
, 1);
597 rb_define_method(cX509Store
, "trust=", ossl_x509store_set_trust
, 1);
598 rb_define_method(cX509Store
, "time=", ossl_x509store_set_time
, 1);
599 rb_define_method(cX509Store
, "add_path", ossl_x509store_add_path
, 1);
600 rb_define_method(cX509Store
, "add_file", ossl_x509store_add_file
, 1);
601 rb_define_method(cX509Store
, "set_default_paths", ossl_x509store_set_default_paths
, 0);
602 rb_define_method(cX509Store
, "add_cert", ossl_x509store_add_cert
, 1);
603 rb_define_method(cX509Store
, "add_crl", ossl_x509store_add_crl
, 1);
604 rb_define_method(cX509Store
, "verify", ossl_x509store_verify
, -1);
606 cX509StoreContext
= rb_define_class_under(mX509
,"StoreContext",rb_cObject
);
607 x509stctx
= cX509StoreContext
;
608 rb_define_alloc_func(cX509StoreContext
, ossl_x509stctx_alloc
);
609 rb_define_method(x509stctx
,"initialize", ossl_x509stctx_initialize
, -1);
610 rb_define_method(x509stctx
,"verify", ossl_x509stctx_verify
, 0);
611 rb_define_method(x509stctx
,"chain", ossl_x509stctx_get_chain
,0);
612 rb_define_method(x509stctx
,"error", ossl_x509stctx_get_err
, 0);
613 rb_define_method(x509stctx
,"error=", ossl_x509stctx_set_error
, 1);
614 rb_define_method(x509stctx
,"error_string",ossl_x509stctx_get_err_string
,0);
615 rb_define_method(x509stctx
,"error_depth", ossl_x509stctx_get_err_depth
, 0);
616 rb_define_method(x509stctx
,"current_cert",ossl_x509stctx_get_curr_cert
, 0);
617 rb_define_method(x509stctx
,"current_crl", ossl_x509stctx_get_curr_crl
, 0);
618 rb_define_method(x509stctx
,"cleanup", ossl_x509stctx_cleanup
, 0);
619 rb_define_method(x509stctx
,"flags=", ossl_x509stctx_set_flags
, 1);
620 rb_define_method(x509stctx
,"purpose=", ossl_x509stctx_set_purpose
, 1);
621 rb_define_method(x509stctx
,"trust=", ossl_x509stctx_set_trust
, 1);
622 rb_define_method(x509stctx
,"time=", ossl_x509stctx_set_time
, 1);