diff options
Diffstat (limited to 'ext/openssl/ossl_config.c')
-rw-r--r-- | ext/openssl/ossl_config.c | 440 |
1 files changed, 11 insertions, 429 deletions
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c index f5e57ba1f2..5bde9cf768 100644 --- a/ext/openssl/ossl_config.c +++ b/ext/openssl/ossl_config.c @@ -10,22 +10,6 @@ */ #include "ossl.h" -#define WrapConfig(klass, obj, conf) do { \ - if (!conf) { \ - ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \ - } \ - 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 @@ -39,46 +23,31 @@ VALUE eConfigError; static CONF *parse_config(VALUE, CONF*); +/* + * GetConfigPtr is a public C-level function for getting OpenSSL CONF struct + * from an OpenSSL::Config(eConfig) instance. We decided to implement + * OpenSSL::Config in Ruby level but we need to pass native CONF struct for + * some OpenSSL features such as X509V3_EXT_*. + */ CONF * GetConfigPtr(VALUE obj) { CONF *conf; - - SafeGetConfig(obj, conf); - - return conf; -} - -CONF * -DupConfigPtr(VALUE obj) -{ 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; + OSSL_Check_Kind(obj, cConfig); + str = rb_funcall(obj, rb_intern("to_s"), 0); bio = ossl_obj2bio(str); - conf = dst ? dst : NCONF_new(NULL); + conf = 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); + 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); @@ -88,378 +57,6 @@ parse_config(VALUE str, CONF *dst) 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_raise(eConfigError, NULL); - WrapConfig(klass, obj, conf); - - return obj; -} - -static VALUE -ossl_config_copy(VALUE self, VALUE other) -{ - VALUE str; - CONF *conf; - - str = rb_funcall(self, rb_intern("to_s"), 0); - GetConfig(other, conf); - parse_config(str, conf); - - return self; -} - -static VALUE -ossl_config_initialize(int argc, VALUE *argv, VALUE self) -{ - CONF *conf; - long eline = -1; - char *filename; - VALUE path; - - rb_scan_args(argc, argv, "01", &path); - if(!NIL_P(path)){ - SafeStringValue(path); - filename = StringValuePtr(path); - GetConfig(self, conf); - 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); - } - } -#ifdef OSSL_NO_CONF_API - else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)"); -#else - else { - GetConfig(self, conf); - _CONF_new_data(conf); - } -#endif - - return self; -} - -static VALUE -ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value) -{ -#ifdef OSSL_NO_CONF_API - rb_notimplement(); -#else - CONF *conf; - CONF_VALUE *sv, *cv; - - StringValue(section); - StringValue(name); - StringValue(value); - GetConfig(self, conf); - if(!(sv = _CONF_get_section(conf, RSTRING_PTR(section)))){ - if(!(sv = _CONF_new_section(conf, RSTRING_PTR(section)))){ - ossl_raise(eConfigError, NULL); - } - } - if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){ - ossl_raise(eConfigError, NULL); - } - cv->name = BUF_strdup(RSTRING_PTR(name)); - cv->value = BUF_strdup(RSTRING_PTR(value)); - 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"); - } - - return value; -#endif -} - -static void -rb_ossl_config_modify_check(VALUE config) -{ - if (OBJ_FROZEN(config)) rb_error_frozen("OpenSSL::Config"); - if (!OBJ_TAINTED(config) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't modify OpenSSL config"); -} - -static VALUE -ossl_config_add_value_m(VALUE self, VALUE section, VALUE name, VALUE value) -{ -#if defined(OSSL_NO_CONF_API) - rb_notimplement(); -#else - rb_ossl_config_modify_check(self); - return ossl_config_add_value(self, section, name, value); -#endif -} - -static VALUE -ossl_config_get_value(VALUE self, VALUE section, VALUE name) -{ - CONF *conf; - char *str; - - StringValue(section); - StringValue(name); - GetConfig(self, conf); - str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name)); - if(!str){ - ERR_clear_error(); - return Qnil; - } - - 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); - - /* support conf.value(nil, "HOME") -> conf.get_value("", "HOME") */ - if (NIL_P(section)) section = rb_str_new2(""); - /* support conf.value("HOME") -> conf.get_value("", "HOME") */ - if (NIL_P(name)) { - name = section; - section = rb_str_new2(""); - } - /* NOTE: Don't care about conf.get_value(nil, nil) */ - 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; - - Check_Type(i, T_ARRAY); - 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]; - - rb_ossl_config_modify_check(self); - arg[0] = self; - arg[1] = section; - rb_block_call(hash, rb_intern("each"), 0, 0, 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) -{ - CONF *conf; - STACK_OF(CONF_VALUE) *sk; - CONF_VALUE *entry; - int i, entries; - VALUE hash; - - hash = rb_hash_new(); - StringValue(section); - GetConfig(self, conf); - if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) { - ERR_clear_error(); - return hash; - } - if ((entries = sk_CONF_VALUE_num(sk)) < 0) { - OSSL_Debug("# of items in section is < 0?!?"); - return hash; - } - for (i=0; i<entries; i++) { - 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); -} - -#ifdef IMPLEMENT_LHASH_DOALL_ARG_FN -#define IMPLEMENT_LHASH_DOALL_ARG_FN_098(f_name,o_type,a_type) \ - void f_name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \ - o_type a = (o_type)arg1; \ - a_type b = (a_type)arg2; \ - f_name(a,b); } - -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_098(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_098(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 void -each_conf_value(CONF_VALUE *cv, void* dummy) -{ - STACK_OF(CONF_VALUE) *sk; - CONF_VALUE *v; - VALUE section, name, value, args; - int i, num; - - if (cv->name) return; - sk = (STACK_OF(CONF_VALUE)*)cv->value; - num = sk_CONF_VALUE_num(sk); - section = rb_str_new2(cv->section); - for(i = 0; i < num; i++){ - v = sk_CONF_VALUE_value(sk, i); - name = v->name ? rb_str_new2(v->name) : Qnil; - value = v->value ? rb_str_new2(v->value) : Qnil; - args = rb_ary_new3(3, section, name, value); - rb_yield(args); - } -} - -static IMPLEMENT_LHASH_DOALL_ARG_FN_098(each_conf_value, CONF_VALUE*, void*) - -static VALUE -ossl_config_each(VALUE self) -{ - CONF *conf; - - RETURN_ENUMERATOR(self, 0, 0); - - GetConfig(self, conf); - lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(each_conf_value), (void*)NULL); - - return self; -} -#else -static VALUE -ossl_config_get_sections(VALUE self) -{ - rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT); - return rb_ary_new(); -} - -static VALUE -ossl_config_to_s(VALUE self) -{ - rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT); - return rb_str_new(0, 0); -} - -static VALUE -ossl_config_each(VALUE self) -{ - rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT); - return self; -} -#endif - -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 */ @@ -474,20 +71,5 @@ Init_ossl_config() rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", rb_str_new2(default_config_file)); OPENSSL_free(default_config_file); - rb_include_module(cConfig, rb_mEnumerable); - 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_m, 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, "each", ossl_config_each, 0); - rb_define_method(cConfig, "inspect", ossl_config_inspect, 0); + /* methods are defined by openssl/config.rb */ } |