00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ossl.h"
00012
00013 #define WrapX509Store(klass, obj, st) do { \
00014 if (!(st)) { \
00015 ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
00016 } \
00017 (obj) = Data_Wrap_Struct((klass), 0, X509_STORE_free, (st)); \
00018 } while (0)
00019 #define GetX509Store(obj, st) do { \
00020 Data_Get_Struct((obj), X509_STORE, (st)); \
00021 if (!(st)) { \
00022 ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
00023 } \
00024 } while (0)
00025 #define SafeGetX509Store(obj, st) do { \
00026 OSSL_Check_Kind((obj), cX509Store); \
00027 GetX509Store((obj), (st)); \
00028 } while (0)
00029
00030 #define WrapX509StCtx(klass, obj, ctx) do { \
00031 if (!(ctx)) { \
00032 ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
00033 } \
00034 (obj) = Data_Wrap_Struct((klass), 0, ossl_x509stctx_free, (ctx)); \
00035 } while (0)
00036 #define GetX509StCtx(obj, ctx) do { \
00037 Data_Get_Struct((obj), X509_STORE_CTX, (ctx)); \
00038 if (!(ctx)) { \
00039 ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
00040 } \
00041 } while (0)
00042 #define SafeGetX509StCtx(obj, storep) do { \
00043 OSSL_Check_Kind((obj), cX509StoreContext); \
00044 GetX509Store((obj), (ctx)); \
00045 } while (0)
00046
00047
00048
00049
00050 VALUE cX509Store;
00051 VALUE cX509StoreContext;
00052 VALUE eX509StoreError;
00053
00054
00055
00056
00057 VALUE
00058 ossl_x509store_new(X509_STORE *store)
00059 {
00060 VALUE obj;
00061
00062 WrapX509Store(cX509Store, obj, store);
00063
00064 return obj;
00065 }
00066
00067 X509_STORE *
00068 GetX509StorePtr(VALUE obj)
00069 {
00070 X509_STORE *store;
00071
00072 SafeGetX509Store(obj, store);
00073
00074 return store;
00075 }
00076
00077 X509_STORE *
00078 DupX509StorePtr(VALUE obj)
00079 {
00080 X509_STORE *store;
00081
00082 SafeGetX509Store(obj, store);
00083 CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
00084
00085 return store;
00086 }
00087
00088
00089
00090
00091 static VALUE
00092 ossl_x509store_alloc(VALUE klass)
00093 {
00094 X509_STORE *store;
00095 VALUE obj;
00096
00097 if((store = X509_STORE_new()) == NULL){
00098 ossl_raise(eX509StoreError, NULL);
00099 }
00100 WrapX509Store(klass, obj, store);
00101
00102 return obj;
00103 }
00104
00105
00106
00107
00108 static VALUE
00109 ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
00110 {
00111 X509_STORE *store;
00112
00113 GetX509Store(self, store);
00114 X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb);
00115 rb_iv_set(self, "@verify_callback", cb);
00116
00117 return cb;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 static VALUE
00127 ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
00128 {
00129 X509_STORE *store;
00130
00131
00132 GetX509Store(self, store);
00133 store->ex_data.sk = NULL;
00134 X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
00135 ossl_x509store_set_vfy_cb(self, Qnil);
00136
00137 #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
00138 rb_iv_set(self, "@flags", INT2NUM(0));
00139 rb_iv_set(self, "@purpose", INT2NUM(0));
00140 rb_iv_set(self, "@trust", INT2NUM(0));
00141 #endif
00142
00143
00144 rb_iv_set(self, "@error", Qnil);
00145 rb_iv_set(self, "@error_string", Qnil);
00146 rb_iv_set(self, "@chain", Qnil);
00147 rb_iv_set(self, "@time", Qnil);
00148
00149 return self;
00150 }
00151
00152 static VALUE
00153 ossl_x509store_set_flags(VALUE self, VALUE flags)
00154 {
00155 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00156 X509_STORE *store;
00157 long f = NUM2LONG(flags);
00158
00159 GetX509Store(self, store);
00160 X509_STORE_set_flags(store, f);
00161 #else
00162 rb_iv_set(self, "@flags", flags);
00163 #endif
00164
00165 return flags;
00166 }
00167
00168 static VALUE
00169 ossl_x509store_set_purpose(VALUE self, VALUE purpose)
00170 {
00171 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00172 X509_STORE *store;
00173 int p = NUM2INT(purpose);
00174
00175 GetX509Store(self, store);
00176 X509_STORE_set_purpose(store, p);
00177 #else
00178 rb_iv_set(self, "@purpose", purpose);
00179 #endif
00180
00181 return purpose;
00182 }
00183
00184 static VALUE
00185 ossl_x509store_set_trust(VALUE self, VALUE trust)
00186 {
00187 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00188 X509_STORE *store;
00189 int t = NUM2INT(trust);
00190
00191 GetX509Store(self, store);
00192 X509_STORE_set_trust(store, t);
00193 #else
00194 rb_iv_set(self, "@trust", trust);
00195 #endif
00196
00197 return trust;
00198 }
00199
00200 static VALUE
00201 ossl_x509store_set_time(VALUE self, VALUE time)
00202 {
00203 rb_iv_set(self, "@time", time);
00204 return time;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 static VALUE
00217 ossl_x509store_add_file(VALUE self, VALUE file)
00218 {
00219 X509_STORE *store;
00220 X509_LOOKUP *lookup;
00221 char *path = NULL;
00222
00223 if(file != Qnil){
00224 SafeStringValue(file);
00225 path = RSTRING_PTR(file);
00226 }
00227 GetX509Store(self, store);
00228 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
00229 if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
00230 if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
00231 ossl_raise(eX509StoreError, NULL);
00232 }
00233
00234 return self;
00235 }
00236
00237 static VALUE
00238 ossl_x509store_add_path(VALUE self, VALUE dir)
00239 {
00240 X509_STORE *store;
00241 X509_LOOKUP *lookup;
00242 char *path = NULL;
00243
00244 if(dir != Qnil){
00245 SafeStringValue(dir);
00246 path = RSTRING_PTR(dir);
00247 }
00248 GetX509Store(self, store);
00249 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
00250 if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
00251 if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
00252 ossl_raise(eX509StoreError, NULL);
00253 }
00254
00255 return self;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 static VALUE
00269 ossl_x509store_set_default_paths(VALUE self)
00270 {
00271 X509_STORE *store;
00272
00273 GetX509Store(self, store);
00274 if (X509_STORE_set_default_paths(store) != 1){
00275 ossl_raise(eX509StoreError, NULL);
00276 }
00277
00278 return Qnil;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288 static VALUE
00289 ossl_x509store_add_cert(VALUE self, VALUE arg)
00290 {
00291 X509_STORE *store;
00292 X509 *cert;
00293
00294 cert = GetX509CertPtr(arg);
00295 GetX509Store(self, store);
00296 if (X509_STORE_add_cert(store, cert) != 1){
00297 ossl_raise(eX509StoreError, NULL);
00298 }
00299
00300 return self;
00301 }
00302
00303 static VALUE
00304 ossl_x509store_add_crl(VALUE self, VALUE arg)
00305 {
00306 X509_STORE *store;
00307 X509_CRL *crl;
00308
00309 crl = GetX509CRLPtr(arg);
00310 GetX509Store(self, store);
00311 if (X509_STORE_add_crl(store, crl) != 1){
00312 ossl_raise(eX509StoreError, NULL);
00313 }
00314
00315 return self;
00316 }
00317
00318 static VALUE ossl_x509stctx_get_err(VALUE);
00319 static VALUE ossl_x509stctx_get_err_string(VALUE);
00320 static VALUE ossl_x509stctx_get_chain(VALUE);
00321
00322 static VALUE
00323 ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
00324 {
00325 VALUE cert, chain;
00326 VALUE ctx, proc, result;
00327
00328 rb_scan_args(argc, argv, "11", &cert, &chain);
00329 ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
00330 proc = rb_block_given_p() ? rb_block_proc() :
00331 rb_iv_get(self, "@verify_callback");
00332 rb_iv_set(ctx, "@verify_callback", proc);
00333 result = rb_funcall(ctx, rb_intern("verify"), 0);
00334
00335 rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
00336 rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
00337 rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
00338
00339 return result;
00340 }
00341
00342
00343
00344
00345 static void ossl_x509stctx_free(X509_STORE_CTX*);
00346
00347 VALUE
00348 ossl_x509stctx_new(X509_STORE_CTX *ctx)
00349 {
00350 VALUE obj;
00351
00352 WrapX509StCtx(cX509StoreContext, obj, ctx);
00353
00354 return obj;
00355 }
00356
00357 VALUE
00358 ossl_x509stctx_clear_ptr(VALUE obj)
00359 {
00360 OSSL_Check_Kind(obj, cX509StoreContext);
00361 RDATA(obj)->data = NULL;
00362
00363 return obj;
00364 }
00365
00366
00367
00368
00369 static void
00370 ossl_x509stctx_free(X509_STORE_CTX *ctx)
00371 {
00372 if(ctx->untrusted)
00373 sk_X509_pop_free(ctx->untrusted, X509_free);
00374 if(ctx->cert)
00375 X509_free(ctx->cert);
00376 X509_STORE_CTX_free(ctx);
00377 }
00378
00379 static VALUE
00380 ossl_x509stctx_alloc(VALUE klass)
00381 {
00382 X509_STORE_CTX *ctx;
00383 VALUE obj;
00384
00385 if((ctx = X509_STORE_CTX_new()) == NULL){
00386 ossl_raise(eX509StoreError, NULL);
00387 }
00388 WrapX509StCtx(klass, obj, ctx);
00389
00390 return obj;
00391 }
00392
00393 static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
00394 static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
00395 static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
00396 static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
00397
00398 static VALUE
00399 ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
00400 {
00401 VALUE store, cert, chain, t;
00402 X509_STORE_CTX *ctx;
00403 X509_STORE *x509st;
00404 X509 *x509 = NULL;
00405 STACK_OF(X509) *x509s = NULL;
00406
00407 rb_scan_args(argc, argv, "12", &store, &cert, &chain);
00408 GetX509StCtx(self, ctx);
00409 SafeGetX509Store(store, x509st);
00410 if(!NIL_P(cert)) x509 = DupX509CertPtr(cert);
00411 if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
00412 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00413 if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
00414 sk_X509_pop_free(x509s, X509_free);
00415 ossl_raise(eX509StoreError, NULL);
00416 }
00417 #else
00418 X509_STORE_CTX_init(ctx, x509st, x509, x509s);
00419 ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
00420 ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
00421 ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
00422 #endif
00423 if (!NIL_P(t = rb_iv_get(store, "@time")))
00424 ossl_x509stctx_set_time(self, t);
00425 rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
00426 rb_iv_set(self, "@cert", cert);
00427
00428 return self;
00429 }
00430
00431 static VALUE
00432 ossl_x509stctx_verify(VALUE self)
00433 {
00434 X509_STORE_CTX *ctx;
00435 int result;
00436
00437 GetX509StCtx(self, ctx);
00438 X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
00439 (void*)rb_iv_get(self, "@verify_callback"));
00440 result = X509_verify_cert(ctx);
00441
00442 return result ? Qtrue : Qfalse;
00443 }
00444
00445 static VALUE
00446 ossl_x509stctx_get_chain(VALUE self)
00447 {
00448 X509_STORE_CTX *ctx;
00449 STACK_OF(X509) *chain;
00450 X509 *x509;
00451 int i, num;
00452 VALUE ary;
00453
00454 GetX509StCtx(self, ctx);
00455 if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){
00456 return Qnil;
00457 }
00458 if((num = sk_X509_num(chain)) < 0){
00459 OSSL_Debug("certs in chain < 0???");
00460 return rb_ary_new();
00461 }
00462 ary = rb_ary_new2(num);
00463 for(i = 0; i < num; i++) {
00464 x509 = sk_X509_value(chain, i);
00465 rb_ary_push(ary, ossl_x509_new(x509));
00466 }
00467
00468 return ary;
00469 }
00470
00471 static VALUE
00472 ossl_x509stctx_get_err(VALUE self)
00473 {
00474 X509_STORE_CTX *ctx;
00475
00476 GetX509StCtx(self, ctx);
00477
00478 return INT2FIX(X509_STORE_CTX_get_error(ctx));
00479 }
00480
00481 static VALUE
00482 ossl_x509stctx_set_error(VALUE self, VALUE err)
00483 {
00484 X509_STORE_CTX *ctx;
00485
00486 GetX509StCtx(self, ctx);
00487 X509_STORE_CTX_set_error(ctx, NUM2INT(err));
00488
00489 return err;
00490 }
00491
00492 static VALUE
00493 ossl_x509stctx_get_err_string(VALUE self)
00494 {
00495 X509_STORE_CTX *ctx;
00496 long err;
00497
00498 GetX509StCtx(self, ctx);
00499 err = X509_STORE_CTX_get_error(ctx);
00500
00501 return rb_str_new2(X509_verify_cert_error_string(err));
00502 }
00503
00504 static VALUE
00505 ossl_x509stctx_get_err_depth(VALUE self)
00506 {
00507 X509_STORE_CTX *ctx;
00508
00509 GetX509StCtx(self, ctx);
00510
00511 return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
00512 }
00513
00514 static VALUE
00515 ossl_x509stctx_get_curr_cert(VALUE self)
00516 {
00517 X509_STORE_CTX *ctx;
00518
00519 GetX509StCtx(self, ctx);
00520
00521 return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
00522 }
00523
00524 static VALUE
00525 ossl_x509stctx_get_curr_crl(VALUE self)
00526 {
00527 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00528 X509_STORE_CTX *ctx;
00529
00530 GetX509StCtx(self, ctx);
00531 if(!ctx->current_crl) return Qnil;
00532
00533 return ossl_x509crl_new(ctx->current_crl);
00534 #else
00535 return Qnil;
00536 #endif
00537 }
00538
00539 static VALUE
00540 ossl_x509stctx_set_flags(VALUE self, VALUE flags)
00541 {
00542 X509_STORE_CTX *store;
00543 long f = NUM2LONG(flags);
00544
00545 GetX509StCtx(self, store);
00546 X509_STORE_CTX_set_flags(store, f);
00547
00548 return flags;
00549 }
00550
00551 static VALUE
00552 ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
00553 {
00554 X509_STORE_CTX *store;
00555 int p = NUM2INT(purpose);
00556
00557 GetX509StCtx(self, store);
00558 X509_STORE_CTX_set_purpose(store, p);
00559
00560 return purpose;
00561 }
00562
00563 static VALUE
00564 ossl_x509stctx_set_trust(VALUE self, VALUE trust)
00565 {
00566 X509_STORE_CTX *store;
00567 int t = NUM2INT(trust);
00568
00569 GetX509StCtx(self, store);
00570 X509_STORE_CTX_set_trust(store, t);
00571
00572 return trust;
00573 }
00574
00575
00576
00577
00578
00579 static VALUE
00580 ossl_x509stctx_set_time(VALUE self, VALUE time)
00581 {
00582 X509_STORE_CTX *store;
00583 long t;
00584
00585 t = NUM2LONG(rb_Integer(time));
00586 GetX509StCtx(self, store);
00587 X509_STORE_CTX_set_time(store, 0, t);
00588
00589 return time;
00590 }
00591
00592
00593
00594
00595 void
00596 Init_ossl_x509store()
00597 {
00598 VALUE x509stctx;
00599
00600 #if 0
00601 mOSSL = rb_define_module("OpenSSL");
00602 mX509 = rb_define_module_under(mOSSL, "X509");
00603 #endif
00604
00605 eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
00642 rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
00643 rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
00644 rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
00645 rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
00646 rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
00647 rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
00648 rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
00649 rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
00650 rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
00651 rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
00652 rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
00653 rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
00654 rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
00655 rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
00656 rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
00657 rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
00658 rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
00659
00660 cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject);
00661 x509stctx = cX509StoreContext;
00662 rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
00663 rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
00664 rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
00665 rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
00666 rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
00667 rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
00668 rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
00669 rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
00670 rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
00671 rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
00672 rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
00673 rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
00674 rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
00675 rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
00676
00677 }
00678