Ruby  3.1.0dev(2021-09-10revisionb76ad15ed0da636161de0243c547ee1e6fc95681)
ossl_config.c
Go to the documentation of this file.
1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4  * All rights reserved.
5  */
6 /*
7  * This program is licensed under the same licence as Ruby.
8  * (See the file 'LICENCE'.)
9  */
10 #include "ossl.h"
11 
12 static VALUE cConfig, eConfigError;
13 
14 static void
15 nconf_free(void *conf)
16 {
17  NCONF_free(conf);
18 }
19 
20 static const rb_data_type_t ossl_config_type = {
21  "OpenSSL/CONF",
22  {
23  0, nconf_free,
24  },
26 };
27 
28 CONF *
30 {
31  CONF *conf;
32 
33  TypedData_Get_Struct(obj, CONF, &ossl_config_type, conf);
34  if (!conf)
35  rb_raise(rb_eRuntimeError, "CONF is not initialized");
36  return conf;
37 }
38 
39 static VALUE
40 config_s_alloc(VALUE klass)
41 {
42  VALUE obj;
43  CONF *conf;
44 
45  obj = TypedData_Wrap_Struct(klass, &ossl_config_type, 0);
46  conf = NCONF_new(NULL);
47  if (!conf)
48  ossl_raise(eConfigError, "NCONF_new");
49  RTYPEDDATA_DATA(obj) = conf;
50  return obj;
51 }
52 
53 static void
54 config_load_bio(CONF *conf, BIO *bio)
55 {
56  long eline = -1;
57 
58  if (!NCONF_load_bio(conf, bio, &eline)) {
59  BIO_free(bio);
60  if (eline <= 0)
61  ossl_raise(eConfigError, "wrong config format");
62  else
63  ossl_raise(eConfigError, "error in line %d", eline);
64  }
65  BIO_free(bio);
66 
67  /*
68  * Clear the error queue even if it is parsed successfully.
69  * Particularly, when the .include directive refers to a non-existent file,
70  * it is only reported in the error queue.
71  */
73 }
74 
75 /*
76  * call-seq:
77  * Config.parse(string) -> OpenSSL::Config
78  *
79  * Parses a given _string_ as a blob that contains configuration for OpenSSL.
80  */
81 static VALUE
82 config_s_parse(VALUE klass, VALUE str)
83 {
84  VALUE obj = config_s_alloc(klass);
85  CONF *conf = GetConfig(obj);
86  BIO *bio;
87 
88  bio = ossl_obj2bio(&str);
89  config_load_bio(conf, bio); /* Consumes BIO */
90  return obj;
91 }
92 
93 static VALUE config_get_sections(VALUE self);
94 static VALUE config_get_section(VALUE self, VALUE section);
95 
96 /*
97  * call-seq:
98  * Config.parse_config(io) -> hash
99  *
100  * Parses the configuration data read from _io_ and returns the whole content
101  * as a Hash.
102  */
103 static VALUE
104 config_s_parse_config(VALUE klass, VALUE io)
105 {
106  VALUE obj, sections, ret;
107  long i;
108 
109  obj = config_s_parse(klass, io);
110  sections = config_get_sections(obj);
111  ret = rb_hash_new();
112  for (i = 0; i < RARRAY_LEN(sections); i++) {
113  VALUE section = rb_ary_entry(sections, i);
114  rb_hash_aset(ret, section, config_get_section(obj, section));
115  }
116  return ret;
117 }
118 
119 /*
120  * call-seq:
121  * Config.new(filename) -> OpenSSL::Config
122  *
123  * Creates an instance of OpenSSL::Config from the content of the file
124  * specified by _filename_.
125  *
126  * This can be used in contexts like OpenSSL::X509::ExtensionFactory.config=
127  *
128  * This can raise IO exceptions based on the access, or availability of the
129  * file. A ConfigError exception may be raised depending on the validity of
130  * the data being configured.
131  */
132 static VALUE
133 config_initialize(int argc, VALUE *argv, VALUE self)
134 {
135  CONF *conf = GetConfig(self);
136  VALUE filename;
137 
138  /* 0-arguments call has no use-case, but is kept for compatibility */
139  rb_scan_args(argc, argv, "01", &filename);
140  rb_check_frozen(self);
141  if (!NIL_P(filename)) {
142  BIO *bio = BIO_new_file(StringValueCStr(filename), "rb");
143  if (!bio)
144  ossl_raise(eConfigError, "BIO_new_file");
145  config_load_bio(conf, bio); /* Consumes BIO */
146  }
147  return self;
148 }
149 
150 static VALUE
151 config_initialize_copy(VALUE self, VALUE other)
152 {
153  CONF *conf = GetConfig(self);
154  VALUE str;
155  BIO *bio;
156 
157  str = rb_funcall(other, rb_intern("to_s"), 0);
158  rb_check_frozen(self);
159  bio = ossl_obj2bio(&str);
160  config_load_bio(conf, bio); /* Consumes BIO */
161  return self;
162 }
163 
164 /*
165  * call-seq:
166  * config.get_value(section, key) -> string
167  *
168  * Gets the value of _key_ from the given _section_.
169  *
170  * Given the following configurating file being loaded:
171  *
172  * config = OpenSSL::Config.load('foo.cnf')
173  * #=> #<OpenSSL::Config sections=["default"]>
174  * puts config.to_s
175  * #=> [ default ]
176  * # foo=bar
177  *
178  * You can get a specific value from the config if you know the _section_
179  * and _key_ like so:
180  *
181  * config.get_value('default','foo')
182  * #=> "bar"
183  */
184 static VALUE
185 config_get_value(VALUE self, VALUE section, VALUE key)
186 {
187  CONF *conf = GetConfig(self);
188  const char *str, *sectionp;
189 
190  StringValueCStr(section);
192  /* For compatibility; NULL means "default". */
193  sectionp = RSTRING_LEN(section) ? RSTRING_PTR(section) : NULL;
194  str = NCONF_get_string(conf, sectionp, RSTRING_PTR(key));
195  if (!str) {
197  return Qnil;
198  }
199  return rb_str_new_cstr(str);
200 }
201 
202 /*
203  * call-seq:
204  * config[section] -> hash
205  *
206  * Gets all key-value pairs in a specific _section_ from the current
207  * configuration.
208  *
209  * Given the following configurating file being loaded:
210  *
211  * config = OpenSSL::Config.load('foo.cnf')
212  * #=> #<OpenSSL::Config sections=["default"]>
213  * puts config.to_s
214  * #=> [ default ]
215  * # foo=bar
216  *
217  * You can get a hash of the specific section like so:
218  *
219  * config['default']
220  * #=> {"foo"=>"bar"}
221  *
222  */
223 static VALUE
224 config_get_section(VALUE self, VALUE section)
225 {
226  CONF *conf = GetConfig(self);
227  STACK_OF(CONF_VALUE) *sk;
228  int i, entries;
229  VALUE hash;
230 
231  hash = rb_hash_new();
232  StringValueCStr(section);
233  if (!(sk = NCONF_get_section(conf, RSTRING_PTR(section)))) {
235  return hash;
236  }
237  entries = sk_CONF_VALUE_num(sk);
238  for (i = 0; i < entries; i++) {
239  CONF_VALUE *entry = sk_CONF_VALUE_value(sk, i);
240  rb_hash_aset(hash, rb_str_new_cstr(entry->name),
241  rb_str_new_cstr(entry->value));
242  }
243  return hash;
244 }
245 
246 static void
247 get_conf_section_doall_arg(CONF_VALUE *cv, VALUE *aryp)
248 {
249  if (cv->name)
250  return;
251  rb_ary_push(*aryp, rb_str_new_cstr(cv->section));
252 }
253 
254 /* IMPLEMENT_LHASH_DOALL_ARG_CONST() requires >= OpenSSL 1.1.0 */
255 static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE, VALUE)
256 
257 /*
258  * call-seq:
259  * config.sections -> array of string
260  *
261  * Get the names of all sections in the current configuration.
262  */
263 static VALUE
264 config_get_sections(VALUE self)
265 {
266  CONF *conf = GetConfig(self);
267  VALUE ary;
268 
269  ary = rb_ary_new();
270  lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(get_conf_section),
271  &ary);
272  return ary;
273 }
274 
275 static void
276 dump_conf_value_doall_arg(CONF_VALUE *cv, VALUE *strp)
277 {
278  VALUE str = *strp;
279  STACK_OF(CONF_VALUE) *sk;
280  int i, num;
281 
282  if (cv->name)
283  return;
284  sk = (STACK_OF(CONF_VALUE) *)cv->value;
285  num = sk_CONF_VALUE_num(sk);
286  rb_str_cat_cstr(str, "[ ");
287  rb_str_cat_cstr(str, cv->section);
288  rb_str_cat_cstr(str, " ]\n");
289  for (i = 0; i < num; i++){
290  CONF_VALUE *v = sk_CONF_VALUE_value(sk, i);
291  rb_str_cat_cstr(str, v->name ? v->name : "None");
292  rb_str_cat_cstr(str, "=");
293  rb_str_cat_cstr(str, v->value ? v->value : "None");
294  rb_str_cat_cstr(str, "\n");
295  }
296  rb_str_cat_cstr(str, "\n");
297 }
298 
299 static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, VALUE)
300 
301 /*
302  * call-seq:
303  * config.to_s -> string
304  *
305  *
306  * Gets the parsable form of the current configuration.
307  *
308  * Given the following configuration being created:
309  *
310  * config = OpenSSL::Config.new
311  * #=> #<OpenSSL::Config sections=[]>
312  * config['default'] = {"foo"=>"bar","baz"=>"buz"}
313  * #=> {"foo"=>"bar", "baz"=>"buz"}
314  * puts config.to_s
315  * #=> [ default ]
316  * # foo=bar
317  * # baz=buz
318  *
319  * You can parse get the serialized configuration using #to_s and then parse
320  * it later:
321  *
322  * serialized_config = config.to_s
323  * # much later...
324  * new_config = OpenSSL::Config.parse(serialized_config)
325  * #=> #<OpenSSL::Config sections=["default"]>
326  * puts new_config
327  * #=> [ default ]
328  * foo=bar
329  * baz=buz
330  */
331 static VALUE
332 config_to_s(VALUE self)
333 {
334  CONF *conf = GetConfig(self);
335  VALUE str;
336 
337  str = rb_str_new(NULL, 0);
338  lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(dump_conf_value),
339  &str);
340  return str;
341 }
342 
343 static void
344 each_conf_value_doall_arg(CONF_VALUE *cv, void *unused)
345 {
346  STACK_OF(CONF_VALUE) *sk;
347  VALUE section;
348  int i, num;
349 
350  if (cv->name)
351  return;
352  sk = (STACK_OF(CONF_VALUE) *)cv->value;
353  num = sk_CONF_VALUE_num(sk);
354  section = rb_str_new_cstr(cv->section);
355  for (i = 0; i < num; i++){
356  CONF_VALUE *v = sk_CONF_VALUE_value(sk, i);
357  VALUE name = v->name ? rb_str_new_cstr(v->name) : Qnil;
358  VALUE value = v->value ? rb_str_new_cstr(v->value) : Qnil;
359  rb_yield(rb_ary_new3(3, section, name, value));
360  }
361 }
362 
363 static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE, void)
364 
365 /*
366  * call-seq:
367  * config.each { |section, key, value| }
368  *
369  * Retrieves the section and its pairs for the current configuration.
370  *
371  * config.each do |section, key, value|
372  * # ...
373  * end
374  */
375 static VALUE
376 config_each(VALUE self)
377 {
378  CONF *conf = GetConfig(self);
379 
380  RETURN_ENUMERATOR(self, 0, 0);
381 
382  lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(each_conf_value),
383  NULL);
384  return self;
385 }
386 
387 /*
388  * call-seq:
389  * config.inspect -> string
390  *
391  * String representation of this configuration object, including the class
392  * name and its sections.
393  */
394 static VALUE
395 config_inspect(VALUE self)
396 {
397  VALUE str, ary = config_get_sections(self);
398  const char *cname = rb_class2name(rb_obj_class(self));
399 
400  str = rb_str_new_cstr("#<");
401  rb_str_cat_cstr(str, cname);
402  rb_str_cat_cstr(str, " sections=");
404  rb_str_cat_cstr(str, ">");
405 
406  return str;
407 }
408 
409 void
411 {
412  char *path;
413  VALUE path_str;
414 
415 #if 0
416  mOSSL = rb_define_module("OpenSSL");
418 #endif
419 
420  /* Document-class: OpenSSL::Config
421  *
422  * Configuration for the openssl library.
423  *
424  * Many system's installation of openssl library will depend on your system
425  * configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for
426  * the location of the file for your host.
427  *
428  * See also http://www.openssl.org/docs/apps/config.html
429  */
430  cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
431 
432  /* Document-class: OpenSSL::ConfigError
433  *
434  * General error for openssl library configuration files. Including formatting,
435  * parsing errors, etc.
436  */
437  eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
438 
440  rb_define_singleton_method(cConfig, "parse", config_s_parse, 1);
441  rb_define_singleton_method(cConfig, "parse_config", config_s_parse_config, 1);
442  rb_define_alias(CLASS_OF(cConfig), "load", "new");
443  rb_define_alloc_func(cConfig, config_s_alloc);
444  rb_define_method(cConfig, "initialize", config_initialize, -1);
445  rb_define_method(cConfig, "initialize_copy", config_initialize_copy, 1);
446  rb_define_method(cConfig, "get_value", config_get_value, 2);
447  rb_define_method(cConfig, "[]", config_get_section, 1);
448  rb_define_method(cConfig, "sections", config_get_sections, 0);
449  rb_define_method(cConfig, "to_s", config_to_s, 0);
450  rb_define_method(cConfig, "each", config_each, 0);
451  rb_define_method(cConfig, "inspect", config_inspect, 0);
452 
453  /* Document-const: DEFAULT_CONFIG_FILE
454  *
455  * The default system configuration file for OpenSSL.
456  */
457  path = CONF_get1_default_config_file();
458  path_str = ossl_buf2str(path, rb_long2int(strlen(path)));
459  rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", path_str);
460 }
GetConfig
CONF * GetConfig(VALUE obj)
Definition: ossl_config.c:29
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:984
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: rtypeddata.h:101
rb_define_singleton_method
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:670
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1526
CLASS_OF
#define CLASS_OF
Definition: globals.h:154
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:784
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1377
ossl_obj2bio
BIO * ossl_obj2bio(volatile VALUE *pobj)
Definition: ossl_bio.c:13
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:887
ossl.h
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:591
argv
char ** argv
Definition: ruby.c:243
ossl_clear_error
void ossl_clear_error(void)
Definition: ossl.c:310
RSTRING_LEN
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:3109
strlen
size_t strlen(const char *)
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:2050
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:3022
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1683
NIL_P
#define NIL_P
Definition: special_consts.h:46
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:243
ossl_buf2str
VALUE ossl_buf2str(char *buf, int len)
Definition: ossl.c:126
rb_long2int
#define rb_long2int
Definition: long.h:62
mOSSL
VALUE mOSSL
Definition: ossl.c:237
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:50
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1312
Qnil
#define Qnil
Definition: special_consts.h:51
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:299
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:1091
NULL
#define NULL
Definition: regenc.h:69
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: enumerator.h:74
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: rtypeddata.h:47
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2347
key
key
Definition: openssl_missing.h:145
Init_ossl_config
void Init_ossl_config(void)
Definition: ossl_config.c:410
VALUE
unsigned long VALUE
Definition: value.h:38
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1113
STACK_OF
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
rb_ary_new3
#define rb_ary_new3
Definition: array.h:73
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
ret
return ret
Definition: memory.h:232
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2892
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:3168
rb_check_frozen
#define rb_check_frozen
Definition: error.h:72
argc
int argc
Definition: ruby.c:242
rb_str_cat_cstr
#define rb_str_cat_cstr(buf, str)
Definition: string.h:266
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: rtypeddata.h:130
rb_data_type_struct
Definition: rtypeddata.h:70
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: string.h:219
rb_class2name
const char * rb_class2name(VALUE)
Definition: variable.c:301
eOSSLError
VALUE eOSSLError
Definition: ossl.c:242
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:809
StringValueCStr
#define StringValueCStr(v)
Definition: rstring.h:52
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:655
RARRAY_LEN
#define RARRAY_LEN
Definition: rarray.h:52
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:754
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:27
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:1090
name
const char * name
Definition: nkf.c:208