00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00032
00033 VALUE cConfig;
00034 VALUE eConfigError;
00035
00036
00037
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
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
00240 if (NIL_P(section)) section = rb_str_new2("");
00241
00242 if (NIL_P(name)) {
00243 name = section;
00244 section = rb_str_new2("");
00245 }
00246
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
00278
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
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