PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/openssl/ossl_config.c

https://github.com/diabolo/ruby
C | 492 lines | 390 code | 73 blank | 29 comment | 36 complexity | e0aff7437e0d5977666746f46a4a022f MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /*
  2. * $Id$
  3. * 'OpenSSL for Ruby' project
  4. * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
  5. * All rights reserved.
  6. */
  7. /*
  8. * This program is licenced under the same licence as Ruby.
  9. * (See the file 'LICENCE'.)
  10. */
  11. #include "ossl.h"
  12. #define WrapConfig(klass, obj, conf) do { \
  13. if (!conf) { \
  14. ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
  15. } \
  16. obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \
  17. } while (0)
  18. #define GetConfig(obj, conf) do { \
  19. Data_Get_Struct(obj, CONF, conf); \
  20. if (!conf) { \
  21. ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
  22. } \
  23. } while (0)
  24. #define SafeGetConfig(obj, conf) do { \
  25. OSSL_Check_Kind(obj, cConfig); \
  26. GetConfig(obj, conf); \
  27. } while(0);
  28. /*
  29. * Classes
  30. */
  31. VALUE cConfig;
  32. VALUE eConfigError;
  33. /*
  34. * Public
  35. */
  36. static CONF *parse_config(VALUE, CONF*);
  37. CONF *
  38. GetConfigPtr(VALUE obj)
  39. {
  40. CONF *conf;
  41. SafeGetConfig(obj, conf);
  42. return conf;
  43. }
  44. CONF *
  45. DupConfigPtr(VALUE obj)
  46. {
  47. VALUE str;
  48. OSSL_Check_Kind(obj, cConfig);
  49. str = rb_funcall(obj, rb_intern("to_s"), 0);
  50. return parse_config(str, NULL);
  51. }
  52. /*
  53. * Private
  54. */
  55. static CONF *
  56. parse_config(VALUE str, CONF *dst)
  57. {
  58. CONF *conf;
  59. BIO *bio;
  60. long eline = -1;
  61. bio = ossl_obj2bio(str);
  62. conf = dst ? dst : NCONF_new(NULL);
  63. if(!conf){
  64. BIO_free(bio);
  65. ossl_raise(eConfigError, NULL);
  66. }
  67. if(!NCONF_load_bio(conf, bio, &eline)){
  68. BIO_free(bio);
  69. if(!dst) NCONF_free(conf);
  70. if (eline <= 0) ossl_raise(eConfigError, "wrong config format");
  71. else ossl_raise(eConfigError, "error in line %d", eline);
  72. ossl_raise(eConfigError, NULL);
  73. }
  74. BIO_free(bio);
  75. return conf;
  76. }
  77. static VALUE
  78. ossl_config_s_parse(VALUE klass, VALUE str)
  79. {
  80. CONF *conf;
  81. VALUE obj;
  82. conf = parse_config(str, NULL);
  83. WrapConfig(klass, obj, conf);
  84. return obj;
  85. }
  86. static VALUE
  87. ossl_config_s_alloc(VALUE klass)
  88. {
  89. CONF *conf;
  90. VALUE obj;
  91. if(!(conf = NCONF_new(NULL)))
  92. ossl_raise(eConfigError, NULL);
  93. WrapConfig(klass, obj, conf);
  94. return obj;
  95. }
  96. static VALUE
  97. ossl_config_copy(VALUE self, VALUE other)
  98. {
  99. VALUE str;
  100. CONF *conf;
  101. str = rb_funcall(self, rb_intern("to_s"), 0);
  102. GetConfig(other, conf);
  103. parse_config(str, conf);
  104. return self;
  105. }
  106. static VALUE
  107. ossl_config_initialize(int argc, VALUE *argv, VALUE self)
  108. {
  109. CONF *conf;
  110. long eline = -1;
  111. char *filename;
  112. VALUE path;
  113. rb_scan_args(argc, argv, "01", &path);
  114. if(!NIL_P(path)){
  115. SafeStringValue(path);
  116. filename = StringValuePtr(path);
  117. GetConfig(self, conf);
  118. if (!NCONF_load(conf, filename, &eline)){
  119. if (eline <= 0)
  120. ossl_raise(eConfigError, "wrong config file %s", filename);
  121. else
  122. ossl_raise(eConfigError, "error in %s:%d", filename, eline);
  123. }
  124. }
  125. #ifdef OSSL_NO_CONF_API
  126. else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
  127. #else
  128. else {
  129. GetConfig(self, conf);
  130. _CONF_new_data(conf);
  131. }
  132. #endif
  133. return self;
  134. }
  135. static VALUE
  136. ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
  137. {
  138. #ifdef OSSL_NO_CONF_API
  139. rb_notimplement();
  140. #else
  141. CONF *conf;
  142. CONF_VALUE *sv, *cv;
  143. StringValue(section);
  144. StringValue(name);
  145. StringValue(value);
  146. GetConfig(self, conf);
  147. if(!(sv = _CONF_get_section(conf, RSTRING_PTR(section)))){
  148. if(!(sv = _CONF_new_section(conf, RSTRING_PTR(section)))){
  149. ossl_raise(eConfigError, NULL);
  150. }
  151. }
  152. if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
  153. ossl_raise(eConfigError, NULL);
  154. }
  155. cv->name = BUF_strdup(RSTRING_PTR(name));
  156. cv->value = BUF_strdup(RSTRING_PTR(value));
  157. if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
  158. OPENSSL_free(cv->name);
  159. OPENSSL_free(cv->value);
  160. OPENSSL_free(cv);
  161. ossl_raise(eConfigError, "_CONF_add_string failure");
  162. }
  163. return value;
  164. #endif
  165. }
  166. static void
  167. rb_ossl_config_modify_check(VALUE config)
  168. {
  169. if (OBJ_FROZEN(config)) rb_error_frozen("OpenSSL::Config");
  170. if (!OBJ_UNTRUSTED(config) && rb_safe_level() >= 4)
  171. rb_raise(rb_eSecurityError, "Insecure: can't modify OpenSSL config");
  172. }
  173. #if !defined(OSSL_NO_CONF_API)
  174. static VALUE
  175. ossl_config_add_value_m(VALUE self, VALUE section, VALUE name, VALUE value)
  176. {
  177. rb_ossl_config_modify_check(self);
  178. return ossl_config_add_value(self, section, name, value);
  179. }
  180. #else
  181. #define ossl_config_add_value_m rb_f_notimplement
  182. #endif
  183. static VALUE
  184. ossl_config_get_value(VALUE self, VALUE section, VALUE name)
  185. {
  186. CONF *conf;
  187. char *str;
  188. StringValue(section);
  189. StringValue(name);
  190. GetConfig(self, conf);
  191. str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name));
  192. if(!str){
  193. ERR_clear_error();
  194. return Qnil;
  195. }
  196. return rb_str_new2(str);
  197. }
  198. static VALUE
  199. ossl_config_get_value_old(int argc, VALUE *argv, VALUE self)
  200. {
  201. VALUE section, name;
  202. rb_scan_args(argc, argv, "11", &section, &name);
  203. /* support conf.value(nil, "HOME") -> conf.get_value("", "HOME") */
  204. if (NIL_P(section)) section = rb_str_new2("");
  205. /* support conf.value("HOME") -> conf.get_value("", "HOME") */
  206. if (NIL_P(name)) {
  207. name = section;
  208. section = rb_str_new2("");
  209. }
  210. /* NOTE: Don't care about conf.get_value(nil, nil) */
  211. rb_warn("Config#value is deprecated; use Config#get_value");
  212. return ossl_config_get_value(self, section, name);
  213. }
  214. static VALUE
  215. set_conf_section_i(VALUE i, VALUE *arg)
  216. {
  217. VALUE name, value;
  218. Check_Type(i, T_ARRAY);
  219. name = rb_ary_entry(i, 0);
  220. value = rb_ary_entry(i, 1);
  221. ossl_config_add_value(arg[0], arg[1], name, value);
  222. return Qnil;
  223. }
  224. static VALUE
  225. ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
  226. {
  227. VALUE arg[2];
  228. rb_ossl_config_modify_check(self);
  229. arg[0] = self;
  230. arg[1] = section;
  231. rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
  232. return hash;
  233. }
  234. /*
  235. * Get all numbers as strings - use str.to_i to convert
  236. * long number = CONF_get_number(confp->config, sect, StringValuePtr(item));
  237. */
  238. static VALUE
  239. ossl_config_get_section(VALUE self, VALUE section)
  240. {
  241. CONF *conf;
  242. STACK_OF(CONF_VALUE) *sk;
  243. CONF_VALUE *entry;
  244. int i, entries;
  245. VALUE hash;
  246. hash = rb_hash_new();
  247. StringValue(section);
  248. GetConfig(self, conf);
  249. if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) {
  250. ERR_clear_error();
  251. return hash;
  252. }
  253. if ((entries = sk_CONF_VALUE_num(sk)) < 0) {
  254. OSSL_Debug("# of items in section is < 0?!?");
  255. return hash;
  256. }
  257. for (i=0; i<entries; i++) {
  258. entry = sk_CONF_VALUE_value(sk, i);
  259. rb_hash_aset(hash, rb_str_new2(entry->name), rb_str_new2(entry->value));
  260. }
  261. return hash;
  262. }
  263. static VALUE
  264. ossl_config_get_section_old(VALUE self, VALUE section)
  265. {
  266. rb_warn("Config#section is deprecated; use Config#[]");
  267. return ossl_config_get_section(self, section);
  268. }
  269. #if defined(IMPLEMENT_LHASH_DOALL_ARG_FN) && defined(LHASH_OF)
  270. static void
  271. get_conf_section_doall_arg(CONF_VALUE *cv, void *tmp)
  272. {
  273. VALUE ary = (VALUE)tmp;
  274. if(cv->name) return;
  275. rb_ary_push(ary, rb_str_new2(cv->section));
  276. }
  277. static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE, void)
  278. static VALUE
  279. ossl_config_get_sections(VALUE self)
  280. {
  281. CONF *conf;
  282. VALUE ary;
  283. GetConfig(self, conf);
  284. ary = rb_ary_new();
  285. lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(get_conf_section),
  286. (void*)ary);
  287. return ary;
  288. }
  289. static void
  290. dump_conf_value_doall_arg(CONF_VALUE *cv, void *tmp)
  291. {
  292. VALUE str = (VALUE)tmp;
  293. STACK_OF(CONF_VALUE) *sk;
  294. CONF_VALUE *v;
  295. int i, num;
  296. if (cv->name) return;
  297. sk = (STACK_OF(CONF_VALUE)*)cv->value;
  298. num = sk_CONF_VALUE_num(sk);
  299. rb_str_cat2(str, "[ ");
  300. rb_str_cat2(str, cv->section);
  301. rb_str_cat2(str, " ]\n");
  302. for(i = 0; i < num; i++){
  303. v = sk_CONF_VALUE_value(sk, i);
  304. rb_str_cat2(str, v->name ? v->name : "None");
  305. rb_str_cat2(str, "=");
  306. rb_str_cat2(str, v->value ? v->value : "None");
  307. rb_str_cat2(str, "\n");
  308. }
  309. rb_str_cat2(str, "\n");
  310. }
  311. static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, void)
  312. static VALUE
  313. dump_conf(CONF *conf)
  314. {
  315. VALUE str;
  316. str = rb_str_new(0, 0);
  317. lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(dump_conf_value),
  318. (void*)str);
  319. return str;
  320. }
  321. static VALUE
  322. ossl_config_to_s(VALUE self)
  323. {
  324. CONF *conf;
  325. GetConfig(self, conf);
  326. return dump_conf(conf);
  327. }
  328. static void
  329. each_conf_value_doall_arg(CONF_VALUE *cv, void *dummy)
  330. {
  331. STACK_OF(CONF_VALUE) *sk;
  332. CONF_VALUE *v;
  333. VALUE section, name, value, args;
  334. int i, num;
  335. if (cv->name) return;
  336. sk = (STACK_OF(CONF_VALUE)*)cv->value;
  337. num = sk_CONF_VALUE_num(sk);
  338. section = rb_str_new2(cv->section);
  339. for(i = 0; i < num; i++){
  340. v = sk_CONF_VALUE_value(sk, i);
  341. name = v->name ? rb_str_new2(v->name) : Qnil;
  342. value = v->value ? rb_str_new2(v->value) : Qnil;
  343. args = rb_ary_new3(3, section, name, value);
  344. rb_yield(args);
  345. }
  346. }
  347. static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE, void *)
  348. static VALUE
  349. ossl_config_each(VALUE self)
  350. {
  351. CONF *conf;
  352. RETURN_ENUMERATOR(self, 0, 0);
  353. GetConfig(self, conf);
  354. lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(each_conf_value),
  355. (void*)NULL);
  356. return self;
  357. }
  358. #else
  359. static VALUE
  360. ossl_config_get_sections(VALUE self)
  361. {
  362. rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT);
  363. return rb_ary_new();
  364. }
  365. static VALUE
  366. ossl_config_to_s(VALUE self)
  367. {
  368. rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT);
  369. return rb_str_new(0, 0);
  370. }
  371. static VALUE
  372. ossl_config_each(VALUE self)
  373. {
  374. rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT);
  375. return self;
  376. }
  377. #endif
  378. static VALUE
  379. ossl_config_inspect(VALUE self)
  380. {
  381. VALUE str, ary = ossl_config_get_sections(self);
  382. const char *cname = rb_class2name(rb_obj_class(self));
  383. str = rb_str_new2("#<");
  384. rb_str_cat2(str, cname);
  385. rb_str_cat2(str, " sections=");
  386. rb_str_append(str, rb_inspect(ary));
  387. rb_str_cat2(str, ">");
  388. return str;
  389. }
  390. /*
  391. * INIT
  392. */
  393. void
  394. Init_ossl_config()
  395. {
  396. char *default_config_file;
  397. eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
  398. cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
  399. default_config_file = CONF_get1_default_config_file();
  400. rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
  401. rb_str_new2(default_config_file));
  402. OPENSSL_free(default_config_file);
  403. rb_include_module(cConfig, rb_mEnumerable);
  404. rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1);
  405. rb_define_alias(CLASS_OF(cConfig), "load", "new");
  406. rb_define_alloc_func(cConfig, ossl_config_s_alloc);
  407. rb_define_copy_func(cConfig, ossl_config_copy);
  408. rb_define_method(cConfig, "initialize", ossl_config_initialize, -1);
  409. rb_define_method(cConfig, "get_value", ossl_config_get_value, 2);
  410. rb_define_method(cConfig, "value", ossl_config_get_value_old, -1);
  411. rb_define_method(cConfig, "add_value", ossl_config_add_value_m, 3);
  412. rb_define_method(cConfig, "[]", ossl_config_get_section, 1);
  413. rb_define_method(cConfig, "section", ossl_config_get_section_old, 1);
  414. rb_define_method(cConfig, "[]=", ossl_config_set_section, 2);
  415. rb_define_method(cConfig, "sections", ossl_config_get_sections, 0);
  416. rb_define_method(cConfig, "to_s", ossl_config_to_s, 0);
  417. rb_define_method(cConfig, "each", ossl_config_each, 0);
  418. rb_define_method(cConfig, "inspect", ossl_config_inspect, 0);
  419. }