Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_config.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_config.c 27460 2010-04-23 14:28:56Z akr $
    00003  * 'OpenSSL for Ruby' project
    00004  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
    00005  * All rights reserved.
    00006  */
    00007 /*
    00008  * This program is licenced under the same licence as Ruby.
    00009  * (See the file 'LICENCE'.)
    00010  */
    00011 #include "ossl.h"
    00012
    00013 #define WrapConfig(klass, obj, conf) do { \
    00014     if (!conf) { \
    00015         ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
    00016     } \
    00017     obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \
    00018 } while (0)
    00019 #define GetConfig(obj, conf) do { \
    00020     Data_Get_Struct(obj, CONF, conf); \
    00021     if (!conf) { \
    00022         ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
    00023     } \
    00024 } while (0)
    00025 #define SafeGetConfig(obj, conf) do { \
    00026     OSSL_Check_Kind(obj, cConfig); \
    00027     GetConfig(obj, conf); \
    00028 } while(0);
    00029
    00030 /*
    00031  * Classes
    00032  */
    00033 VALUE cConfig;
    00034 VALUE eConfigError;
    00035
    00036 /*
    00037  * Public
    00038  */
    00039
    00040 static CONF *parse_config(VALUE, CONF*);
    00041
    00042 CONF *
    00043 GetConfigPtr(VALUE obj)
    00044 {
    00045     CONF *conf;
    00046
    00047     SafeGetConfig(obj, conf);
    00048
    00049     return conf;
    00050 }
    00051
    00052 CONF *
    00053 DupConfigPtr(VALUE obj)
    00054 {
    00055     VALUE str;
    00056
    00057     OSSL_Check_Kind(obj, cConfig);
    00058     str = rb_funcall(obj, rb_intern("to_s"), 0);
    00059
    00060     return parse_config(str, NULL);
    00061 }
    00062
    00063 /*
    00064  * Private
    00065  */
    00066 static CONF *
    00067 parse_config(VALUE str, CONF *dst)
    00068 {
    00069     CONF *conf;
    00070     BIO *bio;
    00071     long eline = -1;
    00072
    00073     bio = ossl_obj2bio(str);
    00074     conf = dst ? dst : NCONF_new(NULL);
    00075     if(!conf){
    00076         BIO_free(bio);
    00077         ossl_raise(eConfigError, NULL);
    00078     }
    00079     if(!NCONF_load_bio(conf, bio, &eline)){
    00080         BIO_free(bio);
    00081         if(!dst) NCONF_free(conf);
    00082         if (eline <= 0) ossl_raise(eConfigError, "wrong config format");
    00083         else ossl_raise(eConfigError, "error in line %d", eline);
    00084         ossl_raise(eConfigError, NULL);
    00085     }
    00086     BIO_free(bio);
    00087
    00088     return conf;
    00089 }
    00090
    00091 static VALUE
    00092 ossl_config_s_parse(VALUE klass, VALUE str)
    00093 {
    00094     CONF *conf;
    00095     VALUE obj;
    00096
    00097     conf = parse_config(str, NULL);
    00098     WrapConfig(klass, obj, conf);
    00099
    00100     return obj;
    00101 }
    00102
    00103 static VALUE
    00104 ossl_config_s_alloc(VALUE klass)
    00105 {
    00106     CONF *conf;
    00107     VALUE obj;
    00108
    00109     if(!(conf = NCONF_new(NULL)))
    00110         ossl_raise(eConfigError, NULL);
    00111     WrapConfig(klass, obj, conf);
    00112
    00113     return obj;
    00114 }
    00115
    00116 static VALUE
    00117 ossl_config_copy(VALUE self, VALUE other)
    00118 {
    00119     VALUE str;
    00120     CONF *conf;
    00121
    00122     str = rb_funcall(self, rb_intern("to_s"), 0);
    00123     GetConfig(other, conf);
    00124     parse_config(str, conf);
    00125
    00126     return self;
    00127 }
    00128
    00129 static VALUE
    00130 ossl_config_initialize(int argc, VALUE *argv, VALUE self)
    00131 {
    00132     CONF *conf;
    00133     long eline = -1;
    00134     char *filename;
    00135     VALUE path;
    00136
    00137     rb_scan_args(argc, argv, "01", &path);
    00138     if(!NIL_P(path)){
    00139         SafeStringValue(path);
    00140         filename = StringValuePtr(path);
    00141         GetConfig(self, conf);
    00142         if (!NCONF_load(conf, filename, &eline)){
    00143             if (eline <= 0)
    00144                 ossl_raise(eConfigError, "wrong config file %s", filename);
    00145             else
    00146                 ossl_raise(eConfigError, "error in %s:%d", filename, eline);
    00147         }
    00148     }
    00149 #ifdef OSSL_NO_CONF_API
    00150     else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
    00151 #else
    00152     else {
    00153         GetConfig(self, conf);
    00154         _CONF_new_data(conf);
    00155     }
    00156 #endif
    00157
    00158     return self;
    00159 }
    00160
    00161 static VALUE
    00162 ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
    00163 {
    00164 #ifdef OSSL_NO_CONF_API
    00165     rb_notimplement();
    00166 #else
    00167     CONF *conf;
    00168     CONF_VALUE *sv, *cv;
    00169
    00170     StringValue(section);
    00171     StringValue(name);
    00172     StringValue(value);
    00173     GetConfig(self, conf);
    00174     if(!(sv = _CONF_get_section(conf, RSTRING_PTR(section)))){
    00175         if(!(sv = _CONF_new_section(conf, RSTRING_PTR(section)))){
    00176             ossl_raise(eConfigError, NULL);
    00177         }
    00178     }
    00179     if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
    00180         ossl_raise(eConfigError, NULL);
    00181     }
    00182     cv->name = BUF_strdup(RSTRING_PTR(name));
    00183     cv->value = BUF_strdup(RSTRING_PTR(value));
    00184     if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
    00185         OPENSSL_free(cv->name);
    00186         OPENSSL_free(cv->value);
    00187         OPENSSL_free(cv);
    00188         ossl_raise(eConfigError, "_CONF_add_string failure");
    00189     }
    00190
    00191     return value;
    00192 #endif
    00193 }
    00194
    00195 static void
    00196 rb_ossl_config_modify_check(VALUE config)
    00197 {
    00198     if (OBJ_FROZEN(config)) rb_error_frozen("OpenSSL::Config");
    00199     if (!OBJ_UNTRUSTED(config) && rb_safe_level() >= 4)
    00200         rb_raise(rb_eSecurityError, "Insecure: can't modify OpenSSL config");
    00201 }
    00202
    00203 #if !defined(OSSL_NO_CONF_API)
    00204 static VALUE
    00205 ossl_config_add_value_m(VALUE self, VALUE section, VALUE name, VALUE value)
    00206 {
    00207     rb_ossl_config_modify_check(self);
    00208     return ossl_config_add_value(self, section, name, value);
    00209 }
    00210 #else
    00211 #define ossl_config_add_value_m rb_f_notimplement
    00212 #endif
    00213
    00214 static VALUE
    00215 ossl_config_get_value(VALUE self, VALUE section, VALUE name)
    00216 {
    00217     CONF *conf;
    00218     char *str;
    00219
    00220     StringValue(section);
    00221     StringValue(name);
    00222     GetConfig(self, conf);
    00223     str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name));
    00224     if(!str){
    00225         ERR_clear_error();
    00226         return Qnil;
    00227     }
    00228
    00229     return rb_str_new2(str);
    00230 }
    00231
    00232 static VALUE
    00233 ossl_config_get_value_old(int argc, VALUE *argv, VALUE self)
    00234 {
    00235     VALUE section, name;
    00236
    00237     rb_scan_args(argc, argv, "11", &section, &name);
    00238
    00239     /* support conf.value(nil, "HOME") -> conf.get_value("", "HOME") */
    00240     if (NIL_P(section)) section = rb_str_new2("");
    00241     /* support conf.value("HOME") -> conf.get_value("", "HOME") */
    00242     if (NIL_P(name)) {
    00243         name = section;
    00244         section = rb_str_new2("");
    00245     }
    00246     /* NOTE: Don't care about conf.get_value(nil, nil) */
    00247     rb_warn("Config#value is deprecated; use Config#get_value");
    00248     return ossl_config_get_value(self, section, name);
    00249 }
    00250
    00251 static VALUE
    00252 set_conf_section_i(VALUE i, VALUE *arg)
    00253 {
    00254     VALUE name, value;
    00255
    00256     Check_Type(i, T_ARRAY);
    00257     name = rb_ary_entry(i, 0);
    00258     value = rb_ary_entry(i, 1);
    00259     ossl_config_add_value(arg[0], arg[1], name, value);
    00260
    00261     return Qnil;
    00262 }
    00263
    00264 static VALUE
    00265 ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
    00266 {
    00267     VALUE arg[2];
    00268
    00269     rb_ossl_config_modify_check(self);
    00270     arg[0] = self;
    00271     arg[1] = section;
    00272     rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
    00273     return hash;
    00274 }
    00275
    00276 /*
    00277  * Get all numbers as strings - use str.to_i to convert
    00278  * long number = CONF_get_number(confp->config, sect, StringValuePtr(item));
    00279  */
    00280 static VALUE
    00281 ossl_config_get_section(VALUE self, VALUE section)
    00282 {
    00283     CONF *conf;
    00284     STACK_OF(CONF_VALUE) *sk;
    00285     CONF_VALUE *entry;
    00286     int i, entries;
    00287     VALUE hash;
    00288
    00289     hash = rb_hash_new();
    00290     StringValue(section);
    00291     GetConfig(self, conf);
    00292     if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) {
    00293         ERR_clear_error();
    00294         return hash;
    00295     }
    00296     if ((entries = sk_CONF_VALUE_num(sk)) < 0) {
    00297         OSSL_Debug("# of items in section is < 0?!?");
    00298         return hash;
    00299     }
    00300     for (i=0; i<entries; i++) {
    00301         entry = sk_CONF_VALUE_value(sk, i);
    00302         rb_hash_aset(hash, rb_str_new2(entry->name), rb_str_new2(entry->value));
    00303     }
    00304
    00305     return hash;
    00306 }
    00307
    00308 static VALUE
    00309 ossl_config_get_section_old(VALUE self, VALUE section)
    00310 {
    00311     rb_warn("Config#section is deprecated; use Config#[]");
    00312     return ossl_config_get_section(self, section);
    00313 }
    00314
    00315 #if defined(IMPLEMENT_LHASH_DOALL_ARG_FN) && defined(LHASH_OF)
    00316 static void
    00317 get_conf_section_doall_arg(CONF_VALUE *cv, void *tmp)
    00318 {
    00319     VALUE ary = (VALUE)tmp;
    00320     if(cv->name) return;
    00321     rb_ary_push(ary, rb_str_new2(cv->section));
    00322 }
    00323
    00324 static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE, void)
    00325
    00326 static VALUE
    00327 ossl_config_get_sections(VALUE self)
    00328 {
    00329     CONF *conf;
    00330     VALUE ary;
    00331
    00332     GetConfig(self, conf);
    00333     ary = rb_ary_new();
    00334     lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(get_conf_section),
    00335                  (void*)ary);
    00336
    00337     return ary;
    00338 }
    00339
    00340 static void
    00341 dump_conf_value_doall_arg(CONF_VALUE *cv, void *tmp)
    00342 {
    00343     VALUE str = (VALUE)tmp;
    00344     STACK_OF(CONF_VALUE) *sk;
    00345     CONF_VALUE *v;
    00346     int i, num;
    00347
    00348     if (cv->name) return;
    00349     sk = (STACK_OF(CONF_VALUE)*)cv->value;
    00350     num = sk_CONF_VALUE_num(sk);
    00351     rb_str_cat2(str, "[ ");
    00352     rb_str_cat2(str, cv->section);
    00353     rb_str_cat2(str, " ]\n");
    00354     for(i = 0; i < num; i++){
    00355         v = sk_CONF_VALUE_value(sk, i);
    00356         rb_str_cat2(str, v->name ? v->name : "None");
    00357         rb_str_cat2(str, "=");
    00358         rb_str_cat2(str, v->value ? v->value : "None");
    00359         rb_str_cat2(str, "\n");
    00360     }
    00361     rb_str_cat2(str, "\n");
    00362 }
    00363
    00364 static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, void)
    00365
    00366 static VALUE
    00367 dump_conf(CONF *conf)
    00368 {
    00369     VALUE str;
    00370
    00371     str = rb_str_new(0, 0);
    00372     lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(dump_conf_value),
    00373                  (void*)str);
    00374
    00375     return str;
    00376 }
    00377
    00378 static VALUE
    00379 ossl_config_to_s(VALUE self)
    00380 {
    00381     CONF *conf;
    00382
    00383     GetConfig(self, conf);
    00384
    00385     return dump_conf(conf);
    00386 }
    00387
    00388 static void
    00389 each_conf_value_doall_arg(CONF_VALUE *cv, void *dummy)
    00390 {
    00391     STACK_OF(CONF_VALUE) *sk;
    00392     CONF_VALUE *v;
    00393     VALUE section, name, value, args;
    00394     int i, num;
    00395
    00396     if (cv->name) return;
    00397     sk = (STACK_OF(CONF_VALUE)*)cv->value;
    00398     num = sk_CONF_VALUE_num(sk);
    00399     section = rb_str_new2(cv->section);
    00400     for(i = 0; i < num; i++){
    00401         v = sk_CONF_VALUE_value(sk, i);
    00402         name = v->name ? rb_str_new2(v->name) : Qnil;
    00403         value = v->value ? rb_str_new2(v->value) : Qnil;
    00404         args = rb_ary_new3(3, section, name, value);
    00405         rb_yield(args);
    00406     }
    00407 }
    00408
    00409 static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE, void *)
    00410
    00411 static VALUE
    00412 ossl_config_each(VALUE self)
    00413 {
    00414     CONF *conf;
    00415
    00416     RETURN_ENUMERATOR(self, 0, 0);
    00417
    00418     GetConfig(self, conf);
    00419     lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(each_conf_value),
    00420                  (void*)NULL);
    00421
    00422     return self;
    00423 }
    00424 #else
    00425 static VALUE
    00426 ossl_config_get_sections(VALUE self)
    00427 {
    00428     rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT);
    00429     return rb_ary_new();
    00430 }
    00431
    00432 static VALUE
    00433 ossl_config_to_s(VALUE self)
    00434 {
    00435     rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT);
    00436     return rb_str_new(0, 0);
    00437 }
    00438
    00439 static VALUE
    00440 ossl_config_each(VALUE self)
    00441 {
    00442     rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT);
    00443     return self;
    00444 }
    00445 #endif
    00446
    00447 static VALUE
    00448 ossl_config_inspect(VALUE self)
    00449 {
    00450     VALUE str, ary = ossl_config_get_sections(self);
    00451     const char *cname = rb_class2name(rb_obj_class(self));
    00452
    00453     str = rb_str_new2("#<");
    00454     rb_str_cat2(str, cname);
    00455     rb_str_cat2(str, " sections=");
    00456     rb_str_append(str, rb_inspect(ary));
    00457     rb_str_cat2(str, ">");
    00458
    00459     return str;
    00460 }
    00461
    00462 /*
    00463  * INIT
    00464  */
    00465 void
    00466 Init_ossl_config()
    00467 {
    00468     char *default_config_file;
    00469     eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
    00470     cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
    00471
    00472     default_config_file = CONF_get1_default_config_file();
    00473     rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
    00474                     rb_str_new2(default_config_file));
    00475     OPENSSL_free(default_config_file);
    00476     rb_include_module(cConfig, rb_mEnumerable);
    00477     rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1);
    00478     rb_define_alias(CLASS_OF(cConfig), "load", "new");
    00479     rb_define_alloc_func(cConfig, ossl_config_s_alloc);
    00480     rb_define_copy_func(cConfig, ossl_config_copy);
    00481     rb_define_method(cConfig, "initialize", ossl_config_initialize, -1);
    00482     rb_define_method(cConfig, "get_value", ossl_config_get_value, 2);
    00483     rb_define_method(cConfig, "value", ossl_config_get_value_old, -1);
    00484     rb_define_method(cConfig, "add_value", ossl_config_add_value_m, 3);
    00485     rb_define_method(cConfig, "[]", ossl_config_get_section, 1);
    00486     rb_define_method(cConfig, "section", ossl_config_get_section_old, 1);
    00487     rb_define_method(cConfig, "[]=", ossl_config_set_section, 2);
    00488     rb_define_method(cConfig, "sections", ossl_config_get_sections, 0);
    00489     rb_define_method(cConfig, "to_s", ossl_config_to_s, 0);
    00490     rb_define_method(cConfig, "each", ossl_config_each, 0);
    00491     rb_define_method(cConfig, "inspect", ossl_config_inspect, 0);
    00492 }
    00493