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 long p = NUM2LONG(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 long t = NUM2LONG(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 static VALUE
00208 ossl_x509store_add_file(VALUE self, VALUE file)
00209 {
00210 X509_STORE *store;
00211 X509_LOOKUP *lookup;
00212 char *path = NULL;
00213
00214 if(file != Qnil){
00215 SafeStringValue(file);
00216 path = RSTRING_PTR(file);
00217 }
00218 GetX509Store(self, store);
00219 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
00220 if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
00221 if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
00222 ossl_raise(eX509StoreError, NULL);
00223 }
00224
00225 return self;
00226 }
00227
00228 static VALUE
00229 ossl_x509store_add_path(VALUE self, VALUE dir)
00230 {
00231 X509_STORE *store;
00232 X509_LOOKUP *lookup;
00233 char *path = NULL;
00234
00235 if(dir != Qnil){
00236 SafeStringValue(dir);
00237 path = RSTRING_PTR(dir);
00238 }
00239 GetX509Store(self, store);
00240 lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
00241 if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
00242 if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
00243 ossl_raise(eX509StoreError, NULL);
00244 }
00245
00246 return self;
00247 }
00248
00249 static VALUE
00250 ossl_x509store_set_default_paths(VALUE self)
00251 {
00252 X509_STORE *store;
00253
00254 GetX509Store(self, store);
00255 if (X509_STORE_set_default_paths(store) != 1){
00256 ossl_raise(eX509StoreError, NULL);
00257 }
00258
00259 return Qnil;
00260 }
00261
00262 static VALUE
00263 ossl_x509store_add_cert(VALUE self, VALUE arg)
00264 {
00265 X509_STORE *store;
00266 X509 *cert;
00267
00268 cert = GetX509CertPtr(arg);
00269 GetX509Store(self, store);
00270 if (X509_STORE_add_cert(store, cert) != 1){
00271 ossl_raise(eX509StoreError, NULL);
00272 }
00273
00274 return self;
00275 }
00276
00277 static VALUE
00278 ossl_x509store_add_crl(VALUE self, VALUE arg)
00279 {
00280 X509_STORE *store;
00281 X509_CRL *crl;
00282
00283 crl = GetX509CRLPtr(arg);
00284 GetX509Store(self, store);
00285 if (X509_STORE_add_crl(store, crl) != 1){
00286 ossl_raise(eX509StoreError, NULL);
00287 }
00288
00289 return self;
00290 }
00291
00292 static VALUE ossl_x509stctx_get_err(VALUE);
00293 static VALUE ossl_x509stctx_get_err_string(VALUE);
00294 static VALUE ossl_x509stctx_get_chain(VALUE);
00295
00296 static VALUE
00297 ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
00298 {
00299 VALUE cert, chain;
00300 VALUE ctx, proc, result;
00301
00302 rb_scan_args(argc, argv, "11", &cert, &chain);
00303 ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
00304 proc = rb_block_given_p() ? rb_block_proc() :
00305 rb_iv_get(self, "@verify_callback");
00306 rb_iv_set(ctx, "@verify_callback", proc);
00307 result = rb_funcall(ctx, rb_intern("verify"), 0);
00308
00309 rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
00310 rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
00311 rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
00312
00313 return result;
00314 }
00315
00316
00317
00318
00319 static void ossl_x509stctx_free(X509_STORE_CTX*);
00320
00321 VALUE
00322 ossl_x509stctx_new(X509_STORE_CTX *ctx)
00323 {
00324 VALUE obj;
00325
00326 WrapX509StCtx(cX509StoreContext, obj, ctx);
00327
00328 return obj;
00329 }
00330
00331 VALUE
00332 ossl_x509stctx_clear_ptr(VALUE obj)
00333 {
00334 OSSL_Check_Kind(obj, cX509StoreContext);
00335 RDATA(obj)->data = NULL;
00336
00337 return obj;
00338 }
00339
00340
00341
00342
00343 static void
00344 ossl_x509stctx_free(X509_STORE_CTX *ctx)
00345 {
00346 if(ctx->untrusted)
00347 sk_X509_pop_free(ctx->untrusted, X509_free);
00348 if(ctx->cert)
00349 X509_free(ctx->cert);
00350 X509_STORE_CTX_free(ctx);
00351 }
00352
00353 static VALUE
00354 ossl_x509stctx_alloc(VALUE klass)
00355 {
00356 X509_STORE_CTX *ctx;
00357 VALUE obj;
00358
00359 if((ctx = X509_STORE_CTX_new()) == NULL){
00360 ossl_raise(eX509StoreError, NULL);
00361 }
00362 WrapX509StCtx(klass, obj, ctx);
00363
00364 return obj;
00365 }
00366
00367 static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
00368 static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
00369 static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
00370 static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
00371
00372 static VALUE
00373 ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
00374 {
00375 VALUE store, cert, chain, t;
00376 X509_STORE_CTX *ctx;
00377 X509_STORE *x509st;
00378 X509 *x509 = NULL;
00379 STACK_OF(X509) *x509s = NULL;
00380
00381 rb_scan_args(argc, argv, "12", &store, &cert, &chain);
00382 GetX509StCtx(self, ctx);
00383 SafeGetX509Store(store, x509st);
00384 if(!NIL_P(cert)) x509 = DupX509CertPtr(cert);
00385 if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
00386 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00387 if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
00388 sk_X509_pop_free(x509s, X509_free);
00389 ossl_raise(eX509StoreError, NULL);
00390 }
00391 #else
00392 X509_STORE_CTX_init(ctx, x509st, x509, x509s);
00393 ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
00394 ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
00395 ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
00396 #endif
00397 if (!NIL_P(t = rb_iv_get(store, "@time")))
00398 ossl_x509stctx_set_time(self, t);
00399 rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
00400 rb_iv_set(self, "@cert", cert);
00401
00402 return self;
00403 }
00404
00405 static VALUE
00406 ossl_x509stctx_verify(VALUE self)
00407 {
00408 X509_STORE_CTX *ctx;
00409 int result;
00410
00411 GetX509StCtx(self, ctx);
00412 X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
00413 (void*)rb_iv_get(self, "@verify_callback"));
00414 result = X509_verify_cert(ctx);
00415
00416 return result ? Qtrue : Qfalse;
00417 }
00418
00419 static VALUE
00420 ossl_x509stctx_get_chain(VALUE self)
00421 {
00422 X509_STORE_CTX *ctx;
00423 STACK_OF(X509) *chain;
00424 X509 *x509;
00425 int i, num;
00426 VALUE ary;
00427
00428 GetX509StCtx(self, ctx);
00429 if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){
00430 return Qnil;
00431 }
00432 if((num = sk_X509_num(chain)) < 0){
00433 OSSL_Debug("certs in chain < 0???");
00434 return rb_ary_new();
00435 }
00436 ary = rb_ary_new2(num);
00437 for(i = 0; i < num; i++) {
00438 x509 = sk_X509_value(chain, i);
00439 rb_ary_push(ary, ossl_x509_new(x509));
00440 }
00441
00442 return ary;
00443 }
00444
00445 static VALUE
00446 ossl_x509stctx_get_err(VALUE self)
00447 {
00448 X509_STORE_CTX *ctx;
00449
00450 GetX509StCtx(self, ctx);
00451
00452 return INT2FIX(X509_STORE_CTX_get_error(ctx));
00453 }
00454
00455 static VALUE
00456 ossl_x509stctx_set_error(VALUE self, VALUE err)
00457 {
00458 X509_STORE_CTX *ctx;
00459
00460 GetX509StCtx(self, ctx);
00461 X509_STORE_CTX_set_error(ctx, NUM2INT(err));
00462
00463 return err;
00464 }
00465
00466 static VALUE
00467 ossl_x509stctx_get_err_string(VALUE self)
00468 {
00469 X509_STORE_CTX *ctx;
00470 long err;
00471
00472 GetX509StCtx(self, ctx);
00473 err = X509_STORE_CTX_get_error(ctx);
00474
00475 return rb_str_new2(X509_verify_cert_error_string(err));
00476 }
00477
00478 static VALUE
00479 ossl_x509stctx_get_err_depth(VALUE self)
00480 {
00481 X509_STORE_CTX *ctx;
00482
00483 GetX509StCtx(self, ctx);
00484
00485 return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
00486 }
00487
00488 static VALUE
00489 ossl_x509stctx_get_curr_cert(VALUE self)
00490 {
00491 X509_STORE_CTX *ctx;
00492
00493 GetX509StCtx(self, ctx);
00494
00495 return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
00496 }
00497
00498 static VALUE
00499 ossl_x509stctx_get_curr_crl(VALUE self)
00500 {
00501 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
00502 X509_STORE_CTX *ctx;
00503
00504 GetX509StCtx(self, ctx);
00505 if(!ctx->current_crl) return Qnil;
00506
00507 return ossl_x509crl_new(ctx->current_crl);
00508 #else
00509 return Qnil;
00510 #endif
00511 }
00512
00513 static VALUE
00514 ossl_x509stctx_cleanup(VALUE self)
00515 {
00516 X509_STORE_CTX *ctx;
00517
00518 GetX509StCtx(self, ctx);
00519 X509_STORE_CTX_cleanup(ctx);
00520
00521 return self;
00522 }
00523
00524 static VALUE
00525 ossl_x509stctx_set_flags(VALUE self, VALUE flags)
00526 {
00527 X509_STORE_CTX *store;
00528 long f = NUM2LONG(flags);
00529
00530 GetX509StCtx(self, store);
00531 X509_STORE_CTX_set_flags(store, f);
00532
00533 return flags;
00534 }
00535
00536 static VALUE
00537 ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
00538 {
00539 X509_STORE_CTX *store;
00540 long p = NUM2LONG(purpose);
00541
00542 GetX509StCtx(self, store);
00543 X509_STORE_CTX_set_purpose(store, p);
00544
00545 return purpose;
00546 }
00547
00548 static VALUE
00549 ossl_x509stctx_set_trust(VALUE self, VALUE trust)
00550 {
00551 X509_STORE_CTX *store;
00552 long t = NUM2LONG(trust);
00553
00554 GetX509StCtx(self, store);
00555 X509_STORE_CTX_set_trust(store, t);
00556
00557 return trust;
00558 }
00559
00560
00561
00562
00563
00564 static VALUE
00565 ossl_x509stctx_set_time(VALUE self, VALUE time)
00566 {
00567 X509_STORE_CTX *store;
00568 long t;
00569
00570 t = NUM2LONG(rb_Integer(time));
00571 GetX509StCtx(self, store);
00572 X509_STORE_CTX_set_time(store, 0, t);
00573
00574 return time;
00575 }
00576
00577
00578
00579
00580 void
00581 Init_ossl_x509store()
00582 {
00583 VALUE x509stctx;
00584
00585 eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
00586
00587 cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
00588 rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
00589 rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
00590 rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
00591 rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
00592 rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
00593 rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
00594 rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
00595 rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
00596 rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
00597 rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
00598 rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
00599 rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
00600 rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
00601 rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
00602 rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
00603 rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
00604 rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
00605
00606 cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject);
00607 x509stctx = cX509StoreContext;
00608 rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
00609 rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
00610 rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
00611 rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
00612 rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
00613 rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
00614 rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
00615 rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
00616 rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
00617 rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
00618 rb_define_method(x509stctx,"cleanup", ossl_x509stctx_cleanup, 0);
00619 rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
00620 rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
00621 rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
00622 rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
00623
00624 }
00625