|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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", §ion, &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
1.7.3