Change soft-fail to use the config, rather than env
[rbx.git] / stdlib / ext / openssl / ossl_x509store.c
blobdf1ffe7f1c8d66e6107f0ffe40e49ec3782eb99e
1 /*
2 * $Id: ossl_x509store.c 11708 2007-02-12 23:01:19Z shyouhei $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5 * All rights reserved.
6 */
7 /*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
11 #include "ossl.h"
12 #include <rubysig.h>
14 #define WrapX509Store(klass, obj, st) do { \
15 if (!st) { \
16 ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
17 } \
18 obj = Data_Wrap_Struct(klass, 0, X509_STORE_free, st); \
19 } while (0)
20 #define GetX509Store(obj, st) do { \
21 Data_Get_Struct(obj, X509_STORE, st); \
22 if (!st) { \
23 ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
24 } \
25 } while (0)
26 #define SafeGetX509Store(obj, st) do { \
27 OSSL_Check_Kind(obj, cX509Store); \
28 GetX509Store(obj, st); \
29 } while (0)
31 #define WrapX509StCtx(klass, obj, ctx) do { \
32 if (!ctx) { \
33 ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
34 } \
35 obj = Data_Wrap_Struct(klass, 0, ossl_x509stctx_free, ctx); \
36 } while (0)
37 #define GetX509StCtx(obj, ctx) do { \
38 Data_Get_Struct(obj, X509_STORE_CTX, ctx); \
39 if (!ctx) { \
40 ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
41 } \
42 } while (0)
43 #define SafeGetX509StCtx(obj, storep) do { \
44 OSSL_Check_Kind(obj, cX509StoreContext); \
45 GetX509Store(obj, ctx); \
46 } while (0)
49 * Classes
51 VALUE cX509Store;
52 VALUE cX509StoreContext;
53 VALUE eX509StoreError;
56 * Public functions
58 VALUE
59 ossl_x509store_new(X509_STORE *store)
61 VALUE obj;
63 WrapX509Store(cX509Store, obj, store);
65 return obj;
68 X509_STORE *
69 GetX509StorePtr(VALUE obj)
71 X509_STORE *store;
73 SafeGetX509Store(obj, store);
75 return store;
78 X509_STORE *
79 DupX509StorePtr(VALUE obj)
81 X509_STORE *store;
83 SafeGetX509Store(obj, store);
84 CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
86 return store;
90 * Private functions
92 static VALUE
93 ossl_x509store_alloc(VALUE klass)
95 X509_STORE *store;
96 VALUE obj;
98 if((store = X509_STORE_new()) == NULL){
99 ossl_raise(eX509StoreError, NULL);
101 WrapX509Store(klass, obj, store);
103 return obj;
107 * General callback for OpenSSL verify
109 static VALUE
110 ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
112 X509_STORE *store;
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);
118 return cb;
121 static VALUE
122 ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
124 X509_STORE *store;
126 GetX509Store(self, store);
127 X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
128 ossl_x509store_set_vfy_cb(self, Qnil);
130 #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
131 rb_iv_set(self, "@flags", INT2NUM(0));
132 rb_iv_set(self, "@purpose", INT2NUM(0));
133 rb_iv_set(self, "@trust", INT2NUM(0));
134 #endif
136 /* last verification status */
137 rb_iv_set(self, "@error", Qnil);
138 rb_iv_set(self, "@error_string", Qnil);
139 rb_iv_set(self, "@chain", Qnil);
140 rb_iv_set(self, "@time", Qnil);
142 return self;
145 static VALUE
146 ossl_x509store_set_flags(VALUE self, VALUE flags)
148 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
149 X509_STORE *store;
150 long f = NUM2LONG(flags);
152 GetX509Store(self, store);
153 X509_STORE_set_flags(store, f);
154 #else
155 rb_iv_set(self, "@flags", flags);
156 #endif
158 return flags;
161 static VALUE
162 ossl_x509store_set_purpose(VALUE self, VALUE purpose)
164 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
165 X509_STORE *store;
166 long p = NUM2LONG(purpose);
168 GetX509Store(self, store);
169 X509_STORE_set_purpose(store, p);
170 #else
171 rb_iv_set(self, "@purpose", purpose);
172 #endif
174 return purpose;
177 static VALUE
178 ossl_x509store_set_trust(VALUE self, VALUE trust)
180 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
181 X509_STORE *store;
182 long t = NUM2LONG(trust);
184 GetX509Store(self, store);
185 X509_STORE_set_trust(store, t);
186 #else
187 rb_iv_set(self, "@trust", trust);
188 #endif
190 return trust;
193 static VALUE
194 ossl_x509store_set_time(VALUE self, VALUE time)
196 rb_iv_set(self, "@time", time);
197 return time;
200 static VALUE
201 ossl_x509store_add_file(VALUE self, VALUE file)
203 X509_STORE *store;
204 X509_LOOKUP *lookup;
205 char *path = NULL;
207 if(file != Qnil){
208 Check_SafeStr(file);
209 path = RSTRING(file)->ptr;
211 GetX509Store(self, store);
212 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
213 if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
214 if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
215 ossl_raise(eX509StoreError, NULL);
218 return self;
221 static VALUE
222 ossl_x509store_add_path(VALUE self, VALUE dir)
224 X509_STORE *store;
225 X509_LOOKUP *lookup;
226 char *path = NULL;
228 if(dir != Qnil){
229 Check_SafeStr(dir);
230 path = RSTRING(dir)->ptr;
232 GetX509Store(self, store);
233 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
234 if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
235 if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
236 ossl_raise(eX509StoreError, NULL);
239 return self;
242 static VALUE
243 ossl_x509store_set_default_paths(VALUE self)
245 X509_STORE *store;
247 GetX509Store(self, store);
248 if (X509_STORE_set_default_paths(store) != 1){
249 ossl_raise(eX509StoreError, NULL);
252 return Qnil;
255 static VALUE
256 ossl_x509store_add_cert(VALUE self, VALUE arg)
258 X509_STORE *store;
259 X509 *cert;
261 cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
262 GetX509Store(self, store);
263 if (X509_STORE_add_cert(store, cert) != 1){
264 ossl_raise(eX509StoreError, NULL);
267 return self;
270 static VALUE
271 ossl_x509store_add_crl(VALUE self, VALUE arg)
273 X509_STORE *store;
274 X509_CRL *crl;
276 crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
277 GetX509Store(self, store);
278 if (X509_STORE_add_crl(store, crl) != 1){
279 ossl_raise(eX509StoreError, NULL);
282 return self;
285 static VALUE ossl_x509stctx_get_err(VALUE);
286 static VALUE ossl_x509stctx_get_err_string(VALUE);
287 static VALUE ossl_x509stctx_get_chain(VALUE);
289 static VALUE
290 ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
292 VALUE cert, chain;
293 VALUE ctx, proc, result;
295 rb_scan_args(argc, argv, "11", &cert, &chain);
296 ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
297 proc = rb_block_given_p() ? rb_block_proc() :
298 rb_iv_get(self, "@verify_callback");
299 rb_iv_set(ctx, "@verify_callback", proc);
300 result = rb_funcall(ctx, rb_intern("verify"), 0);
302 rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
303 rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
304 rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
306 return result;
310 * Public Functions
312 static void ossl_x509stctx_free(X509_STORE_CTX*);
314 VALUE
315 ossl_x509stctx_new(X509_STORE_CTX *ctx)
317 VALUE obj;
319 WrapX509StCtx(cX509StoreContext, obj, ctx);
321 return obj;
324 VALUE
325 ossl_x509stctx_clear_ptr(VALUE obj)
327 OSSL_Check_Kind(obj, cX509StoreContext);
328 RDATA(obj)->data = NULL;
330 return obj;
334 * Private functions
336 static void
337 ossl_x509stctx_free(X509_STORE_CTX *ctx)
339 if(ctx->untrusted)
340 sk_X509_pop_free(ctx->untrusted, X509_free);
341 if(ctx->cert)
342 X509_free(ctx->cert);
343 X509_STORE_CTX_free(ctx);
346 static VALUE
347 ossl_x509stctx_alloc(VALUE klass)
349 X509_STORE_CTX *ctx;
350 VALUE obj;
352 if((ctx = X509_STORE_CTX_new()) == NULL){
353 ossl_raise(eX509StoreError, NULL);
355 WrapX509StCtx(klass, obj, ctx);
357 return obj;
360 static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
361 static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
362 static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
363 static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
365 static VALUE
366 ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
368 VALUE store, cert, chain, t;
369 X509_STORE_CTX *ctx;
370 X509_STORE *x509st;
371 X509 *x509 = NULL;
372 STACK_OF(X509) *x509s = NULL;
374 rb_scan_args(argc, argv, "12", &store, &cert, &chain);
375 GetX509StCtx(self, ctx);
376 SafeGetX509Store(store, x509st);
377 if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
378 if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
379 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
380 if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
381 sk_X509_pop_free(x509s, X509_free);
382 ossl_raise(eX509StoreError, NULL);
384 #else
385 X509_STORE_CTX_init(ctx, x509st, x509, x509s);
386 ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
387 ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
388 ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
389 #endif
390 if (!NIL_P(t = rb_iv_get(store, "@time")))
391 ossl_x509stctx_set_time(self, t);
392 rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
393 rb_iv_set(self, "@cert", cert);
395 return self;
398 static VALUE
399 ossl_x509stctx_verify(VALUE self)
401 X509_STORE_CTX *ctx;
402 int result;
404 GetX509StCtx(self, ctx);
405 X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
406 (void*)rb_iv_get(self, "@verify_callback"));
407 result = X509_verify_cert(ctx);
409 return result ? Qtrue : Qfalse;
412 static VALUE
413 ossl_x509stctx_get_chain(VALUE self)
415 X509_STORE_CTX *ctx;
416 STACK_OF(X509) *chain;
417 X509 *x509;
418 int i, num;
419 VALUE ary;
421 GetX509StCtx(self, ctx);
422 if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){
423 return Qnil;
425 if((num = sk_X509_num(chain)) < 0){
426 OSSL_Debug("certs in chain < 0???");
427 return rb_ary_new();
429 ary = rb_ary_new2(num);
430 for(i = 0; i < num; i++) {
431 x509 = sk_X509_value(chain, i);
432 rb_ary_push(ary, ossl_x509_new(x509));
435 return ary;
438 static VALUE
439 ossl_x509stctx_get_err(VALUE self)
441 X509_STORE_CTX *ctx;
443 GetX509StCtx(self, ctx);
445 return INT2FIX(X509_STORE_CTX_get_error(ctx));
448 static VALUE
449 ossl_x509stctx_set_error(VALUE self, VALUE err)
451 X509_STORE_CTX *ctx;
453 GetX509StCtx(self, ctx);
454 X509_STORE_CTX_set_error(ctx, FIX2INT(err));
456 return err;
459 static VALUE
460 ossl_x509stctx_get_err_string(VALUE self)
462 X509_STORE_CTX *ctx;
463 long err;
465 GetX509StCtx(self, ctx);
466 err = X509_STORE_CTX_get_error(ctx);
468 return rb_str_new2(X509_verify_cert_error_string(err));
471 static VALUE
472 ossl_x509stctx_get_err_depth(VALUE self)
474 X509_STORE_CTX *ctx;
476 GetX509StCtx(self, ctx);
478 return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
481 static VALUE
482 ossl_x509stctx_get_curr_cert(VALUE self)
484 X509_STORE_CTX *ctx;
486 GetX509StCtx(self, ctx);
488 return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
491 static VALUE
492 ossl_x509stctx_get_curr_crl(VALUE self)
494 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
495 X509_STORE_CTX *ctx;
497 GetX509StCtx(self, ctx);
498 if(!ctx->current_crl) return Qnil;
500 return ossl_x509crl_new(ctx->current_crl);
501 #else
502 return Qnil;
503 #endif
506 static VALUE
507 ossl_x509stctx_cleanup(VALUE self)
509 X509_STORE_CTX *ctx;
511 GetX509StCtx(self, ctx);
512 X509_STORE_CTX_cleanup(ctx);
514 return self;
517 static VALUE
518 ossl_x509stctx_set_flags(VALUE self, VALUE flags)
520 X509_STORE_CTX *store;
521 long f = NUM2LONG(flags);
523 GetX509StCtx(self, store);
524 X509_STORE_CTX_set_flags(store, f);
526 return flags;
529 static VALUE
530 ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
532 X509_STORE_CTX *store;
533 long p = NUM2LONG(purpose);
535 GetX509StCtx(self, store);
536 X509_STORE_CTX_set_purpose(store, p);
538 return purpose;
541 static VALUE
542 ossl_x509stctx_set_trust(VALUE self, VALUE trust)
544 X509_STORE_CTX *store;
545 long t = NUM2LONG(trust);
547 GetX509StCtx(self, store);
548 X509_STORE_CTX_set_trust(store, t);
550 return trust;
553 static VALUE
554 ossl_x509stctx_set_time(VALUE self, VALUE time)
556 X509_STORE_CTX *store;
557 long t;
559 t = NUM2LONG(rb_Integer(time));
560 GetX509StCtx(self, store);
561 X509_STORE_CTX_set_time(store, 0, t);
563 return time;
567 * INIT
569 void
570 Init_ossl_x509store()
572 VALUE x509stctx;
574 eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
576 cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
577 rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
578 rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
579 rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
580 rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
581 rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
582 rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
583 rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
584 rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
585 rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
586 rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
587 rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
588 rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
589 rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
590 rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
591 rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
592 rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
593 rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
595 cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject);
596 x509stctx = cX509StoreContext;
597 rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
598 rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
599 rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
600 rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
601 rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
602 rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
603 rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
604 rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
605 rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
606 rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
607 rb_define_method(x509stctx,"cleanup", ossl_x509stctx_cleanup, 0);
608 rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
609 rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
610 rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
611 rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);