From 78ff3833fb67c8005a9b851037e74b3eea940aa3 Mon Sep 17 00:00:00 2001 From: gotoyuzo Date: Mon, 8 Sep 2003 10:31:38 +0000 Subject: * ext/openssl/ossl.h: include openssl/conf.h and openssl/conf_api.h. * ext/openssl/ossl_config.c: refine all with backward compatibility. * ext/openssl/ossl_config.h: export GetConfigPtr() and DupConfigPtr(). * ext/openssl/ossl_x509.c: added new constants under X509 module. DEFAULT_CERT_AREA, DEFAULT_CERT_DIR, DEFAULT_CERT_FILE, DEFAULT_CERT_DIR_ENV, DEFAULT_CERT_FILE_ENV and DEFAULT_PRIVATE_DIR. * ext/openssl/ossl_x509ext.c (ossl_x509extfactory_free): don't free the members of the struct. it's left to GC. * ext/openssl/ossl_x509ext.c (ossl_x509_set_config): add for config=. * ext/openssl/ossl_x509ext.c (Xossl_x509extfactory_initialize): add attr readers: issuer_certificate, subject_certificate, subject_request, crl and config. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4531 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 +- ext/openssl/ossl.h | 2 + ext/openssl/ossl_config.c | 325 ++++++++++++++++++++++++++++++++++++++------- ext/openssl/ossl_config.h | 2 + ext/openssl/ossl_x509.c | 9 ++ ext/openssl/ossl_x509ext.c | 33 ++++- 6 files changed, 316 insertions(+), 61 deletions(-) diff --git a/ChangeLog b/ChangeLog index b331c7c772..d467857bda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,9 +6,9 @@ Mon Sep 8 19:26:33 2003 GOTOU Yuuzou * ext/openssl/ossl_config.h: export GetConfigPtr() and DupConfigPtr(). - * ext/openssl/ossl_x509.c: new constants DEFAULT_CERT_AREA, - DEFAULT_CERT_DIR, DEFAULT_CERT_FILE, DEFAULT_CERT_DIR_ENV, - DEFAULT_CERT_FILE_ENV and DEFAULT_PRIVATE_DIR in X509 module. + * ext/openssl/ossl_x509.c: added new constants under X509 module. + DEFAULT_CERT_AREA, DEFAULT_CERT_DIR, DEFAULT_CERT_FILE, + DEFAULT_CERT_DIR_ENV, DEFAULT_CERT_FILE_ENV and DEFAULT_PRIVATE_DIR. * ext/openssl/ossl_x509ext.c (ossl_x509extfactory_free): don't free the members of the struct. it's left to GC. diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 7a8b3e1853..e684d212e6 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -32,6 +32,8 @@ extern "C" { #include #include #include +#include +#include #undef X509_NAME #undef PKCS7_SIGNER_INFO #if defined(HAVE_OPENSSL_OCSP_H) diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c index f721bb90b1..1aeaa2306b 100644 --- a/ext/openssl/ossl_config.c +++ b/ext/openssl/ossl_config.c @@ -16,13 +16,16 @@ } \ obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \ } while (0) - #define GetConfig(obj, conf) do { \ Data_Get_Struct(obj, CONF, conf); \ if (!conf) { \ ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \ } \ } while (0) +#define SafeGetConfig(obj, conf) do { \ + OSSL_Check_Kind(obj, cConfig); \ + GetConfig(obj, conf); \ +} while(0); /* * Classes @@ -34,77 +37,200 @@ VALUE eConfigError; * Public */ +static CONF *parse_config(VALUE, CONF*); + +CONF * +GetConfigPtr(VALUE obj) +{ + CONF *conf; + + SafeGetConfig(obj, conf); + + return conf; +} + +CONF * +DupConfigPtr(VALUE obj) +{ + CONF *conf; + VALUE str; + + OSSL_Check_Kind(obj, cConfig); + str = rb_funcall(obj, rb_intern("to_s"), 0); + + return parse_config(str, NULL); +} + /* * Private */ +static CONF * +parse_config(VALUE str, CONF *dst) +{ + CONF *conf; + BIO *bio; + long eline = -1; + VALUE obj; + + bio = ossl_obj2bio(str); + conf = dst ? dst : NCONF_new(NULL); + if(!conf){ + BIO_free(bio); + ossl_raise(eConfigError, NULL); + } + if(!NCONF_load_bio(conf, bio, &eline)){ + BIO_free(bio); + if(!dst) NCONF_free(conf); + if (eline <= 0) ossl_raise(eConfigError, "wrong config format"); + else ossl_raise(eConfigError, "error in line %d", eline); + ossl_raise(eConfigError, NULL); + } + BIO_free(bio); + + return conf; +} + +static VALUE +ossl_config_s_parse(VALUE klass, VALUE str) +{ + CONF *conf; + VALUE obj; + + conf = parse_config(str, NULL); + WrapConfig(klass, obj, conf); + + return obj; +} + +static VALUE +ossl_config_s_alloc(VALUE klass) +{ + CONF *conf; + VALUE obj; + + if(!(conf = NCONF_new(NULL))) + ossl_rasie(eConfigError, NULL); + WrapConfig(klass, obj, conf); + + return obj; +} + +static VALUE +ossl_config_copy(VALUE self, VALUE other) +{ + VALUE str; + CONF *conf; + + GetConfig(other, conf); + str = rb_funcall(self, rb_intern("to_s"), 0); + parse_config(str, conf); + + return self; +} + static VALUE -ossl_config_s_load(int argc, VALUE *argv, VALUE klass) +ossl_config_initialize(int argc, VALUE *argv, VALUE self) { CONF *conf; - long err_line = -1; + long eline = -1; char *filename; - VALUE path, obj; + VALUE path; - if (rb_scan_args(argc, argv, "01", &path) == 1) { + GetConfig(self, conf); + rb_scan_args(argc, argv, "01", &path); + if(!NIL_P(path)){ SafeStringValue(path); - filename = BUF_strdup(RSTRING(path)->ptr); + filename = StringValuePtr(path); + if (!NCONF_load(conf, filename, &eline)){ + if (eline <= 0) + ossl_raise(eConfigError, "wrong config file %s", filename); + else + ossl_raise(eConfigError, "error in %s:%d", filename, eline); + } } - else { - if (!(filename = CONF_get1_default_config_file())) { + else _CONF_new_data(conf); + + return self; +} + +static VALUE +ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value) +{ + CONF *conf; + CONF_VALUE *sv, *cv; + + GetConfig(self, conf); + StringValue(section); + StringValue(name); + StringValue(value); + if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){ + if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){ ossl_raise(eConfigError, NULL); } } - if (!(conf = NCONF_new(NULL))) { - OPENSSL_free(filename); + if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){ ossl_raise(eConfigError, NULL); } - OSSL_Debug("Loading file: %s", filename); - - if (!NCONF_load(conf, filename, &err_line)) { - char tmp[255]; - - memcpy(tmp, filename, strlen(filename)>=sizeof(tmp)?sizeof(tmp):strlen(filename)); - tmp[sizeof(tmp)-1] = '\0'; - OPENSSL_free(filename); - - if (err_line <= 0) { - ossl_raise(eConfigError, "wrong config file (%s)", tmp); - } else { - ossl_raise(eConfigError, "error on line %ld in config file \"%s\"", - err_line, tmp); - } + cv->name = BUF_strdup(RSTRING(name)->ptr); + cv->value = BUF_strdup(RSTRING(value)->ptr); + if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){ + OPENSSL_free(cv->name); + OPENSSL_free(cv->value); + OPENSSL_free(cv); + ossl_raise(eConfigError, "_CONF_add_string failure"); } - OPENSSL_free(filename); - WrapConfig(klass, obj, conf); - return obj; + return value; } static VALUE -ossl_config_get_value(int argc, VALUE *argv, VALUE self) +ossl_config_get_value(VALUE self, VALUE section, VALUE name) { CONF *conf; - VALUE section, item; - char *sect = NULL, *str; - + char *str; + GetConfig(self, conf); + StringValue(section); + StringValue(name); + str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr); + if(!str) ossl_raise(eConfigError, NULL); - if (rb_scan_args(argc, argv, "11", §ion, &item) == 1) { - item = section; - } else if (!NIL_P(section)) { - sect = StringValuePtr(section); - } - if (!(str = NCONF_get_string(conf, sect, StringValuePtr(item)))) { - ossl_raise(eConfigError, NULL); - } return rb_str_new2(str); } +static VALUE +ossl_config_get_value_old(int argc, VALUE *argv, VALUE self) +{ + VALUE section, name; + rb_scan_args(argc, argv, "11", §ion, &name); + rb_warn("Config#value is deprecated; use Config#get_value"); + return ossl_config_get_value(self, section, name); +} + +static VALUE +set_conf_section_i(VALUE i, VALUE *arg) +{ + VALUE name, value; + + name = rb_ary_entry(i, 0); + value = rb_ary_entry(i, 1); + ossl_config_add_value(arg[0], arg[1], name, value); + + return Qnil; +} + +static VALUE +ossl_config_set_section(VALUE self, VALUE section, VALUE hash) +{ + VALUE arg[2] = { self, section }; + rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg); + return hash; +} + /* * Get all numbers as strings - use str.to_i to convert * long number = CONF_get_number(confp->config, sect, StringValuePtr(item)); */ - static VALUE ossl_config_get_section(VALUE self, VALUE section) { @@ -115,12 +241,10 @@ ossl_config_get_section(VALUE self, VALUE section) VALUE hash; GetConfig(self, conf); - if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) { ossl_raise(eConfigError, NULL); } hash = rb_hash_new(); - if ((entries = sk_CONF_VALUE_num(sk)) < 0) { OSSL_Debug("# of items in section is < 0?!?"); return hash; @@ -129,9 +253,100 @@ ossl_config_get_section(VALUE self, VALUE section) entry = sk_CONF_VALUE_value(sk, i); rb_hash_aset(hash, rb_str_new2(entry->name), rb_str_new2(entry->value)); } + return hash; } +static VALUE +ossl_config_get_section_old(VALUE self, VALUE section) +{ + rb_warn("Config#section is deprecated; use Config#[]"); + return ossl_config_get_section(self, section); +} + +static void +get_conf_section(CONF_VALUE *cv, VALUE ary) +{ + if(cv->name) return; + rb_ary_push(ary, rb_str_new2(cv->section)); +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE*, VALUE); + +static VALUE +ossl_config_get_sections(VALUE self) +{ + CONF *conf; + VALUE ary; + + GetConfig(self, conf); + ary = rb_ary_new(); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(get_conf_section), (void*)ary); + + return ary; +} + +static void +dump_conf_value(CONF_VALUE *cv, VALUE str) +{ + STACK_OF(CONF_VALUE) *sk; + CONF_VALUE *v; + int i, num; + + if (cv->name) return; + sk = (STACK_OF(CONF_VALUE)*)cv->value; + num = sk_CONF_VALUE_num(sk); + rb_str_cat2(str, "[ "); + rb_str_cat2(str, cv->section); + rb_str_cat2(str, " ]\n"); + for(i = 0; i < num; i++){ + v = sk_CONF_VALUE_value(sk, i); + rb_str_cat2(str, v->name ? v->name : "None"); + rb_str_cat2(str, "="); + rb_str_cat2(str, v->value ? v->value : "None"); + rb_str_cat2(str, "\n"); + } + rb_str_cat2(str, "\n"); +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE*, VALUE); + +static VALUE +dump_conf(CONF *conf) +{ + VALUE str; + + str = rb_str_new(0, 0); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_conf_value), (void*)str); + + return str; +} + +static VALUE +ossl_config_to_s(VALUE self) +{ + CONF *conf; + + GetConfig(self, conf); + + return dump_conf(conf); +} + +static VALUE +ossl_config_inspect(VALUE self) +{ + VALUE str, ary = ossl_config_get_sections(self); + char *cname = rb_class2name(rb_obj_class(self)); + + str = rb_str_new2("#<"); + rb_str_cat2(str, cname); + rb_str_cat2(str, " sections="); + rb_str_append(str, rb_inspect(ary)); + rb_str_cat2(str, ">"); + + return str; +} + /* * INIT */ @@ -139,14 +354,22 @@ void Init_ossl_config() { eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError); - cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject); - - rb_define_singleton_method(cConfig, "load", ossl_config_s_load, -1); - rb_define_alias(CLASS_OF(cConfig), "new", "load"); - rb_define_method(cConfig, "value", ossl_config_get_value, -1); - rb_define_method(cConfig, "section", ossl_config_get_section, 1); - rb_define_alias(cConfig, "[]", "section"); + rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", + rb_str_new2(CONF_get1_default_config_file())); + rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1); + rb_define_alias(CLASS_OF(cConfig), "load", "new"); + rb_define_alloc_func(cConfig, ossl_config_s_alloc); + rb_define_copy_func(cConfig, ossl_config_copy); + rb_define_method(cConfig, "initialize", ossl_config_initialize, -1); + rb_define_method(cConfig, "get_value", ossl_config_get_value, 2); + rb_define_method(cConfig, "value", ossl_config_get_value_old, -1); + rb_define_method(cConfig, "add_value", ossl_config_add_value, 3); + rb_define_method(cConfig, "[]", ossl_config_get_section, 1); + rb_define_method(cConfig, "section", ossl_config_get_section_old, 1); + rb_define_method(cConfig, "[]=", ossl_config_set_section, 2); + rb_define_method(cConfig, "sections", ossl_config_get_sections, 0); + rb_define_method(cConfig, "to_s", ossl_config_to_s, 0); + rb_define_method(cConfig, "inspect", ossl_config_inspect, 0); } - diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h index c45619dc1b..cb226b27e5 100644 --- a/ext/openssl/ossl_config.h +++ b/ext/openssl/ossl_config.h @@ -14,6 +14,8 @@ extern VALUE cConfig; extern VALUE eConfigError; +CONF* GetConfigPtr(VALUE obj); +CONF* DupConfigPtr(VALUE obj); void Init_ossl_config(void); #endif /* _OSSL_CONFIG_H_ */ diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c index 1fe50abf2c..fd1d9b6c7e 100644 --- a/ext/openssl/ossl_x509.c +++ b/ext/openssl/ossl_x509.c @@ -13,6 +13,8 @@ VALUE mX509; #define DefX509Const(x) rb_define_const(mX509, #x,INT2FIX(X509_##x)) +#define DefX509Default(x,i) \ + rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i())) void Init_ossl_x509() @@ -91,5 +93,12 @@ Init_ossl_x509() #if defined(X509_TRUST_OCSP_REQUEST) DefX509Const(TRUST_OCSP_REQUEST); #endif + + DefX509Default(CERT_AREA, cert_area); + DefX509Default(CERT_DIR, cert_dir); + DefX509Default(CERT_FILE, cert_file); + DefX509Default(CERT_DIR_ENV, cert_dir_env); + DefX509Default(CERT_FILE_ENV, cert_file_env); + DefX509Default(PRIVATE_DIR, private_dir); } diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index d65320311a..c1f443df66 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -97,13 +97,7 @@ DupX509ExtPtr(VALUE obj) static void ossl_x509extfactory_free(X509V3_CTX *ctx) { - if (ctx) { - if (ctx->issuer_cert) X509_free(ctx->issuer_cert); - if (ctx->subject_cert) X509_free(ctx->subject_cert); - if (ctx->crl) X509_CRL_free(ctx->crl); - if (ctx->subject_req) X509_REQ_free(ctx->subject_req); - OPENSSL_free(ctx); - } + OPENSSL_free(ctx); } static VALUE @@ -123,6 +117,7 @@ ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert) X509V3_CTX *ctx; GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@issuer_certificate", cert); ctx->issuer_cert = DupX509CertPtr(cert); /* DUP NEEDED */ return cert; @@ -134,6 +129,7 @@ ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert) X509V3_CTX *ctx; GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@subject_certificate", cert); ctx->subject_cert = DupX509CertPtr(cert); /* DUP NEEDED */ return cert; @@ -145,6 +141,7 @@ ossl_x509extfactory_set_subject_req(VALUE self, VALUE req) X509V3_CTX *ctx; GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@subject_request", req); ctx->subject_req = DupX509ReqPtr(req); return req; @@ -156,11 +153,26 @@ ossl_x509extfactory_set_crl(VALUE self, VALUE crl) X509V3_CTX *ctx; GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@crl", crl); ctx->crl = DupX509CRLPtr(crl); return crl; } +static VALUE +ossl_x509extfactory_set_config(VALUE self, VALUE config) +{ + X509V3_CTX *ctx; + CONF *conf; + + GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@config", config); + conf = GetConfigPtr(config); + X509V3_set_nconf(ctx, conf); + + return config; +} + static VALUE ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) { @@ -408,10 +420,17 @@ Init_ossl_x509ext() rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc); rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1); + rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse); + rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1); rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1); + rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1); rb_define_method(cX509ExtFactory, "create_ext_from_array", ossl_x509extfactory_create_ext_from_array, 1); cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); -- cgit v1.2.3