• 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 

Generated on Sat Jul 7 2012 15:29:10 for Ruby by  doxygen 1.7.1