openssl 2.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +35 -45
  3. data/History.md +426 -0
  4. data/README.md +38 -21
  5. data/ext/openssl/extconf.rb +132 -72
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +62 -46
  8. data/ext/openssl/ossl.c +177 -252
  9. data/ext/openssl/ossl.h +39 -17
  10. data/ext/openssl/ossl_asn1.c +53 -14
  11. data/ext/openssl/ossl_bn.c +288 -146
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +42 -32
  14. data/ext/openssl/ossl_config.c +412 -41
  15. data/ext/openssl/ossl_config.h +4 -7
  16. data/ext/openssl/ossl_digest.c +32 -63
  17. data/ext/openssl/ossl_engine.c +19 -28
  18. data/ext/openssl/ossl_hmac.c +61 -146
  19. data/ext/openssl/ossl_kdf.c +15 -23
  20. data/ext/openssl/ossl_ns_spki.c +2 -2
  21. data/ext/openssl/ossl_ocsp.c +17 -70
  22. data/ext/openssl/ossl_ocsp.h +3 -3
  23. data/ext/openssl/ossl_pkcs12.c +23 -4
  24. data/ext/openssl/ossl_pkcs7.c +49 -81
  25. data/ext/openssl/ossl_pkcs7.h +16 -0
  26. data/ext/openssl/ossl_pkey.c +1508 -195
  27. data/ext/openssl/ossl_pkey.h +41 -78
  28. data/ext/openssl/ossl_pkey_dh.c +153 -348
  29. data/ext/openssl/ossl_pkey_dsa.c +157 -413
  30. data/ext/openssl/ossl_pkey_ec.c +257 -343
  31. data/ext/openssl/ossl_pkey_rsa.c +166 -490
  32. data/ext/openssl/ossl_provider.c +211 -0
  33. data/ext/openssl/ossl_provider.h +5 -0
  34. data/ext/openssl/ossl_rand.c +2 -40
  35. data/ext/openssl/ossl_ssl.c +666 -456
  36. data/ext/openssl/ossl_ssl_session.c +29 -30
  37. data/ext/openssl/ossl_ts.c +1539 -0
  38. data/ext/openssl/ossl_ts.h +16 -0
  39. data/ext/openssl/ossl_x509.c +86 -1
  40. data/ext/openssl/ossl_x509attr.c +1 -1
  41. data/ext/openssl/ossl_x509cert.c +170 -14
  42. data/ext/openssl/ossl_x509crl.c +14 -11
  43. data/ext/openssl/ossl_x509ext.c +29 -9
  44. data/ext/openssl/ossl_x509name.c +24 -12
  45. data/ext/openssl/ossl_x509req.c +14 -11
  46. data/ext/openssl/ossl_x509revoked.c +4 -4
  47. data/ext/openssl/ossl_x509store.c +205 -96
  48. data/lib/openssl/bn.rb +1 -1
  49. data/lib/openssl/buffering.rb +42 -20
  50. data/lib/openssl/cipher.rb +1 -1
  51. data/lib/openssl/digest.rb +10 -16
  52. data/lib/openssl/hmac.rb +78 -0
  53. data/lib/openssl/marshal.rb +30 -0
  54. data/lib/openssl/pkcs5.rb +1 -1
  55. data/lib/openssl/pkey.rb +447 -1
  56. data/lib/openssl/ssl.rb +68 -24
  57. data/lib/openssl/version.rb +5 -0
  58. data/lib/openssl/x509.rb +177 -1
  59. data/lib/openssl.rb +24 -9
  60. metadata +18 -71
  61. data/ext/openssl/deprecation.rb +0 -23
  62. data/ext/openssl/ossl_version.h +0 -15
  63. data/ext/openssl/ruby_missing.h +0 -24
  64. data/lib/openssl/config.rb +0 -474
@@ -42,7 +42,7 @@ static const rb_data_type_t ossl_cipher_type = {
42
42
  {
43
43
  0, ossl_cipher_free,
44
44
  },
45
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
46
46
  };
47
47
 
48
48
  /*
@@ -104,7 +104,7 @@ ossl_cipher_alloc(VALUE klass)
104
104
  * call-seq:
105
105
  * Cipher.new(string) -> cipher
106
106
  *
107
- * The string must be a valid cipher name like "AES-128-CBC" or "3DES".
107
+ * The string must contain a valid cipher name like "aes-256-cbc".
108
108
  *
109
109
  * A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
110
110
  */
@@ -149,11 +149,11 @@ ossl_cipher_copy(VALUE self, VALUE other)
149
149
  return self;
150
150
  }
151
151
 
152
- static void*
153
- add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
152
+ static void
153
+ add_cipher_name_to_ary(const OBJ_NAME *name, void *arg)
154
154
  {
155
+ VALUE ary = (VALUE)arg;
155
156
  rb_ary_push(ary, rb_str_new2(name->name));
156
- return NULL;
157
157
  }
158
158
 
159
159
  /*
@@ -169,7 +169,7 @@ ossl_s_ciphers(VALUE self)
169
169
 
170
170
  ary = rb_ary_new();
171
171
  OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
172
- (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
172
+ add_cipher_name_to_ary,
173
173
  (void*)ary);
174
174
 
175
175
  return ary;
@@ -237,8 +237,7 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
237
237
  ossl_raise(eCipherError, NULL);
238
238
  }
239
239
 
240
- if (p_key)
241
- rb_ivar_set(self, id_key_set, Qtrue);
240
+ rb_ivar_set(self, id_key_set, p_key ? Qtrue : Qfalse);
242
241
 
243
242
  return self;
244
243
  }
@@ -317,6 +316,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
317
316
  salt = (unsigned char *)RSTRING_PTR(vsalt);
318
317
  }
319
318
  iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
319
+ if (iter <= 0)
320
+ rb_raise(rb_eArgError, "iterations must be a positive integer");
320
321
  digest = NIL_P(vdigest) ? EVP_md5() : ossl_evp_get_digestbyname(vdigest);
321
322
  GetCipher(self, ctx);
322
323
  EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
@@ -383,8 +384,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
383
384
 
384
385
  StringValue(data);
385
386
  in = (unsigned char *)RSTRING_PTR(data);
386
- if ((in_len = RSTRING_LEN(data)) == 0)
387
- ossl_raise(rb_eArgError, "data must not be empty");
387
+ in_len = RSTRING_LEN(data);
388
388
  GetCipher(self, ctx);
389
389
  out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
390
390
  if (out_len <= 0) {
@@ -812,6 +812,31 @@ ossl_cipher_block_size(VALUE self)
812
812
  return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
813
813
  }
814
814
 
815
+ /*
816
+ * call-seq:
817
+ * cipher.ccm_data_len = integer -> integer
818
+ *
819
+ * Sets the length of the plaintext / ciphertext message that will be
820
+ * processed in CCM mode. Make sure to call this method after #key= and
821
+ * #iv= have been set, and before #auth_data=.
822
+ *
823
+ * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
824
+ */
825
+ static VALUE
826
+ ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
827
+ {
828
+ int in_len, out_len;
829
+ EVP_CIPHER_CTX *ctx;
830
+
831
+ in_len = NUM2INT(data_len);
832
+
833
+ GetCipher(self, ctx);
834
+ if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1)
835
+ ossl_raise(eCipherError, NULL);
836
+
837
+ return data_len;
838
+ }
839
+
815
840
  /*
816
841
  * INIT
817
842
  */
@@ -848,23 +873,7 @@ Init_ossl_cipher(void)
848
873
  * individual components name, key length and mode. Either all uppercase
849
874
  * or all lowercase strings may be used, for example:
850
875
  *
851
- * cipher = OpenSSL::Cipher.new('AES-128-CBC')
852
- *
853
- * For each algorithm supported, there is a class defined under the
854
- * Cipher class that goes by the name of the cipher, e.g. to obtain an
855
- * instance of AES, you could also use
856
- *
857
- * # these are equivalent
858
- * cipher = OpenSSL::Cipher::AES.new(128, :CBC)
859
- * cipher = OpenSSL::Cipher::AES.new(128, 'CBC')
860
- * cipher = OpenSSL::Cipher::AES.new('128-CBC')
861
- *
862
- * Finally, due to its wide-spread use, there are also extra classes
863
- * defined for the different key sizes of AES
864
- *
865
- * cipher = OpenSSL::Cipher::AES128.new(:CBC)
866
- * cipher = OpenSSL::Cipher::AES192.new(:CBC)
867
- * cipher = OpenSSL::Cipher::AES256.new(:CBC)
876
+ * cipher = OpenSSL::Cipher.new('aes-128-cbc')
868
877
  *
869
878
  * === Choosing either encryption or decryption mode
870
879
  *
@@ -894,7 +903,7 @@ Init_ossl_cipher(void)
894
903
  * without processing the password further. A simple and secure way to
895
904
  * create a key for a particular Cipher is
896
905
  *
897
- * cipher = OpenSSL::AES256.new(:CFB)
906
+ * cipher = OpenSSL::Cipher.new('aes-256-cfb')
898
907
  * cipher.encrypt
899
908
  * key = cipher.random_key # also sets the generated key on the Cipher
900
909
  *
@@ -962,14 +971,14 @@ Init_ossl_cipher(void)
962
971
  *
963
972
  * data = "Very, very confidential data"
964
973
  *
965
- * cipher = OpenSSL::Cipher::AES.new(128, :CBC)
974
+ * cipher = OpenSSL::Cipher.new('aes-128-cbc')
966
975
  * cipher.encrypt
967
976
  * key = cipher.random_key
968
977
  * iv = cipher.random_iv
969
978
  *
970
979
  * encrypted = cipher.update(data) + cipher.final
971
980
  * ...
972
- * decipher = OpenSSL::Cipher::AES.new(128, :CBC)
981
+ * decipher = OpenSSL::Cipher.new('aes-128-cbc')
973
982
  * decipher.decrypt
974
983
  * decipher.key = key
975
984
  * decipher.iv = iv
@@ -1005,7 +1014,7 @@ Init_ossl_cipher(void)
1005
1014
  * not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the
1006
1015
  * security guarantees of GCM mode.
1007
1016
  *
1008
- * cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt
1017
+ * cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
1009
1018
  * cipher.key = key
1010
1019
  * cipher.iv = nonce
1011
1020
  * cipher.auth_data = auth_data
@@ -1021,7 +1030,7 @@ Init_ossl_cipher(void)
1021
1030
  * ciphertext with a probability of 1/256.
1022
1031
  *
1023
1032
  * raise "tag is truncated!" unless tag.bytesize == 16
1024
- * decipher = OpenSSL::Cipher::AES.new(128, :GCM).decrypt
1033
+ * decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
1025
1034
  * decipher.key = key
1026
1035
  * decipher.iv = nonce
1027
1036
  * decipher.auth_tag = tag
@@ -1058,6 +1067,7 @@ Init_ossl_cipher(void)
1058
1067
  rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
1059
1068
  rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
1060
1069
  rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
1070
+ rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1);
1061
1071
 
1062
1072
  id_auth_tag_len = rb_intern_const("auth_tag_len");
1063
1073
  id_key_set = rb_intern_const("key_set");
@@ -9,81 +9,452 @@
9
9
  */
10
10
  #include "ossl.h"
11
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
+ },
25
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
26
+ };
27
+
28
+ CONF *
29
+ GetConfig(VALUE obj)
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 %ld", 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
+ */
72
+ ossl_clear_error();
73
+ }
12
74
 
13
75
  /*
14
- * Classes
15
- */
16
- VALUE cConfig;
17
- /* Document-class: OpenSSL::ConfigError
76
+ * call-seq:
77
+ * Config.parse(string) -> OpenSSL::Config
18
78
  *
19
- * General error for openssl library configuration files. Including formatting,
20
- * parsing errors, etc.
79
+ * Parses a given _string_ as a blob that contains configuration for OpenSSL.
21
80
  */
22
- VALUE eConfigError;
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);
23
95
 
24
96
  /*
25
- * Public
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.
26
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
+ }
27
118
 
28
119
  /*
29
- * DupConfigPtr is a public C-level function for getting OpenSSL CONF struct
30
- * from an OpenSSL::Config(eConfig) instance. We decided to implement
31
- * OpenSSL::Config in Ruby level but we need to pass native CONF struct for
32
- * some OpenSSL features such as X509V3_EXT_*.
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.
33
131
  */
34
- CONF *
35
- DupConfigPtr(VALUE obj)
132
+ static VALUE
133
+ config_initialize(int argc, VALUE *argv, VALUE self)
36
134
  {
37
- CONF *conf;
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);
38
154
  VALUE str;
39
155
  BIO *bio;
40
- long eline = -1;
41
156
 
42
- OSSL_Check_Kind(obj, cConfig);
43
- str = rb_funcall(obj, rb_intern("to_s"), 0);
157
+ str = rb_funcall(other, rb_intern("to_s"), 0);
158
+ rb_check_frozen(self);
44
159
  bio = ossl_obj2bio(&str);
45
- conf = NCONF_new(NULL);
46
- if(!conf){
47
- BIO_free(bio);
48
- ossl_raise(eConfigError, NULL);
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);
191
+ StringValueCStr(key);
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) {
196
+ ossl_clear_error();
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)))) {
234
+ ossl_clear_error();
235
+ return hash;
49
236
  }
50
- if(!NCONF_load_bio(conf, bio, &eline)){
51
- BIO_free(bio);
52
- NCONF_free(conf);
53
- if (eline <= 0)
54
- ossl_raise(eConfigError, "wrong config format");
55
- else
56
- ossl_raise(eConfigError, "error in line %d", eline);
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));
57
242
  }
58
- BIO_free(bio);
243
+ return hash;
244
+ }
59
245
 
60
- return conf;
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));
61
252
  }
62
253
 
63
- /* Document-const: DEFAULT_CONFIG_FILE
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
64
260
  *
65
- * The default system configuration file for openssl
261
+ * Get the names of all sections in the current configuration.
66
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)
67
300
 
68
301
  /*
69
- * INIT
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
70
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=");
403
+ rb_str_append(str, rb_inspect(ary));
404
+ rb_str_cat_cstr(str, ">");
405
+
406
+ return str;
407
+ }
408
+
71
409
  void
72
410
  Init_ossl_config(void)
73
411
  {
74
- char *default_config_file;
412
+ char *path;
413
+ VALUE path_str;
75
414
 
76
415
  #if 0
77
416
  mOSSL = rb_define_module("OpenSSL");
78
417
  eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
79
418
  #endif
80
419
 
81
- eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
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
+ */
82
430
  cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
83
431
 
84
- default_config_file = CONF_get1_default_config_file();
85
- rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
86
- rb_str_new2(default_config_file));
87
- OPENSSL_free(default_config_file);
88
- /* methods are defined by openssl/config.rb */
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
+
439
+ rb_include_module(cConfig, rb_mEnumerable);
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);
89
460
  }
@@ -7,13 +7,10 @@
7
7
  * This program is licensed under the same licence as Ruby.
8
8
  * (See the file 'LICENCE'.)
9
9
  */
10
- #if !defined(_OSSL_CONFIG_H_)
11
- #define _OSSL_CONFIG_H_
10
+ #ifndef OSSL_CONFIG_H
11
+ #define OSSL_CONFIG_H
12
12
 
13
- extern VALUE cConfig;
14
- extern VALUE eConfigError;
15
-
16
- CONF* DupConfigPtr(VALUE obj);
13
+ CONF *GetConfig(VALUE obj);
17
14
  void Init_ossl_config(void);
18
15
 
19
- #endif /* _OSSL_CONFIG_H_ */
16
+ #endif /* OSSL_CONFIG_H */